Monster AI improvements:
- [+] replace f_target with f_targetlf - [+] wantrange. for melee fighters (default), it's 0. for spells/archers, it's higiher. - [+] if we are further away than bestrange, move towards. - [+] if we are closer than bestrange, move away - [+] AND: move to wantrange before doing spells etc - [+] if we have a ranged attack and wantrange is default, increase it. - [+] in movetowards/away, cells in the wrong dir should NEVER be acceptable! * [+] mflag_push for monsters http://roguelikedeveloper.blogspot.com/2007/10/unangband-monst er-ai-part-three.html - [+] randomly use ranged attacks when adjacent * [+] show trail in askcoords - [+] when throwing, pass range to askcoords - [+] max monsters per room is depth + 1 * [+] why do humans take ages to appear? - [+] fireball spell is slow - [+] why can i throw objects through magic barriers? - [+] add a bonus for mastery of cartography - magic mapping every 50 turns. - [+] crash with monsters moving off edge of world map - [+] make magic barriers be ON stairs, not around them. - [+] handle DIAGONAL entry to maps - [+] OR make this impossible. - [+] druid should get auto nature knoeldge as they levle up (levs 5 10 15). - [+] CRASH flagpile corrupt - [+] happening during AI movement. - [+] make lightning storm only hit enemies - [+] store last known movement dir in TARGETLF and PETOF. - [+] limit monsters per room not working?!?! - [+] make askcoords let you show object piles with . - [+] make askcoords say "A magical barrier (+xx other objects)" - [+] combine getlastknownmovedir into getlastknowncell * [+] BUG: secret doors are showing up as . again! * [+] implement trails (footprints & scent) * [+] aimovetowardslf(lf, wantattack) * [+] make pets use wantdist code? - [+] what does expert/master tracking give you? - [+] ex: your tracks don't last as long - [+] ms: you don't leave tracks. - [+] change f_reducemovement from multiplier to addition - [+] comma still showing up scents and footprints incorrectly!!!!!!!! Initial shallow/deep water: - [+] restrict movement - [+] check for drowning in turneffectslf AND movelf - [+] warn before walking onto dangerous objects. - [+] change how walkdam works for deepwater. - [+] don't use walkdam flags. - [+] don't make splashes of water on top of deepwater. * [+] deep water will drown you if - [+] don't leave footprints in either - [+] create steam on fire damage, but don't CONVERT to it. - [+] f_waterbreathing - [+] can't drown in water - [+] extra damage from cold/elec if in deep/shallow water Initial swimming implementation * [+] sacred/cursed ground - [+] vending machine - [+] don't transfer f_rarity flag when making objects / lifeforms. Initial work on adding a goal to the game!
This commit is contained in:
parent
a763c3c4b1
commit
69982623ed
710
ai.c
710
ai.c
|
@ -34,7 +34,7 @@ void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
|
|||
}
|
||||
|
||||
// already targetting this lf?
|
||||
f = lfhasflagval(lf, F_TARGET, victim->id, NA, NA, NULL);
|
||||
f = lfhasflagval(lf, F_TARGETLF, victim->id, NA, NA, NULL);
|
||||
if (f) {
|
||||
if ((f->lifetime > 0) && (f->lifetime < timelimit)) {
|
||||
f->lifetime = timelimit;
|
||||
|
@ -46,17 +46,17 @@ void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
|
|||
char lfname[BUFLEN],vicname[BUFLEN];
|
||||
getlfname(lf, lfname);
|
||||
getlfname(victim, vicname);
|
||||
dblog(".oO { %s settings new target: %s }", lfname, vicname);
|
||||
dblog(".oO { %s setting new target: %s }", lfname, vicname);
|
||||
}
|
||||
|
||||
killflagsofid(lf->flags, F_TARGET);
|
||||
killflagsofid(lf->flags, F_TARGETLF);
|
||||
killflagsofid(lf->flags, F_TARGETCELL);
|
||||
|
||||
|
||||
if ((timelimit == PERMENANT) || (timelimit == UNLIMITED)) {
|
||||
addflag(lf->flags, F_TARGET, victim->id, victim->cell->x, victim->cell->y, NULL);
|
||||
addflag(lf->flags, F_TARGETLF, victim->id, victim->cell->x, victim->cell->y, NULL);
|
||||
} else {
|
||||
addtempflag(lf->flags, F_TARGET, victim->id , victim->cell->x , victim->cell->y, NULL,timelimit);
|
||||
addtempflag(lf->flags, F_TARGETLF, victim->id , victim->cell->x , victim->cell->y, NULL,timelimit);
|
||||
}
|
||||
// tell the player
|
||||
if (cansee(player, lf)) {
|
||||
|
@ -155,6 +155,109 @@ enum OBTYPE aigetfleespell(lifeform_t *lf) {
|
|||
return OT_NONE;
|
||||
}
|
||||
|
||||
// this function assumes that you can't just SEE the target!
|
||||
cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *lasty, int *lastdir) {
|
||||
flag_t *f, *tflag, *bestflag;
|
||||
cell_t *c = NULL;
|
||||
int besttime = -1;
|
||||
int i;
|
||||
|
||||
// check scent/footprints first
|
||||
for (i = 0; i < lf->nlos; i++) {
|
||||
if (hastrailof(lf->los[i]->obpile, target, NA, &tflag, lf)) {
|
||||
if (tflag->lifetime > besttime) {
|
||||
besttime = tflag->lifetime;
|
||||
bestflag = tflag;
|
||||
c = lf->los[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c) {
|
||||
if (lastx) *lastx = c->x;
|
||||
if (lasty) *lasty = c->y;
|
||||
if (lastdir) {
|
||||
// can only obtain direction from footprints if your
|
||||
// tracking skill is high enough.
|
||||
if (bestflag->val[2] == S_SIGHT) {
|
||||
if (getskill(lf, SK_TRACKING) >= PR_SKILLED) {
|
||||
*lastdir = bestflag->val[1];
|
||||
} else {
|
||||
*lastdir = D_NONE;
|
||||
}
|
||||
} else {
|
||||
*lastdir = bestflag->val[1];
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
f = ispetortarget(lf, target);
|
||||
if (f) {
|
||||
c = getcellat(lf->cell->map, f->val[1], f->val[2]);
|
||||
if (c) {
|
||||
if (lastx) *lastx = c->x;
|
||||
if (lasty) *lasty = c->y;
|
||||
if (lastdir && strlen(f->text)) {
|
||||
*lastdir = atoi(f->text);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
if (lastx) *lastx = NA;
|
||||
if (lasty) *lasty = NA;
|
||||
if (lastdir) *lastdir = D_NONE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra) {
|
||||
int db = B_FALSE;
|
||||
object_t *o;
|
||||
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
|
||||
|
||||
o = getfirearm(lf);
|
||||
if (o && getammo(lf)) {
|
||||
if (db) {
|
||||
char gunname[BUFLEN];
|
||||
getobname(o, gunname, o->amt);
|
||||
if (db) dblog(".oO { will fire my gun (%s) at target. }",gunname);
|
||||
}
|
||||
*ra = RA_GUN;
|
||||
return o;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name);
|
||||
|
||||
*ra = RA_WAND;
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
// can we attack by throwing something?
|
||||
if (hasbp(lf, BP_HANDS)) {
|
||||
o = getbestthrowmissile(lf);
|
||||
if (o) {
|
||||
if (db) dblog(".oO { will throw %s at my target }", o->type->name);
|
||||
*ra = RA_THROW;
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
if (db) dblog(".oO { found no ranged attack. }");
|
||||
*ra = RA_NONE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose) {
|
||||
int specialcase = B_FALSE;
|
||||
flag_t *f;
|
||||
|
@ -293,7 +396,7 @@ flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int t
|
|||
dblog(".oO { %s going to targecell: %d, %d }", lfname, c->x, c->y);
|
||||
}
|
||||
|
||||
killflagsofid(lf->flags, F_TARGET);
|
||||
killflagsofid(lf->flags, F_TARGETLF);
|
||||
killflagsofid(lf->flags, F_TARGETCELL);
|
||||
|
||||
if (why == MR_LF) {
|
||||
|
@ -312,6 +415,296 @@ flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int t
|
|||
return f;
|
||||
}
|
||||
|
||||
|
||||
// returns B_FALSE if we did something.
|
||||
// returns B_TRUE if we failed (ie. did nothing)
|
||||
int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
|
||||
int db = B_FALSE;
|
||||
int ismaster = B_FALSE;
|
||||
flag_t *targetflag = NULL;
|
||||
|
||||
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
|
||||
|
||||
targetflag = lfhasflagval(lf, F_PETOF, target->id, NA, NA, NULL);
|
||||
if (targetflag) {
|
||||
ismaster = B_TRUE;
|
||||
} else {
|
||||
targetflag = lfhasflagval(lf, F_TARGETLF, target->id, NA, NA, NULL);
|
||||
}
|
||||
|
||||
if (cansee(lf, target)) {
|
||||
int dist,wantdistmin,wantdistmax;
|
||||
int attackok;
|
||||
enum OBTYPE spell;
|
||||
object_t *rangedob = NULL;
|
||||
enum RANGEATTACK rangedattack = RA_NONE;
|
||||
int movefailed = B_FALSE;
|
||||
|
||||
// pet movement
|
||||
if (ismaster) {
|
||||
if (isresting(target)) {
|
||||
// rest as well.
|
||||
rest(lf, B_TRUE);
|
||||
return B_FALSE;
|
||||
} else if (isadjacent(lf->cell, target->cell)) {
|
||||
if (db) dblog(".oO { i can see my master adjacent - moving randomly }");
|
||||
// move randomly. TODO: just return ??
|
||||
dorandommove(lf, B_NOBADMOVES, B_TRUE);
|
||||
return B_FALSE;
|
||||
}
|
||||
// otherwise fall through to below movement code.
|
||||
}
|
||||
|
||||
// how far away is my target ?
|
||||
dist = getcelldist(lf->cell, target->cell);
|
||||
// how far away do i _want_ to be?
|
||||
getwantdistance(lf,&wantdistmin,&wantdistmax, wantattack);
|
||||
|
||||
// reset F_TARGET lifetime to full.
|
||||
if (targetflag) {
|
||||
if (targetflag->id == F_TARGETLF) {
|
||||
targetflag->lifetime = AI_FOLLOWTIME;
|
||||
}
|
||||
if (db) dblog(".oO { i can see my target (at %d,%d). might move towards it. }",target->cell->x,target->cell->y);
|
||||
// remember their location
|
||||
targetflag->val[1] = target->cell->x;
|
||||
targetflag->val[2] = target->cell->y;
|
||||
}
|
||||
|
||||
// is an attack possible?
|
||||
attackok = B_FALSE;
|
||||
if (wantattack) {
|
||||
if (dist == 1) {
|
||||
attackok = B_TRUE;
|
||||
} else if (!lfhasflag(lf, F_HIDING)) {
|
||||
attackok = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (attackok) {
|
||||
objecttype_t *st;
|
||||
// drink boost potions
|
||||
if (!useitemwithflag(lf, F_AIBOOSTITEM)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// try spells first.
|
||||
// can we attack with spells (ie. ones which target the victim)?
|
||||
// if target is adjacent, we will normally just attack rather than try a spell.
|
||||
spell = aigetattackspell(lf, target);
|
||||
st = findot(spell);
|
||||
if ( (spell != OT_NONE) && // found a valid spell/ability to use
|
||||
((dist != 1) || // there is distance between us and target
|
||||
(st->obclass->id == OC_ABILITY) || // OR this works from adjacent
|
||||
(rnd(1,3) == 1)) // OR random chance of using anyway...
|
||||
) {
|
||||
int spellfailed = B_FALSE;
|
||||
lifeform_t *spelllf = NULL;
|
||||
cell_t *spellcell = NULL;
|
||||
object_t *spellob = NULL;
|
||||
if (db) {
|
||||
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 B_FALSE;
|
||||
}
|
||||
|
||||
// see if we have a ranged attack. if so, adjust wantdist
|
||||
// to maintain distance.
|
||||
rangedob = aigetrangedattack(lf, &rangedattack);
|
||||
if (rangedattack != RA_NONE) {
|
||||
if (wantdistmin < 2) wantdistmin = 2;
|
||||
if (wantdistmax < wantdistmin) wantdistmax = wantdistmin;
|
||||
}
|
||||
} // end if attackok
|
||||
|
||||
// move towards the target lf.
|
||||
// try to get to our ideal range from them.
|
||||
if (db) dblog(".oO { i am at distance %d, want to be at %d-%d }", dist, wantdistmin, wantdistmax);
|
||||
if (dist > wantdistmax) {
|
||||
if (db) dblog(".oO { moving towards target. }");
|
||||
if (!movetowards(lf, target->cell, DT_ORTH)) {
|
||||
// success
|
||||
return B_FALSE;
|
||||
} else {
|
||||
if (db) dblog(".oO { move towards failed! - reason = %d }",reason);
|
||||
movefailed = B_TRUE;
|
||||
}
|
||||
} else if (dist < wantdistmin) {
|
||||
if (db) dblog(".oO { moving away from target. }");
|
||||
if (!moveawayfrom(lf, target->cell, DT_ORTH)) {
|
||||
// success
|
||||
return B_FALSE;
|
||||
} else {
|
||||
if (db) dblog(".oO { move towards failed! - reason = %d }",reason);
|
||||
movefailed = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// if we got here, we're either at the correct distance or couldn't
|
||||
// move.
|
||||
if (attackok) {
|
||||
enum IQBRACKET iqb;
|
||||
iqb = getiqname(getattr(lf, A_IQ), NULL);
|
||||
|
||||
// if not adjacent, check for guns, wands, throwing
|
||||
if ( (rangedattack != RA_NONE) &&
|
||||
haslof(lf->cell, target->cell, LOF_NEED, NULL) && // and we have line of fire to them
|
||||
(onein(2) || (getcelldist(lf->cell, target->cell) > 1) ) && // and we're not adjacent to target OR random
|
||||
(iqb > IQ_ANIMAL) ) { // and we are smarter than an animal
|
||||
if (rangedattack == RA_GUN) {
|
||||
setguntarget(lf, target);
|
||||
if (!shoot(lf)) {
|
||||
// succesful
|
||||
return B_FALSE;
|
||||
} else {
|
||||
if (db) dblog(".oO { shoot gun failed! reason = %d }", reason);
|
||||
}
|
||||
} else if (rangedattack == RA_THROW) {
|
||||
// try to throw it!
|
||||
if (!throwat(lf, rangedob, target->cell)) {
|
||||
// succesful
|
||||
return B_FALSE;
|
||||
} else {
|
||||
if (db) dblog(".oO { throw failed! }");
|
||||
}
|
||||
} else if (rangedattack == RA_WAND) {
|
||||
objecttype_t *st;
|
||||
cell_t *zapcell = NULL;
|
||||
st = getlinkspell(rangedob);
|
||||
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 (!operate(lf, rangedob, zapcell)) {
|
||||
// succesful
|
||||
return B_FALSE;
|
||||
} else {
|
||||
if (db) dblog(".oO { zap failed! }");
|
||||
}
|
||||
}
|
||||
} // end if rangedattackok
|
||||
} // end if attackok
|
||||
|
||||
// if we could see our traget, but everything we tried failed (spells, moving and ranged attack),
|
||||
// just rest.
|
||||
if (movefailed) {
|
||||
rest(lf, B_TRUE);
|
||||
return B_FALSE;
|
||||
}
|
||||
} else {
|
||||
// can't see target.
|
||||
// move towards their last known location instead
|
||||
cell_t *targcell;
|
||||
int lastx,lasty;
|
||||
int lastdir;
|
||||
|
||||
targcell = aigetlastknownpos(lf, target, &lastx, &lasty, &lastdir);
|
||||
|
||||
if (targcell) {
|
||||
// are we already AT their last known location?
|
||||
if (targcell == lf->cell) {
|
||||
if (db) dblog(".oO { cannot see target. i am already at their last known loc %d/%d }",lastx, lasty);
|
||||
|
||||
// go in their last known direction.
|
||||
if (lastdir == D_NONE) {
|
||||
if (db) dblog(".oO { i don't know my target's last known movement dir. }");
|
||||
} else {
|
||||
// try going in last known dir
|
||||
if (db) dblog(".oO { trying my master's last known move dir (%s) }",getdirname(lastdir));
|
||||
if (!trymove(lf, lastdir, B_TRUE)) {
|
||||
if (db) dblog(".oO { ...successfully }");
|
||||
// we now don't know their last known dir.
|
||||
if (targetflag) {
|
||||
free(targetflag->text);
|
||||
targetflag->text = strdup("");
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// not already at their last known cell. try to go there.
|
||||
if (db) dblog(".oO { i cannot see my target. moving to last known loc %d/%d }",lastx,lasty);
|
||||
if (!aigoto(lf, targcell, MR_LF, target, PERMENANT)) {
|
||||
if (db) dblog(".oO { aigoto target's last known loc failed! }");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// we don't know their last known location....
|
||||
if (db) dblog(".oO { go to target's last known loc failed! }");
|
||||
}
|
||||
}
|
||||
|
||||
if (db) dblog(".oO { aimovetolf failed. }");
|
||||
// FAILED.
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
void aimovetotargetcell(lifeform_t *lf, flag_t *f) {
|
||||
int x,y;
|
||||
cell_t *c;
|
||||
|
@ -402,7 +795,6 @@ void aiturn(lifeform_t *lf) {
|
|||
int icanattack = B_FALSE;
|
||||
object_t *curgun,*bestgun;
|
||||
flag_t *f;
|
||||
flag_t *mf;
|
||||
//flag_t *nextf;
|
||||
// lifeform_t *fleefrom = NULL;
|
||||
lifeform_t *target,*newtarget;
|
||||
|
@ -450,9 +842,9 @@ void aiturn(lifeform_t *lf) {
|
|||
|
||||
|
||||
// are we a pet?
|
||||
mf = lfhasflagval(lf, F_PETOF, NA, NA, NA, NULL);
|
||||
if (mf && (getallegiance(lf) == AL_FRIENDLY)) {
|
||||
master = findlf(lf->cell->map, mf->val[0]);
|
||||
f = lfhasflagval(lf, F_PETOF, NA, NA, NA, NULL);
|
||||
if (f && (getallegiance(lf) == AL_FRIENDLY)) {
|
||||
master = findlf(lf->cell->map, f->val[0]);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
@ -597,7 +989,7 @@ void aiturn(lifeform_t *lf) {
|
|||
///////////////////////////////////////////////
|
||||
|
||||
// do we already have a target we are attacking?
|
||||
f = hasflag(lf->flags, F_TARGET);
|
||||
f = hasflag(lf->flags, F_TARGETLF);
|
||||
if (f) {
|
||||
int targid;
|
||||
int lastx,lasty;
|
||||
|
@ -608,222 +1000,9 @@ void aiturn(lifeform_t *lf) {
|
|||
target = findlf(lf->cell->map, targid);
|
||||
if (target) {
|
||||
if (db) dblog(".oO { my target is lfid %d (%s). }", targid, target->race->name);
|
||||
if (cansee(lf, target)) {
|
||||
int goingtomove = B_TRUE;
|
||||
enum OBTYPE spell;
|
||||
object_t *gun;
|
||||
|
||||
// reset F_TARGET lifetime to full.
|
||||
f->lifetime = AI_FOLLOWTIME;
|
||||
if (db) dblog(".oO { i can see my target (at %d,%d). might move towards it. }",target->cell->x,target->cell->y);
|
||||
// remember last known loc
|
||||
f->val[1] = target->cell->x;
|
||||
f->val[2] = target->cell->y;
|
||||
|
||||
goingtomove = B_TRUE;
|
||||
|
||||
// drink boost potions
|
||||
if (!useitemwithflag(lf, F_AIBOOSTITEM)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lfhasflag(lf, F_HIDING)) {
|
||||
objecttype_t *st;
|
||||
// can we attack with spells (ie. ones which target the victim)?
|
||||
// if target is adjacent, we will normally just attack rather than try a spell.
|
||||
spell = aigetattackspell(lf, target);
|
||||
st = findot(spell);
|
||||
if ( (spell != OT_NONE) && // found a valid spell/ability to use
|
||||
((getcelldist(lf->cell, target->cell) != 1) || // there is distance between us and target
|
||||
(st->obclass->id == OC_ABILITY) || // OR this works from adjacent
|
||||
(rnd(1,3) == 1)) // OR random chance of using anyway...
|
||||
) {
|
||||
int spellfailed = B_FALSE;
|
||||
lifeform_t *spelllf = NULL;
|
||||
cell_t *spellcell = NULL;
|
||||
object_t *spellob = NULL;
|
||||
if (db) {
|
||||
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) {
|
||||
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
|
||||
return;
|
||||
} 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
|
||||
return;
|
||||
} else {
|
||||
if (db) dblog(".oO { zap failed! }");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if !hiding
|
||||
|
||||
// do we have a valid melee attack?
|
||||
if (!icanattack) {
|
||||
if (db) dblog(".oO { won't move towards target - i have no weapon. }");
|
||||
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 (!movetowards(lf, target->cell, DT_ORTH)) {
|
||||
// success
|
||||
return;
|
||||
} else {
|
||||
if (db) dblog(".oO { move towards failed! - reason = %d }",reason);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cell_t *targcell;
|
||||
if (db) dblog(".oO { i cannot see my target. moving to last known loc %d/%d }",lastx,lasty);
|
||||
|
||||
// can't see target.
|
||||
// move towards their last known location instead
|
||||
targcell = getcellat(lf->cell->map, lastx, lasty);
|
||||
if (targcell) {
|
||||
if (!aigoto(lf, targcell, MR_LF, target, PERMENANT)) {
|
||||
|
||||
if (db) dblog(".oO { aigoto target's last known loc failed! }");
|
||||
}
|
||||
} else {
|
||||
if (db) dblog(".oO { go to target's last known loc failed! }");
|
||||
}
|
||||
|
||||
/*
|
||||
// just try to move in a random direction
|
||||
if (db) dblog(".oO { will move randomly }");
|
||||
// dorandommove will call taketime() if it fails,
|
||||
// so it's safe to just return
|
||||
dorandommove(lf, B_NOBADMOVES);
|
||||
if (!aimovetolf(lf, target, B_TRUE)) {
|
||||
// success
|
||||
return;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1025,68 +1204,10 @@ void aiturn(lifeform_t *lf) {
|
|||
// master is resting. the normal rest code underneath this section
|
||||
// will never be called.
|
||||
if (master) {
|
||||
lifeform_t *master;
|
||||
master = findlf(lf->cell->map, mf->val[0]);
|
||||
if (master && cansee(lf, master)) {
|
||||
// can see my master
|
||||
if (isresting(master)) {
|
||||
// rest as well.
|
||||
rest(lf, B_TRUE);
|
||||
return;
|
||||
}
|
||||
// - either move towards them or randomly
|
||||
if (isadjacent(lf->cell, master->cell)) {
|
||||
if (db) dblog(".oO { i can see my master - moving randomly }");
|
||||
dorandommove(lf, B_NOBADMOVES, B_TRUE);
|
||||
} else {
|
||||
// move towards master if not adjacent
|
||||
if (db) dblog(".oO { i can see my master - moving towards them }");
|
||||
if (movetowards(lf, master->cell, DT_ORTH)) {
|
||||
// failed
|
||||
if (db) dblog(".oO { failed. moving randomly }");
|
||||
dorandommove(lf, B_NOBADMOVES, B_TRUE);
|
||||
} else {
|
||||
// success
|
||||
if (db) dblog(".oO { success. }");
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// try to move towards master's last known loc
|
||||
if (mf->val[1] != NA) {
|
||||
flag_t *movetoflag = NULL;
|
||||
cell_t *newcell;
|
||||
newcell = getcellat(lf->cell->map, mf->val[1], mf->val[2]);
|
||||
|
||||
if (newcell == lf->cell) {
|
||||
int lastdir;
|
||||
|
||||
lastdir = getownerlastdir(lf);
|
||||
if (lastdir != D_NONE) {
|
||||
// try going in last known dir
|
||||
if (db) dblog(".oO { cannot see my master and am at last known loc. trying last known dir (%s) }",getdirname(lastdir));
|
||||
if (!trymove(lf, lastdir, B_TRUE)) {
|
||||
if (db) dblog(".oO { ...successfully }");
|
||||
killflagsofid(lf->flags, F_OWNERLASTDIR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (db) dblog(".oO { cannot see my master - adding F_TARGETCELL for last known loc }");
|
||||
movetoflag = aigoto(lf, newcell, MR_LF, master, PERMENANT);
|
||||
}
|
||||
|
||||
|
||||
if (movetoflag) {
|
||||
aimovetotargetcell(lf, movetoflag);
|
||||
} else {
|
||||
if (db) dblog(".oO { cannot see my master and aigoto last known loc/dir failed. randommove. }");
|
||||
dorandommove(lf, B_NOBADMOVES, B_TRUE);
|
||||
}
|
||||
} else {
|
||||
if (db) dblog(".oO { cannot see my master and dont have a last known location. randommove. }");
|
||||
dorandommove(lf, B_NOBADMOVES, B_TRUE);
|
||||
}
|
||||
//lifeform_t *master;
|
||||
//master = findlf(lf->cell->map, mf->val[0]);
|
||||
if (!aimovetolf(lf, master, B_FALSE)) {
|
||||
// success
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1273,13 +1394,13 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
|
|||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
dblog(".oO { cant cast %s - specialcase conditions not yet coded }", ot ? ot->name : "?unkownspell?");
|
||||
if (db) dblog(".oO { cant cast %s - specialcase conditions not yet coded }", ot ? ot->name : "?unkownspell?");
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
dblog(".oO { cant cast %s - targetting conditions cannot be met }", ot ? ot->name : "?unkownspell?");
|
||||
if (db) dblog(".oO { cant cast %s - targetting conditions cannot be met }", ot ? ot->name : "?unkownspell?");
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1409,15 +1530,6 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
|
|||
}
|
||||
|
||||
|
||||
int getownerlastdir(lifeform_t *lf) {
|
||||
flag_t *odflag;
|
||||
odflag = lfhasflag(lf, F_OWNERLASTDIR);
|
||||
if (odflag) {
|
||||
return odflag->val[0];
|
||||
}
|
||||
return D_NONE;
|
||||
}
|
||||
|
||||
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op) {
|
||||
object_t *o;
|
||||
|
||||
|
|
4
ai.h
4
ai.h
|
@ -4,16 +4,18 @@ void addignorecell(lifeform_t *lf, cell_t *c);
|
|||
void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit);
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim);
|
||||
enum OBTYPE aigetfleespell(lifeform_t *lf);
|
||||
cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *lasty, int *lastdir);
|
||||
object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra);
|
||||
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);
|
||||
flag_t *aigoto(lifeform_t *lf, cell_t *c, enum MOVEREASON why, void *data, int timelimit);
|
||||
int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack);
|
||||
void aimovetotargetcell(lifeform_t *lf, flag_t *f);
|
||||
int aipickup(lifeform_t *lf, object_t *o);
|
||||
int aipickupok(lifeform_t *lf, object_t *o);
|
||||
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target);
|
||||
int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG purpose);
|
||||
void aiturn(lifeform_t *lf);
|
||||
int getownerlastdir(lifeform_t *lf);
|
||||
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op);
|
||||
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op);
|
||||
int lookforobs(lifeform_t *lf, int covetsonly);
|
||||
|
|
5
attack.c
5
attack.c
|
@ -475,7 +475,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
|
|||
getskill(lf, SK_BACKSTAB) && // able to backstab
|
||||
!cansee(victim, lf) && // victim can't see us
|
||||
!lfhasflagval(victim, F_STABBEDBY, lf->id, NA, NA, NULL) && // haven't stabbed them before
|
||||
!lfhasflagval(victim, F_TARGET, lf->id, NA, NA, NULL) // victim isnt attacking us
|
||||
!lfhasflagval(victim, F_TARGETLF, lf->id, NA, NA, NULL) // victim isnt attacking us
|
||||
) {
|
||||
addflag(victim->flags, F_STABBEDBY, lf->id, NA, NA, NULL);
|
||||
dam[0] *= (getskill(lf, SK_BACKSTAB)*2);
|
||||
|
@ -1163,6 +1163,9 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
|
|||
}
|
||||
} else if (damtype == DT_TOUCH) {
|
||||
return "touch";
|
||||
} else if (damtype == DT_WATER) {
|
||||
// for when water-vulnerable things go into water
|
||||
return "hurt";
|
||||
} else if (damtype == DT_UNARMED) {
|
||||
if (onein(2)) {
|
||||
return "punch";
|
||||
|
|
76
defs.h
76
defs.h
|
@ -50,7 +50,9 @@ enum SKILL {
|
|||
SK_SPELLCASTING,
|
||||
SK_SPOTHIDDEN,
|
||||
SK_STEALTH,
|
||||
SK_SWIMMING,
|
||||
SK_TECHUSAGE,
|
||||
SK_TRACKING,
|
||||
SK_TRAPS,
|
||||
SK_TWOWEAPON,
|
||||
// knowledge
|
||||
|
@ -83,7 +85,7 @@ enum SKILL {
|
|||
SK_SS_TRANSLOCATION,
|
||||
SK_SS_WILD,
|
||||
};
|
||||
#define MAXSKILLS 44
|
||||
#define MAXSKILLS 46
|
||||
|
||||
// proficiency levels
|
||||
enum SKILLLEVEL {
|
||||
|
@ -169,6 +171,14 @@ enum LFCONDITION {
|
|||
C_HEALTHY = 5,
|
||||
};
|
||||
|
||||
enum SENSE {
|
||||
S_HEARING,
|
||||
S_SIGHT,
|
||||
S_SMELL,
|
||||
S_TASTE,
|
||||
S_TOUCH,
|
||||
};
|
||||
|
||||
// AI defs
|
||||
|
||||
// if target lf is out of view for this many turns, abandon chase
|
||||
|
@ -210,7 +220,11 @@ enum LFCONDITION {
|
|||
#define TICK_INTERVAL (20)
|
||||
|
||||
|
||||
#define SCENTTIME (15)
|
||||
#define FOOTPRINTTIME (20)
|
||||
|
||||
// STRINGS
|
||||
#define BUFLENTINY 10
|
||||
#define BUFLENSMALL 64
|
||||
#define BUFLEN 128
|
||||
#define HUGEBUFLEN 1024
|
||||
|
@ -341,6 +355,8 @@ enum LOFTYPE {
|
|||
#define SP_ULTRASLOW 35
|
||||
#define SP_SLOWEST 40
|
||||
|
||||
#define SPEEDUNIT 5
|
||||
|
||||
// speed settings (lower is faster)
|
||||
#define SPEED_ATTACK SP_NORMAL
|
||||
#define SPEED_DEAD 50
|
||||
|
@ -734,6 +750,8 @@ enum OBTYPE {
|
|||
OT_WOODENTABLE,
|
||||
OT_WOODENBARREL,
|
||||
OT_WOODENSTOOL,
|
||||
OT_HOLYCIRCLE,
|
||||
OT_PENTAGRAM,
|
||||
OT_STAIRSDOWN,
|
||||
OT_STAIRSUP,
|
||||
OT_VENDINGMACHINE,
|
||||
|
@ -1196,6 +1214,8 @@ enum OBTYPE {
|
|||
OT_SPLASHWATER,
|
||||
OT_PUDDLEWATER,
|
||||
OT_PUDDLEWATERL,
|
||||
OT_WATERSHALLOW,
|
||||
OT_WATERDEEP,
|
||||
OT_ACIDSPLASH,
|
||||
OT_ACIDPUDDLE,
|
||||
OT_ACIDPOOL,
|
||||
|
@ -1208,6 +1228,9 @@ enum OBTYPE {
|
|||
OT_MELTEDWAX,
|
||||
OT_SOGGYPAPER,
|
||||
OT_FLESHCHUNK,
|
||||
// trail objects
|
||||
OT_FOOTPRINT,
|
||||
OT_SCENT,
|
||||
// effects
|
||||
OT_FIRELARGE,
|
||||
OT_FIREMED,
|
||||
|
@ -1396,6 +1419,15 @@ enum BODYPART {
|
|||
};
|
||||
#define MAXBODYPARTS (12)
|
||||
|
||||
// depth on a human
|
||||
enum DEPTH {
|
||||
DP_HEAD = 4,
|
||||
DP_SHOULDERS = 3,
|
||||
DP_WAIST = 2,
|
||||
DP_FEET = 1,
|
||||
DP_NONE = 0,
|
||||
};
|
||||
|
||||
// empty types
|
||||
#define WE_WALKABLE 1
|
||||
#define WE_EMPTY 2
|
||||
|
@ -1437,6 +1469,13 @@ enum POISONTYPE {
|
|||
P_WEAKNESS,
|
||||
};
|
||||
|
||||
enum RANGEATTACK {
|
||||
RA_NONE = 0,
|
||||
RA_GUN,
|
||||
RA_THROW,
|
||||
RA_WAND,
|
||||
};
|
||||
|
||||
enum FLAG {
|
||||
F_NONE, // dummy flag
|
||||
// map flags
|
||||
|
@ -1452,6 +1491,14 @@ enum FLAG {
|
|||
// text is an object it contains.
|
||||
F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc
|
||||
F_STARTBLESSED, // v0 = b_blessed or b_cursed
|
||||
F_REPELBLESSED, // v0 = b_blessed or b_cursed. repels other obejcts
|
||||
// of this blesstype.
|
||||
F_TRAIL, // this object denotes the trail left by a lf.
|
||||
// v0 = raceid of lf who left it
|
||||
// v1 = direction the lf moved out of this cell
|
||||
// v2 = enum sense used to see this (ie. s_smell, s_sight)
|
||||
// (optional) text = lfid of lf who left this.
|
||||
// should only be used for SCENT, not footprints.
|
||||
// for items in shops
|
||||
F_SHOPITEM, // causes shops to show this item as identified
|
||||
F_VALUE, // how much an item is worth (over its base weight+material)
|
||||
|
@ -1473,7 +1520,7 @@ enum FLAG {
|
|||
// v0 = con skillcheck difficulty.
|
||||
F_BLOCKSVIEW, // if v0 = true, cannot see past this
|
||||
// if v0 > 0, reduces your vision by v0.
|
||||
F_BLOCKSTHROW, // cannot throw past this
|
||||
F_BLOCKSLOF, // this object interrupts line of fire
|
||||
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
|
||||
|
@ -1484,6 +1531,9 @@ enum FLAG {
|
|||
F_NOQUALITY, // can't be masterwork / shoddy
|
||||
F_CORPSEOF, // this is a corpse of montype val0.
|
||||
F_DTCONVERT, // damtype val0 converts this to f->text
|
||||
F_DTCREATEOB, // damtype val0 creates object f->text here
|
||||
// v1 = radius to burst in
|
||||
// v2 = dirtype
|
||||
F_NODTCONVERT, // overrides DTCONVERT .
|
||||
F_NOMATCONVERT, // overrides MATCONVERT .
|
||||
F_MATCONVERT, // touching material id val0 converts this to f->text
|
||||
|
@ -1537,6 +1587,7 @@ enum FLAG {
|
|||
// v2 = nutrition left when partially eaten
|
||||
F_DRINKABLE, // you can drink this. val1 = nutrition. 100 = a meal
|
||||
// -1 means "nutrition is weight x abs(val1)"
|
||||
// if v2=DONTKILL, this object does NOT die when drunk.
|
||||
F_OPERABLE, // can operate?
|
||||
F_POURABLE, // can pour?
|
||||
F_PUSHABLE, // can push this object
|
||||
|
@ -1556,6 +1607,7 @@ enum FLAG {
|
|||
F_JAMMED, // is this door jammed? v0 is # turns it'll take to open it.
|
||||
F_SECRET, // this object is secret. v0 is sc_search difficulty
|
||||
// to find it.
|
||||
// NA means 'can never find this'
|
||||
// stairs / teleporters / portals
|
||||
F_CLIMBABLE, // this is a stiarcase, v0 = up/down/in
|
||||
// also use this for portals
|
||||
|
@ -1664,6 +1716,7 @@ enum FLAG {
|
|||
F_HASHIDDENNAME, // whether this object class has a hidden name
|
||||
F_IDENTIFIED, // whether this object is fully identified
|
||||
// bad flags
|
||||
F_DEEPWATER, // v0 = depth.oooooooooooo
|
||||
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
|
||||
|
@ -1756,6 +1809,8 @@ enum FLAG {
|
|||
// v1 = whether this spell needs line of fire
|
||||
// MONSTER AI FLAGS
|
||||
F_DEMANDSBRIBE, // lf will demand gold from the player.
|
||||
F_NOSWAP, // other mosnters won't swap with this one.
|
||||
// cleared at start of turn.
|
||||
F_VARLEVEL, // lf is generated with random level between
|
||||
// 1 and its map dificulty/depth.
|
||||
// if v0 is set, this is the max level.
|
||||
|
@ -1767,10 +1822,11 @@ enum FLAG {
|
|||
F_XPMULTIPLY, // multiply xp val for killing this lf by v0
|
||||
F_NOJOBTEXT, // this lf's name is 'a xxx', not 'a xxx wizard' etc
|
||||
F_LASTDIR, // this is the last direction we moved.
|
||||
F_OWNERLASTDIR, // for pets, this it the last dir our owner moved
|
||||
//F_OWNERLASTDIR, // for pets, this it the last dir our owner moved
|
||||
// when we could see them.
|
||||
F_PETOF, // this lf is a pet of lfid v0
|
||||
// v1/2 = last known location of my owner.
|
||||
// optional text is last known movement dir.
|
||||
F_SUMMONEDBY, // this lf was summoned by lfid v0. if they die, we
|
||||
// vanish.
|
||||
// v1 is lifetime left. this decrements each turn.
|
||||
|
@ -1789,7 +1845,10 @@ enum FLAG {
|
|||
F_FLEEONDAM, // lf will run away instead of counterattacking
|
||||
F_FLEEONHPPCT, // lf will run away if its hp drop to v0% or lower
|
||||
F_NOFLEE, // lf will not run away
|
||||
F_TARGET, // lf will attack lfid v0. lastknown x/y is v1/v2
|
||||
F_ATTACKRANGE, // v0/v1 = min/max celldist to stay away
|
||||
// from f_targetlf (ie. lf we are attacking)
|
||||
F_TARGETLF, // lf will attack lfid v0. lastknown x/y is v1/v2
|
||||
// optional text is last known movement dir.
|
||||
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
|
||||
|
@ -1837,6 +1896,8 @@ enum FLAG {
|
|||
// text=spell text
|
||||
// for monsters
|
||||
F_DOESNTMOVE, // this race doesn't move (but can still attack)
|
||||
F_AQUATIC, // this race can attack normally in water and suffers no
|
||||
// movement penalties
|
||||
F_HUMANOID, // this race can wear armour / use weapons
|
||||
F_INSECT, // this race is classed as an insect
|
||||
F_UNDEAD, // this race is classed as undead
|
||||
|
@ -1870,6 +1931,7 @@ enum FLAG {
|
|||
// this flag does not get announced.
|
||||
F_BLEEDABIL, // will automatically use the ability v0 when
|
||||
// this lf starts bleeding.
|
||||
F_BREATHWATER, // can breath normally underwater
|
||||
F_CANWILL, // can cast the spell/ability val0 without using MP
|
||||
// v1 is counter untiluse
|
||||
// v2 is what you need to use it
|
||||
|
@ -1890,6 +1952,7 @@ enum FLAG {
|
|||
F_DETECTOBS, // autodetect nearby obs in orthog dist v0
|
||||
F_DRUNK, // v1 is drunknness - 1-5.
|
||||
F_ENHANCESEARCH, // gives v0 bonus on search checks.
|
||||
F_ENHANCESMELL, // can 'see' scents.
|
||||
F_EXTRADAM, // do 'text' extra damage of damtype v0 when you hit
|
||||
// if v1 is TRUE, also deal extra damage based on
|
||||
// the flagpile's F_BONUS flag.
|
||||
|
@ -1912,6 +1975,7 @@ enum FLAG {
|
|||
F_HIDING, // lifeform is hiding. v0 is modifier to stealth checks.
|
||||
F_INVISIBLE, // lifeform is invisible
|
||||
F_INVULNERABLE,// immune to most damage
|
||||
// this can apply to objects too!
|
||||
F_QUICKBITE, // deals v0 d d1 + d2 damage when you hit a bleeding victim
|
||||
// (bypasses armour)
|
||||
F_GRAVBOOSTED,// cannot walk or throw stuff
|
||||
|
@ -2037,6 +2101,8 @@ enum HUNGER {
|
|||
#define B_FALSE (0)
|
||||
#define B_TRUE (-1)
|
||||
|
||||
#define B_DONTKILL (-1)
|
||||
|
||||
#define FALLTHRU (-8765)
|
||||
|
||||
//#define B_TEMP (-1)
|
||||
|
@ -2164,6 +2230,8 @@ enum ERROR {
|
|||
E_NOOB = 52,
|
||||
E_LEVITATING = 53,
|
||||
E_PRONE = 54,
|
||||
E_PENTAGRAM = 55,
|
||||
E_SWIMMING = 56,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
@ = human
|
||||
: = timid animal
|
||||
} = gas cloud
|
||||
{ = water
|
||||
} = gas
|
||||
^ = trap / dangerous thing
|
||||
) = dancing weapon
|
||||
A = avian / bird
|
||||
a = ant
|
||||
|
|
12
flag.c
12
flag.c
|
@ -117,7 +117,6 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
|
||||
f->pile = fp;
|
||||
|
||||
|
||||
// notify
|
||||
if ((gamemode == GM_GAMESTARTED)) {
|
||||
if (f->pile->owner) {
|
||||
|
@ -253,6 +252,7 @@ int flagcausesredraw(lifeform_t *lf, enum FLAG fid) {
|
|||
case F_BLIND:
|
||||
case F_DETECTLIFE:
|
||||
case F_DETECTOBS:
|
||||
case F_ENHANCESMELL:
|
||||
case F_FASTMOVE:
|
||||
case F_HIDING:
|
||||
case F_INVISIBLE:
|
||||
|
@ -289,6 +289,7 @@ int flagcausesstatredraw(lifeform_t *lf, enum FLAG fid) {
|
|||
|
||||
switch (fid) {
|
||||
case F_ASLEEP:
|
||||
case F_ATTRMOD:
|
||||
case F_BLIND:
|
||||
case F_EATING:
|
||||
case F_FASTMOVE:
|
||||
|
@ -415,6 +416,10 @@ void killflag(flag_t *f) {
|
|||
int redostat = B_FALSE;
|
||||
int redoscreen = B_FALSE;
|
||||
|
||||
if (f->id == F_SIZE) {
|
||||
dblog("xxx");
|
||||
}
|
||||
|
||||
lf = f->pile->owner;
|
||||
|
||||
if (gamemode == GM_GAMESTARTED) {
|
||||
|
@ -534,6 +539,11 @@ void killflagpile(flagpile_t *fp) {
|
|||
}
|
||||
|
||||
void timeeffectsflag(flag_t *f, int howlong) {
|
||||
// special case:
|
||||
if (f->id == F_TRAIL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) {
|
||||
// special case - fast metabolism speeds up poison too.
|
||||
if (f->id == F_POISONED) {
|
||||
|
|
326
io.c
326
io.c
|
@ -29,6 +29,8 @@ int statdirty = B_TRUE;
|
|||
|
||||
int hascolour = B_TRUE;
|
||||
|
||||
int noredraw = B_FALSE;
|
||||
|
||||
extern int needredraw;
|
||||
extern int numdraws;
|
||||
|
||||
|
@ -291,15 +293,16 @@ void animradial(cell_t *src, int radius, char ch, int colour) {
|
|||
|
||||
gl.ch = ch;
|
||||
gl.colour = colour;
|
||||
|
||||
// update screen
|
||||
updateviewfor(src);
|
||||
drawlevelfor(player);
|
||||
|
||||
// hide cursor
|
||||
curs_set(0);
|
||||
for (i = 0; i <= radius; i++) {
|
||||
int drawn = B_FALSE;
|
||||
|
||||
// update screen
|
||||
updateviewfor(src);
|
||||
drawlevelfor(player);
|
||||
|
||||
for (y = src->y - radius ; y <= src->y + radius ; y++) {
|
||||
for (x = src->x - radius ; x <= src->x + radius ; x++) {
|
||||
c = getcellat(src->map, x, y);
|
||||
|
@ -331,14 +334,16 @@ void animradialorth(cell_t *src, int radius, char ch,int colour) {
|
|||
|
||||
gl.ch = ch;
|
||||
gl.colour = colour;
|
||||
|
||||
// update screen
|
||||
updateviewfor(src);
|
||||
drawlevelfor(player);
|
||||
|
||||
// hide cursor
|
||||
curs_set(0);
|
||||
for (i = 0; i <= radius; i++) {
|
||||
int drawn = B_FALSE;
|
||||
|
||||
// update screen
|
||||
updateviewfor(src);
|
||||
drawlevelfor(player);
|
||||
|
||||
for (y = src->y - radius ; y <= src->y + radius ; y++) {
|
||||
for (x = src->x - radius ; x <= src->x + radius ; x++) {
|
||||
|
@ -448,7 +453,7 @@ char askchar(char *prompt, char *validchars, char *def, int showchars) {
|
|||
return ch;
|
||||
}
|
||||
|
||||
cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange) {
|
||||
cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange, enum LOFTYPE loftype, int wanttrail) {
|
||||
static int startlf = -1;
|
||||
int finished = B_FALSE;
|
||||
int moved = B_FALSE;
|
||||
|
@ -531,6 +536,8 @@ cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange)
|
|||
drawlevelfor(player);
|
||||
|
||||
if (moved) {
|
||||
int inlof = B_TRUE, inrange = B_TRUE;
|
||||
cell_t *trailtarg = NULL;
|
||||
// show what we are over in msg bar
|
||||
strcpy(buf, "");
|
||||
if (haslos(player, c)) {
|
||||
|
@ -739,21 +746,13 @@ cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange)
|
|||
// if scanned, show it.
|
||||
} else {
|
||||
// otherwise, show objects
|
||||
object_t *o;
|
||||
// find top object name
|
||||
o = gettopobject(c);
|
||||
if (o) {
|
||||
getobname(o, buf, o->amt);
|
||||
}
|
||||
gettopobname(c, buf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object_t *o;
|
||||
// find top object name
|
||||
o = gettopobject(c);
|
||||
if (o) {
|
||||
getobname(o, buf, o->amt);
|
||||
}
|
||||
gettopobname(c, buf);
|
||||
}
|
||||
} else {
|
||||
// can't see objects or lf there
|
||||
|
@ -772,12 +771,51 @@ cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange)
|
|||
capitalise(buf);
|
||||
if (srclf && (maxrange != UNLIMITED)) {
|
||||
if (getcelldist(srclf->cell, c) > maxrange) {
|
||||
strcat(buf, " [outofrange]");
|
||||
inrange = B_FALSE;
|
||||
strcat(buf, " [too-far]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
trailtarg = c;
|
||||
if (loftype != LOF_DONTNEED) {
|
||||
cell_t *newcell;
|
||||
if (!haslof(srclf->cell, c, loftype, &newcell)) {
|
||||
inlof = B_FALSE;
|
||||
strcat(buf, " [no-lof]");
|
||||
}
|
||||
if (newcell) {
|
||||
trailtarg = newcell;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wclear(msgwin);
|
||||
mvwprintw(msgwin, 0, 0, "%s",buf);
|
||||
wrefresh(msgwin);
|
||||
|
||||
// show our line of fire
|
||||
if (wanttrail && inrange) {
|
||||
cell_t *retcell[MAXRETCELLS];
|
||||
int nretcell,i;
|
||||
glyph_t screenglyph;
|
||||
// calc path
|
||||
calcbresnham(srclf->cell->map, srclf->cell->x, srclf->cell->y, trailtarg->x, trailtarg->y, retcell, &nretcell);
|
||||
for (i = 0; i < nretcell; i++) {
|
||||
int thisx,thisy;
|
||||
thisx = retcell[i]->x - viewx;
|
||||
thisy = retcell[i]->y - viewy;
|
||||
// get screen cell;
|
||||
screenglyph.ch = mvwinch(gamewin, thisy, thisx) & A_CHARTEXT;
|
||||
screenglyph.colour = PAIR_NUMBER(mvwinch(gamewin, thisy, thisx) & A_COLOR);
|
||||
// draw it inverse.
|
||||
setcol(gamewin, screenglyph.colour);
|
||||
wattron(gamewin, A_REVERSE);
|
||||
mvwprintw(gamewin, thisy, thisx, "%lc", screenglyph.ch);
|
||||
wattroff(gamewin, A_REVERSE);
|
||||
unsetcol(gamewin, screenglyph.colour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -791,10 +829,23 @@ cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange)
|
|||
clearmsg();
|
||||
|
||||
// remember this target
|
||||
if (c->lf) {
|
||||
if (c->lf && cansee(player, c->lf)) {
|
||||
startlf = c->lf->id;
|
||||
}
|
||||
return c;
|
||||
} else if (ch == 'v') { // view
|
||||
// TODO: show obpile or view lf
|
||||
if (c->lf && cansee(player, c->lf)) {
|
||||
showlfstats(c->lf, B_FALSE);
|
||||
} else if (haslos(player, c)) {
|
||||
object_t *o;
|
||||
// show objects
|
||||
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, AO_NONE, F_NONE);
|
||||
while (o) {
|
||||
describeob(o);
|
||||
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, AO_NONE, F_NONE);
|
||||
}
|
||||
}
|
||||
} else if (ch == 27) { // ESC - cancel
|
||||
finished = B_TRUE;
|
||||
} else if ((ch == '\'') && (ntargets > 0)) { // cycle targets
|
||||
|
@ -984,6 +1035,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
|
|||
}
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
case F_BREATHWATER:
|
||||
if (isplayer(lf)) {
|
||||
msg("%s can now breath underwater.",lfname);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case F_CANCAST:
|
||||
if (isplayer(lf)) { // don't know if monsters get it
|
||||
objecttype_t *ot;
|
||||
|
@ -1139,6 +1196,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
|
|||
}
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
case F_ENHANCESMELL:
|
||||
if (isplayer(lf)) {
|
||||
msg("Your sense of smell is enhanced!");
|
||||
}
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
case F_DRUNK:
|
||||
msg("%s %s tipsy.", lfname, isplayer(lf) ? "feel" : "looks");
|
||||
donesomething = B_TRUE;
|
||||
|
@ -1454,6 +1517,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
|
|||
msg("%s can see again.",lfname);
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
case F_BREATHWATER:
|
||||
if (isplayer(lf)) {
|
||||
msg("%s can no longer breath underwater.",lfname);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
break;
|
||||
case F_CANCAST:
|
||||
if (isplayer(lf)) { // don't know if monsters lose it
|
||||
objecttype_t *ot;
|
||||
|
@ -1516,6 +1585,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
|
|||
}
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
case F_ENHANCESMELL:
|
||||
if (isplayer(lf)) {
|
||||
msg("Your sense of smell is no longer enhanced.");
|
||||
}
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
case F_DRUNK:
|
||||
msg("%s %s more steady now.", lfname, isplayer(lf) ? "feel" : "looks");
|
||||
donesomething = B_TRUE;
|
||||
|
@ -2078,10 +2153,14 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
|
|||
ammo = getammo(op->owner);
|
||||
}
|
||||
|
||||
if (countobs(op) <= 0) {
|
||||
// no objects in pack
|
||||
if (countobs(op, B_TRUE) <= 0) {
|
||||
// no objects here
|
||||
cls();
|
||||
mvwprintw(mainwin, 2, 0, "You have no possessions.");
|
||||
if (op->owner) {
|
||||
mvwprintw(mainwin, 2, 0, "You have no possessions.");
|
||||
} else {
|
||||
mvwprintw(mainwin, 2, 0, "There is nothing here.");
|
||||
}
|
||||
// wait for key
|
||||
centre(mainwin, getmaxy(mainwin)-1, "[Press any key]");
|
||||
getch();
|
||||
|
@ -2115,11 +2194,15 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
|
|||
// can we include this object?
|
||||
ok = B_TRUE;
|
||||
|
||||
// check for wanted flags
|
||||
for (n = 0; n < nwantflags; n++) {
|
||||
if (!hasflag(o->flags, wantflag[n])) {
|
||||
ok = B_FALSE;
|
||||
break;
|
||||
if (!canseeob(player, o)) ok = B_FALSE;
|
||||
|
||||
if (ok) {
|
||||
// check for wanted flags
|
||||
for (n = 0; n < nwantflags; n++) {
|
||||
if (!hasflag(o->flags, wantflag[n])) {
|
||||
ok = B_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2270,7 +2353,7 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
|
|||
|
||||
clearretobs();
|
||||
|
||||
if (countobs(op) <= 0) {
|
||||
if (countobs(op, B_FALSE) <= 0) {
|
||||
// no objects in pack
|
||||
cls();
|
||||
mvwprintw(mainwin, 2, 0, "You have no possessions.");
|
||||
|
@ -2304,8 +2387,13 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
|
|||
for (o = op->first ; o ; o = o->next) {
|
||||
if (o->type->obclass->id == sortorder[c]) {
|
||||
int ok;
|
||||
|
||||
// can we include this object?
|
||||
ok = obmatchescondition(o, opts);
|
||||
if (!canseeob(player, o)) {
|
||||
ok = B_FALSE;
|
||||
} else {
|
||||
ok = obmatchescondition(o, opts);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
mylist[i] = o;
|
||||
|
@ -2550,7 +2638,12 @@ void updatestatus(void) {
|
|||
wrefresh(statwin);
|
||||
}
|
||||
|
||||
void updateviewfor(cell_t *cell) {
|
||||
|
||||
// returns true if view changed
|
||||
int updateviewfor(cell_t *cell) {
|
||||
int oldvx,oldvy;
|
||||
oldvx = viewx;
|
||||
oldvy = viewy;
|
||||
// calculate viewport if required
|
||||
if ((viewx == -9999) || (viewy == -9999)) {
|
||||
// try to centre player
|
||||
|
@ -2570,6 +2663,11 @@ void updateviewfor(cell_t *cell) {
|
|||
while ((cell->y - viewy) <= (SCREENH/3)) {
|
||||
viewy--;
|
||||
}
|
||||
|
||||
if ((viewx != oldvx) || (viewy != oldvy)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2968,6 +3066,9 @@ void describeob(object_t *o) {
|
|||
case F_BLIND:
|
||||
mvwprintw(mainwin, y, 0, "%s prevents you from seeing.", buf); y++;
|
||||
break;
|
||||
case F_BREATHWATER:
|
||||
mvwprintw(mainwin, y, 0, "%s allows you to breath normally while underwater.", buf); y++;
|
||||
break;
|
||||
case F_CONTROL:
|
||||
mvwprintw(mainwin, y, 0, "%s lets you control teleportation and polymorphic effects.", buf); y++;
|
||||
break;
|
||||
|
@ -2986,6 +3087,9 @@ void describeob(object_t *o) {
|
|||
case F_ENHANCESEARCH:
|
||||
mvwprintw(mainwin, y, 0, "%s enhances your searching ability.", buf); y++;
|
||||
break;
|
||||
case F_ENHANCESMELL:
|
||||
mvwprintw(mainwin, y, 0, "%s enhances your sense of smell.", buf); y++;
|
||||
break;
|
||||
case F_DRUNK:
|
||||
mvwprintw(mainwin, y, 0, "%s makes you tipsy.", buf); y++;
|
||||
break;
|
||||
|
@ -3375,7 +3479,7 @@ void docomms(void) {
|
|||
char ch;
|
||||
flag_t *f;
|
||||
|
||||
where = askcoords("Talk to who?", TT_MONSTER, player, UNLIMITED);
|
||||
where = askcoords("Talk to who?", TT_MONSTER, player, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (where && where->lf && cansee(player, where->lf)) {
|
||||
lf = where->lf;
|
||||
}
|
||||
|
@ -3416,7 +3520,7 @@ void docomms(void) {
|
|||
char lfname2[BUFLEN];
|
||||
case 'a':
|
||||
sprintf(buf, "Tell %s to attack who?",lfname);
|
||||
c = askcoords(buf, TT_MONSTER, player, UNLIMITED);
|
||||
c = askcoords(buf, TT_MONSTER, player, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (c && c->lf && cansee(player, c->lf)) {
|
||||
lf2 = c->lf;
|
||||
|
||||
|
@ -3890,7 +3994,8 @@ void dolook(cell_t *where, int onpurpose) {
|
|||
// (also count objects without this flag)
|
||||
numobs = 0;
|
||||
for (o = where->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_SECRET)) continue;
|
||||
if (!canseeob(player, o)) continue;
|
||||
//if (hasflag(o->flags, F_SECRET)) continue;
|
||||
if (hasflag(o->flags, F_COSMETIC)) continue;
|
||||
|
||||
f = hasflag(o->flags, F_THEREISHERE);
|
||||
|
@ -3922,11 +4027,11 @@ void dolook(cell_t *where, int onpurpose) {
|
|||
msg("You %s %s here.", seeverb, buf);
|
||||
}
|
||||
} else if ((numobs > 1) && (numobs <= 3)) {
|
||||
msg("You %s a few objects here.", seeverb);
|
||||
msg("You %s a few things here.", seeverb);
|
||||
} else if ((numobs > 3) && (numobs <= 6)) {
|
||||
msg("You %s some objects here.", seeverb);
|
||||
msg("You %s some things here.", seeverb);
|
||||
} else if (numobs > 6) {
|
||||
msg("You %s many objects here.", seeverb);
|
||||
msg("You %s many things here.", seeverb);
|
||||
}
|
||||
seensomething = B_TRUE;
|
||||
}
|
||||
|
@ -4253,29 +4358,49 @@ int dopickup(obpile_t *op) {
|
|||
lifeform_t *fromlf = NULL;
|
||||
char lfname[BUFLEN];
|
||||
char buf[BUFLEN];
|
||||
int needtoask = B_TRUE;
|
||||
int failed = B_FALSE;
|
||||
|
||||
if (op->owner) {
|
||||
fromlf = op->owner;
|
||||
getlfname(fromlf, lfname);
|
||||
}
|
||||
|
||||
|
||||
obcount = countobs(op);
|
||||
obcount = countobs(op, B_TRUE);
|
||||
// anything here?
|
||||
if (obcount == 0) {
|
||||
failed = B_TRUE;
|
||||
} else if (!fromlf && (obcount == 1)) {
|
||||
object_t *o;
|
||||
// find first visible object
|
||||
o = op->first;
|
||||
while (o && !canseeob(player, o)) {
|
||||
o = o->next;
|
||||
}
|
||||
if (o) {
|
||||
if (o->amt == 1) {
|
||||
// just get it
|
||||
howmany = ALL;
|
||||
retobs[0] = op->first;
|
||||
retobscount[0] = op->first->amt;
|
||||
nretobs = 1;
|
||||
needtoask = B_FALSE;
|
||||
}
|
||||
} else {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
if (fromlf) {
|
||||
msg("%s is not carrying anything!", lfname);
|
||||
} else {
|
||||
msg("There is nothing here to pick up!");
|
||||
}
|
||||
return B_TRUE;
|
||||
} else if (!fromlf && (obcount == 1) && (op->first->amt == 1)) {
|
||||
// just get it
|
||||
howmany = ALL;
|
||||
retobs[0] = op->first;
|
||||
retobscount[0] = op->first->amt;
|
||||
nretobs = 1;
|
||||
} else {
|
||||
}
|
||||
|
||||
if (needtoask) {
|
||||
if (fromlf) {
|
||||
sprintf(buf, "Take what from %s",lfname);
|
||||
} else {
|
||||
|
@ -4329,33 +4454,9 @@ void doenter(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
void doexplain(char *question) {
|
||||
char buf[BUFLEN];
|
||||
cell_t *where;
|
||||
int done = B_FALSE;
|
||||
|
||||
while (!done) {
|
||||
//sprintf(buf, "Select glyph to explain (ESC to cancel):");
|
||||
where = askcoords(question, TT_NONE, player, UNLIMITED);
|
||||
if (!where) {
|
||||
clearmsg();
|
||||
break;
|
||||
}
|
||||
|
||||
// explain it
|
||||
if (where->lf && cansee(player, where->lf)) {
|
||||
showlfstats(where->lf, B_FALSE);
|
||||
} else {
|
||||
object_t *o;
|
||||
// object description
|
||||
o = gettopobject(where);
|
||||
if (o) {
|
||||
getobdesc(o, buf);
|
||||
}
|
||||
msg("%s", buf);
|
||||
}
|
||||
}
|
||||
msg("Done.");
|
||||
askcoords(question, TT_NONE, player, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
restoregamewindows();
|
||||
msg("Done.");
|
||||
}
|
||||
|
||||
void dofinaloblist(obpile_t *op) {
|
||||
|
@ -4715,7 +4816,7 @@ void doselguntarget(void) {
|
|||
getobname(gun, gunname, 1);
|
||||
|
||||
sprintf(buf, "Aim %s where?",gunname);
|
||||
where = askcoords(buf, TT_MONSTER, player, UNLIMITED);
|
||||
where = askcoords(buf, TT_MONSTER, player, UNLIMITED, LOF_NEED, B_TRUE);
|
||||
if (where) {
|
||||
if (where->lf && haslof(player->cell, where, LOF_NEED, NULL)) {
|
||||
setguntarget(player, where->lf);
|
||||
|
@ -4787,7 +4888,7 @@ void dothrow(obpile_t *op) {
|
|||
|
||||
// ask where to throw it
|
||||
sprintf(buf2, "Throw %s where?",buf);
|
||||
where = askcoords(buf2, TT_MONSTER, player, UNLIMITED);
|
||||
where = askcoords(buf2, TT_MONSTER, player, maxdist, LOF_NEED, B_TRUE);
|
||||
|
||||
if (where) {
|
||||
cell_t *newwhere = NULL;
|
||||
|
@ -4942,6 +5043,10 @@ void drawlevelfor(lifeform_t *lf) {
|
|||
int db = B_FALSE;
|
||||
int w,h;
|
||||
|
||||
if (noredraw) {
|
||||
return;
|
||||
}
|
||||
|
||||
map = lf->cell->map;
|
||||
|
||||
needredraw = B_FALSE;
|
||||
|
@ -4960,8 +5065,7 @@ void drawlevelfor(lifeform_t *lf) {
|
|||
}
|
||||
for (y = 0; y < h; y++) {
|
||||
for (x = 0; x < w; x++) {
|
||||
glyph_t glyph,screenglyph;
|
||||
int needdraw = B_FALSE;
|
||||
glyph_t glyph;
|
||||
cell = getcellat(map, x + viewx, y + viewy);
|
||||
|
||||
if (cell) {
|
||||
|
@ -4972,23 +5076,16 @@ void drawlevelfor(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
// only draw if screen char/colour is different
|
||||
screenglyph.ch = mvwinch(gamewin, y, x) & A_CHARTEXT;
|
||||
if (screenglyph.ch != glyph.ch) {
|
||||
needdraw = B_TRUE;
|
||||
} else {
|
||||
screenglyph.colour = PAIR_NUMBER(mvwinch(gamewin, y, x) & A_COLOR);
|
||||
if (screenglyph.colour != glyph.colour) {
|
||||
needdraw = B_TRUE;
|
||||
}
|
||||
}
|
||||
if (needdraw) {
|
||||
if (!screenglyphmatches(x, y, &glyph)) {
|
||||
drawglyph(&glyph, x, y);
|
||||
/*
|
||||
if (db) {
|
||||
dblog(" drawing char '%lc'/%d at %d,%d (screenglyph was '%lc'/%d)\n\n",
|
||||
glyph.ch, glyph.ch,
|
||||
x,y,
|
||||
screenglyph.ch, screenglyph.ch);
|
||||
}
|
||||
*/
|
||||
ndrawn++;
|
||||
}
|
||||
}
|
||||
|
@ -5574,7 +5671,7 @@ void handleinput(void) {
|
|||
// something here?
|
||||
if (hasgettableobs) {
|
||||
stoprunning(player);
|
||||
} else if (!canmove(player, dir, NULL)) { // can't move anymore?
|
||||
} else if (!moveclear(player, dir, NULL)) { // can't move anymore?
|
||||
stoprunning(player);
|
||||
} else {
|
||||
if (trymove(player, dir, B_TRUE)) {
|
||||
|
@ -6104,6 +6201,12 @@ void drawstatus(void) {
|
|||
unsetcol(statwin, C_RED);
|
||||
}
|
||||
|
||||
if (isswimming(player)) {
|
||||
setcol(statwin, C_BOLDBLUE);
|
||||
wprintw(statwin, " Swimming");
|
||||
unsetcol(statwin, C_BOLDBLUE);
|
||||
}
|
||||
|
||||
// paralysed somehow?
|
||||
if (isresting(player)) {
|
||||
setcol(statwin, C_CYAN);
|
||||
|
@ -6448,6 +6551,17 @@ void redraw(void) {
|
|||
wrefresh(gamewin);
|
||||
}
|
||||
|
||||
void redrawpause(void) {
|
||||
noredraw = B_TRUE;
|
||||
}
|
||||
|
||||
void redrawresume(void) {
|
||||
noredraw = B_FALSE;
|
||||
if (needredraw) {
|
||||
drawlevelfor(player);
|
||||
}
|
||||
}
|
||||
|
||||
void restoregamewindows(void) {
|
||||
needredraw = B_TRUE;
|
||||
statdirty = B_TRUE;
|
||||
|
@ -6456,6 +6570,28 @@ void restoregamewindows(void) {
|
|||
drawscreen();
|
||||
}
|
||||
|
||||
int screenglyphmatches(int x, int y, glyph_t *g) {
|
||||
int attribs;
|
||||
glyph_t screenglyph;
|
||||
|
||||
screenglyph.ch = mvwinch(gamewin, y, x) & A_CHARTEXT;
|
||||
if (screenglyph.ch != g->ch) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
screenglyph.colour = PAIR_NUMBER(mvwinch(gamewin, y, x) & A_COLOR);
|
||||
if (screenglyph.colour != g->colour) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// reverse video highlight from askcoords?
|
||||
attribs = mvwinch(gamewin, y, x) & A_ATTRIBUTES;
|
||||
if (attribs & A_REVERSE) {
|
||||
return B_FALSE;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
void setcol(WINDOW *win, enum COLOUR col) {
|
||||
if (needsbold(col)) {
|
||||
wattron(win, A_BOLD);
|
||||
|
@ -7687,6 +7823,10 @@ void showlfstats(lifeform_t *lf, int showall) {
|
|||
}
|
||||
|
||||
// flags which aren't really intrinsics
|
||||
if (lfhasflag(lf, F_AQUATIC)) {
|
||||
mvwprintw(mainwin, y, 0, "%s %s aquatic, and move normally through water.", you(lf), is(lf));
|
||||
y++;
|
||||
}
|
||||
if (lfhasflag(lf, F_VEGETARIAN)) {
|
||||
mvwprintw(mainwin, y, 0, "%s %s a vegetarian.", you(lf), is(lf));
|
||||
y++;
|
||||
|
@ -7746,6 +7886,11 @@ void showlfstats(lifeform_t *lf, int showall) {
|
|||
mvwprintw(mainwin, y, 0, buf);
|
||||
y++;
|
||||
}
|
||||
f = lfhasknownflag(lf, F_BREATHWATER);
|
||||
if (f) {
|
||||
mvwprintw(mainwin, y, 0, "%s can breath normally while underwater.", you(lf));
|
||||
y++;
|
||||
}
|
||||
f = lfhasknownflag(lf, F_CONTROL);
|
||||
if (f) {
|
||||
mvwprintw(mainwin, y, 0, "%s can control teleportation and polymorphic effects.", you(lf));
|
||||
|
@ -7782,6 +7927,11 @@ void showlfstats(lifeform_t *lf, int showall) {
|
|||
mvwprintw(mainwin, y, 0, "%s searching ability is enhanced.", you(lf), isplayer(lf) ? "Your" : "Its");
|
||||
y++;
|
||||
}
|
||||
f = lfhasknownflag(lf, F_ENHANCESMELL);
|
||||
if (f) {
|
||||
mvwprintw(mainwin, y, 0, "%s %s an enhanced sense of smell.", you(lf), isplayer(lf) ? "have" : "has");
|
||||
y++;
|
||||
}
|
||||
|
||||
f = lfhasknownflag(lf, F_DRUNK);
|
||||
if (f) {
|
||||
|
@ -8058,7 +8208,7 @@ void showlfstats(lifeform_t *lf, int showall) {
|
|||
y = 2;
|
||||
if (lfhasflag(lf, F_NOPACK)) {
|
||||
mvwprintw(mainwin, y, 0, "It cannot carry anything.");
|
||||
} else if (countobs(lf->pack)) {
|
||||
} else if (countobs(lf->pack, B_FALSE)) {
|
||||
char invtitle[BUFLEN];
|
||||
float packweight,maxweight,pct;
|
||||
packweight = getobpileweight(lf->pack);
|
||||
|
|
7
io.h
7
io.h
|
@ -20,7 +20,7 @@ object_t *askobjectwithflag(obpile_t *op, char *title, int *count, long opts, en
|
|||
object_t *doaskobject(obpile_t *op, char *title, int *count, int forpickup, int showpoints, long opts, ...);
|
||||
int askobjectmulti(obpile_t *op, char *prompt, long opts);
|
||||
char askchar(char *prompt, char *validchars, char *def, int showchars);
|
||||
cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange);
|
||||
cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange, enum LOFTYPE loftype, int wanttrail);
|
||||
char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def);
|
||||
void centre(WINDOW *win, int y, char *format, ... );
|
||||
int chartodir(char ch);
|
||||
|
@ -95,7 +95,10 @@ int needsbold(enum COLOUR col);
|
|||
void nothinghappens(void);
|
||||
void dblog(char *format, ... );
|
||||
void redraw(void);
|
||||
void redrawpause(void);
|
||||
void redrawresume(void);
|
||||
void restoregamewindows(void);
|
||||
int screenglyphmatches(int x, int y, glyph_t *g);
|
||||
void setcol(WINDOW *win, enum COLOUR col);
|
||||
void unsetcol(WINDOW *win, enum COLOUR col);
|
||||
void setobcolour(WINDOW *win, object_t *o, int set);
|
||||
|
@ -103,4 +106,4 @@ void showlfarmour(lifeform_t *lf);
|
|||
void showlfstats(lifeform_t *lf, int showall);
|
||||
void tombstone(lifeform_t *lf);
|
||||
void updatestatus(void);
|
||||
void updateviewfor(cell_t *cell);
|
||||
int updateviewfor(cell_t *cell);
|
||||
|
|
9
lf.h
9
lf.h
|
@ -6,6 +6,7 @@ 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, 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);
|
||||
void addtrail(lifeform_t *lf, int dir);
|
||||
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);
|
||||
|
@ -35,7 +36,8 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where);
|
|||
int canweild(lifeform_t *lf, object_t *o);
|
||||
int cantakeoff(lifeform_t *lf, object_t *o);
|
||||
int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell);
|
||||
void checkxp(enum RACE rid);
|
||||
int checkfordrowning(lifeform_t *lf, object_t *o);
|
||||
//void checkxp(enum RACE rid);
|
||||
float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
|
||||
int countinnateattacks(lifeform_t *lf);
|
||||
int countmoney(lifeform_t *lf);
|
||||
|
@ -91,6 +93,7 @@ char *getbodypartname(enum BODYPART bp);
|
|||
char *getbodypartequipname(enum BODYPART bp);
|
||||
object_t *getequippedob(obpile_t *op, enum BODYPART bp);
|
||||
object_t *getfirearm(lifeform_t *lf);
|
||||
int getfootprinttime(lifeform_t *lf);
|
||||
lifeform_t *getguntarget(lifeform_t *lf);
|
||||
int getguntargetid(lifeform_t *lf);
|
||||
//int gethealtime(lifeform_t *lf);
|
||||
|
@ -160,6 +163,7 @@ char *getskilldesc(enum SKILL id );
|
|||
char *getskillname(enum SKILL id );
|
||||
char *getskilllevelname(enum SKILLLEVEL sl);
|
||||
int getthrowspeed(int str);
|
||||
void getwantdistance(lifeform_t *lf, int *min, int *max, int attacking);
|
||||
object_t *getweapon(lifeform_t *lf);
|
||||
long getxpforlev(int level);
|
||||
void givejob(lifeform_t *lf, enum JOB jobid);
|
||||
|
@ -206,6 +210,7 @@ int isloreskill(enum SKILL skid);
|
|||
int ismaxedskill(lifeform_t *lf, enum SKILL skid);
|
||||
int ispeaceful(lifeform_t *lf);
|
||||
int ispetof(lifeform_t *lf, lifeform_t *owner);
|
||||
flag_t *ispetortarget(lifeform_t *lf, lifeform_t *ownertarget);
|
||||
int isplayer(lifeform_t *lf);
|
||||
flag_t *ispoisoned(lifeform_t *lf);
|
||||
flag_t *ispoisonedwith(lifeform_t *lf, enum POISONTYPE pt);
|
||||
|
@ -214,6 +219,8 @@ int isprone(lifeform_t *lf);
|
|||
flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt);
|
||||
flag_t *isresting(lifeform_t *lf);
|
||||
object_t *isstuck(lifeform_t *lf);
|
||||
int isswimming(lifeform_t *lf);
|
||||
int isundead(lifeform_t *lf);
|
||||
flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt);
|
||||
void killjob(job_t *job);
|
||||
void killlf(lifeform_t *lf);
|
||||
|
|
539
log.txt
539
log.txt
|
@ -2,364 +2,183 @@
|
|||
|
||||
|
||||
====== NEW LOGFILE ====
|
||||
givejob() starting.
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 175 (kobold) spending 20 time
|
||||
|
||||
lfid 180 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
lfid 181 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 175 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
lfid 180 (kobold) spending 20 time
|
||||
|
||||
fireat(): dam = throwdam(3) * speed(2)/2 = 3
|
||||
lfid 181 (kobold) spending 20 time
|
||||
|
||||
fireat(): dam = throwdam(2) * speed(3)/2 = 2
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 195 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 175 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
lfid 178 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
lfid 180 (kobold) spending 20 time
|
||||
|
||||
fireat(): dam = throwdam(3) * speed(2)/2 = 3
|
||||
xxx
|
||||
lfid 181 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 195 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 175 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
lfid 178 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 195 (kobold) spending 15 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
lfid 170 (giant rat) spending 15 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 178 (kobold) spending 15 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 167 (xat) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 40 time
|
||||
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 198 (human) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
lfid 175 (kobold) spending 20 time
|
||||
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
xxx
|
||||
rollhitdice() for xat - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +32%
|
||||
rollhitdice() ---- die 1/1 == 3
|
||||
TOTAL: 3
|
||||
-> modified to: 3
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +0%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for xat - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +54%
|
||||
rollhitdice() ---- die 1/1 == 2
|
||||
TOTAL: 2
|
||||
-> modified to: 3
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +0%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +44%
|
||||
rollhitdice() ---- die 1/1 == 3
|
||||
TOTAL: 3
|
||||
-> modified to: 4
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +-16%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 4
|
||||
rollhitdice() for xat - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +76%
|
||||
rollhitdice() ---- die 1/1 == 1
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +10%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 4
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +76%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 7
|
||||
rollhitdice() for xat - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +-27%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 3
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +22%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +10%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +0%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +-5%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 4
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +88%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 7
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +-5%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 4
|
||||
rollhitdice() for troglodyte - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +0%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 4
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +10%
|
||||
rollhitdice() ---- die 1/1 == 1
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +0%
|
||||
rollhitdice() ---- die 1/1 == 1
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +-11%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +76%
|
||||
rollhitdice() ---- die 1/1 == 3
|
||||
TOTAL: 3
|
||||
-> modified to: 5
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +32%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +-11%
|
||||
rollhitdice() ---- die 1/1 == 2
|
||||
TOTAL: 2
|
||||
-> modified to: 2
|
||||
rollhitdice() for xat - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +66%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 6
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +76%
|
||||
rollhitdice() ---- die 1/1 == 1
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for xat - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +32%
|
||||
rollhitdice() ---- die 1/1 == 2
|
||||
TOTAL: 2
|
||||
-> modified to: 2
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +54%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +54%
|
||||
rollhitdice() ---- die 1/1 == 1
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +10%
|
||||
rollhitdice() ---- die 1/1 == 3
|
||||
TOTAL: 3
|
||||
-> modified to: 3
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +0%
|
||||
rollhitdice() ---- die 1/1 == 3
|
||||
TOTAL: 3
|
||||
-> modified to: 3
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +32%
|
||||
rollhitdice() ---- die 1/1 == 3
|
||||
TOTAL: 3
|
||||
-> modified to: 3
|
||||
rollhitdice() for giant rat - rolling 0d4 + 1
|
||||
rollhitdice() - mod is +-16%
|
||||
TOTAL: 1
|
||||
-> modified to: 1
|
||||
rollhitdice() for xat - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +22%
|
||||
rollhitdice() ---- die 1/1 == 2
|
||||
TOTAL: 2
|
||||
-> modified to: 2
|
||||
rollhitdice() for giant newt - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +66%
|
||||
rollhitdice() ---- die 1/1 == 4
|
||||
TOTAL: 4
|
||||
-> modified to: 6
|
||||
rollhitdice() for human - rolling 2d4 + 2
|
||||
rollhitdice() - mod is +0%
|
||||
rollhitdice() ---- die 1/2 == 6
|
||||
rollhitdice() ---- die 2/2 == 4
|
||||
TOTAL: 10
|
||||
-> modified to: 10
|
||||
rollhitdice() for young wolf - rolling 2d4 + 2
|
||||
rollhitdice() - mod is +100%
|
||||
rollhitdice() ---- die 1/2 == 4
|
||||
rollhitdice() ---- die 2/2 == 4
|
||||
TOTAL: 8
|
||||
-> modified to: 16
|
||||
xxx
|
||||
rollhitdice() for kobold - rolling 1d4 + 0
|
||||
rollhitdice() - mod is +44%
|
||||
rollhitdice() ---- die 1/1 == 3
|
||||
TOTAL: 3
|
||||
-> modified to: 4
|
||||
xxx
|
||||
|
|
128
map.c
128
map.c
|
@ -112,11 +112,13 @@ map_t *addmap(void) {
|
|||
|
||||
|
||||
// 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 *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded) {
|
||||
lifeform_t *lf = NULL;
|
||||
race_t *r;
|
||||
int db = B_FALSE;
|
||||
|
||||
if (nadded) *nadded = 0;
|
||||
|
||||
// ie. don't create mosnters on closed doors!
|
||||
if (!cellwalkable(NULL, c, NULL)) {
|
||||
return NULL;
|
||||
|
@ -133,13 +135,25 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
|
||||
assert(r);
|
||||
|
||||
if (db) dblog("adding rand lf %s to cell %d,%d",r->name,c->x,c->y);
|
||||
|
||||
if (db) {
|
||||
char buf[BUFLEN];
|
||||
sprintf(buf, "start addmonster for %s",r->name);
|
||||
dbtimestart(buf);
|
||||
}
|
||||
|
||||
//if (db) dblog("adding rand lf %s to cell %d,%d",r->name,c->x,c->y);
|
||||
|
||||
if (r) {
|
||||
if (db) dbtime("doing lf addition");
|
||||
lf = addlf(c, r->id, getrandommonlevel(r, c->map));
|
||||
if (db) dbtime("finished lf addition");
|
||||
if (lf) {
|
||||
flag_t *f;
|
||||
|
||||
if (nadded) (*nadded)++;
|
||||
|
||||
if (db) dbtime("checking for job");
|
||||
lf->born = B_FALSE;
|
||||
if (jobok) {
|
||||
for (f = lf->flags->first ; f ; f = f->next) {
|
||||
|
@ -173,6 +187,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
}
|
||||
|
||||
// appears in groups?
|
||||
if (db) dbtime("handling groups");
|
||||
if (autogen) {
|
||||
f = hasflag(lf->flags, F_NUMAPPEAR);
|
||||
if (f) {
|
||||
|
@ -188,7 +203,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
lifeform_t *newlf;
|
||||
// find an adjacent cell to one of the newly added monsters,
|
||||
// starting with the first one
|
||||
adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL);
|
||||
// did we find one?
|
||||
if (!adjcell) break;
|
||||
|
||||
|
@ -196,6 +211,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
if (!newlf) {
|
||||
break;
|
||||
}
|
||||
if (nadded) (*nadded)++;
|
||||
newlf->born = B_FALSE;
|
||||
|
||||
// initial monster shoudl remember its minions
|
||||
|
@ -215,6 +231,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
}
|
||||
|
||||
// minons?
|
||||
// appears in groups?
|
||||
if (db) dbtime("handling minions");
|
||||
if (autogen) {
|
||||
f = hasflag(lf->flags, F_MINIONS);
|
||||
if (f) {
|
||||
|
@ -229,7 +247,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
lifeform_t *newlf;
|
||||
race_t *newr;
|
||||
|
||||
adjcell = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL);
|
||||
if (!adjcell) break;
|
||||
|
||||
newr = findracebyname(f->text);
|
||||
|
@ -238,6 +256,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
newlf = addlf(adjcell, newr->id, getrandommonlevel(newr, adjcell->map));
|
||||
if (!newlf) break;
|
||||
|
||||
if (nadded) (*nadded)++;
|
||||
|
||||
newlf->born = B_FALSE;
|
||||
if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
|
||||
newlf->born = B_TRUE;
|
||||
|
@ -247,6 +267,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
}
|
||||
|
||||
|
||||
if (db) dbtime("handling random objects");
|
||||
// sometimes give the lf random objects (extra monsters through
|
||||
// 'numappears' don't get them.
|
||||
if (lfhasflag(lf, F_HUMANOID) && !lfhasflag(lf, F_NOPACK)) {
|
||||
|
@ -266,6 +287,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
}
|
||||
}
|
||||
|
||||
if (db) dbtime("giving torches");
|
||||
// humanoids on dark levels which can't see will probably have some
|
||||
// kind of light producing device
|
||||
if (!islit(c) && !hasflag(lf->flags, F_SEEINDARK) && !hasflag(lf->flags, F_TREMORSENSE)) {
|
||||
|
@ -294,6 +316,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
} // end if lf
|
||||
}
|
||||
|
||||
if (db) dbtimeend("finished addmonster");
|
||||
|
||||
return lf;
|
||||
}
|
||||
|
||||
|
@ -313,18 +337,21 @@ object_t *addrandomob(cell_t *c) {
|
|||
return o;
|
||||
}
|
||||
|
||||
int addrandomthing(cell_t *c, int obchance) {
|
||||
int addrandomthing(cell_t *c, int obchance, int *nadded) {
|
||||
int rv = TT_NONE;
|
||||
// if there's already someone there,
|
||||
// then add an object.
|
||||
if (c->lf || (rnd(1,100) <= obchance)) {
|
||||
object_t *o;
|
||||
// object
|
||||
if (addrandomob(c)) {
|
||||
o = addrandomob(c);
|
||||
if (o) {
|
||||
if (nadded) *nadded = o->amt;
|
||||
rv = TT_OBJECT;
|
||||
}
|
||||
} else {
|
||||
// monster
|
||||
if (addmonster(c, R_RANDOM, B_TRUE, 1, B_TRUE)) {
|
||||
if (addmonster(c, R_RANDOM, B_TRUE, 1, B_TRUE, nadded)) {
|
||||
rv = TT_MONSTER;
|
||||
}
|
||||
}
|
||||
|
@ -486,7 +513,6 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
|
|||
|
||||
if (haslos(viewer, c)) {
|
||||
// show cell contents
|
||||
//drawcellwithcontents(cell, x-viewx, y-viewy);
|
||||
if (c->lf && cansee(viewer, c->lf)) { // lifeform here which we can see
|
||||
// draw the lf's race glyph
|
||||
*g = *(getlfglyph(c->lf));
|
||||
|
@ -506,7 +532,7 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
|
|||
}
|
||||
|
||||
// objects here?
|
||||
if ((countobs(c->obpile) > 0)) {
|
||||
if ((countobs(c->obpile, B_FALSE) > 0)) {
|
||||
object_t *o;
|
||||
|
||||
// draw highest object in sort order
|
||||
|
@ -516,8 +542,6 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
|
|||
*g = *(getglyph(o));
|
||||
} else {
|
||||
// objects here, but we can't see them. draw the cell.
|
||||
// otherwise just draw the cell
|
||||
//*g = c->obpile->first->type->obclass->glyph;
|
||||
*g = c->type->glyph;
|
||||
if (!islit(c)) {
|
||||
g->colour = C_BLUE;
|
||||
|
@ -618,6 +642,7 @@ object_t *gettopobject(cell_t *where) {
|
|||
flag_t *f;
|
||||
// ignore hidden traps, but not secret doors
|
||||
if (hasflag(o->flags, F_SECRET) && !isdoor(o, NULL)) {
|
||||
} else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) {
|
||||
} else {
|
||||
f = hasflag(o->flags, F_IMPASSABLE);
|
||||
if (f && (f->val[0] > largest)) {
|
||||
|
@ -638,7 +663,9 @@ object_t *gettopobject(cell_t *where) {
|
|||
// appear first.
|
||||
for (o = where->obpile->last ; o ; o = o->prev) {
|
||||
if (o->type->obclass->id == sortorder[c]) {
|
||||
if (!hasflag(o->flags, F_SECRET)){
|
||||
if (hasflag(o->flags, F_SECRET)) {
|
||||
} else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) {
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
@ -1083,26 +1110,46 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
}
|
||||
|
||||
|
||||
// add staircases - dungeons alway shave an up and down stairs
|
||||
// add staircases - dungeons always have an up and down stairs
|
||||
for (i = 0; i < 3; i++) {
|
||||
// add up stairs
|
||||
c = NULL;
|
||||
while (!c || !isempty(c) || countobs(c->obpile)) {
|
||||
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
|
||||
c = getrandomroomcell(map, ANYROOM);
|
||||
}
|
||||
o = addob(c->obpile, "staircase going up");
|
||||
linkstairs(o);
|
||||
// first dungeon level has barriers over the exit stairs
|
||||
if ((map->region == RG_FIRSTDUNGEON) && (map->depth == 1)) {
|
||||
if (c->lf) killlf(c->lf);
|
||||
addob(c->obpile, "magical barrier");
|
||||
/*
|
||||
int d;
|
||||
// surround stairs with barriers
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
cell_t *newc;
|
||||
newc = getcellindir(c, d);
|
||||
|
||||
if (newc && !newc->type->solid) {
|
||||
// kill lfs there
|
||||
if (newc->lf) killlf(newc->lf);
|
||||
// add a barrier
|
||||
addob(newc->obpile, "magical barrier");
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
c = NULL;
|
||||
while (!c || !isempty(c) || countobs(c->obpile)) {
|
||||
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
|
||||
c = getrandomroomcell(map, ANYROOM);
|
||||
}
|
||||
o = addob(c->obpile, "staircase going down");
|
||||
linkstairs(o);
|
||||
}
|
||||
|
||||
// add pillars & objects & monsters to rooms
|
||||
if (wantrooms && (numrooms > 0)) {
|
||||
// add pillars & objects & monsters to rooms
|
||||
for (i = 0; i < numrooms; i++) {
|
||||
int numobsmin,numobsmax,numobs,n;
|
||||
int maxpillars;
|
||||
|
@ -1120,7 +1167,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
cell_t *c;
|
||||
c = getrandomroomcell(map, i);
|
||||
|
||||
if (c && isempty(c) && !countobs(c->obpile)) {
|
||||
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
|
||||
setcelltype(cell, CT_WALL);
|
||||
}
|
||||
}
|
||||
|
@ -1154,8 +1201,9 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
while (!done) {
|
||||
c = getrandomroomcell(map, i);
|
||||
// if nothing there
|
||||
if (c && isempty(c) && !countobs(c->obpile)) {
|
||||
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
|
||||
int obchance;
|
||||
int nadded = 0;
|
||||
|
||||
// limit # monster per room to depth+1
|
||||
if (nmonsters >= (depth+1)) {
|
||||
|
@ -1165,8 +1213,8 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
obchance = getobchance(map->habitat) + 10;
|
||||
}
|
||||
|
||||
if (addrandomthing(c,obchance) == TT_MONSTER) {
|
||||
nmonsters++;
|
||||
if (addrandomthing(c,obchance, &nadded) == TT_MONSTER) {
|
||||
nmonsters += nadded;
|
||||
}
|
||||
done = B_TRUE;
|
||||
} else {
|
||||
|
@ -1314,6 +1362,7 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
|
|||
for (i = depth-1; i <= depth+1; i += 2) {
|
||||
map_t *othermap;
|
||||
othermap = findregionmap(map->region, i);
|
||||
// TODO: set upmap/downmap for use later on.
|
||||
if (othermap) {
|
||||
if (i == (depth-1)) {
|
||||
map->nextmap[D_UP] = othermap->id;
|
||||
|
@ -1438,7 +1487,7 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
|
|||
}
|
||||
}
|
||||
|
||||
// join up any unlinked staircases
|
||||
// join up any unlinked staircases in this map.
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
cell_t *c;
|
||||
|
@ -1451,6 +1500,9 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: search for unlinked pits/holes in roof in adjacent maps
|
||||
// if we find any, add a matching end as close as we can in this map.
|
||||
|
||||
// add random objects and monsters
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
|
@ -1458,7 +1510,7 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
|
|||
c = getcellat(map, x, y);
|
||||
if (c && isempty(c)) {
|
||||
if (rnd(1,100) <= getthingchance(map->habitat)) {
|
||||
addrandomthing(c, getobchance(map->habitat));
|
||||
addrandomthing(c, getobchance(map->habitat), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1833,6 +1885,7 @@ cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf) {
|
|||
cell_t *selection = NULL;
|
||||
cell_t *bestcell = NULL;
|
||||
int closest = 999;
|
||||
// oooooo TODO handle side being diagonal
|
||||
switch (side) {
|
||||
case D_N:
|
||||
x = 0;
|
||||
|
@ -2120,10 +2173,10 @@ int getthingchance(int habitat) {
|
|||
}
|
||||
|
||||
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) {
|
||||
return real_getrandomadjcell(c, wantempty, allowexpand, NULL);
|
||||
return real_getrandomadjcell(c, wantempty, allowexpand, LOF_NEED, NULL);
|
||||
}
|
||||
|
||||
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum OBTYPE *dontwantob) {
|
||||
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob) {
|
||||
int radius = 1;
|
||||
int x,y;
|
||||
cell_t *poss[MAXCANDIDATES];
|
||||
|
@ -2139,7 +2192,7 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum OB
|
|||
if (new &&
|
||||
(new != c) &&
|
||||
(getcelldist(c,new) == radius) &&
|
||||
haslof(c, new, LOF_WALLSTOP, NULL)) {
|
||||
haslof(c, new, needlof, NULL)) {
|
||||
enum OBTYPE *badoid;
|
||||
int ok = B_FALSE;
|
||||
numwithlof++;
|
||||
|
@ -2159,7 +2212,8 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum OB
|
|||
}
|
||||
}
|
||||
} else if (wantempty == WE_NOTWALL) {
|
||||
if (!new->type->solid){
|
||||
if ((!new->type->solid) && !hasobwithflag(new->obpile, F_IMPASSABLE)) {
|
||||
//if (!new->type->solid) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
|
@ -2372,13 +2426,33 @@ int hasobject(cell_t *c) {
|
|||
int hasknownobject(cell_t *c) {
|
||||
object_t *o;
|
||||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
if (o && !hasflag(o->flags, F_SECRET)) {
|
||||
if (o && canseeob(player, o)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tflag, lifeform_t *viewer) {
|
||||
object_t *o;
|
||||
flag_t *f;
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (viewer && !canseeob(viewer, o)) continue;
|
||||
if ((oid == NA) || (o->type->id == oid)) {
|
||||
f = hasflag(o->flags, F_TRAIL);
|
||||
// raceid and lfid must match
|
||||
if (f && (f->val[0] == lf->race->id) && (atoi(f->text) == lf->id)) {
|
||||
if (tflag) {
|
||||
*tflag = f;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int isadjacent(cell_t *src, cell_t *dst) {
|
||||
if (getcelldist(src, dst) == 1) {
|
||||
return B_TRUE;
|
||||
|
|
7
map.h
7
map.h
|
@ -3,9 +3,9 @@
|
|||
cell_t *addcell(map_t *map, int x, int y);
|
||||
void addhomeobs(lifeform_t *lf);
|
||||
map_t *addmap(void);
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen);
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded);
|
||||
object_t *addrandomob(cell_t *c);
|
||||
int addrandomthing(cell_t *c, int obchance);
|
||||
int addrandomthing(cell_t *c, int obchance, int *nadded);
|
||||
int cellhaslos(cell_t *c1, cell_t *dest);
|
||||
cell_t *getcellat(map_t *map, int x, int y);
|
||||
int getcelldist(cell_t *src, cell_t *dst);
|
||||
|
@ -43,7 +43,7 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
|
|||
int getobchance(int habitat);
|
||||
int getthingchance(int habitat);
|
||||
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 *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob);
|
||||
cell_t *getrandomcell(map_t *map);
|
||||
cell_t *getrandomcelloftype(map_t *map, int id);
|
||||
int getrandomdir(int dirtype);
|
||||
|
@ -55,6 +55,7 @@ object_t *hasenterableobject(cell_t *c);
|
|||
lifeform_t *haslf(cell_t *c);
|
||||
int hasknownobject(cell_t *c);
|
||||
int hasobject(cell_t *c);
|
||||
object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tflag, lifeform_t *viewer);
|
||||
int isadjacent(cell_t *src, cell_t *dst);
|
||||
int isdark(cell_t *c);
|
||||
int isdiggable(cell_t *c);
|
||||
|
|
388
move.c
388
move.c
|
@ -29,66 +29,65 @@ extern WINDOW *gamewin, *msgwin;
|
|||
|
||||
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
if (isplayer(lf)) {
|
||||
if (canmove(lf, dir, error)) {
|
||||
if (ispossiblemove(lf, dir)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (canmove(lf, dir, error) && willmove(lf, dir, error)) {
|
||||
if (ispossiblemove(lf, dir) && willmove(lf, dir, error)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
cell_t *cell;
|
||||
flag_t *f;
|
||||
|
||||
// default
|
||||
if (error) {
|
||||
*error = E_OK;
|
||||
rdata = NULL;
|
||||
int isorthogonal(int dir) {
|
||||
switch (dir) {
|
||||
case D_N:
|
||||
case D_E:
|
||||
case D_S:
|
||||
case D_W:
|
||||
case DC_N:
|
||||
case DC_E:
|
||||
case DC_S:
|
||||
case DC_W:
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (isburdened(lf) >= BR_OVERLOADED) {
|
||||
if (error) *error = E_TOOHEAVY;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// check if we are paralyzed, frozen, etc
|
||||
if (isimmobile(lf)) {
|
||||
if (error) *error = E_CANTMOVE;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
if (!cell) {
|
||||
if (error) *error = E_OFFMAP;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
f = lfhasflag(lf, F_GRABBEDBY);
|
||||
if (f) {
|
||||
lifeform_t *lf2;
|
||||
lf2 = findlf(NULL, f->val[0]);
|
||||
if (lf2 && (lf2 != cell->lf)) {
|
||||
if (error) {
|
||||
rdata = lf2;
|
||||
*error = E_GRABBEDBY;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// not attacking
|
||||
if (lfhasflag(lf, F_DOESNTMOVE) && !cell->lf) {
|
||||
*error = E_CANTMOVE;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
return cellwalkable(lf, cell, error);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// ie. moving into a wall isn't possible
|
||||
// moving into a lf/door IS possible since you will attack/open it
|
||||
// moving while grabbed IS possible since you'll try to break free
|
||||
int ispossiblemove(lifeform_t *lf, int dir) {
|
||||
enum ERROR error;
|
||||
if (moveclear(lf, dir, &error)) {
|
||||
return B_TRUE;
|
||||
} else {
|
||||
object_t *inway = NULL;
|
||||
switch (error) {
|
||||
case E_OFFMAP:
|
||||
if (lf->cell->map->region == RG_WORLDMAP) {
|
||||
return B_TRUE;
|
||||
}
|
||||
break;
|
||||
case E_DOORINWAY:
|
||||
case E_CANTMOVE:
|
||||
case E_GRABBEDBY:
|
||||
case E_TOOHEAVY:
|
||||
case E_LFINWAY:
|
||||
return B_TRUE;
|
||||
case E_OBINWAY:
|
||||
inway = (object_t *)rdata;
|
||||
if (inway && ispushable(inway)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// lf is the one moving, lf2 is the one who is being forced to swap
|
||||
int canswapwith(lifeform_t *lf, lifeform_t *lf2) {
|
||||
|
@ -96,6 +95,12 @@ int canswapwith(lifeform_t *lf, lifeform_t *lf2) {
|
|||
if (isplayer(lf2)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// mosnters don't swap with people who have F_NOSWAP.
|
||||
if (!isplayer(lf) && lfhasflag(lf2, F_NOSWAP)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// cannot swap if lf's cell is dangerous to lf2
|
||||
if (celldangerous(lf2, lf->cell, B_FALSE, NULL)) {
|
||||
return B_FALSE;
|
||||
|
@ -133,6 +138,16 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
|
|||
// obvious things that you can see
|
||||
if (!onlyifknown || (haslos(lf, cell) && !lfhasflag(lf, F_UNDEAD))) {
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
f = hasflag(o->flags, F_DEEPWATER);
|
||||
if (f) {
|
||||
if (!isairborne(lf) && (getobdepth(o, lf) >= DP_HEAD) && !getskill(lf, SK_SWIMMING)) {
|
||||
if (error) {
|
||||
*error = E_AVOIDOB;
|
||||
rdata = o;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
f = hasflag(o->flags, F_WALKDAM);
|
||||
if (f) {
|
||||
if ((f->val[0] != DT_WATER) || isvulnto(lf->flags, DT_WATER)) {
|
||||
|
@ -205,6 +220,14 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
|||
// must check for lf before checking for impassable objects,
|
||||
// so that we are able to attack monsters embedded in walls.
|
||||
if (cell->lf && (cell->lf != lf)) {
|
||||
// usually can't attack while swimming
|
||||
if (isswimming(lf) && (getskill(lf, SK_SWIMMING) <= PR_EXPERT)) {
|
||||
if (!lfhasflag(lf, F_AQUATIC)) {
|
||||
if (error) *error = E_SWIMMING;
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) *error = E_LFINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -345,6 +368,12 @@ int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int d
|
|||
int nposs;
|
||||
enum ERROR error;
|
||||
|
||||
if (dirtype == DT_ORTH) {
|
||||
maxdist = getcelldistorth(src, dst);
|
||||
} else {
|
||||
maxdist = getcelldist(src, dst);
|
||||
}
|
||||
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
dist[d - DC_N] = -1;
|
||||
}
|
||||
|
@ -429,12 +458,19 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in
|
|||
int nposs;
|
||||
enum ERROR error;
|
||||
|
||||
if (dirtype == DT_ORTH) {
|
||||
mindist = getcelldistorth(src, dst);
|
||||
} else {
|
||||
mindist = getcelldist(src, dst);
|
||||
}
|
||||
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
dist[d - DC_N] = -1;
|
||||
}
|
||||
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
int ok = B_FALSE;
|
||||
int thisdist;
|
||||
c = getcellindir(src, d);
|
||||
if (!c) continue;
|
||||
|
||||
|
@ -465,16 +501,20 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in
|
|||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// get distance
|
||||
if (ok) {
|
||||
int thisdist;
|
||||
if (dirtype == DT_ORTH) {
|
||||
thisdist = getcelldistorth(c, dst);
|
||||
} else {
|
||||
thisdist = getcelldist(c, dst);
|
||||
}
|
||||
dist[d - DC_N] = thisdist;
|
||||
|
||||
if (thisdist < mindist) {
|
||||
dist[d - DC_N] = thisdist;
|
||||
mindist = thisdist;
|
||||
} else {
|
||||
dist[d - DC_N] = -1;
|
||||
}
|
||||
} else {
|
||||
dist[d - DC_N] = -1; // ie. invalid
|
||||
|
@ -536,7 +576,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
|
|||
}
|
||||
|
||||
for (i = 0; i < howfar; i++) {
|
||||
if (canmove(lf, dir, &reason)) {
|
||||
if (moveclear(lf, dir, &reason)) {
|
||||
if ((i == 0) && seen) {
|
||||
msg("%s %s knocked backwards!",lfname,is(lf));
|
||||
}
|
||||
|
@ -561,6 +601,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
|
|||
// don't fall
|
||||
mightfall = B_FALSE;
|
||||
break;
|
||||
case E_SWIMMING:
|
||||
case E_LFINWAY:
|
||||
newcell = getcellindir(lf->cell, dir);
|
||||
newlf = newcell->lf;
|
||||
|
@ -619,6 +660,62 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
// ie. is the destination cell free?
|
||||
int moveclear(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
cell_t *cell;
|
||||
flag_t *f;
|
||||
|
||||
// default
|
||||
if (error) {
|
||||
*error = E_OK;
|
||||
rdata = NULL;
|
||||
}
|
||||
|
||||
if (isburdened(lf) >= BR_OVERLOADED) {
|
||||
if (error) *error = E_TOOHEAVY;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// check if we are paralyzed, frozen, etc
|
||||
if (isimmobile(lf)) {
|
||||
if (error) *error = E_CANTMOVE;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
if (!cell) {
|
||||
if (error) *error = E_OFFMAP;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
f = lfhasflag(lf, F_GRABBEDBY);
|
||||
if (f) {
|
||||
lifeform_t *lf2;
|
||||
lf2 = findlf(NULL, f->val[0]);
|
||||
if (lf2 && (lf2 != cell->lf)) {
|
||||
if (error) {
|
||||
rdata = lf2;
|
||||
*error = E_GRABBEDBY;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((lf->race->id == RC_DEMON) && hasob(cell->obpile, OT_PENTAGRAM)) {
|
||||
*error = E_PENTAGRAM;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
// not attacking
|
||||
if (lfhasflag(lf, F_DOESNTMOVE) && !cell->lf) {
|
||||
*error = E_CANTMOVE;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
return cellwalkable(lf, cell, error);
|
||||
}
|
||||
|
||||
|
||||
// IMPORTANT: don't modify lf's flagpile during this code!
|
||||
// particularly don't remove flags...
|
||||
|
@ -673,6 +770,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
int changedlev = B_FALSE;
|
||||
int preroom = -1, postroom = -1;
|
||||
int prespeed = B_FALSE, postspeed = B_FALSE;
|
||||
int prewater = B_FALSE;
|
||||
|
||||
assert(newcell);
|
||||
|
||||
|
@ -689,8 +787,14 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
// update current cell + room id
|
||||
prespeed = getmovespeed(lf);
|
||||
preroom = lf->cell->roomid;
|
||||
lf->cell->lf = NULL;
|
||||
|
||||
// getting out of water?
|
||||
if (hasobwithflag(lf->cell->obpile, F_DEEPWATER)) {
|
||||
prewater = B_TRUE;
|
||||
}
|
||||
|
||||
// move out...
|
||||
lf->cell->lf = NULL;
|
||||
|
||||
// if required, relink lifeform to new map
|
||||
if (newcell->map != lf->cell->map) {
|
||||
|
@ -756,10 +860,39 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
}
|
||||
|
||||
|
||||
if (isplayer(lf)) {
|
||||
if (prewater && !hasobwithflag(newcell->obpile, F_DEEPWATER)) {
|
||||
// getitng out of water?
|
||||
statdirty = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// check ground objects
|
||||
if (!isairborne(lf)) {
|
||||
for (o = newcell->obpile->first ; o ; o = nexto ) {
|
||||
nexto = o->next;
|
||||
|
||||
f = hasflag(o->flags, F_DEEPWATER);
|
||||
if (f) {
|
||||
if (checkfordrowning(lf, o)) {
|
||||
didmsg = B_TRUE;
|
||||
if (isdead(lf)) return B_TRUE;
|
||||
}
|
||||
// did you just enter the water?
|
||||
if (!prewater) {
|
||||
if (getskill(lf, SK_SWIMMING)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You start swimming.");
|
||||
didmsg = B_TRUE;
|
||||
statdirty = B_TRUE;
|
||||
} else if (cansee(player, lf)) {
|
||||
msg("%s starts swimming.", lfname);
|
||||
didmsg = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f = hasflag(o->flags, F_SHARP);
|
||||
if (f && hasbp(lf, BP_FEET)) {
|
||||
object_t *boots;
|
||||
|
@ -994,7 +1127,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
|
|||
// see objects on ground
|
||||
if (isplayer(lf)) {
|
||||
int numobs;
|
||||
numobs = countnoncosmeticobs(newcell->obpile);
|
||||
numobs = countnoncosmeticobs(newcell->obpile, B_TRUE);
|
||||
if ((numobs == 0) && !newcell->writing) {
|
||||
// just clear the message buffer
|
||||
if (!didmsg) clearmsg();
|
||||
|
@ -1363,11 +1496,26 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
|
|||
// do pre-move checks like slipping on stuff in your current cell,
|
||||
// webs, etc.
|
||||
// cell can be null if you're using stairs.
|
||||
|
||||
// return true if something happened
|
||||
int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
|
||||
object_t *o, *nexto;
|
||||
char buf[BUFLEN];
|
||||
flag_t *f;
|
||||
|
||||
// demon in pentagram
|
||||
if ((getraceclass(lf) == RC_DEMON) && hasob(lf->cell->obpile, OT_PENTAGRAM)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You cannot escape the pentagram!");
|
||||
} else if (cansee(player, lf)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(lf, lfname);
|
||||
msg("%s struggles within a pentagram!", lfname);
|
||||
}
|
||||
reason = E_OK;
|
||||
taketime(lf, getmovespeed(lf));
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// gravboosted
|
||||
if (lfhasflag(lf, F_GRAVBOOSTED)) {
|
||||
|
@ -1544,6 +1692,11 @@ void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int onpurpose) {
|
|||
// move them...
|
||||
lf2->cell = cell1;
|
||||
cell1->lf = lf2;
|
||||
|
||||
// remember that we just swapped
|
||||
if (!isplayer(lf1)) {
|
||||
addflag(lf1->flags, F_NOSWAP, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// teleport somewhere, along with puffs of smoke etc
|
||||
|
@ -1585,7 +1738,7 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
|
|||
// show any objects here, just like if we moved.
|
||||
// BUT don't let dolook() clear the msg bar if there are
|
||||
// no objects here.
|
||||
if (isplayer(lf) && countnoncosmeticobs(lf->cell->obpile)) {
|
||||
if (isplayer(lf) && countnoncosmeticobs(lf->cell->obpile, B_TRUE)) {
|
||||
dolook(lf->cell, B_FALSE);
|
||||
}
|
||||
return B_FALSE;
|
||||
|
@ -1598,6 +1751,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
char buf[BUFLEN];
|
||||
int dontclearmsg = B_FALSE;
|
||||
int moveok;
|
||||
int drunk = B_FALSE;
|
||||
flag_t *f;
|
||||
|
||||
f = isdrunk(lf);
|
||||
|
@ -1606,19 +1760,36 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
if (rnd(1,6) <= ((f->lifetime/DRUNKTIME)+1)) {
|
||||
// randomize move
|
||||
dir = rnd(DC_N, DC_NW);
|
||||
drunk = B_TRUE; // ie. you can walk into walls now.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
|
||||
moveok = B_FALSE;
|
||||
if (onpurpose) {
|
||||
if (canandwillmove(lf, dir, &errcode)) {
|
||||
moveok = B_TRUE;
|
||||
if (celldangerous(lf, cell, B_TRUE, &errcode)) {
|
||||
if ((errcode == E_AVOIDOB) && rdata) {
|
||||
char obname[BUFLEN];
|
||||
char ques[BUFLEN];
|
||||
char ch;
|
||||
object_t *avoidob;
|
||||
avoidob = (object_t *)rdata;
|
||||
getobname(avoidob, obname, avoidob->amt);
|
||||
sprintf(ques, "Really %s into %s?", getmoveverb(lf), obname);
|
||||
ch = askchar(ques, "yn","n", B_TRUE);
|
||||
if (ch != 'y') {
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (canmove(lf, dir, &errcode)) {
|
||||
}
|
||||
|
||||
moveok = B_FALSE;
|
||||
if (moveclear(lf, dir, &errcode)) {
|
||||
if (onpurpose) {
|
||||
if (canandwillmove(lf, dir, &errcode)) {
|
||||
moveok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
moveok = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -1627,27 +1798,36 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
lifeform_t *alf;
|
||||
if (initiatemove(lf, cell, &dontclearmsg)) {
|
||||
// failed?
|
||||
return B_FALSE;
|
||||
return B_TRUE;
|
||||
}
|
||||
// move to new cell
|
||||
|
||||
reason = E_OK;
|
||||
|
||||
// remember last dir we walked
|
||||
killflagsofid(lf->flags, F_LASTDIR);
|
||||
addflag(lf->flags, F_LASTDIR, dir, NA, NA, NULL);
|
||||
|
||||
// add footprints in our current cell.
|
||||
addtrail(lf, dir);
|
||||
|
||||
// do your pets see you move?
|
||||
if (isplayer(lf) && (gamemode == GM_GAMESTARTED)) {
|
||||
lifeform_t *l;
|
||||
for (l = lf->cell->map->lf ; l ; l = l->next) {
|
||||
if (ispetof(l,lf) && cansee(l, lf)) {
|
||||
killflagsofid(l->flags, F_OWNERLASTDIR);
|
||||
addflag(l->flags, F_OWNERLASTDIR, dir, NA, NA, NULL);
|
||||
if (cansee(l, lf)) {
|
||||
flag_t *tf;
|
||||
tf = ispetortarget(l, lf);
|
||||
if (tf) {
|
||||
// update text field
|
||||
free(tf->text);
|
||||
asprintf(&(tf->text), "%d", dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moveto(lf, cell, onpurpose, dontclearmsg);
|
||||
// now move to new cell
|
||||
moveto(lf, cell, drunk ? B_FALSE : onpurpose, dontclearmsg);
|
||||
if (onpurpose) {
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
|
@ -1662,7 +1842,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
newdir = getdirtowards(alf->cell, lf->cell, alf, B_FALSE, DT_ORTH);
|
||||
// do a manual canmove check here first, to avoid 'the stirge flies into a wall'
|
||||
// if the move fails.
|
||||
if ((newdir != D_NONE) && canmove(alf, newdir, NULL)) {
|
||||
if ((newdir != D_NONE) && moveclear(alf, newdir, NULL)) {
|
||||
trymove(alf, newdir, B_FALSE);
|
||||
}
|
||||
|
||||
|
@ -1675,11 +1855,11 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
reason = errcode;
|
||||
switch (errcode) {
|
||||
case E_OFFMAP:
|
||||
if (lf->cell->map->region == RG_WORLDMAP) {
|
||||
if ((lf->cell->map->region == RG_WORLDMAP) && (isorthogonal(dir))) {
|
||||
// we are allowed to walk off the edge
|
||||
walkoffmap(lf, dir, B_TRUE);
|
||||
return walkoffmap(lf, dir, B_TRUE);
|
||||
}
|
||||
break;
|
||||
// otherwise fall through...
|
||||
case E_WALLINWAY:
|
||||
if (isplayer(lf)) {
|
||||
msg("Ouch! You %s into a wall.", getmoveverb(lf));
|
||||
|
@ -1718,7 +1898,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
opendoor(lf, inway);
|
||||
} else {
|
||||
msg("Ouch! You %s into a door.", getmoveverb(lf));
|
||||
setcellknown(cell, B_FALSE);
|
||||
setcellknown(cell, B_FALSE);
|
||||
sprintf(buf, "%sing into a door", getmoveverb(lf));
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
if (onpurpose) taketime(lf, getmovespeed(lf));
|
||||
|
@ -1777,6 +1957,11 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case E_SWIMMING:
|
||||
if (isplayer(lf)) {
|
||||
msg("You can't attack while swimming!");
|
||||
}
|
||||
break;
|
||||
case E_LFINWAY:
|
||||
if (canswapwith(lf, cell->lf)) {
|
||||
lifeform_t *lfinway;
|
||||
|
@ -1828,6 +2013,12 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
}
|
||||
if (onpurpose) taketime(lf, getmovespeed(lf));
|
||||
break;
|
||||
case E_PENTAGRAM:
|
||||
if (isplayer(lf)) {
|
||||
msg("You cannot seem to enter the pentagram.");
|
||||
}
|
||||
if (onpurpose) taketime(lf, getmovespeed(lf));
|
||||
break;
|
||||
case E_TOOHEAVY:
|
||||
if (isplayer(lf)) {
|
||||
msg("Your load is too heavy to move with!");
|
||||
|
@ -1956,13 +2147,14 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
|||
}
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
if (celldangerous(lf, cell, B_TRUE, error)) {
|
||||
|
||||
if (cell && celldangerous(lf, cell, B_TRUE, error)) {
|
||||
if (error) *error = E_WONT;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// don't attack other monsters
|
||||
if (cell->lf) { // if someone is in the way
|
||||
if (cell && 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;
|
||||
|
@ -1993,33 +2185,35 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
|||
}
|
||||
|
||||
// look for avoided objects (because they are cursed).
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
flag_t *f;
|
||||
sprintf(buf, "%ld",o->id);
|
||||
f = lfhasflagval(lf, F_AVOIDCURSEDOB, NA, NA, NA, buf);
|
||||
if (f) {
|
||||
// still cursed?
|
||||
if (iscursed(o)) {
|
||||
if (error) *error = E_WONT;
|
||||
return B_FALSE;
|
||||
} else {
|
||||
// remove the flag.
|
||||
killflag(f);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasflag(o->flags, F_TRAP)) {
|
||||
if (hasflag(o->flags, F_SECRET)) {
|
||||
// hidden traps?
|
||||
if (iq >= IQ_SMART) {
|
||||
if (cell) {
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
flag_t *f;
|
||||
sprintf(buf, "%ld",o->id);
|
||||
f = lfhasflagval(lf, F_AVOIDCURSEDOB, NA, NA, NA, buf);
|
||||
if (f) {
|
||||
// still cursed?
|
||||
if (iscursed(o)) {
|
||||
if (error) *error = E_WONT;
|
||||
return B_FALSE;
|
||||
} else {
|
||||
// remove the flag.
|
||||
killflag(f);
|
||||
}
|
||||
} else {
|
||||
// non-hidden traps?
|
||||
if (iq >= IQ_AVERAGE) {
|
||||
if (error) *error = E_WONT;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
if (hasflag(o->flags, F_TRAP)) {
|
||||
if (hasflag(o->flags, F_SECRET)) {
|
||||
// hidden traps?
|
||||
if (iq >= IQ_SMART) {
|
||||
if (error) *error = E_WONT;
|
||||
return B_FALSE;
|
||||
}
|
||||
} else {
|
||||
// non-hidden traps?
|
||||
if (iq >= IQ_AVERAGE) {
|
||||
if (error) *error = E_WONT;
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
4
move.h
4
move.h
|
@ -1,7 +1,6 @@
|
|||
#include "defs.h"
|
||||
|
||||
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
int canswapwith(lifeform_t *lf, lifeform_t *lf2);
|
||||
int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *error);
|
||||
int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error);
|
||||
|
@ -13,6 +12,7 @@ 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 knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff);
|
||||
int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype);
|
||||
int moveclear(lifeform_t *lf, int dir, enum ERROR *error);
|
||||
int moveeffects(lifeform_t *lf);
|
||||
int movelf(lifeform_t *lf, cell_t *newcell);
|
||||
int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg);
|
||||
|
@ -21,6 +21,8 @@ int opendoorat(lifeform_t *lf, cell_t *c);
|
|||
int opendoor(lifeform_t *lf, object_t *o);
|
||||
int pullnextto(lifeform_t *lf, cell_t *c);
|
||||
int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg);
|
||||
int isorthogonal(int dir);
|
||||
int ispossiblemove(lifeform_t *lf, int dir);
|
||||
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int onpurpose);
|
||||
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke);
|
||||
int trymove(lifeform_t *lf, int dir, int onpurpose);
|
||||
|
|
43
nexus.c
43
nexus.c
|
@ -3,6 +3,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "ai.h"
|
||||
|
@ -34,6 +35,9 @@ hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
|
|||
|
||||
glyph_t playerglyph,tempglyph;
|
||||
|
||||
double startticks,lastticks;
|
||||
struct timeval starttv, tv,newtv;
|
||||
|
||||
// maintains unique lifeform ID numbers
|
||||
long nextlfid = 0;
|
||||
|
||||
|
@ -58,6 +62,8 @@ void *rdata; // globel for returning data
|
|||
lifeform_t *player = NULL;
|
||||
int gameover;
|
||||
|
||||
int obdb = B_FALSE;
|
||||
|
||||
enum GAMEMODE gamemode = GM_FIRST;
|
||||
|
||||
long curtime = 0;
|
||||
|
@ -171,7 +177,9 @@ int main(int argc, char **argv) {
|
|||
if (where->lf) {
|
||||
killlf(where->lf);
|
||||
}
|
||||
// add player
|
||||
|
||||
// add player nearby
|
||||
where = real_getrandomadjcell(where, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL);
|
||||
real_addlf(where, R_HUMAN, 1, C_PLAYER); // this will assign 'player'
|
||||
|
||||
user = getenv("USER");
|
||||
|
@ -464,6 +472,27 @@ void cleanup(void) {
|
|||
// free races
|
||||
}
|
||||
|
||||
void dbtimestart(char *text) {
|
||||
gettimeofday(&tv, NULL);
|
||||
starttv = tv;
|
||||
dblog("START\t%s", text);
|
||||
}
|
||||
|
||||
void dbtime(char *text) {
|
||||
double ticks;
|
||||
gettimeofday(&newtv, NULL);
|
||||
ticks = ((newtv.tv_sec - tv.tv_sec) * 1000000) + (newtv.tv_usec - tv.tv_usec);
|
||||
dblog("+%f\t%s", ticks, text);
|
||||
tv = newtv;
|
||||
}
|
||||
|
||||
void dbtimeend(char *text) {
|
||||
double ticks;
|
||||
gettimeofday(&newtv, NULL);
|
||||
ticks = ((newtv.tv_sec - starttv.tv_sec) * 1000000) + (newtv.tv_usec - starttv.tv_usec);
|
||||
dblog("FINISHED %s (total time %f)", text, ticks);
|
||||
}
|
||||
|
||||
void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, int dinc2, int *xinc, int *yinc, int *dinc) {
|
||||
if (d < 0) {
|
||||
*xinc = xinc1;
|
||||
|
@ -953,7 +982,7 @@ int rollhitdice(lifeform_t *lf) {
|
|||
int roll = 0;
|
||||
int i;
|
||||
float mod;
|
||||
int db = B_FALSE;
|
||||
int db = B_TRUE;
|
||||
|
||||
f = hasflag(lf->flags, F_HITDICE);
|
||||
if (f) {
|
||||
|
@ -964,11 +993,11 @@ int rollhitdice(lifeform_t *lf) {
|
|||
ndice = 1;
|
||||
plus = 0;
|
||||
}
|
||||
if (db && isplayer(lf)) dblog("rollhitdice() - rolling %dd4 + %d",ndice,plus);
|
||||
if (db) dblog("rollhitdice() for %s - rolling %dd4 + %d",lf->race->name,ndice,plus);
|
||||
|
||||
mod = getstatmod(lf, A_CON);
|
||||
if (mod > 0) mod *= 2;
|
||||
if (db && isplayer(lf)) dblog("rollhitdice() - mod is +%0.0f%%",mod);
|
||||
if (db) dblog("rollhitdice() - mod is +%0.0f%%",mod);
|
||||
|
||||
if (ndice == 0) {
|
||||
int thisroll;
|
||||
|
@ -983,14 +1012,14 @@ int rollhitdice(lifeform_t *lf) {
|
|||
int thisroll;
|
||||
thisroll = rolldie(1, 4) + plus;
|
||||
if (thisroll < 1) thisroll = 1;
|
||||
if (db && isplayer(lf)) dblog("rollhitdice() ---- die %d/%d == %d",i+1,ndice,thisroll);
|
||||
if (db) dblog("rollhitdice() ---- die %d/%d == %d",i+1,ndice,thisroll);
|
||||
|
||||
roll += thisroll;
|
||||
}
|
||||
}
|
||||
if (db && isplayer(lf)) dblog("TOTAL: %d",roll);
|
||||
if (db) dblog("TOTAL: %d",roll);
|
||||
roll = roll + (int)((float)roll * (mod/100));
|
||||
if (db && isplayer(lf)) dblog(" -> modified to: %d",roll);
|
||||
if (db) dblog(" -> modified to: %d",roll);
|
||||
return roll;
|
||||
}
|
||||
|
||||
|
|
3
nexus.h
3
nexus.h
|
@ -5,6 +5,9 @@ command_t *addcommand(enum COMMAND id, char c, char *desc);
|
|||
void checkdeath(void);
|
||||
void checkendgame(void);
|
||||
void cleanup(void);
|
||||
void dbtime(char *text);
|
||||
void dbtimeend(char *text);
|
||||
void dbtimestart(char *text);
|
||||
void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, int dinc2, int *xinc, int *yinc, int *dinc);
|
||||
void donextturn(map_t *map);
|
||||
char *getdirname(int dir);
|
||||
|
|
528
objects.c
528
objects.c
|
@ -44,6 +44,8 @@ extern int reason;
|
|||
extern int needredraw;
|
||||
extern int statdirty;
|
||||
|
||||
extern int obdb;
|
||||
|
||||
|
||||
char letorder[MAXPILEOBS] = {
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
|
@ -658,6 +660,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
|
||||
// inherit flags from objecttype
|
||||
copyflags(o->flags, ot->flags, NA);
|
||||
// don't want certain objecttype only flags...
|
||||
killflagsofid(o->flags, F_RARITY);
|
||||
|
||||
// random flags...
|
||||
f = hasflag(o->flags, F_RNDCHARGES);
|
||||
|
@ -1146,6 +1150,8 @@ int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fr
|
|||
|
||||
if (!where) return 0;
|
||||
|
||||
redrawpause();
|
||||
|
||||
if (dirtype == DT_ORTH) {
|
||||
distfunc = getcelldistorth;
|
||||
} else {
|
||||
|
@ -1168,6 +1174,7 @@ int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fr
|
|||
}
|
||||
}
|
||||
|
||||
redrawresume();
|
||||
return nadded;
|
||||
}
|
||||
|
||||
|
@ -1413,6 +1420,11 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) {
|
|||
}
|
||||
}
|
||||
|
||||
if (hasflag(o->flags, F_INVULNERABLE)) {
|
||||
*dam = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// immune?
|
||||
if (isimmuneto(o->flags, damtype)) {
|
||||
*dam = 0;
|
||||
|
@ -1750,6 +1762,54 @@ int canbepoisoned(enum OBTYPE oid) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int canseeob(lifeform_t *lf, object_t *o) {
|
||||
flag_t *f;
|
||||
if (gamemode != GM_GAMESTARTED) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (hasflag(o->flags, F_SECRET) && isplayer(lf)) {
|
||||
// can't see
|
||||
return B_FALSE;
|
||||
}
|
||||
f = hasflag(o->flags, F_TRAIL);
|
||||
if (f) {
|
||||
if (f->val[2] == S_SIGHT) {
|
||||
enum SKILLLEVEL slev;
|
||||
int cutoffpct;
|
||||
int cutoff;
|
||||
slev = getskill(lf, SK_TRACKING);
|
||||
switch (slev) {
|
||||
case PR_NOVICE: cutoffpct = 80; break;
|
||||
case PR_BEGINNER: cutoffpct = 65; break;
|
||||
case PR_ADEPT: cutoffpct = 50; break;
|
||||
case PR_SKILLED: cutoffpct = 35; break;
|
||||
case PR_EXPERT: cutoffpct = 20; break;
|
||||
case PR_MASTER: cutoffpct = 0; break;
|
||||
default:
|
||||
case PR_INEPT: cutoffpct = 200; break;
|
||||
}
|
||||
|
||||
cutoff = pctof(cutoffpct, FOOTPRINTTIME);
|
||||
|
||||
if (f->lifetime >= cutoff) {
|
||||
return B_TRUE;
|
||||
} else {
|
||||
return B_FALSE;
|
||||
}
|
||||
} else {
|
||||
// ie. SCENT
|
||||
// can't smell your own race...
|
||||
if ((f->val[0] != lf->race->id) && lfhasflag(lf, F_ENHANCESMELL)) {
|
||||
return B_TRUE;
|
||||
} else {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// does the pile "op" have an object we can
|
||||
// stack "match" with
|
||||
object_t *canstackob(obpile_t *op, object_t *match) {
|
||||
|
@ -1929,23 +1989,35 @@ int countnames(char **list) {
|
|||
return count;
|
||||
}
|
||||
|
||||
int countobs(obpile_t *op) {
|
||||
int countobs(obpile_t *op, int onlyifknown) {
|
||||
object_t *o;
|
||||
|
||||
int count = 0;
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
count++;
|
||||
if (onlyifknown) {
|
||||
if (canseeob(player, o)) {
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int countnoncosmeticobs(obpile_t *op) {
|
||||
int countnoncosmeticobs(obpile_t *op, int onlyifknown) {
|
||||
object_t *o;
|
||||
|
||||
int count = 0;
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (!hasflag(o->flags, F_COSMETIC) && !hasflag(o->flags, F_SECRET)) {
|
||||
count++;
|
||||
if (onlyifknown) {
|
||||
if (canseeob(player, o)) {
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
@ -1993,11 +2065,17 @@ int curseob(object_t *o) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
void damageallobs(object_t *exception, obpile_t *op, int howmuch, int damtype) {
|
||||
void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype) {
|
||||
object_t *o, *nexto;
|
||||
for (o = op->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
if ((o != exception) && !hasflag(o->flags, F_DEAD)) {
|
||||
|
||||
// special case to stop steam from hurting water
|
||||
if (srcob && (srcob->material->id == MT_GAS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((o != srcob) && !hasflag(o->flags, F_DEAD)) {
|
||||
takedamage(o, howmuch, damtype);
|
||||
}
|
||||
}
|
||||
|
@ -3023,6 +3101,22 @@ int getnutrition(object_t *o) {
|
|||
return (int)nutrition;
|
||||
}
|
||||
|
||||
enum DEPTH getobdepth(object_t *o, lifeform_t *lf) {
|
||||
int depth = DP_NONE;
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_DEEPWATER);
|
||||
if (f) {
|
||||
depth = f->val[0];
|
||||
if (lf) {
|
||||
int mod;
|
||||
mod = SZ_HUMAN - getlfsize(lf);
|
||||
depth += mod;
|
||||
limit(&depth, DP_NONE, DP_HEAD);
|
||||
}
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
char *getobdesc(object_t *o, char *buf) {
|
||||
if (isknown(o)) {
|
||||
if (o->type->id == OT_CORPSE) {
|
||||
|
@ -3197,10 +3291,88 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
|
|||
showall = B_TRUE;
|
||||
}
|
||||
|
||||
if (showall) {
|
||||
strcpy(basename,o->type->name);
|
||||
f = hasflag(o->flags, F_TRAIL);
|
||||
if (f) {
|
||||
race_t *r = NULL;
|
||||
enum SKILLLEVEL slev;
|
||||
slev = getskill(player, SK_TRACKING);
|
||||
r = findrace(f->val[0]);
|
||||
assert(r);
|
||||
|
||||
if (f->val[2] == S_SMELL) {
|
||||
char buf[BUFLEN];
|
||||
float pct;
|
||||
char dname[BUFLEN];
|
||||
char adjective[BUFLEN];
|
||||
|
||||
lifeform_t *who = NULL;
|
||||
pct = ((float)f->lifetime / (float)SCENTTIME)*100;
|
||||
if (pct >= 66) {
|
||||
strcpy(adjective, "strong ");
|
||||
} else if (pct >= 33) {
|
||||
strcpy(adjective, "");
|
||||
} else {
|
||||
strcpy(adjective, "weak ");
|
||||
}
|
||||
|
||||
strcpy(basename, "");
|
||||
|
||||
if (strlen(f->text)) {
|
||||
who = findlf(where->map, atoi(f->text));
|
||||
}
|
||||
if (who) {
|
||||
char lfname[BUFLEN];
|
||||
real_getlfname(who, lfname, B_FALSE);
|
||||
sprintf(buf, "%s%s %sscent",lfname,getpossessive(lfname), adjective);
|
||||
} else {
|
||||
sprintf(buf, "%s %sscent",r->name, adjective);
|
||||
}
|
||||
strcat(basename, buf);
|
||||
|
||||
strcat(basename, " leading ");
|
||||
sprintf(dname, "%s", getdirname(f->val[1]));
|
||||
dname[0] = tolower(dname[0]);
|
||||
strcat(basename, dname);
|
||||
} else {
|
||||
char buf[BUFLEN];
|
||||
// adept and upwards gets depth
|
||||
if (slev >= PR_BEGINNER) {
|
||||
float pct;
|
||||
pct = ((float)f->lifetime / (float)FOOTPRINTTIME)*100;
|
||||
if (pct >= 66) {
|
||||
strcpy(basename, "fresh ");
|
||||
} else if (pct >= 33) {
|
||||
strcpy(basename, "");
|
||||
} else {
|
||||
strcpy(basename, "faint ");
|
||||
}
|
||||
} else {
|
||||
strcpy(basename, "");
|
||||
}
|
||||
|
||||
// adept and upwards get "monstername footprints"
|
||||
if (slev >= PR_ADEPT) {
|
||||
sprintf(buf, "%s %s",r->name, o->type->name);
|
||||
strcat(basename, buf);
|
||||
} else {
|
||||
sprintf(basename, "%s", o->type->name);
|
||||
}
|
||||
|
||||
// skilled and upwards get the direction
|
||||
if (slev >= PR_SKILLED) {
|
||||
char dname[BUFLEN];
|
||||
strcat(basename, " leading ");
|
||||
sprintf(dname, "%s", getdirname(f->val[1]));
|
||||
dname[0] = tolower(dname[0]);
|
||||
strcat(basename, dname);
|
||||
}
|
||||
} // end if sight/smell
|
||||
} else {
|
||||
strcpy(basename,gethiddenname(o));
|
||||
if (showall) {
|
||||
strcpy(basename,o->type->name);
|
||||
} else {
|
||||
strcpy(basename,gethiddenname(o));
|
||||
}
|
||||
}
|
||||
|
||||
if (o->type->obclass->id == OC_BOOK) {
|
||||
|
@ -3306,7 +3478,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
|
|||
strcpy(localbuf, "");
|
||||
|
||||
// figure out pluralname
|
||||
if ((count == 1) && !hasflag(o->flags, F_NO_A)) {
|
||||
if (count == 1) {
|
||||
pluralname = strdup(basename);
|
||||
} else {
|
||||
// multiple objects?
|
||||
|
@ -3399,7 +3571,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
|
|||
int bonus;
|
||||
bonus = f->val[0];
|
||||
if (bonus != 0) {
|
||||
sprintf(buf2, "%s%d ", (bonus < 0) ? "" : "+", bonus);
|
||||
sprintf(buf2, "%s%d ", (bonus < 0) ? "-" : "+", abs(bonus));
|
||||
strcat(localbuf, buf2);
|
||||
}
|
||||
}
|
||||
|
@ -3513,23 +3685,32 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
|
|||
}
|
||||
|
||||
// apply prefix now!
|
||||
if ((count == 1) && !hasflag(o->flags, F_NO_A)) {
|
||||
if (hasflag(o->flags, F_UNIQUE)) { // TODO: && o->identified
|
||||
strcpy(prefix, "The");
|
||||
} else {
|
||||
if (needan(localbuf)) {
|
||||
strcpy(prefix, "an");
|
||||
if (count == 1) {
|
||||
if (hasflag(o->flags, F_NO_A)) {
|
||||
if (o->type->id == OT_GOLD) {
|
||||
sprintf(prefix, "%d ",count);
|
||||
} else {
|
||||
strcpy(prefix, "a");
|
||||
// nothing.
|
||||
strcpy(prefix, "");
|
||||
}
|
||||
} else {
|
||||
if (hasflag(o->flags, F_UNIQUE)) { // TODO: && o->identified
|
||||
strcpy(prefix, "The ");
|
||||
} else {
|
||||
if (needan(localbuf)) {
|
||||
strcpy(prefix, "an ");
|
||||
} else {
|
||||
strcpy(prefix, "a ");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// multiple objects?
|
||||
sprintf(prefix, "%d",count);
|
||||
sprintf(prefix, "%d ",count);
|
||||
}
|
||||
|
||||
// prepend prefix on to buf
|
||||
sprintf(buf, "%s %s", prefix, localbuf);
|
||||
sprintf(buf, "%s%s", prefix, localbuf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -3688,8 +3869,10 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
|
|||
flag_t *omposs[MAXCANDIDATES];
|
||||
int noms = 0;
|
||||
|
||||
db = obdb;
|
||||
|
||||
if (forcedepth != NA) {
|
||||
//if (forcedepth != NA) {
|
||||
if (forcedepth >= 0) {
|
||||
depth = forcedepth;
|
||||
} else {
|
||||
depth = getmapdifficulty(map);
|
||||
|
@ -3751,7 +3934,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
|
|||
}
|
||||
|
||||
if (rarok && condok) {
|
||||
//if (db) dblog("-> possibility: %s, rarity=%d",ot->name, rarflag->val[1]);
|
||||
if (db) dblog("-> possibility: %s, rarity=%d",ot->name, rarflag->val[1]);
|
||||
poss[nposs] = ot;
|
||||
nposs++;
|
||||
if (nposs >= MAXRANDOMOBCANDIDATES) break;
|
||||
|
@ -3901,6 +4084,7 @@ char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf) {
|
|||
|
||||
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod) {
|
||||
//return real_getrandomob(map, buf, RO_OBCLASS, cid, map->depth + depthmod);
|
||||
if (depthmod == NA) depthmod = 0;
|
||||
return real_getrandomob(map, buf, RO_OBCLASS, cid, getmapdifficulty(map) + depthmod);
|
||||
}
|
||||
|
||||
|
@ -4060,6 +4244,25 @@ int getthrowdam(object_t *o) {
|
|||
return (int)dam;
|
||||
}
|
||||
|
||||
char *gettopobname(cell_t *c, char *retbuf) {
|
||||
char buf[BUFLEN];
|
||||
object_t *o;
|
||||
o = gettopobject(c);
|
||||
if (o) {
|
||||
int nother;
|
||||
getobname(o, buf, o->amt);
|
||||
strcat(retbuf, buf);
|
||||
// other obs here too?
|
||||
nother = countnoncosmeticobs(c->obpile, B_TRUE) - 1;
|
||||
if (nother >= 1) {
|
||||
sprintf(buf, " (+%d other thing%s)", nother, (nother == 1) ? "" : "s");
|
||||
strcat(retbuf, buf);
|
||||
}
|
||||
return retbuf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded) {
|
||||
enum BODYPART weildloc;
|
||||
if (o) {
|
||||
|
@ -4570,7 +4773,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_DOOR, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL);
|
||||
|
@ -4583,7 +4786,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_DOOR, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL);
|
||||
|
@ -4599,7 +4802,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
|
||||
// addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
|
@ -4611,7 +4814,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "'");
|
||||
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
|
||||
|
@ -4621,7 +4824,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'");
|
||||
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
|
||||
|
@ -4643,16 +4846,56 @@ void initobjects(void) {
|
|||
|
||||
addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_DFEATURE);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, "");
|
||||
addflag(lastot->flags, F_GLYPH, C_WHITE, NA, NA, "_");
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "_");
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addot(OT_HOLYCIRCLE, "holy circle", "A consecrated area imbued with holy power.", MT_NOTHING, 0, OC_DFEATURE);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, "");
|
||||
addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "_");
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
|
||||
addflag(lastot->flags, F_REPELBLESSED, B_CURSED, NA, NA, NULL);
|
||||
|
||||
addot(OT_PENTAGRAM, "pentagram", "A area imbued with evil.", MT_NOTHING, 0, OC_DFEATURE);
|
||||
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, "");
|
||||
addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "_");
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
|
||||
addflag(lastot->flags, F_REPELBLESSED, B_BLESSED, NA, NA, NULL);
|
||||
|
||||
addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_DFEATURE);
|
||||
addflag(lastot->flags, F_GLYPH, C_BOLDGREEN, NA, NA, "&");
|
||||
addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addot(OT_WATERSHALLOW, "shallow water", "Waist-deep water.", MT_WATER, 150, OC_DFEATURE);
|
||||
addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "{");
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DEEPWATER, DP_WAIST, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice");
|
||||
addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 1, DT_COMPASS, "cloud of steam");
|
||||
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, B_DONTKILL, NULL);
|
||||
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_REDUCEMOVEMENT, 3, NA, NA, NULL);
|
||||
|
||||
addot(OT_WATERDEEP, "deep water", "Very deep water.", MT_WATER, 300, OC_DFEATURE);
|
||||
addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_BOLDBLUE, NA, NA, "{");
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice");
|
||||
addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 1, DT_COMPASS, "cloud of steam");
|
||||
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, B_DONTKILL, NULL);
|
||||
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DEEPWATER, DP_HEAD, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_REDUCEMOVEMENT, 4, NA, NA, NULL);
|
||||
|
||||
// traps
|
||||
addot(OT_TRAPTRIP, "tripwire", "A thin wire at ankle height.", MT_NOTHING, 0, OC_MISC);
|
||||
addflag(lastot->flags, F_TRAP, 10, B_FALSE, 20, NULL);
|
||||
|
@ -4805,7 +5048,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "#");
|
||||
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
|
||||
|
@ -5143,15 +5386,18 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
|
||||
// l4
|
||||
addot(OT_S_WEAKEN, "weaken", "Temporarily lowers the target's muscle strength.", MT_NOTHING, 0, OC_SPELL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
|
||||
addot(OT_S_PARALYZE, "paralyze", "Disables the target's muscles, leaving them unable to move.", MT_NOTHING, 0, OC_SPELL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
|
||||
addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
||||
|
@ -5162,6 +5408,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
|
||||
// l7
|
||||
addot(OT_S_POSSESSION, "possession", "Completely possess an enemy, moving your consciousness into their body.", MT_NOTHING, 0, OC_SPELL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
||||
|
@ -5457,6 +5704,7 @@ void initobjects(void) {
|
|||
addot(OT_S_DIG, "dig", "Blasts away earth to create passages.", MT_NOTHING, 0, OC_SPELL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
|
||||
addot(OT_S_ENTANGLE, "entangle", "Causes magical vines to hold enemies.", MT_NOTHING, 0, OC_SPELL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
||||
|
@ -5708,11 +5956,13 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
|
||||
// l5
|
||||
addot(OT_S_DISPERSAL, "dispersal", "Scatters everything in the target cell around the area.", MT_NOTHING, 0, OC_SPELL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
|
||||
// l6
|
||||
addot(OT_S_GATE, "gate", "Creates a portal to a different dungeon level.", MT_NOTHING, 0, OC_SPELL);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
||||
|
@ -6487,7 +6737,7 @@ void initobjects(void) {
|
|||
addot(OT_ICESHEET, "sheet of ice", "A large sheet of slippery ice.", MT_ICE, 0.5, OC_MISC);
|
||||
addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "_");
|
||||
addflag(lastot->flags, F_GLYPH, C_WHITE, NA, NA, "_");
|
||||
addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "large puddle of water");
|
||||
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "large puddle of water");
|
||||
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "melts");
|
||||
|
@ -6584,7 +6834,7 @@ void initobjects(void) {
|
|||
addot(OT_PUDDLEOIL, "puddle of oil", "A slippery puddle of oil.", MT_OIL, 0, OC_MISC);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, ","); // should really be dark grey
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FLAMMABLE, 5, NA, NA, "medium fire");
|
||||
|
@ -6612,9 +6862,9 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
|
||||
|
||||
addot(OT_MUDPOOL, "pool of mud", "A large puddle of wet mud.", MT_WATER, 0, OC_MISC);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, ",");
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, ",");
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL);
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
|
@ -6627,7 +6877,7 @@ void initobjects(void) {
|
|||
addot(OT_PUDDLEWATER, "small puddle of water", "A small puddle of water.", MT_WATER, 0, OC_MISC);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, ",");
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL);
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
|
@ -6641,7 +6891,7 @@ void initobjects(void) {
|
|||
addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool of water.", MT_WATER, 0, OC_MISC);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, ",");
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_FOREST, 85, NA, NULL);
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
|
@ -6651,6 +6901,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+2");
|
||||
|
||||
|
||||
addot(OT_BLOODSTAIN, "blood stain", "A dried stain of blood.", MT_BLOOD, 0, OC_MISC);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
|
@ -6746,9 +6997,27 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
|
||||
// trail objects
|
||||
addot(OT_FOOTPRINT, "footprints", "Footprints which show the passage of some kind of creature.", MT_NOTHING, 0, OC_MISC);
|
||||
addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NO_PLURAL, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "."); // ie not really visible
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
// NOTE: must add F_TRAIL when creating this object.
|
||||
addot(OT_SCENT, "scent", "The scent of a creature, only perceivable to those with an enhanced sense of smell.", MT_NOTHING, 0, OC_MISC);
|
||||
addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NO_PLURAL, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "."); // ie not really visible
|
||||
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
// NOTE: must add F_TRAIL when creating this object.
|
||||
|
||||
// effects
|
||||
addot(OT_FIRELARGE, "large fire", "A large, roaring inferno.", MT_FIRE, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_ORANGE, NA, NA, "}");
|
||||
addflag(lastot->flags, F_GLYPH, C_ORANGE, NA, NA, "^");
|
||||
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little");
|
||||
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "medium fire");
|
||||
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
||||
|
@ -6759,7 +7028,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
|
||||
addot(OT_FIREMED, "medium fire", "A medium-sized roaring fire.", MT_FIRE, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "}");
|
||||
addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "^");
|
||||
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small fire");
|
||||
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little");
|
||||
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
||||
|
@ -6770,7 +7039,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
|
||||
addot(OT_FIRESMALL, "small fire", "A small blaze.", MT_FIRE, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "}");
|
||||
addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "^");
|
||||
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "goes out");
|
||||
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
|
@ -6781,7 +7050,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
|
||||
|
||||
addot(OT_STEAMCLOUD, "cloud of steam", "A thick cloud of scalding steam.", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}");
|
||||
addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of steam");
|
||||
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
||||
|
@ -6793,7 +7062,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
|
||||
|
||||
addot(OT_STEAMPUFF, "puff of steam", "A small puff of scalding steam.", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "}");
|
||||
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "disperses");
|
||||
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
|
@ -6805,7 +7074,7 @@ void initobjects(void) {
|
|||
|
||||
|
||||
addot(OT_SLEETSTORM, "storm of sleet", "An intense storm of sleet. Hampers movement", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "}");
|
||||
addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
|
@ -6813,7 +7082,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSVIEW, 3, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_REDUCEMOVEMENT, 2, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_REDUCEMOVEMENT, 3, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
|
||||
addflag(lastot->flags, F_WALKDAMBP, BP_HEAD, DT_WATER, NA, "1d2");
|
||||
addflag(lastot->flags, F_WALKDAMBP, BP_SHOULDERS, DT_WATER, NA, "1d2");
|
||||
|
@ -6823,7 +7092,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, NA, "1d2");
|
||||
|
||||
addot(OT_MIST, "thick mist", "A thick cloud of obscuring mist.", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}");
|
||||
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "clears");
|
||||
addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
|
@ -6833,7 +7102,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
|
||||
|
||||
addot(OT_SMOKECLOUD, "cloud of smoke", "A thick cloud of black smoke.", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}");
|
||||
addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of smoke");
|
||||
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
||||
|
@ -6846,7 +7115,7 @@ void initobjects(void) {
|
|||
|
||||
|
||||
addot(OT_SMOKEPUFF, "puff of smoke", "A small puff of black smoke.", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}");
|
||||
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "disperses");
|
||||
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
|
@ -6857,7 +7126,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_CAUSESCOUGH, 18, NA, NA, NULL);
|
||||
|
||||
addot(OT_POISONCLOUD, "cloud of poison gas", "A thick cloud of poisonous gas.", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "}");
|
||||
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "thins out a little");
|
||||
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of gas");
|
||||
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
||||
|
@ -6869,7 +7138,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_BLOCKSVIEW, 2, NA, NA, NULL);
|
||||
|
||||
addot(OT_POISONPUFF, "puff of poison gas", "A small puff of poisonous gas.", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "}");
|
||||
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "disperses");
|
||||
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
|
@ -6879,7 +7148,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
|
||||
|
||||
addot(OT_HAILSTORM, "hail storm", "An intense storm of damaging hail.", MT_GAS, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_WHITE, NA, NA, "{");
|
||||
addflag(lastot->flags, F_GLYPH, C_WHITE, NA, NA, "}");
|
||||
addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
|
@ -6906,8 +7175,7 @@ void initobjects(void) {
|
|||
addot(OT_MAGICBARRIER, "magical barrier", "A glowing, impassable barrier of magical energy.", MT_MAGIC, 0, OC_EFFECT);
|
||||
addflag(lastot->flags, F_GLYPH, C_YELLOW, NA, NA, "#");
|
||||
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes");
|
||||
addflag(lastot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL);
|
||||
|
@ -7292,6 +7560,7 @@ void initobjects(void) {
|
|||
addot(OT_TEETH, "teeth", "teeth object", MT_BONE, 0, OC_WEAPON);
|
||||
addflag(lastot->flags, F_DAM, DT_BITE, NA, NA, "1d2");
|
||||
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL);
|
||||
|
@ -8178,6 +8447,11 @@ int isimpassableob(object_t *o, lifeform_t *lf) {
|
|||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
if (lf && (lf->race->raceclass->id == RC_UNDEAD)) {
|
||||
if (hasflagval(o->flags, F_REPELBLESSED, B_CURSED, NA, NA, NULL)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -9088,7 +9362,7 @@ void obdie(object_t *o) {
|
|||
}
|
||||
|
||||
int obfits(object_t *o, obpile_t *op) {
|
||||
if (countobs(op) >= MAXPILEOBS) {
|
||||
if (countobs(op, B_FALSE) >= MAXPILEOBS) {
|
||||
return B_FALSE;
|
||||
}
|
||||
return B_TRUE;
|
||||
|
@ -9279,10 +9553,10 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
|
||||
if (isplayer(lf)) {
|
||||
if (strlen(f->text) > 0) {
|
||||
where = askcoords(f->text, ttype, lf, UNLIMITED);
|
||||
where = askcoords(f->text, ttype, lf, UNLIMITED, LOF_NEED, B_TRUE);
|
||||
} else {
|
||||
sprintf(buf, "Where will you aim %s?",obname);
|
||||
where = askcoords(buf, ttype, lf, UNLIMITED);
|
||||
where = askcoords(buf, ttype, lf, UNLIMITED, LOF_NEED, B_TRUE);
|
||||
if (!haslos(lf, where)) {
|
||||
// exception - wand of digging doesn't need los
|
||||
if (isknown(o) && (o->type->id == OT_WAND_DIGGING)) {
|
||||
|
@ -9440,7 +9714,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
case 0: // butterflies around user
|
||||
willid = B_TRUE;
|
||||
where = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
addmonster(where, R_BUTTERFLY, B_FALSE, rnd(10,20), B_FALSE);
|
||||
addmonster(where, R_BUTTERFLY, B_FALSE, rnd(10,20), B_FALSE, NULL);
|
||||
if (haslos(player, where)) {
|
||||
msg("A swarm of butterflies appears!");
|
||||
}
|
||||
|
@ -10147,6 +10421,8 @@ void quaff(lifeform_t *lf, object_t *o) {
|
|||
int playercansee;
|
||||
int forcedrop = B_FALSE;
|
||||
int seen;
|
||||
int killobwhendone = B_TRUE;
|
||||
flag_t *drinkflag;
|
||||
|
||||
getobname(o, obname, 1);
|
||||
|
||||
|
@ -10210,14 +10486,21 @@ void quaff(lifeform_t *lf, object_t *o) {
|
|||
|
||||
if (o->type->obclass->id == OC_POTION) {
|
||||
potioneffects(lf, o->type->id, o->blessed, &seen);
|
||||
} else if (hasflag(o->flags, F_DRINKABLE)) {
|
||||
// drinkable thing which isn't a potion?
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_LINKOB);
|
||||
if (f) {
|
||||
potioneffects(lf, f->val[0], o->blessed, NULL);
|
||||
} else {
|
||||
eat(lf, o);
|
||||
} else {
|
||||
drinkflag= hasflag(o->flags, F_DRINKABLE);
|
||||
if (drinkflag) {
|
||||
// drinkable thing which isn't a potion?
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_LINKOB);
|
||||
if (f) {
|
||||
potioneffects(lf, f->val[0], o->blessed, NULL);
|
||||
} else {
|
||||
eat(lf, o);
|
||||
}
|
||||
//
|
||||
if (drinkflag->val[2] == B_DONTKILL) {
|
||||
killobwhendone = B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10233,8 +10516,11 @@ void quaff(lifeform_t *lf, object_t *o) {
|
|||
// try to add an empty container to our pack
|
||||
addemptyob(lf->pack, o);
|
||||
}
|
||||
// lose the potion
|
||||
removeob(o, 1);
|
||||
|
||||
if (killobwhendone) {
|
||||
// lose the potion
|
||||
removeob(o, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -10544,11 +10830,15 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i
|
|||
if (c && isempty(c)) {
|
||||
object_t *newob;
|
||||
newob = addob(c->obpile, "magical barrier");
|
||||
addflag(newob->flags, F_OBHP, i, i, NA, NULL);
|
||||
if (first && haslos(player, c)) {
|
||||
msg("A magical barrier appears!");
|
||||
first = B_FALSE;
|
||||
}
|
||||
|
||||
// it will disappear eventually
|
||||
addflag(newob->flags, F_OBHP, i, i, NA, NULL);
|
||||
addflag(newob->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(newob->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -11056,7 +11346,7 @@ void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
|
|||
capitalise(obcaps);
|
||||
obcaps = strrep(obcaps, "An ", "The ", NULL);
|
||||
obcaps = strrep(obcaps, "A ", "The ", NULL);
|
||||
msg("%s shatters!",obcaps);
|
||||
msg("%s shatter%s!",obcaps, (o->amt == 1) ? "s" : "");
|
||||
free(obcaps);
|
||||
|
||||
seen = B_TRUE;
|
||||
|
@ -11332,6 +11622,29 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// damage type creates other objects?
|
||||
f = hasflagval(o->flags, F_DTCREATEOB, damtype, NA, NA, NULL);
|
||||
if (f) {
|
||||
cell_t *loc;
|
||||
int radius;
|
||||
int dirtype;
|
||||
objecttype_t *ot;
|
||||
|
||||
loc = getoblocation(o);
|
||||
ot = findotn(f->text);
|
||||
if (ot && !hasob(loc->obpile, ot->id)) {
|
||||
if (f->val[1] == NA) {
|
||||
radius = 0;
|
||||
dirtype = NA;
|
||||
} else {
|
||||
radius = f->val[1];
|
||||
dirtype = f->val[2];
|
||||
}
|
||||
addobburst(loc, radius, dirtype, f->text, NULL, LOF_WALLSTOP);
|
||||
}
|
||||
}
|
||||
|
||||
// damage type converts this into something else?
|
||||
f = hasflagval(o->flags, F_DTCONVERT, damtype, NA, NA, NULL);
|
||||
if (f && !hasflag(o->flags, F_NODTCONVERT)) {
|
||||
|
@ -11348,6 +11661,7 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
|
|||
|
||||
adjustdamob(o, &howmuch, damtype);
|
||||
|
||||
|
||||
// effects which have to happen before damage is applied...
|
||||
// explodes?
|
||||
f = hasflag(o->flags, F_EXPLODEONDAM);
|
||||
|
@ -11445,6 +11759,11 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
|
|||
|
||||
// object dies!
|
||||
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
||||
|
||||
// if we didn't want this announced, don't say that it died either
|
||||
if (!wantannounce) {
|
||||
addflag(o->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
} else if (hpflag) {
|
||||
// object was just damaged
|
||||
getobconditionname(o, postdamname);
|
||||
|
@ -11967,7 +12286,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
|
|||
shatter(newob, youhit, dambuf, thrower);
|
||||
} else {
|
||||
// don't announce damage to the thrown object
|
||||
real_takedamage(newob, speed, DT_BASH, B_FALSE);
|
||||
real_takedamage(newob, speed-1, DT_BASH, B_FALSE);
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
|
@ -11977,24 +12296,42 @@ void timeeffectsob(object_t *o) {
|
|||
flag_t *f, *nextf;
|
||||
cell_t *location;
|
||||
lifeform_t *owner;
|
||||
char obname[BUFLEN];
|
||||
object_t *sg;
|
||||
char obname[BUFLEN],ownername[BUFLEN];
|
||||
|
||||
if (hasflag(o->flags, F_DEAD)) return;
|
||||
|
||||
getobname(o, obname, o->amt);
|
||||
|
||||
location = getoblocation(o);
|
||||
/*
|
||||
if (o->pile->where) {
|
||||
location = o->pile->where;
|
||||
} else {
|
||||
location = NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
if (o->pile->owner) {
|
||||
owner = o->pile->owner;
|
||||
getlfname(owner, ownername);
|
||||
} else {
|
||||
owner = NULL;
|
||||
}
|
||||
|
||||
// special case for trail flags
|
||||
f = hasflag(o->flags, F_TRAIL);
|
||||
if (f) {
|
||||
if (f->lifetime > 0) {
|
||||
f->lifetime--;
|
||||
if (f->lifetime <= 0) {
|
||||
// object dies.
|
||||
killob(o);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// expire flags
|
||||
timeeffectsflags(o->flags);
|
||||
|
||||
|
@ -12073,6 +12410,55 @@ void timeeffectsob(object_t *o) {
|
|||
}
|
||||
}
|
||||
|
||||
// sacred ground?
|
||||
sg = hasobwithflagval(location->obpile, F_REPELBLESSED, o->blessed, NA, NA, NULL);
|
||||
if (sg) {
|
||||
char sgname[BUFLEN];
|
||||
cell_t *newc;
|
||||
int canseeloc = B_FALSE;
|
||||
|
||||
if (haslos(player, location)) {
|
||||
getobname(sg, sgname, sg->amt);
|
||||
canseeloc = B_FALSE;
|
||||
msg("The %s pulses %s!", noprefix(sgname),
|
||||
(o->blessed == B_CURSED) ? "white" : "black");
|
||||
}
|
||||
|
||||
// object gets thrown away
|
||||
newc = getrandomadjcell(location, WE_NOTWALL, B_ALLOWEXPAND);
|
||||
if (newc) {
|
||||
//flag_t *inv;
|
||||
|
||||
// make sure the object doesn't take damage
|
||||
//inv = addflag(o->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL);
|
||||
|
||||
fireat(NULL, o, o->amt, newc, 1, NULL);
|
||||
if (canseeloc) {
|
||||
// player now knows that this is blessed
|
||||
o->blessknown = B_TRUE;
|
||||
}
|
||||
//if (needredraw) drawlevelfor(player);
|
||||
// update location
|
||||
|
||||
//if (inv) killflag(inv);
|
||||
|
||||
location = newc;
|
||||
} else {
|
||||
// object can't go anywhere - it disintegrates.
|
||||
if (owner && cansee(player, owner)) {
|
||||
msg("%s%s vanish%s in a surge of %s power!", ownername, getpossessive(ownername),
|
||||
obname, (o->amt == 1) ? "es" : "",
|
||||
(o->blessed = B_CURSED) ? "holy" : "evil");
|
||||
} else if (haslos(player, location)) {
|
||||
msg("%s vanish%s in a surge of %s power!", obname, (o->amt == 1) ? "es" : "",
|
||||
(o->blessed = B_CURSED) ? "holy" : "evil");
|
||||
}
|
||||
removeob(o, o->amt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (location) {
|
||||
// does object's material change cell type?
|
||||
if (o->material->id == MT_FIRE) {
|
||||
|
@ -12331,7 +12717,9 @@ void timeeffectsob(object_t *o) {
|
|||
object_t *splash;
|
||||
ourcell = getoblocation(o);
|
||||
// drip
|
||||
splash = addob(ourcell->obpile, "splash of water");
|
||||
if (!hasobwithflag(ourcell->obpile, F_DEEPWATER)) {
|
||||
splash = addob(ourcell->obpile, "splash of water");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ void applyobmod(object_t *o, obmod_t *om);
|
|||
int blessob(object_t *o);
|
||||
void brightflash(cell_t *centre, int range, lifeform_t *immunelf);
|
||||
int canbepoisoned(enum OBTYPE oid);
|
||||
int canseeob(lifeform_t *lf, object_t *o);
|
||||
object_t *canstackob(obpile_t *op, object_t *match);
|
||||
object_t *canstacknewot(obpile_t *op, objecttype_t *match);
|
||||
int changemat(object_t *o, enum MATERIAL mat);
|
||||
|
@ -32,10 +33,10 @@ objecttype_t *checkobnames(char *haystack, char *needle);
|
|||
void colourmatchob(object_t *o, lifeform_t *lf);
|
||||
void copyobprops(object_t *dst, object_t *src);
|
||||
int countnames(char **list);
|
||||
int countobs(obpile_t *op);
|
||||
int countnoncosmeticobs(obpile_t *op);
|
||||
int countobs(obpile_t *op, int onlyifknown);
|
||||
int countnoncosmeticobs(obpile_t *op, int onlyifknown);
|
||||
int curseob(object_t *o);
|
||||
void damageallobs(object_t *exception, obpile_t *op, int howmuch, int damtype);
|
||||
void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype);
|
||||
void dumprandomobs(int amt);
|
||||
void explodeob(object_t *o, flag_t *f, int bigness);
|
||||
void extinguish(object_t *o);
|
||||
|
@ -80,6 +81,7 @@ char getnextletter(obpile_t *op, char *wantletter);
|
|||
int getnumshards(object_t *o);
|
||||
int getnutritionbase(object_t *o);
|
||||
int getnutrition(object_t *o);
|
||||
enum DEPTH getobdepth(object_t *o, lifeform_t *lf);
|
||||
char *getobdesc(object_t *o, char *buf);
|
||||
char *getobequipinfo(object_t *o, char *buf);
|
||||
char *getobextrainfo(object_t *o, char *buf);
|
||||
|
@ -104,6 +106,7 @@ char *getschoolnameshort(enum SPELLSCHOOL sch);
|
|||
int getshatterdam(object_t *o);
|
||||
enum SKILLLEVEL gettechlevel(object_t *o);
|
||||
int getthrowdam(object_t *o);
|
||||
char *gettopobname(cell_t *c, char *retbuf);
|
||||
enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded);
|
||||
int hasedibleob(obpile_t *op);
|
||||
object_t *hasknownob(obpile_t *op, enum OBTYPE oid);
|
||||
|
|
256
spell.c
256
spell.c
|
@ -107,7 +107,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
if (isplayer(user)) {
|
||||
sprintf(buf, "Charge who (max range %d)?",range);
|
||||
// TODO: ask for direction
|
||||
targcell = askcoords(buf, TT_MONSTER, user, range);
|
||||
targcell = askcoords(buf, TT_MONSTER, user, range, LOF_NEED, B_TRUE);
|
||||
if (!targcell) {
|
||||
msg("Cancelled.");
|
||||
return TRUE;
|
||||
|
@ -254,7 +254,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
} else {
|
||||
sprintf(buf, "Darkwalk to where?");
|
||||
}
|
||||
targcell = askcoords(buf, TT_NONE, user, range);
|
||||
targcell = askcoords(buf, TT_NONE, user, range, LOF_DONTNEED, B_FALSE);
|
||||
} else {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -538,7 +538,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
sprintf(buf, "Jump where (max distance 2)?");
|
||||
while (!targcell) {
|
||||
// ask where
|
||||
targcell = askcoords(buf, TT_NONE, user, 2);
|
||||
targcell = askcoords(buf, TT_NONE, user, 2, LOF_DONTNEED, B_TRUE);
|
||||
if (!targcell) {
|
||||
return B_TRUE;
|
||||
} else if (getcelldist(user->cell, targcell) > 2) {
|
||||
|
@ -801,7 +801,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
if (isplayer(user)) {
|
||||
sprintf(buf, "Swoop who (max range %d)?",srange);
|
||||
// TODO: ask for direction
|
||||
targcell = askcoords(buf, TT_MONSTER, user, srange);
|
||||
targcell = askcoords(buf, TT_MONSTER, user, srange, LOF_NEED, B_TRUE);
|
||||
if (!targcell) {
|
||||
msg("Cancelled.");
|
||||
return TRUE;
|
||||
|
@ -935,13 +935,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
return B_FALSE;
|
||||
} else if (abilid == OT_A_DEBUG) {
|
||||
cell_t *where;
|
||||
where = askcoords("Debug who?", TT_MONSTER, user, UNLIMITED);
|
||||
where = askcoords("Debug who?", TT_MONSTER, user, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (where && where->lf) {
|
||||
debug(where->lf);
|
||||
}
|
||||
} else if (abilid == OT_A_EMPLOY) {
|
||||
cell_t *where;
|
||||
where = askcoords("Assign job to who?", TT_MONSTER, user, UNLIMITED);
|
||||
where = askcoords("Assign job to who?", TT_MONSTER, user, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (where && where->lf) {
|
||||
char question[BUFLEN];
|
||||
char lfname[BUFLEN];
|
||||
|
@ -965,7 +965,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
}
|
||||
} else if (abilid == OT_A_ENHANCE) {
|
||||
cell_t *where;
|
||||
where = askcoords("Enhance stats of who?", TT_MONSTER, user, UNLIMITED);
|
||||
where = askcoords("Enhance stats of who?", TT_MONSTER, user, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (where && where->lf) {
|
||||
char ch;
|
||||
enum ATTRIB att;
|
||||
|
@ -1483,7 +1483,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else if (spellid == OT_S_BLINDNESS) {
|
||||
int failed = B_FALSE;
|
||||
// ask for target
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if (isblind(target)) {
|
||||
fizzle(caster);
|
||||
|
@ -1547,6 +1548,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// create a line of fire towards the target cell
|
||||
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, targcell->x, targcell->y, retcell, &nretcell);
|
||||
|
||||
redrawpause();
|
||||
// don't set caster's cell on fire!
|
||||
for (i = 1; i < nretcell; i++) {
|
||||
cell_t *c;
|
||||
|
@ -1558,24 +1560,31 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
if (o) {
|
||||
setobcreatedby(o, caster);
|
||||
if (c->lf) {
|
||||
char buf[BUFLEN];
|
||||
char damstring[BUFLEN];
|
||||
char realcname[BUFLEN];
|
||||
getlfname(c->lf,buf);
|
||||
if (!isimmuneto(c->lf->flags, DT_FIRE)) {
|
||||
msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s");
|
||||
}
|
||||
real_getlfname(caster, realcname, B_FALSE);
|
||||
sprintf(damstring, "%s%s wave of fire", realcname, getpossessive(realcname));
|
||||
losehp(c->lf, rolldie(2,10), DT_FIRE, caster, damstring);
|
||||
}
|
||||
}
|
||||
}
|
||||
redrawresume();
|
||||
// now burn things
|
||||
for (i = 1; i < nretcell; i++) {
|
||||
cell_t *c;
|
||||
c = retcell[i];
|
||||
|
||||
if (c->lf) {
|
||||
char buf[BUFLEN];
|
||||
char damstring[BUFLEN];
|
||||
char realcname[BUFLEN];
|
||||
getlfname(c->lf,buf);
|
||||
if (!isimmuneto(c->lf->flags, DT_FIRE)) {
|
||||
msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s");
|
||||
}
|
||||
real_getlfname(caster, realcname, B_FALSE);
|
||||
sprintf(damstring, "%s%s wave of fire", realcname, getpossessive(realcname));
|
||||
losehp(c->lf, rolldie(2,10), DT_FIRE, caster, damstring);
|
||||
}
|
||||
}
|
||||
|
||||
if (cansee(player, caster)) {
|
||||
needredraw = B_TRUE;
|
||||
}
|
||||
|
||||
} else if (spellid == OT_S_CALLLIGHTNING) {
|
||||
int failed = B_FALSE;
|
||||
// ask for a target cell
|
||||
|
@ -1617,13 +1626,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
if (targcell->obpile->first) {
|
||||
// select object from cell...
|
||||
if (countobs(targcell->obpile) == 1) {
|
||||
targob = targcell->obpile->first;
|
||||
} else {
|
||||
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
|
||||
if (!targob) {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
|
||||
if (!targob) {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
failed = B_TRUE;
|
||||
|
@ -2045,7 +2050,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
|
||||
// add the monster
|
||||
newlf = addmonster(targcell, r->id, randomjobsok, 1, B_FALSE);
|
||||
newlf = addmonster(targcell, r->id, randomjobsok, 1, B_FALSE, NULL);
|
||||
if (newlf) {
|
||||
// assign job if required
|
||||
if (forcejob) {
|
||||
|
@ -2152,9 +2157,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else if (spellid == OT_S_DIG) {
|
||||
int numseen = 0;
|
||||
int maxrange;
|
||||
cell_t *retcell[MAXRETCELLS];
|
||||
int nretcell,i;
|
||||
int ndigs;
|
||||
|
||||
// don't need line of fire OR sight!
|
||||
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE;
|
||||
|
@ -2163,25 +2168,47 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y,
|
||||
targcell->x, targcell->y, retcell, &nretcell);
|
||||
|
||||
maxrange = power;
|
||||
ndigs = 0;
|
||||
|
||||
// get rid of rock in the cells...
|
||||
for (i = 0; i < nretcell && (i <= maxrange); i++) {
|
||||
for (i = 0; i < nretcell && (ndigs <= power) ; i++) {
|
||||
int seenthiscell = B_FALSE;
|
||||
if (haslos(player, retcell[i])) seenthiscell = B_TRUE;
|
||||
if (retcell[i]->type->solid) {
|
||||
setcelltype(retcell[i], getemptycelltype(retcell[i]->map->habitat));
|
||||
if (haslos(player, retcell[i])) numseen++;
|
||||
if (seenthiscell) {
|
||||
ndigs++;
|
||||
numseen++;
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
object_t *o;
|
||||
for (o = retcell[i]->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
char obname[BUFLEN];
|
||||
// destroy this object then stop.
|
||||
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
||||
if (seenthiscell) {
|
||||
if (!hasflag(o->flags, F_OBDIETEXT)) {
|
||||
getobname(o, obname, o->amt);
|
||||
msg("%s crumble%s to dust!", obname, (o->amt == 1) ? "s" : "");
|
||||
}
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
ndigs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// announce if any seen
|
||||
// announce destruction of any walls seen
|
||||
if (numseen) {
|
||||
msg("The wall%s crumble%s to dust!",
|
||||
(numseen == 1) ? "" : "s",
|
||||
(numseen == 1) ? "s" : ""
|
||||
);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else {
|
||||
} else if (ndigs == 0) {
|
||||
if (isplayer(caster)) nothinghappens();
|
||||
}
|
||||
} else if (spellid == OT_S_DETECTLIFE) {
|
||||
|
@ -2313,15 +2340,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
object_t *o, *nexto;
|
||||
int donesomething = B_FALSE;
|
||||
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER|TT_OBJECT, spellid, power)) return B_TRUE;
|
||||
if (!targcell) {
|
||||
if (isplayer(caster)) {
|
||||
sprintf(buf, "Where will you target your dispersal?");
|
||||
targcell = askcoords(buf, TT_MONSTER|TT_OBJECT, caster, UNLIMITED);
|
||||
if (!targcell) { // no cell
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
} else {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -2494,7 +2515,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else if (spellid == OT_S_FEEBLEMIND) {
|
||||
// ask for target
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if ((getattr(target, A_IQ) <= 3) || skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
|
||||
if (cansee(player, target)) {
|
||||
|
@ -2588,6 +2610,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
anim(caster->cell, targcell, '^', C_RED);
|
||||
|
||||
redrawpause();
|
||||
// add fires as follows (3 = medium, 2 = medium, 1 = smell)
|
||||
//
|
||||
// 1
|
||||
|
@ -2643,6 +2666,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
}
|
||||
|
||||
redrawresume();
|
||||
|
||||
} else {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
|
@ -3529,21 +3554,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_MINDSCAN) {
|
||||
cell_t *where;
|
||||
int failed = B_FALSE;
|
||||
if (isplayer(caster)) {
|
||||
// ask for a target cell
|
||||
sprintf(buf, "Whose mind will you scan?");
|
||||
where = askcoords(buf, TT_MONSTER, caster, UNLIMITED);
|
||||
if (where && haslos(caster, where) && haslf(where)) {
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
|
||||
if (targcell && haslos(caster, targcell) && haslf(targcell)) {
|
||||
char targname[BUFLEN];
|
||||
lifeform_t *oldplayer;
|
||||
// temporarily change player pointer...
|
||||
oldplayer = player;
|
||||
player = where->lf;
|
||||
player = targcell->lf;
|
||||
|
||||
//
|
||||
getlfname(where->lf, targname);
|
||||
getlfname(targcell->lf, targname);
|
||||
sprintf(buf, "Mindscanning %s, ESC to quit.", targname);
|
||||
doexplain(buf);
|
||||
|
||||
|
@ -3585,7 +3608,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else if (spellid == OT_S_PARALYZE) {
|
||||
int howlong;
|
||||
int saved = B_FALSE;
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if (lfhasflag(target, F_PARALYZED)) {
|
||||
fizzle(caster);
|
||||
|
@ -3619,7 +3643,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else if (spellid == OT_S_PAIN) {
|
||||
int failed = B_FALSE;
|
||||
// ask for target
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if (lfhasflag(target, F_PAIN)) {
|
||||
fizzle(caster);
|
||||
|
@ -3654,7 +3679,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_PETRIFY) {
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
// some thigns can't be stoned
|
||||
if (!lfcanbestoned(target)) {
|
||||
|
@ -3933,11 +3959,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else if (targcell->obpile->first) { // no lifeform there
|
||||
targob = NULL;
|
||||
// select object from cell...
|
||||
if (countobs(targcell->obpile) == 1) {
|
||||
targob = targcell->obpile->first;
|
||||
} else {
|
||||
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
|
||||
}
|
||||
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
|
||||
if (targob) {
|
||||
if (ismetal(targob->material->id)) {
|
||||
|
||||
|
@ -4122,23 +4144,37 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS);
|
||||
knockback(target, dir, 2, caster, 0);
|
||||
} else {
|
||||
o = hasobwithflag(targcell->obpile, F_DOOR);
|
||||
if (o) {
|
||||
int dooropen;
|
||||
isdoor(o, &dooropen); // just check whether it's open, we know it's a door
|
||||
if (dooropen) {
|
||||
fizzle(caster);
|
||||
} else {
|
||||
if (haslos(player, targcell)) {
|
||||
getobname(o, buf, o->amt);
|
||||
msg("%s %s!",isplayer(caster) ? "You blast" : "Something blasts", buf);
|
||||
int donesomething = B_FALSE;
|
||||
object_t *nexto;
|
||||
for (o = targcell->obpile->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
int gotit = B_FALSE;
|
||||
int dooropen;
|
||||
if (isdoor(o, &dooropen)) {
|
||||
if (!dooropen) {
|
||||
gotit = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
gotit = B_TRUE;
|
||||
}
|
||||
|
||||
if (gotit) {
|
||||
if (haslos(player, targcell)) {
|
||||
getobname(o, buf, o->amt);
|
||||
msg("%s %s!",isplayer(caster) ? "You blast" : "Something blasts", buf);
|
||||
}
|
||||
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
takedamage(o, 999, DT_DIRECT);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!donesomething) {
|
||||
fizzle(caster);
|
||||
}
|
||||
|
||||
}
|
||||
} else if (spellid == OT_S_LEVITATION) {
|
||||
flag_t *f;
|
||||
|
@ -4190,7 +4226,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
}
|
||||
// undead will flee from light
|
||||
if (lfhasflag(l, F_UNDEAD)) {
|
||||
if (isundead(l)) {
|
||||
// runs away from caster
|
||||
addtempflag(l->flags, F_FLEEFROM, caster->id, NA, NA, NULL, 20);
|
||||
}
|
||||
|
@ -4254,7 +4290,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
for (i = 0; i < caster->nlos; i++) {
|
||||
target = caster->los[i]->lf;
|
||||
if (target) {
|
||||
if (target && areenemies(caster, target)) {
|
||||
poss[nposs++] = target;
|
||||
}
|
||||
}
|
||||
|
@ -4422,18 +4458,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else if (spellid == OT_S_GRAVBOOST) {
|
||||
// ask for target
|
||||
if (!target) {
|
||||
if (isplayer(caster)) {
|
||||
cell_t *where;
|
||||
sprintf(buf, "Where will you target your spell?");
|
||||
where = askcoords(buf, TT_MONSTER, caster, UNLIMITED);
|
||||
if (where && haslos(caster, where) && haslf(where)) {
|
||||
target = haslf(where);
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
if (target) {
|
||||
int howlong = 15;
|
||||
|
||||
|
@ -4615,7 +4640,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
int donesomething = B_FALSE;
|
||||
|
||||
// stop targetting anybody
|
||||
if (killflagsofid(target->flags, F_TARGET)) {
|
||||
if (killflagsofid(target->flags, F_TARGETLF)) {
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
if (killflagsofid(target->flags, F_TARGETCELL)) {
|
||||
|
@ -4649,16 +4674,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else if (spellid == OT_S_POLYMORPH) {
|
||||
race_t *r = NULL;
|
||||
|
||||
// ask for target if required
|
||||
if (!target && isplayer(caster)) {
|
||||
cell_t *where;
|
||||
where = askcoords("Who will you polymorph?", TT_MONSTER, caster, UNLIMITED);
|
||||
if (haslos(caster, where)) {
|
||||
target = where->lf;
|
||||
} else {
|
||||
target = NULL;
|
||||
}
|
||||
}
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if (!target) {
|
||||
fizzle(caster);
|
||||
|
@ -4968,7 +4985,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
f->obfrom = spellid;
|
||||
} else if (spellid == OT_S_SLEEP) {
|
||||
int howlong;
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if (lfhasflag(target, F_ASLEEP) || !cansleep(target)) {
|
||||
fizzle(caster);
|
||||
|
@ -5023,7 +5041,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else if (spellid == OT_S_SLOW) {
|
||||
int howlong = 15;
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
|
||||
if (isplayer(target)) {
|
||||
|
@ -5064,7 +5083,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
badoid[0] = OT_MUDPOOL;
|
||||
badoid[1] = OT_NONE;
|
||||
for (i = 0; i < powerleft; i++) {
|
||||
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, badoid);
|
||||
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, badoid);
|
||||
if (c) {
|
||||
o = addob(c->obpile, "pool of mud");
|
||||
if (o) {
|
||||
|
@ -5296,7 +5315,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
sprintf(buf, "Where will you teleport to?");
|
||||
while (!c) {
|
||||
int ch;
|
||||
c = askcoords(buf, TT_NONE, caster, UNLIMITED);
|
||||
c = askcoords(buf, TT_NONE, caster, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (!c->known) {
|
||||
// confirm
|
||||
ch = askchar("Are you sure to want to teleport into the unknown?", "yn", "n", B_TRUE);
|
||||
|
@ -5452,17 +5471,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (!targob) {
|
||||
// ask for a target cell (to take objects from)
|
||||
sprintf(buf, "Where will you focus your telekinetic power?");
|
||||
where = askcoords(buf, TT_OBJECT | TT_DOOR, caster, UNLIMITED);
|
||||
where = askcoords(buf, TT_OBJECT | TT_DOOR, caster, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
if (where && haslos(caster, where)) {
|
||||
if (where->obpile->first) {
|
||||
// select object from cell...
|
||||
if (countobs(where->obpile) == 1) {
|
||||
targob = where->obpile->first;
|
||||
} else {
|
||||
targob = askobject(where->obpile, "Target which object", NULL, AO_NONE);
|
||||
if (!targob) {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
targob = askobject(where->obpile, "Target which object", NULL, AO_NONE);
|
||||
if (!targob) {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
// TODO: check object weight!
|
||||
} else {
|
||||
|
@ -5489,7 +5504,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
char obname[BUFLEN];
|
||||
getobname(targob, obname, 1);
|
||||
sprintf(buf, "Where will you move %s to?", obname);
|
||||
targcell = askcoords(buf, TT_MONSTER | TT_PLAYER, caster, UNLIMITED);
|
||||
// TODO: start trail from the object
|
||||
targcell = askcoords(buf, TT_MONSTER | TT_PLAYER, caster, UNLIMITED, LOF_DONTNEED, B_FALSE);
|
||||
}
|
||||
|
||||
// not liftable?
|
||||
|
@ -5554,7 +5570,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
for (i = 0; i < caster->nlos; i++) {
|
||||
targcell = caster->los[i];
|
||||
target = targcell->lf;
|
||||
if (target && hasflag(target->flags, F_UNDEAD)) {
|
||||
if (target && isundead(target)) {
|
||||
int howlong = 10;
|
||||
int worked = B_TRUE;
|
||||
// TODO: does it work? depends on caster level & intelligence & power
|
||||
|
@ -5879,7 +5895,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else if (spellid == OT_S_WEAKEN) {
|
||||
// ask for target
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
|
||||
if (cansee(player, target)) {
|
||||
|
@ -5969,7 +5986,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
// ask for target
|
||||
if (spellid == OT_S_GIFT) {
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
} else {
|
||||
target = caster;
|
||||
}
|
||||
|
@ -6406,6 +6424,9 @@ int getspellrange(enum OBTYPE spellid, int power) {
|
|||
case OT_S_CALLWIND:
|
||||
range = (power*2);
|
||||
break;
|
||||
case OT_S_DIG:
|
||||
range = power;
|
||||
break;
|
||||
case OT_S_LIGHTNINGBOLT:
|
||||
range = (power*3);
|
||||
break;
|
||||
|
@ -6612,7 +6633,7 @@ int summonlfs(lifeform_t *caster, enum RACECLASS wantrc, enum LFSIZE wantsize, i
|
|||
r = findrace(poss[rnd(0,nposs-1)]);
|
||||
if (r) {
|
||||
// add it!
|
||||
newlf = addmonster(c, r->id, B_FALSE, 1, B_FALSE);
|
||||
newlf = addmonster(c, r->id, B_FALSE, 1, B_FALSE, NULL);
|
||||
// not worth any xp
|
||||
killflagsofid(newlf->flags, F_XPVAL);
|
||||
addflag(newlf->flags, F_XPVAL, 0, NA, NA, NULL);
|
||||
|
@ -6644,13 +6665,12 @@ lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **targe
|
|||
maxrange = UNLIMITED;
|
||||
}
|
||||
|
||||
|
||||
// ask for a target lifeform
|
||||
if (isplayer(user)) {
|
||||
cell_t *where;
|
||||
char buf[BUFLEN];
|
||||
sprintf(buf, "Where will you target your %s?",ot->name);
|
||||
where = askcoords(buf, TT_MONSTER, user, maxrange);
|
||||
where = askcoords(buf, TT_MONSTER, user, maxrange, LOF_DONTNEED, B_FALSE);
|
||||
if (where) {
|
||||
if (!haslf(where)) {
|
||||
msg("There is nobody there!");
|
||||
|
@ -6781,7 +6801,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e
|
|||
} else {
|
||||
sprintf(buf, "Where will you target your spell [max range %d]?",maxrange);
|
||||
}
|
||||
where = askcoords(buf, targtype, caster, maxrange);
|
||||
where = askcoords(buf, targtype, caster, maxrange, needlof, needlof ? B_TRUE : B_FALSE);
|
||||
if (!where) {
|
||||
int ch;
|
||||
ch = askchar("Abandon your spell?","yn","n", B_TRUE);
|
||||
|
@ -6862,6 +6882,7 @@ int getmpcost(lifeform_t *lf, enum OBTYPE oid) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **target) {
|
||||
if (!caster) {
|
||||
return *target;
|
||||
|
@ -6888,3 +6909,4 @@ lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **target) {
|
|||
}
|
||||
return *target;
|
||||
}
|
||||
*/
|
||||
|
|
2
spell.h
2
spell.h
|
@ -28,7 +28,7 @@ void stopallspells(lifeform_t *lf);
|
|||
int summonlfs(lifeform_t *caster, enum RACECLASS wantrc, enum LFSIZE wantsize, int howmany, int lifetime);
|
||||
lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target);
|
||||
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power);
|
||||
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
|
||||
//lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue