* [+] backstab

- [+] monsters start asleep and make spot checks ?
    - [+] make them start asleep 
    - [+] then make this random
    - [+] sound will wake them (ie. "makenoise")
    - [+] when you move, make SC_STEALTH check. if you fail, you make
          noise!
- [+] must pass LISTEN check  OR have los to hear something.
- [+] "the blowfly falls asleep" "the blowfly appears" when summoned.
    - [+] don't show 'falls asleep' while being created!
* [+] don't start summoned mosnters asleep!
* [+] clean up bresnham functions
- [+] hearing - instead of just using distance, use distance modiied by
      # of walls!
    - [+] getcelldistsound() - each wall counts as an extra cell!
- [+] add WALK/FLY noises to all monsters!
- [+] don't show 'you hear xxx' when resting.
- [+] extra damage for weapon skill (up to 50% extra)
- [+] make broken glass crushable
- [+] only interrupt rest for non-peaceful, non-friendly monsters
- [+] save to fight off poison
* [+] beholder is never using its BITE attack
* [+] need a price for manuals!!
* [+] change"dobresnham" to populate an array of cells
- [+] make ai cast animate metal (if they ahve a second weapon)
- [+] implement getallegiance() to clean up isfriendly / ispeaceful etc
- [+] bug - f_else f_ifpct etc not working in startobs
* [+] OT_S_CHARM
- [+] update askcoords to show "weilding x AND Y"
- [+] stop enemies from throwing firearm ammo somehow
* [+] implement 
- [+] pacify spell
- [+] make spellbooks less common
- [+] detectmetal not wokring. fixed.
- [+] detectobjects spell
- [+] cleanup using flagcausesredraw()
- [+] increase odds of weapons in rooms, and max ob count in rooms
This commit is contained in:
Rob Pearce 2011-03-24 05:09:31 +00:00
parent 4edc66af47
commit 290d91677e
24 changed files with 1782 additions and 1048 deletions

160
ai.c
View File

@ -165,6 +165,14 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi
// cast spell at the victim
if (spelllf) *spelllf = victim;
if (spellcell) *spellcell = victim->cell;
} else if (spelltype->id == OT_S_CHARM) {
lifeform_t *l;
l = getnearbypeaceful(lf);
if (l) {
if (spelllf) *spelllf = l;
if (spellcell) *spellcell = l->cell;
if (spellob) *spellob = NULL;
}
}
}
}
@ -330,9 +338,17 @@ void aimove(lifeform_t *lf) {
return;
}
if (goingtomove && (getcelldist(lf->cell, target->cell) == 1)) {
}
// 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);
if (spell != OT_NONE) {
if ( (spell != OT_NONE) && // found a valid spell/ability to use
((getcelldist(lf->cell, target->cell) != 1) || (rnd(1,3) == 1))
) {
int spellfailed = B_FALSE;
lifeform_t *spelllf = NULL;
cell_t *spellcell = NULL;
@ -400,7 +416,7 @@ void aimove(lifeform_t *lf) {
}
// if not adjacent, check for guns, wands, throwing
if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell)) {
if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell, B_FALSE, NULL)) {
// can we attack by firing something?
gun = getfirearm(lf);
if (goingtomove && gun && getammo(lf)) {
@ -422,8 +438,8 @@ void aimove(lifeform_t *lf) {
// can we attack by throwing something?
if (goingtomove) {
// TODO: or firing! check if we have a firearm first.
o = getbestmissile(lf);
//
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!
@ -556,63 +572,63 @@ void aimove(lifeform_t *lf) {
// not attacking anyone in particular
if (db) dblog(".oO { i do not have a target or can't move towards it. }");
// are we hostile? if so, look for a target
f = hasflag(lf->flags, F_HOSTILE);
if (f) {
switch (getallegiance(lf)) {
int i;
if (db) dblog(".oO { i am hostile. looking for a target. }");
// look around for a target
for (i = 0; i < lf->nlos; i++) {
cell_t *c;
c = lf->los[i];
if (c->lf && cansee(lf, c->lf)) {
if (isplayer(c->lf)) { // TODO: change to if isenemy ?
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
// target them!
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
// tell the player
if (cansee(player, lf)) {
makenoise(lf, N_GETANGRY);
}
// then move towards them...
if (db) dblog(".oO { moving towards my new target }");
if (curwep) {
if (!movetowards(lf, c)) return;
} else {
if (db) dblog(".oO { won't move towards target - i have no weapon. }");
}
break;
}
}
}
}
// are we friendly? if so, look for a target
f = hasflag(lf->flags, F_FRIENDLY);
if (f) {
int x,y;
if (db) dblog(".oO { i am friendly to the player. looking for a target. }");
// look around for a target
// TODO: use our vis rang einstead of 10!
for (y = lf->cell->y - 10; y <= lf->cell->y + 10; y++) {
for (x = lf->cell->x - 10; x <= lf->cell->x + 10; x++) {
c = getcellat(lf->cell->map, x, y);
// cell exists and we can see it?
if (c && c->lf && (c->lf != lf) && cansee(lf, c->lf)) {
// player there?
if (!isplayer(c->lf)) {
case AL_HOSTILE:
if (db) dblog(".oO { i am hostile. looking for a target. }");
// look around for a target
for (i = 0; i < lf->nlos; i++) {
cell_t *c;
c = lf->los[i];
if (c->lf && cansee(lf, c->lf)) {
if (isplayer(c->lf)) { // TODO: change to if isenemy ?
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
// target them!
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
// tell the player
if (cansee(player, lf)) {
makenoise(lf, N_GETANGRY);
}
// then move towards them...
if (db) dblog(".oO { moving towards my new target }");
if (!movetowards(lf, c)) return;
if (curwep) {
if (!movetowards(lf, c)) return;
} else {
if (db) dblog(".oO { won't move towards target - i have no weapon. }");
}
break;
}
}
}
}
break;
case AL_FRIENDLY: // are we friendly? if so, look for a target
if (db) dblog(".oO { i am friendly to the player. looking for a target. }");
// look around for a target
// TODO: use our vis rang einstead of 10!
for (y = lf->cell->y - 10; y <= lf->cell->y + 10; y++) {
for (x = lf->cell->x - 10; x <= lf->cell->x + 10; x++) {
c = getcellat(lf->cell->map, x, y);
// cell exists and we can see it?
if (c && c->lf && (c->lf != lf) && cansee(lf, c->lf)) {
// player there?
if (!isplayer(c->lf)) {
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
// target them!
addtempflag(lf->flags, F_TARGET, c->lf->id, c->x, c->y, NULL, AI_FOLLOWTIME);
// then move towards them...
if (db) dblog(".oO { moving towards my new target }");
if (!movetowards(lf, c)) return;
}
}
}
}
break;
default:
break;
}
@ -684,6 +700,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
int db = B_FALSE;
int ok = B_FALSE;
int specialcase = B_FALSE;
int specificcheckok = B_FALSE;
if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE;
@ -801,6 +818,10 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if (ok) break;
}
}
} else if (ot->id == OT_S_CHARM) {
if (getnearbypeaceful(lf)) {
ok = B_TRUE;
}
} else {
dblog(".oO { cant cast %s - specialcase conditions not yet coded }", ot ? ot->name : "?unkownspell?");
return B_FALSE;
@ -812,45 +833,58 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
return B_FALSE;
}
// now check whether it meets spellcasting conditions
// now check whether it meets specific spell conditions
specificcheckok = B_TRUE;
if (ot->id == OT_S_ANIMATEMETAL) {
object_t *wep;
wep = getweapon(lf);
if (!wep || !ismetal(wep->material->id)) {
specificcheckok = B_TRUE;
}
}
if ((ot->id == OT_S_BLINDNESS) && isblind(victim)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_HASTE) && lfhasflag(lf, F_FASTACT)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_INVISIBILITY) && lfhasflag(victim, F_INVISIBLE)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_PAIN) && lfhasflag(victim, F_PAIN)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_HEALING) && (lf->hp >= lf->maxhp)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_HEALINGMIN) && (lf->hp >= lf->maxhp)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_PARALYZE) && lfhasflag(victim, F_PARALYZED)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_SLEEP) && lfhasflag(victim, F_ASLEEP)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_SLOW) && lfhasflag(victim, F_SLOWACT)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) {
return B_FALSE;
specificcheckok = B_FALSE;
}
if ((ot->id == OT_S_WEAKEN)) {
flag_t *lff;
for (lff = lf->flags->first; lff ; lff = lff->next) {
if ((lff->id == F_ATTRMOD) && (lff->val[0] == A_STR) && (lff->obfrom == OT_S_WEAKEN)) {
return B_FALSE;
specificcheckok = B_FALSE;
break;
}
}
}
if (!specificcheckok) {
dblog(".oO { cant cast %s - specific spell check failed }", ot ? ot->name : "?unkownspell?");
return B_FALSE;
}
return B_TRUE;
}

341
attack.c
View File

@ -84,6 +84,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
char attackername[BUFLEN];
char victimname[BUFLEN];
int fatal = B_FALSE;
int firstisbackstab = B_FALSE;
flag_t *unarmedflag = NULL;
object_t *wep;
obpile_t *op = NULL;
@ -109,8 +110,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
return B_TRUE;
}
// get names
getlfname(lf, attackername);
@ -124,6 +123,25 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
getlfname(victim, victimname);
}
if (isplayer(lf) && !areenemies(lf,victim)) {
char ch;
switch (getallegiance(victim)) {
case AL_PEACEFUL:
sprintf(buf, "Really attack the peaceful %s?",noprefix(victimname));
break;
case AL_FRIENDLY:
sprintf(buf, "Really attack the allied %s?",noprefix(victimname));
break;
default:
sprintf(buf, "Really attack the allied %s?",noprefix(victimname));
break;
}
ch = askchar(buf, "yn","n", B_TRUE);
if (ch == 'n') {
// cancel.
return B_TRUE;
}
}
if (aidb) dblog(".oO { trying to attack %s }", victimname);
@ -192,43 +210,65 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
// ie. if critical is 0, do this once.
// if critical is 1, do this twice.
// etc.
dam[ndam] = 0;
dam[0] = 0;
for (n = 0; n < critical+1; n++) {
if (unarmedflag) {
// this mosnter's unarmed attack will
// override normal damage calculation
dam[ndam] += getdamrollfromflag(unarmedflag);
dam[0] += getdamrollfromflag(unarmedflag);
} else {
dam[ndam] += getdamroll(wep, victim);
dam[0] += getdamroll(wep, victim);
}
}
if (aidb) dblog("rolled dam[%d] = %d",ndam,dam[ndam]);
if (aidb) dblog("rolled dam[%d] = %d",0,dam[0]);
if (dam[ndam] < 0) {
if (dam[0] < 0) {
willheal = B_TRUE;
}
// damtype?
damtype[0] = getdamtype(wep);
if (!willheal) {
enum SKILLLEVEL slev;
skill_t *sk;
// blessed vs undead
if (isblessed(wep) && lfhasflagval(victim, F_DTVULN, DT_HOLY, NA, NA, NULL)) {
// a little extra damage
dam[0] = (int) ( (float)dam[0] * 1.25 );
}
// modify for strength
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
dam[ndam] = (int)((float)dam[ndam] * getstrdammod(lf));
dam[0] = (int)((float)dam[0] * getstrdammod(lf));
}
// backstab?
if ((damtype[0] == DT_PIERCE) && // using a stabbing weapon
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
) {
addflag(victim->flags, F_STABBEDBY, lf->id, NA, NA, NULL);
dam[0] *= (getskill(lf, SK_BACKSTAB)*2);
firstisbackstab = B_TRUE;
}
// extra damage for being skilled?
sk = getobskill(wep);
if (sk) {
slev = getskill(lf, sk->id);
if (slev > 1) {
float pctextra;
pctextra = ((slev - 1) * 10);
dam[0] += pctof(pctextra, dam[0]);
}
}
}
// damtype?
damtype[ndam] = getdamtype(wep);
if (aidb) dblog(".oO { dealing %d %s damage }", dam[ndam], getdamname(damtype[ndam]));
ndam++;
if (aidb) dblog(".oO { dealing %d %s damage }", dam[0], getdamname(damtype[0]));
// blessed vs undead etc?
ndam = 1;
// determine extra damage for flaming etc.
if (!willheal) {
if (isblessed(wep) && lfhasflagval(victim, F_DTVULN, DT_HOLY, NA, NA, NULL)) {
// a little extra damage
dam[ndam] = (int) ( (float)dam[ndam] * 1.25 );
}
// determine extra damage
getextradam(wep, &dam[0], &damtype[0], &ndam);
}
} else {
@ -243,9 +283,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
for (i = 0; i < ndam; i++) {
int reduceamt;
int backstab = B_FALSE;
if (firstisbackstab && (i == 0)) backstab = B_TRUE;
dblog("initial dam[%d] = %d",i,dam[i]);
if (lfhasflag(lf, F_HEAVYBLOW)) {
if (lfhasflag(lf, F_HEAVYBLOW) || hasflag(wep->flags, F_HEAVYBLOW)) {
dam[i] = (int)((float)dam[i] * 1.5);
dblog("heavy blow makes dam[%d] = %d",i,dam[i]);
}
@ -254,12 +297,14 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
adjustdamlf(victim, &dam[i], damtype[i]);
dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
// modify for defender's armour
reduceamt = getarmourdamreduction(victim, wep, dam[i], damtype[i]);
if (!backstab) {
// modify for defender's armour
reduceamt = getarmourdamreduction(victim, wep, dam[i], damtype[i]);
applyarmourdamreduction(victim, wep, reduceamt, &dam[i], damtype[i]);
applyarmourdamreduction(victim, wep, reduceamt, &dam[i], damtype[i]);
dblog("reduced by armour to dam[%d] = %d",i,dam[i]);
dblog("reduced by armour to dam[%d] = %d",i,dam[i]);
}
// will this hit be fatal?
if (dam[i] >= victim->hp) {
@ -278,7 +323,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
strcpy(extradambuf, "");
}
if (fatal) {
if (backstab && (i == 0)) {
verb = strdup("backstab");
} else if (fatal) {
verb = getkillverb(victim, damtype[i], dam[i], victim->maxhp);
} else {
verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp);
@ -286,7 +333,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
warn("You %s %s%s%s",
verb,
victimname, extradambuf,
fatal ? "!" : ".");
(fatal || backstab) ? "!" : ".");
if (fatal && strstr(verb, "behead")) {
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
@ -296,6 +343,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
// don't also say "the xx dies"
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
}
if (!strcmp(verb, "backstab")) {
free(verb);
}
} else {
if (cansee(player, lf) || isplayer(victim)) {
char withwep[BUFLEN];
@ -303,7 +353,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
char nodamstr[BUFLEN];
// capitalise first letter
sprintf(buf, "%s",attackername);
strcpy(buf, attackername);
capitalise(buf);
if (wep && !unarmedflag && (lf->race->id != R_DANCINGWEAPON) && cansee(player, lf)) {
@ -319,11 +369,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
strcpy(nodamstr, "");
}
warn("%s %s%s %s%s%s.", buf, attackverb,
attackverb[strlen(attackverb)-1] == 's' ? "es" : "s",
needses(attackverb) ? "es" : "s",
victimname,withwep, nodamstr);
} else {
youhear(lf->cell, "sounds of fighting");
}
}
noise(lf->cell, lf, "sounds of fighting.", NULL);
}
@ -362,9 +411,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
} // end foreach damtype
// special weapon effects
if (dam[0]) {
wepeffects(wep->flags, victim->cell);
}
wepeffects(wep->flags, victim->cell, dam[0]);
if (!isdead(victim)) {
if (unarmedflag) {
@ -415,9 +462,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
}
// confer flags from attacker?
if (dam[0]) {
wepeffects(lf->flags, victim->cell);
}
wepeffects(lf->flags, victim->cell, dam[0]);
// special lifeform-based effects
if ((lf->race->id == R_COCKATRICE) && dam[0]) {
@ -464,14 +509,16 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
}
if (lfhasflag(victim, F_DODGES)) {
flag_t *f;
cell_t *adj;
f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
adj = getrandomadjcell(victim->cell, WE_NOTSOLID);
moveto(lf, adj, B_FALSE);
msg("%s dodge%s!",victimname,isplayer(victim) ? "" : "s");
killflag(f);
if (adj) {
flag_t *f;
f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
moveto(victim, adj, B_FALSE);
msg("%s dodge%s!",victimname,isplayer(victim) ? "" : "s");
killflag(f);
}
}
}
@ -565,6 +612,11 @@ int attackob(lifeform_t *lf, object_t *o) {
dam[ndam] = getdamroll(wep, NULL);
}
// modify for strength
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
dam[ndam] = (int)((float)dam[ndam] * getstrdammod(lf));
}
// damtype?
damtype[ndam] = getdamtype(wep);
ndam++;
@ -598,7 +650,7 @@ int attackob(lifeform_t *lf, object_t *o) {
msg("%s %ss %s%s.", attackername,
getattackverb(lf, wep, damtype[i],dam[i],maxhp), obname,withwep);
} else {
youhear(lf->cell, "sounds of fighting");
noise(lf->cell, NULL, "sounds of fighting.", NULL);
}
if ((i == 0) && unarmedflag && hasflag(o->flags, F_HARD)) {
@ -617,9 +669,7 @@ int attackob(lifeform_t *lf, object_t *o) {
} // end foreach damtype
// special weapon effects
if (dam[0]) {
wepeffects(wep->flags, obloc);
}
wepeffects(wep->flags, obloc, dam[0]);
if (unarmedflag) {
// touch effects
@ -857,6 +907,10 @@ char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp)
float pct;
pct = (int)(((float) dam / (float) maxhp) * 100.0);
if (victim->race->id == R_DANCINGWEAPON) {
return "defeat";
}
if ((damtype == DT_BASH) && lfhasflag(victim, F_FROZEN)) {
return "shatter";
}
@ -1189,6 +1243,11 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
acc -= 45;
}
// victim immobile or asleep?
if (isimmobile(victim)) {
acc += 50;
}
if (critical) {
if (rnd(1,20) == 20) *critical = 1;
}
@ -1213,7 +1272,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
return gothit;
}
void wepeffects(flagpile_t *fp, cell_t *where) {
void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
flag_t *f;
lifeform_t *victim;
lifeform_t *owner;
@ -1222,7 +1281,15 @@ void wepeffects(flagpile_t *fp, cell_t *where) {
if (!where) return;
wep = fp->ob;
owner = fp->owner;
if (wep) {
cell_t *c;
c = getoblocation(wep);
if (c && c->lf) {
owner = c->lf;
}
} else {
owner = fp->owner;
}
victim = where->lf;
for (f = fp->first ; f ; f = f->next) {
@ -1237,100 +1304,128 @@ void wepeffects(flagpile_t *fp, cell_t *where) {
}
}
} else if ((f->id == F_REVENGE) && victim && !isdead(victim)) {
lifeform_t *owner;
owner = wep->pile->owner;
if (owner && victim) {
float ratio;
float dampct;
int maxdam;
int extradam;
// figure out hp percentage
ratio = 1.0 - ((float)owner->hp / (float)owner->maxhp);
dampct = (ratio * 100); // ie. lower hp% = higher dampct
if (dampct >= 50) {
getdamrange(wep->flags, NULL, &maxdam);
extradam = (int)(dampct * (float)maxdam);
if (extradam > 0) {
char buf[BUFLEN];
char buf2[BUFLEN];
char obname[BUFLEN];
char damstring[BUFLEN];
char victimname[BUFLEN];
getlfname(owner, buf);
real_getlfname(owner, buf2, B_FALSE);
getlfname(victim, victimname);
getobname(wep, obname, 1);
if (dam) { // only works if we did damage
lifeform_t *owner;
owner = wep->pile->owner;
if (owner && victim) {
float ratio;
float dampct;
int maxdam;
int extradam;
// figure out hp percentage
ratio = 1.0 - ((float)owner->hp / (float)owner->maxhp);
dampct = (ratio * 100); // ie. lower hp% = higher dampct
if (dampct >= 50) {
getdamrange(wep->flags, NULL, &maxdam);
extradam = (int)(dampct * (float)maxdam);
if (extradam > 0) {
char buf[BUFLEN];
char buf2[BUFLEN];
char obname[BUFLEN];
char damstring[BUFLEN];
char victimname[BUFLEN];
getlfname(owner, buf);
real_getlfname(owner, buf2, B_FALSE);
getlfname(victim, victimname);
getobname(wep, obname, 1);
// announce
if (isplayer(owner)) {
msg("Your %s blasts %s!",noprefix(obname),victimname);
f->known = B_TRUE;
} else if (cansee(player, owner)) {
msg("%s%s %s blasts %s!",buf, getpossessive(buf),noprefix(obname),victimname);
f->known = B_TRUE;
// announce
if (isplayer(owner)) {
msg("Your %s blasts %s!",noprefix(obname),victimname);
f->known = B_TRUE;
} else if (cansee(player, owner)) {
msg("%s%s %s blasts %s!",buf, getpossessive(buf),noprefix(obname),victimname);
f->known = B_TRUE;
}
sprintf(damstring, "%s%s blast of revenge",buf2, getpossessive(buf2));
losehp(victim, extradam, DT_DIRECT, owner, damstring);
}
sprintf(damstring, "%s%s blast of revenge",buf2, getpossessive(buf2));
losehp(victim, extradam, DT_DIRECT, owner, damstring);
}
} // end if dampct > 50
} // end if dampct > 50
}
}
} else if ((f->id == F_HEAVYBLOW) && victim && owner) {
int dir;
// knock back victim
dir = getdirtowards(owner->cell, victim->cell, victim, B_FALSE);
dir = getdirtowards(owner->cell, victim->cell, victim, B_FALSE, DT_COMPASS);
knockback(victim, dir , 2, owner);
f->known = B_TRUE;
} else if ((f->id == F_HITCONFER) && victim ) {
enum FLAG fid;
int min,max,howlong;
fid = f->val[0];
if (!lfhasflag(victim, fid)) {
int passedcheck = B_FALSE;
if (!f->val[1] == NA) {
int scdiff;
if (f->val[2] == NA) {
scdiff = 20; // default
} else {
scdiff = f->val[2];
// only works if we did damage
if (dam) {
enum FLAG fid;
int min,max,howlong;
fid = f->val[0];
if (!lfhasflag(victim, fid)) {
int passedcheck = B_FALSE;
if (!f->val[1] == NA) {
int scdiff;
if (f->val[2] == NA) {
scdiff = 20; // default
} else {
scdiff = f->val[2];
}
if (skillcheck(victim, f->val[1], scdiff, 0)) {
passedcheck = B_TRUE;
}
}
if (skillcheck(victim, f->val[1], scdiff, 0)) {
passedcheck = B_TRUE;
}
}
if (!passedcheck) {
int val0;
val0 = f->val[1];
if (f->text) {
char loctext[BUFLEN];
char *word, *dummy;
strcpy(loctext,f->text);
word = strtok_r(loctext, "-", &dummy);
if (word) {
min = atoi(word);
word = strtok_r(NULL, "-", &dummy);
if (!passedcheck) {
int val0;
val0 = f->val[1];
if (f->text) {
char loctext[BUFLEN];
char *word, *dummy;
strcpy(loctext,f->text);
word = strtok_r(loctext, "-", &dummy);
if (word) {
max = atoi(word);
howlong = rnd(min,max);
min = atoi(word);
word = strtok_r(NULL, "-", &dummy);
if (word) {
max = atoi(word);
howlong = rnd(min,max);
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
addtempflag(victim->flags, fid, val0, NA, NA, NULL, howlong);
} // end if passedcheck
} // end (if victim doesn't already have the flag)
if (fid == F_POISONED) {
// need to fill in the name of what poisoned us
char frombuf[BUFLEN];
if (wep) {
if (owner) {
char lfname[BUFLEN];
char wepname[BUFLEN];
getlfnamea(owner, lfname);
getobname(wep, wepname, 1);
// ie. "a goblin's poisoned short sword"
sprintf(frombuf, "%s%s %s",lfname,getpossessive(lfname), wepname);
} else {
char wepname[BUFLEN];
getobname(wep, wepname, 1);
// ie "a poisoned short sword"
sprintf(frombuf, "%s", wepname);
}
} else {
strcpy(frombuf, "something unknown");
}
addtempflag(victim->flags, fid, val0, NA, NA, frombuf, howlong);
} else {
addtempflag(victim->flags, fid, val0, NA, NA, NULL, howlong);
}
} // end if passedcheck
} // end (if victim doesn't already have the flag)
// was this from a poisoned weapon? if so the poison vanishes
if ((f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
killflag(f);
// was this from a poisoned weapon? if so the poison vanishes
if ((f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
killflag(f);
}
}
} // end if (fid == hitconfer)
}

View File

@ -20,4 +20,4 @@ int getdamrollfromflag(flag_t *f);
float getstrdammod(lifeform_t *lf);
obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical);
void wepeffects(flagpile_t *fp, cell_t *where);
void wepeffects(flagpile_t *fp, cell_t *where, int dam);

52
defs.h
View File

@ -43,10 +43,12 @@ enum CHECKTYPE {
//////////
SC_DODGE,
SC_SLIP,
SC_LISTEN,
SC_MORALE,
SC_OPENLOCKS,
SC_POISON,
SC_RESISTMAG,
SC_STEALTH,
SC_WILL,
};
@ -125,6 +127,8 @@ enum LFCONDITION {
#define MAXPILEOBS 52
#define MAXRETCELLS 80
#define MAXCHOICES 150
#define MAXDEPTH 25 // max dungeon depth
@ -197,6 +201,14 @@ enum LFCONDITION {
#define TR_NEEDLOS 1
#define TR_NEEDLOF 2
// line of fire args
enum LOFTYPE {
LOF_DONTNEED = 0,
LOF_WALLSTOP = 2,
LOF_LFSSTOP = 4,
LOF_NEED = 6, // walls AND lfs block
};
// CONTROLLERS
#define C_AI 0
#define C_PLAYER 1
@ -412,6 +424,8 @@ enum HABITAT {
H_ALL = 999
};
#define RARITYVARIANCE (25)
/*
enum RARITY {
RR_UNIQUE = 7,
@ -611,6 +625,7 @@ enum OBTYPE {
OT_SCR_CREATEMONSTER,
OT_SCR_DETECTAURA,
OT_SCR_DETECTLIFE,
OT_SCR_DETECTOBS,
OT_SCR_DETECTMAGIC,
OT_SCR_FLAMEPILLAR,
OT_SCR_FLAMEBURST,
@ -627,11 +642,14 @@ enum OBTYPE {
OT_SCR_WISH,
// BOOKS
OT_MAN_ATHLETICS,
OT_MAN_BACKSTAB,
OT_MAN_FIRSTAID,
OT_MAN_LISTEN,
OT_MAN_LOCKPICKING,
OT_MAN_MAGITEMUSAGE,
OT_MAN_RESEARCH,
OT_MAN_SPELLCASTING,
OT_MAN_STEALTH,
OT_MAN_TECHUSAGE,
// manuals of weaponry
OT_MAN_AXES,
@ -667,6 +685,7 @@ enum OBTYPE {
// -- divination
OT_SB_DETECTAURA,
OT_SB_DETECTLIFE,
OT_SB_DETECTOBS,
OT_SB_IDENTIFY,
OT_SB_MAPPING,
// -- elemental - air
@ -695,8 +714,11 @@ enum OBTYPE {
OT_SB_TURNUNDEAD,
// -- mental / psionic
OT_SB_MINDSCAN,
OT_SB_SLEEP,
OT_SB_TELEKINESIS,
OT_SB_PACIFY,
OT_SB_PSYARMOUR,
OT_SB_CHARM,
// -- modification
OT_SB_GASEOUSFORM,
OT_SB_KNOCK,
@ -734,6 +756,7 @@ enum OBTYPE {
// -- divination
OT_S_DETECTAURA,
OT_S_DETECTLIFE,
OT_S_DETECTOBS,
OT_S_DETECTMAGIC,
OT_S_IDENTIFY,
OT_S_MAPPING,
@ -765,7 +788,9 @@ enum OBTYPE {
OT_S_MINDSCAN,
OT_S_SLEEP,
OT_S_TELEKINESIS,
OT_S_PACIFY,
OT_S_PSYARMOUR,
OT_S_CHARM,
// -- modification
OT_S_ENCHANT,
OT_S_GASEOUSFORM,
@ -782,6 +807,7 @@ enum OBTYPE {
OT_S_CREATEMONSTER,
// -- translocation
OT_S_BLINK,
OT_S_PULL,
OT_S_DISPERSAL,
OT_S_GATE,
OT_S_TELEPORT,
@ -795,6 +821,7 @@ enum OBTYPE {
OT_S_WISH,
OT_S_GIFT,
OT_A_DEBUG,
OT_A_ENHANCE,
OT_A_LEARN,
// abilities
OT_A_GRAB,
@ -1022,6 +1049,8 @@ enum BODYPART {
enum NOISETYPE {
N_GETANGRY,
N_WALK,
N_FLY,
};
enum LFSIZE {
@ -1036,6 +1065,11 @@ enum LFSIZE {
SZ_MAX = 100
};
enum ALLEGIENCE {
AL_HOSTILE, // will attack you on sight
AL_PEACEFUL, // won't attack you on sight
AL_FRIENDLY, // will help you fight
};
enum FLAG {
F_NONE, // dummy flag
@ -1055,7 +1089,7 @@ enum FLAG {
F_CURAMMO, // currently equipped ammo
F_GOESON, // val0 = where it can be equipped.
F_BONUS, // val0=bonus/penalty to damage/armour. ie. +1 sword
F_MISSILE, // weapon would make a good missle - used by AI
F_THROWMISSILE, // weapon would make a good thrown missle - used by AI
F_UNIQUE, // only one may appear
F_GLYPH, // override the glyph with the first char of text
F_NOPICKUP, // cannot pick this up
@ -1207,9 +1241,9 @@ enum FLAG {
F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2
F_ONGOING, // this spell has an ongoing cost
//F_SPELLLETTER, // text[0] = letter to cast this spell
F_AICASTTOFLEE, // AI can cast this spell to help flee
F_AICASTTOFLEE, // AI can cast this spell to help flee/heal
// v0 is who to target
F_AICASTTOATTACK, // AI can cast this spell to help flee
F_AICASTTOATTACK, // AI can cast this spell to attack
// v0 is who to target
F_AIBOOSTITEM, // ai will use this item to boost/buff itself.
// if using this on wands, update aiobok() !
@ -1265,6 +1299,8 @@ enum FLAG {
F_NOFLEE, // lf will not run away
F_TARGET, // lf will attack lfid v0. lastknown x/y is v1/v2
F_TARGETCELL, // lf will go towards this place. val0=x,val1=y
F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed
// by them again until they go out of sight.
F_FLEEFROM, // lf will run away from this lf id
// TEMP FLAGS
@ -1276,6 +1312,7 @@ enum FLAG {
F_SPELLCASTTEXT, // text is announcement for spellcast
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
F_BEHEADED, // use special corpse drop code
F_SILENTMOVE, // lf makes no noise when walking/flying
F_MOVESPEED, // override default move speed
F_ACTIONSPEED, // override default action speed
F_SPELLSPEED, // override default spellcast speed (ie. movespeed)
@ -1322,15 +1359,17 @@ enum FLAG {
// ie. when v1 == v2, ability is ready.
// text is other options, semicolon seperated:
// pw:xx; cast the spell at power xx
F_CHARMEDBY,// you've been charmed by lf id v0
F_DETECTAURAS, // autodetect bless/curse
F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0
F_DETECTMAGIC, // autodetect magic/special objects
F_DETECTMETAL, // autodetect nearby metal
F_DETECTOBS, // autodetect nearby obs in orthog dist v0
F_EXTRAINFO, // knows extra info
F_FLYING, // lf is flying
F_FASTACT, // modifier for action speed
F_FASTMOVE, // modifier for move speed
F_POISONED, // has food poisoning
F_POISONED, // has food poisoning. text = what from.eg'a bad egg'
F_FREEZINGTOUCH,// next thing touched turns to ice!
F_GRABBEDBY,// you've been grabbed by lf id v0
F_GRABBING, // you are grabbing lf id v0
@ -1369,6 +1408,7 @@ enum FLAG {
F_TIRED, // you are too tired to sprint
F_DODGES, // you dodge missed attacks
F_NOTIME, // this lf's actions don't take time
F_PERCEPTION, // v0 = 0-20. perception level.
// skills
F_HASSKILL, // lf has skill v0 at level v1
// COMBAT
@ -1584,6 +1624,7 @@ typedef struct map_s {
int w,h; // width/height of this map
struct cell_s *cell[MAX_MAPW*MAX_MAPH]; // list of cells in this map
int nextmap[MAXDIR_ORTH]; // which map is in each direction
int beingcreated;
struct lifeform_s *lf,*lastlf;
@ -1730,11 +1771,14 @@ typedef struct material_s {
#define SK_NONE -1
enum SKILL {
SK_ATHLETICS,
SK_BACKSTAB,
SK_FIRSTAID,
SK_LISTEN,
SK_LOCKPICKING,
SK_MAGITEMUSAGE,
SK_RESEARCH,
SK_SPELLCASTING,
SK_STEALTH,
SK_TECHUSAGE,
// weaponry
SK_AXES,

View File

@ -14,8 +14,7 @@ lf.c:
update gainlevel() question
update givejob()
update modattr()
io.c:
update announceflaggain() and loss() for this stat
text.c:
add getattrname()

94
flag.c
View File

@ -124,31 +124,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
}
}
// player flags which cause a redraw
if (isplayer(f->pile->owner)) {
switch (f->id) {
case F_BLIND:
case F_SEEINDARK:
case F_SPRINTING:
case F_TIRED:
case F_FASTMOVE:
case F_SLOWMOVE:
case F_INVISIBLE:
case F_SEEINVIS:
doredraw = B_TRUE;
break;
default:
break;
}
} else if (haslos(player, f->pile->owner->cell)) {
// monster flags which cause a redraw
switch (f->id) {
case F_INVISIBLE:
doredraw = B_TRUE;
break;
default:
break;
}
}
doredraw = flagcausesredraw(f->pile->owner, f->id);
} else if (f->pile->ob) {
if (announceobflaggain(f->pile->ob, f)) {
f->known = B_TRUE;
@ -197,6 +173,38 @@ void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {
}
}
int flagcausesredraw(lifeform_t *lf, enum FLAG fid) {
if (!lf) return B_FALSE;
if (isplayer(lf)) {
// player
switch (fid) {
case F_BLIND:
case F_DETECTLIFE:
case F_DETECTOBS:
case F_FASTMOVE:
case F_INVISIBLE:
case F_SEEINDARK:
case F_SEEINVIS:
case F_SPRINTING:
case F_SLOWMOVE:
case F_TIRED:
return B_TRUE;
default:
break;
}
} else if (haslos(player, lf->cell)) {
switch (fid) {
case F_INVISIBLE:
return B_TRUE;
default:
break;
}
// nonplayer
}
return B_FALSE;
}
int flagstacks(enum FLAG fid) {
int res = B_FALSE;
switch (fid) {
@ -292,34 +300,8 @@ void killflag(flag_t *f) {
lf = f->pile->owner;
// player flags which cause a redraw
if (lf) {
if (isplayer(lf)) {
switch (f->id) {
case F_BLIND:
case F_SEEINDARK:
case F_SPRINTING:
case F_TIRED:
case F_FASTMOVE:
case F_SLOWMOVE:
case F_INVISIBLE:
case F_SEEINVIS:
doredraw = B_TRUE;
break;
default:
break;
}
} else if (haslos(player, lf->cell)) {
// monster flags which cause a redraw
switch (f->id) {
case F_INVISIBLE:
doredraw = B_TRUE;
break;
default:
break;
}
}
}
// flags which cause a redraw
doredraw = flagcausesredraw(f->pile->owner, f->id);
// notify
if ((gamemode == GM_GAMESTARTED)) {
@ -390,9 +372,9 @@ void killflagpile(flagpile_t *fp) {
free(fp);
}
void timeeffectsflag(flag_t *f) {
void timeeffectsflag(flag_t *f, int howlong) {
if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) {
f->lifetime--;
f->lifetime -= howlong;
if (f->lifetime <= 0) {
killflag(f);
return;
@ -505,7 +487,7 @@ void timeeffectsflags(flagpile_t *fp) {
flag_t *f,*nextf;
for (f = fp->first ; f ; f = nextf) {
nextf = f->next;
timeeffectsflag(f);
timeeffectsflag(f, 1);
}
}

3
flag.h
View File

@ -7,6 +7,7 @@ flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid);
flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int flagcausesredraw(lifeform_t *lf, enum FLAG fid);
int flagstacks(enum FLAG fid);
flag_t *hasflag(flagpile_t *fp, int id);
flag_t *hasflagknown(flagpile_t *fp, int id);
@ -19,5 +20,5 @@ void killflag(flag_t *f);
void killflagpile(flagpile_t *fp);
void makeflagknown(flagpile_t *fp);
void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2);
void timeeffectsflag(flag_t *f);
void timeeffectsflag(flag_t *f, int howlong);
void timeeffectsflags(flagpile_t *fp);

148
io.c
View File

@ -404,13 +404,21 @@ cell_t *askcoords(char *prompt, int targettype) {
sprintf(extrainfo, "level %d, ",c->lf->level);
}
*/
if (isfriendly(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "ally");
} else if (ispeaceful(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "peaceful");
switch (getallegiance(c->lf)) {
case AL_FRIENDLY:
if (!isplayer(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "ally");
}
break;
case AL_PEACEFUL:
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "peaceful");
break;
case AL_HOSTILE:
break;
}
if (isfleeing(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "fleeing");
@ -438,12 +446,30 @@ cell_t *askcoords(char *prompt, int targettype) {
wep = getweapon(c->lf);
if (wep) {
object_t *secwep;
char obname[BUFLEN];
char buf2[BUFLEN];
getobname(wep, obname, wep->amt);
sprintf(buf2, "weilding %s",obname);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
secwep = getequippedob(c->lf->pack, BP_SECWEAPON);
if (secwep) {
getobname(secwep, obname, secwep->amt);
strcat(buf2, " and ");
strcat(buf2, obname);
}
strcat(extrainfo, buf2);
} else {
wep = getequippedob(c->lf->pack, BP_SECWEAPON);
if (wep) {
char obname[BUFLEN];
char buf2[BUFLEN];
getobname(wep, obname, wep->amt);
sprintf(buf2, "weilding %s",obname);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2);
}
}
f = lfhasflag(c->lf, F_GRABBING);
@ -690,6 +716,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
ot = findot(f->val[0]);
if (ot) {
msg("You have learned the spell '%s'.", ot->name);
donesomething = B_TRUE;
}
}
break;
@ -699,9 +726,18 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
ot = findot(f->val[0]);
if (ot) {
msg("You have learned the ability '%s'.", ot->name);
donesomething = B_TRUE;
}
}
break;
case F_CHARMEDBY:
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfname(lf2, buf);
msg("%s %s now under %s%s power!",lfname, isplayer(lf) ? "are" : "is", buf,getpossessive(buf));
donesomething = B_TRUE;
}
break;
case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel immune to %s!", getdamnamenoun(f->val[0]));
@ -732,6 +768,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
}
break;
case F_DETECTOBS:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can now detect nearby objects.");
donesomething = B_TRUE;
}
break;
case F_DETECTMAGIC:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel sensitive to magical enchantments.");
@ -779,7 +821,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
if (lf2) {
getlfname(lf2, buf);
msg("%s turn%s to flee from %s!", lfname, isplayer(lf) ? "" : "s",
cansee(player, lf2) ? buf : "something");
(cansee(player, lf2) || isplayer(lf2)) ? buf : "something");
}
break;
case F_POISONED:
@ -952,7 +994,7 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
return B_FALSE;
}
if (isdead(player)) return B_FALSE;
if (isdead(lf) || isdead(player)) return B_FALSE;
getlfname(lf, lfname);
// player can't see?
@ -1034,6 +1076,15 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
}
}
break;
case F_CHARMEDBY:
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
char buf[BUFLEN];
getlfname(lf2, buf);
msg("%s break%s free of %s%s control!",lfname, isplayer(lf) ? "" : "s", buf,getpossessive(buf));
donesomething = B_TRUE;
}
break;
case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer immune to %s.", getdamnamenoun(f->val[0]));
@ -1064,6 +1115,9 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("%s stop%s fleeing.", lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_FRIENDLY:
msg("%s no longer looks quite so friendly!", lfname);
break;
case F_POISONED:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You feel less sick now.");
@ -1107,6 +1161,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
}
break;
case F_DETECTOBS:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can no longer detect nearby objects.");
donesomething = B_TRUE;
}
break;
case F_DETECTMAGIC:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can no longer detect magical enchantments.");
@ -2186,7 +2246,7 @@ void describeob(object_t *o) {
}
}
f = hasflag(o->flags, F_MISSILE);
f = hasflag(o->flags, F_THROWMISSILE);
if (f) {
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
int dam;
@ -2299,6 +2359,9 @@ void describeob(object_t *o) {
case F_DETECTLIFE:
mvwprintw(mainwin, y, 0, "%s will detect nearby lifeforms.", buf); y++;
break;
case F_DETECTOBS:
mvwprintw(mainwin, y, 0, "%s will detect nearby objects.", buf); y++;
break;
case F_DETECTMAGIC:
mvwprintw(mainwin, y, 0, "%s will detect magical enchantemnts on objects.", buf); y++;
break;
@ -3591,7 +3654,7 @@ void donextguntarget(void) {
cell_t *c;
c = player->los[i];
if (c->lf && (c->lf != player) && (c->lf != targ)) {
if (haslof(player, c) && isingunrange(player, c)) {
if (haslof(player, c, LOF_NEED, NULL) && isingunrange(player, c)) {
// found one!
setguntarget(player, c->lf);
done = B_TRUE;
@ -3676,7 +3739,7 @@ void dorest(void) {
}
if (strchr(validchars, 'h') && strchr(validchars, 'm')) {
strcat(validchars, "b");
strcat(validchars, "bn");
strcpy(ques, "Rest until full HP, Mana, Both or none");
ch = askchar(ques, validchars, "b", B_TRUE);
if (ch == 'b') {
@ -3739,7 +3802,7 @@ void doselguntarget(void) {
sprintf(buf, "Aim %s where?",gunname);
where = askcoords(buf, TT_MONSTER);
if (where) {
if (where->lf && haslof(player, where)) {
if (where->lf && haslof(player, where, LOF_NEED, NULL)) {
setguntarget(player, where->lf);
} else {
setguntarget(player, NULL);
@ -3807,13 +3870,22 @@ void dothrow(obpile_t *op) {
where = askcoords(buf2, TT_MONSTER);
if (where) {
if (!haslof(player, where)) {
if (reason == E_NOLOS) {
msg("You can't see there!");
} else { // ie. E_NOLOF
msg("You don't have a clear line of fire to there.");
cell_t *newwhere = NULL;
if (!haslof(player, where, LOF_WALLSTOP, &newwhere)) {
if (newwhere) {
// update destination cell.
where = newwhere;
} else {
if (reason == E_NOLOS) {
msg("You can't see there!");
} else { // ie. E_NOLOF
msg("You don't have a clear line of fire to there.");
}
return;
}
} else if (getcelldist(player->cell, where) > maxdist) {
}
if (getcelldist(player->cell, where) > maxdist) {
msg("You can't throw %s that far!",buf);
} else {
throwat(player, o, where);
@ -3929,7 +4001,7 @@ void drawcellwithcontents(cell_t *cell, int x, int y) {
} else {
void *thing;
char glyph;
// scanned lf here?
// scanned lf here?
if (isinscanrange(cell, &thing, NULL, &glyph) == TT_MONSTER) {
//mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph);
mvwprintw(gamewin, y, x, "%c", glyph);
@ -4331,9 +4403,16 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
}
// fill in the name of the completed choice
/*
sprintf(promptstr, "%s %s %s",
prompt->q[prompt->whichq], prompt->maycancel ? "[ESC=cancel, '=next page] " : "",
prompt->choice[validone].text);
*/
sprintf(promptstr, "%s [%s%s] %s",
prompt->q[prompt->whichq],
prompt->maycancel ? "ESC," : "",
showall ? "'=next page,?=toggle" : "?=list",
prompt->choice[validone].text);
mvwprintw(mainwin, 0, 0, "%s", promptstr);
// move the cursor back
@ -4935,6 +5014,7 @@ void nothinghappens(void) {
void drawstatus(void) {
char buf[BUFLEN];
char buf2[BUFLEN];
char mpbuf[BUFLEN];
char waitbuf[BUFLEN];
char pname[BUFLEN];
char maxmpstr[BUFLEN];
@ -5046,10 +5126,17 @@ void drawstatus(void) {
sprintf(maxmpstr, "(%d)",player->maxmp);
}
sprintf(buf, "HP:%d/%d MP:%d/%d%s $:%d St:%d%c Dx:%d%c Iq:%d%c Cn:%d%c DLev:%d",
if (getmaxmp(player) > 0) {
sprintf(mpbuf, "%d/%d%s", player->mp, getmaxmp(player), maxmpstr);
} else {
strcpy(mpbuf, "-");
}
sprintf(buf, "HP:%d/%d MP:%s $:%d AR:%d St:%d%c Dx:%d%c Iq:%d%c Cn:%d%c DLev:%d",
player->hp,player->maxhp,
player->mp, getmaxmp(player), maxmpstr,
mpbuf,
countmoney(player),
getarmourrating(player),
str, (str == player->baseatt[A_STR]) ? ' ' : '*',
dex, (dex == player->baseatt[A_DEX]) ? ' ' : '*',
iq, (iq == player->baseatt[A_IQ]) ? ' ' : '*',
@ -6054,6 +6141,20 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s cannot see.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_CHARMEDBY);
if (f) {
lifeform_t *lf2;
char charmername[BUFLEN];
lf2 = findlf(NULL, f->val[0]);
if (lf2) {
getlfnamea(lf2, charmername);
} else {
strcpy(charmername, "something");
}
sprintf(buf,"%s %s been charmed by %s.",you(lf), isplayer(lf) ? "have" : "has", charmername);
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_DETECTAURAS);
if (f) {
mvwprintw(mainwin, y, 0, "%s automatically detect blessings or curses.", you(lf));
@ -6074,6 +6175,11 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s automatically detect nearby metal.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_DETECTOBS);
if (f) {
mvwprintw(mainwin, y, 0, "%s automatically detect nearby objects.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_EXTRAINFO);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf));

744
lf.c

File diff suppressed because it is too large Load Diff

17
lf.h
View File

@ -6,6 +6,8 @@ job_t *addjob(enum JOB id, char *name);
race_t *addrace(enum RACE id, char *name, float weight, char glyph, enum MATERIAL mat);
skill_t *addskill(enum SKILL id, char *name, char *desc);
void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype);
int areallies(lifeform_t *lf1, lifeform_t *lf2);
int areenemies(lifeform_t *lf1, lifeform_t *lf2);
void autoskill(lifeform_t *lf);
void autotarget(lifeform_t *lf);
void autoweild(lifeform_t *lf);
@ -40,6 +42,8 @@ lifeform_t *findlf(map_t *m, int lfid);
race_t *findrace(enum RACE id);
race_t *findracebyname(char *name);
skill_t *findskill(enum SKILL id);
skill_t *findskillbyname(char *name);
enum SKILLLEVEL findskilllevbyname(char *name);
int flee(lifeform_t *lf);
int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong);
void gainhp(lifeform_t *lf, int amt);
@ -47,12 +51,13 @@ void gainlevel(lifeform_t *lf);
void gainmp(lifeform_t *lf, int amt);
void gainxp(lifeform_t *lf, long amt);
int getactspeed(lifeform_t *lf);
enum ALLEGIENCE getallegiance(lifeform_t *lf);
object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
int getarmourrating(lifeform_t *lf);
int getattackspeed(lifeform_t *lf);
int getattr(lifeform_t *lf, enum ATTRIB attr);
int getevasion(lifeform_t *lf);
object_t *getbestmissile(lifeform_t *lf);
object_t *getbestthrowmissile(lifeform_t *lf);
object_t *getbestweapon(lifeform_t *lf);
object_t *getbestfirearm(lifeform_t *lf);
int getbodyparthitchance(enum BODYPART bp);
@ -85,6 +90,7 @@ int getvisrange(lifeform_t *lf);
int getmovespeed(lifeform_t *lf);
char *getmoveverb(lifeform_t *lf);
char *getmoveverbother(lifeform_t *lf);
lifeform_t *getnearbypeaceful(lifeform_t *lf);
char *getlfname(lifeform_t *lf, char *buf);
char *real_getlfname(lifeform_t *lf, char *buf, int usevis);
char *getlfnamea(lifeform_t *lf, char *buf);
@ -113,6 +119,7 @@ long getxpforlev(int level);
void givejob(lifeform_t *lf, enum JOB jobid);
void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype);
int giveskill(lifeform_t *lf, enum SKILL id);
int giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev);
void givestartobs(lifeform_t *lf, flagpile_t *fp);
void givestartskills(lifeform_t *lf, flagpile_t *fp);
map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs);
@ -125,7 +132,7 @@ flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int
int lockpick(lifeform_t *lf, object_t *target, object_t *device);
void loseobflags(lifeform_t *lf, object_t *o, int kind);
int hasbp(lifeform_t *lf, enum BODYPART bp);
int haslof(lifeform_t *viewer, cell_t *dest);
int haslof(lifeform_t *viewer, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest);
int haslos(lifeform_t *viewer, cell_t *dest);
void initjobs(void);
void initrace(void);
@ -154,7 +161,7 @@ void killlf(lifeform_t *lf);
void killrace(race_t *race);
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc);
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam);
void makefriendly(lifeform_t *lf);
void makefriendly(lifeform_t *lf, int howlong);
void makenauseated(lifeform_t *lf, int amt, int howlong);
void makenoise(lifeform_t *lf, enum NOISETYPE nid);
lifeform_t *makezombie(object_t *o);
@ -162,6 +169,7 @@ void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how);
int modattr(lifeform_t *lf, enum ATTRIB attr, int amt);
void modhunger(lifeform_t *lf, int amt);
float modifybystat(float num, lifeform_t *lf, enum ATTRIB att);
void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext);
void outfitlf(lifeform_t *lf);
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground);
void precalclos(lifeform_t *lf);
@ -180,6 +188,7 @@ void setattr(lifeform_t *lf, enum ATTRIB attr, int val);
void setguntarget(lifeform_t *lf, lifeform_t *targ);
void setrace(lifeform_t *lf, enum RACE rid);
void setlastdam(lifeform_t *lf, char *buf);
void setlftarget(lifeform_t *lf, lifeform_t *victim);
int shoot(lifeform_t *lf);
int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod);
int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *result);
@ -203,4 +212,4 @@ int validateraces(void);
int wear(lifeform_t *lf, object_t *o);
int weild(lifeform_t *lf, object_t *o);
int willflee(lifeform_t *lf);
int youhear(cell_t *c, char *text);
//int youhear(cell_t *c, char *text);

340
log.txt
View File

@ -2,421 +2,117 @@
====== NEW LOGFILE ====
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx
findotn(): modname is 'staircase going up'
checkobnames(): got exact match: 'staircase going up'
findotn(): modname is 'staircase going down'
checkobnames(): got exact match: 'staircase going down'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 2 x bolt ('bolts')
findotn(): modname is 'bolts'
checkobnames(): got match after stripping 's': 'bolt' -> 'bolts'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
adding random object with rarity value between 72 - 100
(must have obclass = Potions)
got 8 possibilities.
random ob: 1 x potion of minor healing ('potion of minor healing')
findotn(): modname is 'potion of minor healing'
checkobnames(): got exact match: 'potion of minor healing'
findotn(): modname is 'claws'
checkobnames(): got exact match: 'claws'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'zapper'
checkobnames(): got exact match: 'zapper'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
adding random object with rarity value between 72 - 100
(must have obclass = Potions)
got 8 possibilities.
random ob: 1 x potion of magic ('potion of magic')
findotn(): modname is 'potion of magic'
checkobnames(): got exact match: 'potion of magic'
findotn(): modname is 'claws'
checkobnames(): got exact match: 'claws'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x potion of oil ('potion of oil')
findotn(): modname is 'potion of oil'
checkobnames(): got exact match: 'potion of oil'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x scimitar ('scimitar')
findotn(): modname is 'scimitar'
checkobnames(): got exact match: 'scimitar'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x potion of magic ('potion of magic')
findotn(): modname is 'potion of magic'
checkobnames(): got exact match: 'potion of magic'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x apple ('apple')
findotn(): modname is 'apple'
checkobnames(): got exact match: 'apple'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 6 x nanodart ('nanodarts')
findotn(): modname is 'nanodarts'
checkobnames(): got match after stripping 's': 'nanodart' -> 'nanodarts'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x knife ('knife')
findotn(): modname is 'knife'
checkobnames(): got exact match: 'knife'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'claws'
checkobnames(): got exact match: 'claws'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 3 x bolt ('bolts')
findotn(): modname is 'bolts'
checkobnames(): got match after stripping 's': 'bolt' -> 'bolts'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x spellbook of inscribe ('spellbook of inscribe')
findotn(): modname is 'spellbook of inscribe'
checkobnames(): got exact match: 'spellbook of inscribe'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x splash of blood ('splash of blood')
findotn(): modname is 'splash of blood'
checkobnames(): got exact match: 'splash of blood'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'short sword'
checkobnames(): got exact match: 'short sword'
findotn(): modname is 'claws'
checkobnames(): got exact match: 'claws'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x potion of fruit juice ('potion of fruit juice')
findotn(): modname is 'potion of fruit juice'
checkobnames(): got exact match: 'potion of fruit juice'
adding random object with rarity value between 72 - 100
got 100 possibilities.
random ob: 1 x boulder ('boulder')
findotn(): modname is 'boulder'
checkobnames(): got exact match: 'boulder'
rollhitdice() - rolling 2d4 + 2
rollhitdice() - mod is +88%
rollhitdice() ---- die 1/2 == 4
rollhitdice() ---- die 2/2 == 4
TOTAL: 8
-> modified to: 15
findotn(): modname is 'fists'
checkobnames(): got exact match: 'fists'
givejob() starting.
processing normal flag: 183
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 144
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 145
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 210
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
processing normal flag: 209
findotn(): modname is 'short sword'
checkobnames(): got exact match: 'short sword'
findotn(): modname is 'hand of god'
checkobnames(): got exact match: 'hand of god'
findotn(): modname is 'block of chocolate'
checkobnames(): got exact match: 'block of chocolate'
findotn(): modname is 'vial of ambrosia'
checkobnames(): got exact match: 'vial of ambrosia'
findotn(): modname is 'leather armour'
checkobnames(): got exact match: 'leather armour'
findotn(): modname is 'leather boots'
findotn(): modname is 'leather gloves'
findotn(): modname is 'graph paper'
findotn(): modname is 'digital watch'
checkobnames(): got exact match: 'digital watch'
findotn(): modname is 'scroll of create monster'
checkobnames(): got exact match: 'scroll of create monster'
findotn(): modname is 'potion of experience'
checkobnames(): got exact match: 'potion of experience'
findotn(): modname is 'ring of invulnerability'
checkobnames(): got exact match: 'ring of invulnerability'
findotn(): modname is 'fists'
checkobnames(): got exact match: 'fists'

57
map.c
View File

@ -72,6 +72,7 @@ map_t *addmap(void) {
for (i = 0; i < MAXDIR_ORTH; i++) {
a->nextmap[i] = -1;
}
a->beingcreated = B_TRUE;
return a;
}
@ -101,6 +102,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
if (lf) {
flag_t *f;
lf->born = B_FALSE;
if (jobok) {
// has a job?
f = hasflag(lf->flags, F_STARTJOB);
@ -111,6 +113,14 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
}
}
if (lf->cell->map->beingcreated) {
// sometimes start off asleep in new maps
// TODO: base this on the time, and whether monster is nocturnal
if (rnd(1,2) == 1) {
addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
}
}
// appears in groups?
f = hasflag(lf->flags, F_NUMAPPEAR);
if (f) {
@ -130,6 +140,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
//adjcell = c;
for ( ; amt > 0; amt--) {
int n;
lifeform_t *newlf;
// find an adjacent cell to one of the newly added monsters,
// starting with the first one
adjcell = NULL;
@ -141,17 +152,25 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
if (!adjcell) break;
//lf = addlf(adjcell, r->id, getrandommonlevel(adjcell->map->depth));
if (!addlf(adjcell, r->id, 1)) {
newlf = addlf(adjcell, r->id, 1);
if (!newlf) {
break;
}
newlf->born = B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
newlf->born = B_TRUE;
moncell[nmoncells] = adjcell;
nmoncells++;
}
free(moncell);
}
}
lf->born = B_TRUE;
} // end if lf
}
return lf;
}
@ -169,10 +188,10 @@ void addrandomob(cell_t *c) {
}
}
void addrandomthing(cell_t *c) {
void addrandomthing(cell_t *c, int obchance) {
// if there's already someone there,
// then add an object.
if (c->lf || (rnd(1,2) == 1)) {
if (c->lf || (rnd(1,100) <= obchance)) {
// object
addrandomob(c);
} else {
@ -564,6 +583,8 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
//int db = B_TRUE;
map->beingcreated = B_TRUE;
sprintf(buf, "Map %d",map->id);
map->name = strdup(buf);
map->habitat = habitat;
@ -1008,7 +1029,7 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
c = getcellat(map, x, y);
if (c && isempty(c)) {
if (rnd(1,100) <= getobchance(map->habitat)) {
addrandomthing(c);
addrandomthing(c, 50);
}
}
}
@ -1047,7 +1068,8 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
} else {
*/
numobsmin = 0;
numobsmax = MAXOF(roomw[i],roomh[i]) / 2;
//numobsmax = MAXOF(roomw[i],roomh[i]) / 2;
numobsmax = MAXOF(roomw[i],roomh[i]);
//}
@ -1086,7 +1108,8 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
}
} else {
*/
addrandomthing(c);
// slightly more chance of objects in rooms
addrandomthing(c,60);
done = B_TRUE;
//dblog("----> Success ob at (%d,%d).",c->x,c->y);
} else {
@ -1232,7 +1255,7 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
//printf("*** Level difficulty is %0.2f\n", getmazedifficulty(curz));
map->beingcreated = B_FALSE;
}
void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
@ -1472,7 +1495,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int
msg("You see %s explosion!", (range > 0) ? "a huge" : "an");
}
} else {
youhear(c, "an explosion!");
noise(c, NULL, "an explosion!", NULL);
}
for (y = c->y - range ; y <= c->y + range ; y++) {
@ -1493,7 +1516,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int
if (cc && (getcelldist(c, cc) <= (range+1))) {
if (cc->lf && !isdead(cc->lf)) {
// move away from centre of explosion
knockback(cc->lf, getdiraway(cc, c, B_FALSE), 2, NULL);
knockback(cc->lf, getdiraway(cc, c, B_FALSE, DT_COMPASS), 2, NULL);
}
}
}
@ -1980,6 +2003,20 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) {
}
}
}
f = lfhasflag(player, F_DETECTOBS);
if (f) {
if (getcelldistorth(player->cell, c) <= f->val[0]) {
object_t *o;
for (o = c->obpile->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_DOOR)) {
*thing = o;
if (glyph) *glyph = '*';
if (desc) sprintf(desc, "an object");
return TT_OBJECT;
}
}
}
}
return B_FALSE;
}

2
map.h
View File

@ -4,7 +4,7 @@ cell_t *addcell(map_t *map, int x, int y);
map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt);
void addrandomob(cell_t *c);
void addrandomthing(cell_t *c);
void addrandomthing(cell_t *c, int obchance);
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);

137
move.c
View File

@ -109,7 +109,7 @@ int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
f = hasflag(o->flags, F_WALKDAM);
if (f) {
// are we immune to this?
if (!lfhasflagval(lf, F_DTIMMUNE, f->val[1], NA, NA, NULL)) {
if (!lfhasflagval(lf, F_DTIMMUNE, f->val[0], NA, NA, NULL)) {
if (error) {
*error = E_AVOIDOB;
rdata = o;
@ -255,7 +255,7 @@ void dorandommove(lifeform_t *lf, int badmovesok) {
// src is where something is
// dst is what we are going away from
// wantcheck is whether to check for dangerous things before considering a direction valid
int getdiraway(cell_t *src, cell_t *dst, int wantcheck) {
int getdiraway(cell_t *src, cell_t *dst, int wantcheck, int dirtype) {
int d;
cell_t *c;
int maxdist=-1,bestdir=D_NONE;
@ -290,8 +290,11 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck) {
}
}
if (ok) {
//thisdist = getcelldistorth(c, dst);
thisdist = getcelldist(c, dst);
if (dirtype == DT_ORTH) {
thisdist = getcelldistorth(c, dst);
} else {
thisdist = getcelldist(c, dst);
}
} else {
thisdist = -1;
}
@ -324,7 +327,7 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck) {
}
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck) {
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype) {
int d;
cell_t *c;
int mindist=9999,bestdir=D_NONE;
@ -362,8 +365,11 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck) {
}
if (ok) {
int thisdist;
//thisdist = getcelldistorth(c, dst);
thisdist = getcelldist(c, dst);
if (dirtype == DT_ORTH) {
thisdist = getcelldistorth(c, dst);
} else {
thisdist = getcelldist(c, dst);
}
dist[d - DC_N] = thisdist;
if (thisdist < mindist) {
mindist = thisdist;
@ -449,7 +455,7 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst ) {
}
// move away from them
dir = getdiraway(lf->cell, dst, B_TRUE);
dir = getdiraway(lf->cell, dst, B_TRUE, DT_COMPASS);
if (dir == D_NONE) {
rv = B_TRUE;
} else {
@ -606,15 +612,26 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if ((gamemode == GM_GAMESTARTED)) {
for (l = newcell->map->lf ; l ; l = l->next) {
if (l != lf) {
// cope with swapping locations with someone!
if (haslos(l, newcell)) {
interrupt(l);
int dointerrupt = B_FALSE;
if (isplayer(l)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_RESTING)) {
char lfname2[BUFLEN];
getlfname(lf, lfname);
sprintf(lfname2, "%s",noprefix(lfname));
msg("%s %s comes into view.",isvowel(lfname2[0]) ? "An" : "A", lfname2);
if (areenemies(lf, l)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_RESTING)) {
char lfname2[BUFLEN];
getlfname(lf, lfname);
sprintf(lfname2, "%s",noprefix(lfname));
msg("%s %s comes into view.",isvowel(lfname2[0]) ? "An" : "A", lfname2);
}
dointerrupt = B_TRUE;
}
} else {
dointerrupt = B_TRUE;
}
if (dointerrupt) {
interrupt(l);
}
}
}
@ -714,6 +731,29 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose) {
}
}
}
// make some noise
// (stealth check to avoid this)
if (!lfhasflag(lf, F_SILENTMOVE)) {
if (!skillcheck(lf, SC_STEALTH, 20, 0)) {
if (isairborne(lf)) {
makenoise(lf, N_FLY);
} else {
makenoise(lf, N_WALK);
}
}
}
// slip on blood in new cell?
if (!isairborne(lf)) {
int slip;
object_t *slipob;
slip = getslipperyness(newcell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
}
}
return B_FALSE;
}
@ -727,7 +767,7 @@ int movetowards(lifeform_t *lf, cell_t *dst) {
}
// move towards them
dir = getdirtowards(lf->cell, dst, lf, B_TRUE);
dir = getdirtowards(lf->cell, dst, lf, B_TRUE, DT_COMPASS);
if (dir != D_NONE) {
rv = trymove(lf, dir, B_TRUE);
}
@ -828,6 +868,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
}
where = getoblocation(o);
noise(where, lf, "a door opening", NULL);
if (player && haslos(player, where)) {
needredraw = B_TRUE;
drawscreen();
@ -943,11 +984,12 @@ int tryrun(lifeform_t *lf, int dir) {
int pullnextto(lifeform_t *lf, cell_t *c) {
int dir;
cell_t *dst = NULL;
cell_t *newdst = NULL;
dst = c;
while (dst->lf) {
dir = getdirtowards(dst, lf->cell, lf, B_FALSE);
dir = getdirtowards(dst, lf->cell, lf, B_FALSE, DT_COMPASS);
if (dir == D_NONE) {
return B_TRUE;
} else {
@ -957,11 +999,20 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
}
}
}
// is the path clear?
if (!dst || !haslof(lf, dst)) {
if (!dst) {
return B_TRUE;
}
if (!haslof(lf, dst, B_FALSE, &newdst)) {
if (newdst) {
// update destination
dst = newdst;
} else {
return B_TRUE;
}
}
if (isplayer(lf) || cansee(player, lf)) {
char buf[BUFLEN];
getlfname(lf, buf);
@ -1066,17 +1117,6 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
reason = E_OK;
moveto(lf, cell, onpurpose);
taketime(lf, getmovespeed(lf));
// slip on blood in new cell?
if (!isairborne(lf)) {
slip = getslipperyness(cell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
// don't move
reason = E_OK;
return B_FALSE;
}
}
} else {
object_t *inway;
int door, dooropen;
@ -1173,8 +1213,37 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
}
break;
case E_LFINWAY:
// attack!
return attacklf(lf, cell->lf);
if (areallies(lf, cell->lf)) {
// if it's the player in the way...
if (isplayer(cell->lf)) {
return attacklf(lf, cell->lf);
} else {
lifeform_t *lfinway;
cell_t *oldcell;
// otherwise swap locations.
// make lf who is there vanish temporarily...
lfinway = cell->lf;
cell->lf = NULL;
lfinway->cell = NULL;
// remember your cell
oldcell = lf->cell;
// move you..
moveto(lf, cell, onpurpose);
taketime(lf, getmovespeed(lf));
// move them...
lfinway->cell = oldcell;
oldcell->lf = lfinway;
reason = E_OK;
}
} else {
// attack!
return attacklf(lf, cell->lf);
}
break;
case E_GRAVBOOSTED:
if (isplayer(lf)) {
msg("You try to move but are unable to lift your feet!");
@ -1254,8 +1323,11 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
if (cell->lf) {
if (!isplayer(lf)) { // if we are a monster
// friendly monsters: don't hit other friendlies
if (isfriendly(lf) && (isfriendly(cell->lf) || isplayer(cell->lf)) ) {
if (!areenemies(lf, cell->lf)) {
// TODO: swap places instead!
return B_FALSE;
}
/*
} else if (ispeaceful(lf)) { // peaceful mosnters: don't hit anyone
return B_FALSE;
} else { // hostile/nonfriendly monsters - don't hit other monsters
@ -1263,6 +1335,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
return B_FALSE;
}
}
*/
}
}
return B_TRUE;

4
move.h
View File

@ -8,8 +8,8 @@ int closedoorat(lifeform_t *lf, cell_t *c);
int closedoor(lifeform_t *lf, object_t *o);
int diropposite(int dir);
void dorandommove(lifeform_t *lf, int badmovesok);
int getdiraway(cell_t *src, cell_t *dst, int wantcheck);
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck);
int getdiraway(cell_t *src, cell_t *dst, int wantcheck, int dirtype);
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher);
int moveawayfrom(lifeform_t *lf, cell_t *dst);
void moveeffects(lifeform_t *lf);

193
nexus.c
View File

@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "ai.h"
#include "attack.h"
#include "io.h"
@ -69,16 +70,33 @@ int main(int argc, char **argv) {
int newworld = B_FALSE;
object_t *o;
char welcomemsg[BUFLEN];
int ch;
FILE *playerfile = NULL;
atexit(cleanup);
while ((ch = getopt(argc, argv, "f:")) != -1) {
switch (ch) {
case 'f':
playerfile = fopen(optarg, "rt");
if (!playerfile) {
fprintf(stderr, "cannot open player file: %s\n",optarg);
exit(1);
}
break;
case 'h':
case '?':
default:
usage(argv[0]);
exit(0);
}
}
// init params
if (init()) {
exit(1);
}
// load whatever maps are available
loadall();
@ -101,20 +119,38 @@ int main(int argc, char **argv) {
if (!player) {
char *user;
char pname[BUFLEN];
job_t *j;
char buf[BUFLEN];
job_t *j = NULL;
char ch;
cell_t *where;
// ask for race
initprompt(&prompt, "Select your race:");
ch = 'a';
for (j = firstjob ; j ; j = j->next) {
addchoice(&prompt, ch++, j->name, NULL, j);
// read from input file if required
if (playerfile) {
char *p;
while (!feof(playerfile)) {
fgets(buf, BUFLEN, playerfile);
buf[strlen(buf)-1] = '\0';
if (strstr(buf, "job:") == buf) {
p = buf + strlen("job:");
j = findjobbyname(p);
if (j) break;
}
}
fseek(playerfile, 0, SEEK_SET);
}
j = NULL;
while (!j) {
getchoice(&prompt);
j = prompt.result;
if (!j) {
// ask for race
initprompt(&prompt, "Select your job:");
ch = 'a';
for (j = firstjob ; j ; j = j->next) {
addchoice(&prompt, ch++, j->name, NULL, j);
}
j = NULL;
while (!j) {
getchoice(&prompt);
j = prompt.result;
}
}
// find staircase
@ -135,6 +171,14 @@ int main(int argc, char **argv) {
}
givejob(player, j->id);
if (playerfile) {
if (parseplayerfile(playerfile, player)) {
// error!
exit(0);
}
fclose(playerfile);
}
// player needs hunger
addflag(player->flags, F_HUNGER, 0, NA, NA, NULL);
@ -325,6 +369,18 @@ void cleanup(void) {
// free races
}
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;
*yinc = yinc1;
*dinc = dinc1;
} else {
*xinc = xinc2;
*yinc = yinc2;
*dinc = dinc2;
}
}
void donextturn(map_t *map) {
lifeform_t *who;
@ -512,6 +568,62 @@ int init(void) {
return B_FALSE;
}
void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels) {
int xinc1,xinc2,yinc1,yinc2,dinc1,dinc2,d;
int xinc,yinc,dinc;
int i;
int x,y;
initbresnham( x1, y1, x2, y2, &xinc1, &yinc1, &dinc1, &xinc2, &yinc2, &dinc2, numpixels, &d);
x = x1;
y = y1;
for (i = 0; i < *numpixels; i++) {
retcell[i] = getcellat(m, x, y);
dobresnham(d, xinc1, yinc1, dinc1, xinc2, yinc2, dinc2, &xinc, &yinc, &dinc);
// move to next cell
d += dinc;
x += xinc;
y += yinc;
}
}
void initbresnham(int x1, int y1, int x2, int y2, int *xinc1, int *yinc1, int *dinc1, int *xinc2, int *yinc2, int *dinc2, int *numpixels, int *d) {
int deltax,deltay;
deltax = (x2 - x1);
if (deltax < 0) deltax = -deltax;
deltay = (y2 - y1);
if (deltay < 0) deltay = -deltay;
if (deltax >= deltay) {
*numpixels = deltax + 1;
*d = (deltay*2) - deltax;
*dinc1 = deltay << 1;
*dinc2 = (deltay-deltax) << 1;
*xinc1 = 1;
*xinc2 = 1;
*yinc1 = 0;
*yinc2 = 1;
} else {
*numpixels = deltay + 1;
*d = (deltax*2) - deltay;
*dinc1 = deltax << 1;
*dinc2 = (deltax - deltay) << 1;
*xinc1 = 0;
*xinc2 = 1;
*yinc1 = 1;
*yinc2 = 1;
}
if (x1 > x2) {
*xinc1 = - *xinc1;
*xinc2 = - *xinc2;
}
if (y1 > y2) {
*yinc1 = - *yinc1;
*yinc2 = - *yinc2;
}
}
void initcommands(void) {
// Actions
addcommand(CMD_UP, '<', "Go up stairs.");
@ -577,6 +689,57 @@ int limit(int *what, int min, int max) {
return limited;
}
int parseplayerfile(FILE *f, lifeform_t *lf) {
// add extra obs etc from f
char *pp;
char localbuf[BUFLEN];
char buf[BUFLEN];
int goterror = B_FALSE;
fgets(buf, BUFLEN, f);
while (!feof(f)) {
if (buf[strlen(buf)-1] == '\n') {
buf[strlen(buf)-1] = '\0';
}
//dblog("got line: [%s]",buf);
if (strstr(buf, "skill:") == buf) {
skill_t *sk;
enum SKILLLEVEL slev;
strcpy(localbuf, buf + strlen("skill:"));
pp = strtok(localbuf, " ");
if (!pp) {
dblog("ERROR in playerfile. unknown skill level in this line:\n%s\n",buf);
goterror = B_TRUE;
}
slev = findskilllevbyname(pp);
pp += (strlen(pp) + 1);
if (!pp) {
dblog("ERROR in playerfile. missing skill name in this line:\n%s\n",buf);
goterror = B_TRUE;
}
sk = findskillbyname(pp);
if (sk) {
giveskilllev(lf, sk->id, slev);
} else {
dblog("ERROR in playerfile. unknown skill (%s) in this line:\n%s\n",pp, buf);
goterror = B_TRUE;
}
} else if (strstr(buf, "ob:") == buf) {
object_t *o;
strcpy(localbuf, buf + strlen("ob:"));
o = addob(lf->pack, localbuf);
if (o) {
identify(o);
} else {
dblog("ERROR in playerfile. unknown object in this line:\n%s\n",buf);
goterror = B_TRUE;
}
}
fgets(buf, BUFLEN, f);
}
return goterror;
}
float pctof(float pct, float num) {
return ((pct / 100.0) * num);
}
@ -908,3 +1071,9 @@ void timeeffectsworld(map_t *map) {
if (db) dblog("cur time is %ld\n",curtime);
}
void usage(char *progname) {
printf("usage: %s [ -f playerfile ]\n",progname);
printf("\t-f xx\tReads player details from file xx.\n");
}

View File

@ -5,14 +5,18 @@ command_t *addcommand(enum COMMAND id, char c, char *desc);
void checkdeath(void);
void checkendgame(void);
void cleanup(void);
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);
celltype_t *findcelltype(int id);
char *getdirname(int dir);
void getrarity(int depth, int *min, int *max, int range);
int init(void);
void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels);
void initbresnham(int x1, int y1, int x2, int y2, int *xinc1, int *yinc1, int *dinc1, int *xinc2, int *yinc2, int *dinc2, int *numpixels, int *d);
void initcommands(void);
int isplayerturn(void);
int limit(int *what, int min, int max);
int parseplayerfile(FILE *f, lifeform_t *lf);
float pctof(float pct, float num);
int rnd(int min, int max);
int roll(char *string);
@ -22,3 +26,4 @@ int rollmpdice(lifeform_t *lf);
//void sortlf(map_t *map);
void sortcommands(void);
void timeeffectsworld(map_t *map);
void usage(char *progname);

162
objects.c
View File

@ -1545,7 +1545,7 @@ int changemat(object_t *o, enum MATERIAL mat) {
objecttype_t *checkobnames(char *haystack, char *needle) {
objecttype_t *ot;
char *pluralname;
int db = B_TRUE;
int db = B_FALSE;
// search for exact match
if (!strcmp(haystack, needle)) {
@ -1650,6 +1650,21 @@ void damageallobs(object_t *exception, obpile_t *op, int howmuch, int damtype) {
}
}
void dumprandomobs(int amt) {
int i;
char buf[BUFLEN];
int min,max;
int depth;
depth = player->cell->map->depth;
getrarity(depth, &min, &max, RARITYVARIANCE);
dblog("Random object dump for depth %d (rarity %d-%d)",depth,min,max);
for (i = 0; i < amt; i++) {
getrandomob(player->cell->map, buf);
dblog(" %s",buf);
}
dblog("END RANDOM OBJECT");
}
void explodeob(object_t *o, flag_t *f, int bigness) {
cell_t *c;
int dam;
@ -1776,9 +1791,13 @@ objecttype_t *findotn(char *name) {
knowledge_t *k;
char *modname;
char *p;
int db = B_TRUE;
int db = B_FALSE;
brand_t *om;
if (!strlen(name)) {
return NULL;
}
modname = strdup(name);
// make some replacements
@ -2126,6 +2145,8 @@ int getobvalue(object_t *o) {
} else if (o->type->obclass->id == OC_WAND) {
price *= 2.25;
}
} else if (f->id == F_MANUALOF) {
price *= 124;
}
}
@ -3107,7 +3128,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
int selidx;
int amt;
flag_t *f;
int db = B_TRUE;
int db = B_FALSE;
char *pluralname;
char brandname[BUFLEN];
char cursestr[BUFLEN];
@ -3124,7 +3145,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
depth = rnd(1,MAXDEPTH);
}
getrarity(depth, &raritymin, &raritymax, 25);
getrarity(depth, &raritymin, &raritymax, RARITYVARIANCE);
while (!done) {
if (db) dblog("adding random object with rarity value between %d - %d",raritymin,raritymax);
@ -3635,7 +3656,7 @@ int getthrowdam(object_t *o) {
// ie. 1 tonne object does 1000 damage (car)
dam = ceil((double)getobunitweight(o));
// missile objects do extra damage
if (hasflag(o->flags, F_MISSILE)) {
if (hasflag(o->flags, F_THROWMISSILE)) {
dam *= 2;
}
// max
@ -4025,7 +4046,6 @@ void initobjects(void) {
addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addoc(OC_ROCK, "Rocks/Gems", "Boring (or not so boring) rocks.", '*');
addoc(OC_FOOD, "Food", "Yum!", '%');
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, "");
@ -4091,7 +4111,7 @@ void initobjects(void) {
// 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);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "50-100 stones");
@ -4144,7 +4164,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addot(OT_ASH, "pile of ash", "A pile of ash", MT_STONE, 0.1, OC_ROCK);
addflag(lastot->flags, F_GLYPH, B_TRUE, NA, NA, ",");
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
@ -4254,7 +4274,7 @@ void initobjects(void) {
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addot(OT_POT_MAGIC, "potion of magic", "Fully restores the drinker's magical energy.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addot(OT_POT_ACROBATICS, "potion of acrobatics", "Allows the drinker to leap large distances.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
addot(OT_POT_ELEMENTENDURE, "potion of endure elements", "Grants the imbiber temporary resistance to both fire and cold.", MT_GLASS, 1, OC_POTION);
@ -4293,7 +4313,7 @@ void initobjects(void) {
addot(OT_POT_POLYMORPH, "potion of polymorph self", "Transmutes the drinker into another living race.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addot(OT_POT_INVULN, "potion of invulnerability", "Grants the drinker temporary immunity to physical harm.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
@ -4328,6 +4348,11 @@ void initobjects(void) {
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTLIFE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
addot(OT_SCR_DETECTOBS, "scroll of detect objects", "Senses objects near the caster.", MT_PAPER, 0.5, OC_SCROLL);
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTOBS, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
addot(OT_SCR_DETECTMAGIC, "scroll of detect magic", "Allows the reader to detect magical enchantments.", MT_PAPER, 0.5, OC_SCROLL);
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTMAGIC, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
@ -4400,12 +4425,14 @@ void initobjects(void) {
addot(OT_S_PULLMETAL, "pull metal", "Pulls metal objects to the caster.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addot(OT_S_ACCELMETAL, "accelerate metal", "Greatly accelerates a metal object thrown by the caster.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addot(OT_S_METALHEAL, "metal healing", "Uses nearby metal for accelerated healing.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
// l3
addot(OT_S_EXPLODEMETAL, "explode metal", "Causes all metal objects in a location explode.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
@ -4417,6 +4444,7 @@ void initobjects(void) {
addot(OT_S_ANIMATEMETAL, "animate metal", "Imbues a metallic weapon with temporary life, enabling it to fight on its own.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
///////////////////
// death
@ -4461,6 +4489,9 @@ void initobjects(void) {
addot(OT_S_MAPPING, "sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addot(OT_S_DETECTOBS, "detect objects", "Senses objects near the caster.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
// l3
addot(OT_S_DETECTAURA, "detect aura", "Senses holiness or evil near the caster.", MT_NOTHING, 0, OC_SPELL);
@ -4599,6 +4630,14 @@ void initobjects(void) {
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
// TODO: hardcode how ai casts this
// l4
addot(OT_S_PACIFY, "pacify", "Induces calmness in another, preventing them from attacking.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addot(OT_S_CHARM, "charm", "Causes another lifeform to temporary become friendly.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
///////////////////
// modification
///////////////////
@ -4662,6 +4701,10 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addot(OT_S_PULL, "pull", "Pulls lifeforms towards the caster.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
// l4
addot(OT_S_TELEPORT, "teleportation", "Causes the caster to teleport to a new location within the same level. Becomes controlled at high power.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
@ -4712,6 +4755,8 @@ void initobjects(void) {
// divine powers
addot(OT_A_DEBUG, "debug", "You can toggle debugging for a lifeform.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_ENHANCE, "enhance", "Enhance a lifeform's stats.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_LEARN, "learn", "Learn new skills.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_S_WISH, "wish", "Grants the caster any item of their choice (with some limitations).", MT_NOTHING, 0, OC_SPELL);
@ -4749,8 +4794,12 @@ void initobjects(void) {
// manuals
addot(OT_MAN_ATHLETICS, "manual of athletics", "Teaches you the skill 'athletics'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_ATHLETICS, NA, NA, NULL);
addot(OT_MAN_BACKSTAB, "manual of stabbing", "Teaches you the skill 'backstab'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_BACKSTAB, NA, NA, NULL);
addot(OT_MAN_FIRSTAID, "manual of first aid", "Teaches you the skill 'first aid'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_FIRSTAID, NA, NA, NULL);
addot(OT_MAN_LISTEN, "manual of listening", "Teaches you the skill 'listen'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_LISTEN, NA, NA, NULL);
addot(OT_MAN_LOCKPICKING, "manual of lockpicking", "Teaches you the skill 'lockpicking'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_LOCKPICKING, NA, NA, NULL);
addot(OT_MAN_RESEARCH, "manual of research", "Teaches you the skill 'research'.", MT_PAPER, 3, OC_BOOK);
@ -4759,6 +4808,8 @@ void initobjects(void) {
addflag(lastot->flags, F_MANUALOF, SK_MAGITEMUSAGE, NA, NA, NULL);
addot(OT_MAN_SPELLCASTING, "manual of spellcasting", "Teaches you the skill 'spellcasting'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SPELLCASTING, NA, NA, NULL);
addot(OT_MAN_STEALTH, "manual of stealth", "Teaches you the skill 'stealth'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_STEALTH, NA, NA, NULL);
addot(OT_MAN_TECHUSAGE, "manual of technology", "Teaches you the skill 'technology'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_TECHUSAGE, NA, NA, NULL);
// weapon manuals
@ -4820,6 +4871,8 @@ void initobjects(void) {
// divination
addot(OT_SB_DETECTLIFE, "spellbook of detect life", "Teaches the spell 'detect life'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTLIFE, NA, NA, NULL);
addot(OT_SB_DETECTOBS, "spellbook of detect objects", "Teaches the spell 'detect objects'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTOBS, NA, NA, NULL);
addot(OT_SB_MAPPING, "spellbook of sense surroundings", "Teaches the spell 'surroundings'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, NA, NA, NULL);
addot(OT_SB_DETECTAURA, "spellbook of detect aura", "Teaches the spell 'detect aura'.", MT_PAPER, 1.5, OC_BOOK);
@ -4867,10 +4920,16 @@ void initobjects(void) {
// mental
addot(OT_SB_MINDSCAN, "spellbook of mind scan", "Teaches the spell 'mind scan'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_MINDSCAN, NA, NA, NULL);
addot(OT_SB_SLEEP, "spellbook of sleep", "Teaches the spell 'sleep'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_SLEEP, NA, NA, NULL);
addot(OT_SB_TELEKINESIS, "spellbook of telekinesis", "Teaches the spell 'telekinesis'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_TELEKINESIS, NA, NA, NULL);
addot(OT_SB_PACIFY, "spellbook of pacify", "Teaches the spell 'pacify'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_PACIFY, NA, NA, NULL);
addot(OT_SB_PSYARMOUR, "spellbook of psychic armour", "Teaches the spell 'psychic armour'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_PSYARMOUR, NA, NA, NULL);
addot(OT_SB_CHARM, "spellbook of charm", "Teaches the spell 'charm'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_CHARM, NA, NA, NULL);
// modification
addot(OT_SB_INSCRIBE, "spellbook of inscribe", "Teaches the spell 'inscribe'.", MT_PAPER, 1.5, OC_BOOK);
addflag(lastot->flags, F_LINKSPELL, OT_S_INSCRIBE, NA, NA, NULL);
@ -4922,7 +4981,8 @@ void initobjects(void) {
f2 = hasflag(spelltype->flags, F_SPELLLEVEL);
if (f2) {
int rarity;
rarity = 90 - (f2->val[0]*12);
// ie. 80 - spelllevel*12
rarity = 80 - (f2->val[0]*12);
addflag(ot->flags, F_RARITY, H_ALL, rarity, NA, NULL);
} else {
dblog("Spell %s has no spell level - can't determine rarity for spellbook.", spelltype->name);
@ -5112,7 +5172,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, "Where will you spray?");
addflag(lastot->flags, F_RNDCHARGES, 5, 10, NA, NULL);
addflag(lastot->flags, F_RNDCHARGES, 1, 5, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_LANTERNLED, "LED lantern", "A low-powered but efficient lantern which will last almost forever.", MT_METAL, 0.5, OC_TECH);
@ -5237,6 +5297,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "^");
addflag(lastot->flags, F_SHARP, 1, 2, NA, NULL);
addflag(lastot->flags, F_CRUSHABLE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addot(OT_CALTROP, "caltrop", "Connected metal spikes arranged such that one will always point upwards.", MT_METAL, 0.2, OC_MISC);
addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL);
@ -5757,7 +5818,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, 10, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, 5, NA, NULL);
// armour - shields
addot(OT_BUCKLER, "buckler", "A small, unobtrusive wooden shield.", MT_WOOD, 3.00, OC_ARMOUR);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
@ -5879,6 +5940,7 @@ void initobjects(void) {
// missiles
addot(OT_DART, "dart", "A small, sharp projectile weapon.", MT_WOOD, 0.5, OC_MISSILE);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_MISSILEDAM, 2, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, "");
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
@ -5886,6 +5948,7 @@ void initobjects(void) {
addot(OT_NANODART, "nanodart", "A metal dart with a laser-sharpened point.", MT_METAL, 0.5, OC_MISSILE);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_MISSILEDAM, 2, NA, NA, "");
addflag(lastot->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, "");
@ -5894,6 +5957,7 @@ void initobjects(void) {
addot(OT_JAVELIN, "javelin", "A long, sharp missile weapon.", MT_METAL, 1.5, OC_MISSILE);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_MISSILEDAM, 3, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, "");
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, "");
@ -5941,7 +6005,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 4, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
@ -5952,7 +6016,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 3, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
addot(OT_SHORTSWORD, "short sword", "A short blade for fighting. Better for stabbing.", MT_METAL, 2.5, OC_WEAPON);
@ -5988,7 +6052,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
@ -6006,7 +6070,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 6, 1, NULL);
addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
addot(OT_BATTLEAXE, "battleaxe", "An axe specifically designed for combat.", MT_METAL, 5, OC_WEAPON);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
@ -6031,7 +6095,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 3, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
@ -6041,7 +6105,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
@ -6104,7 +6168,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 8, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL);
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL);
@ -6498,8 +6562,8 @@ int ismetal(enum MATERIAL mat) {
return metal;
}
int ismissile(object_t *o) {
if (hasflag(o->flags, F_MISSILE)) {
int isthrowmissile(object_t *o) {
if (hasflag(o->flags, F_THROWMISSILE)) {
return B_TRUE;
}
// special cases...
@ -7355,13 +7419,19 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
return B_TRUE;
} else {
if (f->val[1] != NA) {
cell_t *newwhere = NULL;
if ((f->val[1] & TR_NEEDLOS) && !haslos(lf, where)) {
msg("You can't see there!");
return B_TRUE;
}
if ((f->val[1] & TR_NEEDLOF) && !haslof(lf, where)) {
msg("You have no line of fire to there!");
return B_TRUE;
if ((f->val[1] & TR_NEEDLOF) && !haslof(lf, where, B_TRUE, &newwhere)) {
if (newwhere) {
// update destination
where = newwhere;
} else {
msg("You have no line of fire to there!");
return B_TRUE;
}
}
}
}
@ -7545,7 +7615,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
// announce
if (!seen) {
youhear(where, "something spraying.");
noise(where, NULL, "something spraying.", NULL);
}
} else if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) {
object_t *oo,*nextoo;
@ -8029,13 +8099,23 @@ int pour(lifeform_t *lf, object_t *o) {
dst->blessknown = B_TRUE;
// remove bonuses
killflagsofid(dst->flags, F_BONUS);
// remove temporary flags
// remove temporary flags and modify some others
for (f = dst->flags->first ; f ; f = nextf) {
nextf = f->next;
if (f->lifetime > 0) {
killflag(f);
} else if (f->id == F_FROZEN) {
killflag(f);
} else if (f->id == F_ONFIRE) {
killflag(f);
} else if (f->id == F_POISONED) {
killflag(f);
} else if (f->id == F_OBHP) {
f->val[0] = f->val[1];
}
}
// restore hp
if (!isknown(dst)) makeknown(dst->type->id);
} else if (o->type->id == OT_POT_ACID) {
@ -8706,8 +8786,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
char obname[BUFLEN];
getlfname(lf, lfname);
getobname(oo, obname,oo->amt);
msg("%s%s %s %s softly.",lfname,getpossessive(lfname),noprefix(obname),
(oo->amt == 1) ? "glows" : "glow");
msg("A black aura breaks away from %s%s %s.",lfname,getpossessive(lfname),noprefix(obname));
seen = B_TRUE;
}
// uncurse it
@ -9159,6 +9238,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
int acc;
int youhit;
object_t *newob;
cell_t *newloc;
int db = B_TRUE;
reason = E_OK;
@ -9303,6 +9383,22 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
msg("%s", throwstring);
}
// adjust destination location in case something is in the way.
haslof(thrower, where, LOF_NEED, &newloc);
if (newloc) {
where = newloc;
target = where->lf;
if (target && isdead(target)) {
target = NULL;
}
if (target) {
getlfname(target, targetname);
}
}
//taketime(thrower, SPEED_THROW);
// some obejcts will die when thrown.
@ -9406,7 +9502,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
msg("%s", buf2);
} else {
if (willshatter(o->material->id)) {
youhear(where, "shattering glass.");
noise(where, NULL, "shattering glass.", NULL);
}
}
sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea);
@ -9455,7 +9551,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
msg("%s shatters!",obcaps);
free(obcaps);
} else {
youhear(where, "shattering glass.");
noise(where, NULL, "shattering glass.", NULL);
}
shattered = B_TRUE;
}
@ -9593,7 +9689,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (youhit && target) {
if (getobweight(o) >= getlfweight(target, B_NOOBS)) {
int dir;
dir = getdirtowards(srcloc, target->cell, target, B_FALSE);
dir = getdirtowards(srcloc, target->cell, target, B_FALSE, DT_COMPASS);
knockback(target, dir, 1, thrower);
}
}
@ -10233,7 +10329,7 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
}
// penalty for throwing non-missiles
if (missile && !firearm && !ismissile(missile)) {
if (missile && !firearm && !isthrowmissile(missile)) {
acc -= 20;
}
return acc;

View File

@ -31,6 +31,7 @@ int countnames(char **list);
int countobs(obpile_t *op);
int curseob(object_t *o);
void damageallobs(object_t *exception, 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);
material_t *findmaterial(int id);
@ -127,7 +128,7 @@ int isknownot(objecttype_t *ot);
int isidentified(object_t *o);
int isimpassableob(object_t *o, lifeform_t *lf);
int ismetal(enum MATERIAL mat);
int ismissile(object_t *o);
int isthrowmissile(object_t *o);
int isoperable(object_t *o);
int isplainob(object_t *o);
int ispourable(object_t *o);

2
save.c
View File

@ -277,6 +277,7 @@ map_t *loadmap(char *basefile) {
fscanf(f, "%d\n",&m->nextmap[i]); // map dimensons
}
if (db) dblog("--> Finished map info. name='%s', dims=%d x %d\n",m->name, m->w, m->h);
fscanf(f, "beingcreated:%d\n",&m->beingcreated);
fscanf(f, "id:%d\n",&m->id); // map id
// load lifeforms
@ -710,6 +711,7 @@ int savemap(map_t *m) {
for (i = 0; i < MAXDIR_ORTH; i++) {
fprintf(f, "%d\n",m->nextmap[i] ); // map dimensons
}
fprintf(f, "beingcreated:%d\n",m->beingcreated);
// save all non-player lifeforms (includes their objects)
fprintf(f, "lifeforms:\n");

333
spell.c
View File

@ -400,6 +400,36 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else {
msg("There is nobody there!");
}
} else if (abilid == OT_A_ENHANCE) {
cell_t *where;
where = askcoords("Enhance stats of who?", TT_MONSTER);
if (where && where->lf) {
char ch;
enum ATTRIB att;
ch = askchar("Enhance which stat (n for none)?", "sdcin",NULL, B_TRUE);
switch (ch) {
case 's': att = A_STR; break;
case 'd': att = A_DEX; break;
case 'c': att = A_CON; break;
case 'i': att = A_IQ; break;
default: att = A_NONE; break;
}
if (att != A_NONE) {
char buf[BUFLEN];
int val;
askstring("Set stat to what", '?', buf, BUFLEN, NULL);
val = atoi(buf);
if ((val <= 0) || (val > 18)) {
msg("Invalid value.");
} else {
setattr(where->lf, att, val);
getlfname(where->lf, buf);
msg("%s%s %s set to %d.", buf, getpossessive(buf), getattrname(att), val);
}
//
}
}
} else if (abilid == OT_A_HEAVYBLOW) {
object_t *wep;
char dirch;
@ -672,7 +702,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_AIRBLAST) {
int dir;
object_t *o,*nexto;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_NEED, spellid, power)) return B_TRUE;
target = targcell->lf;
if (cansee(player, caster)) {
@ -680,7 +710,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("%s emit%s a powerful blast of air!", castername, isplayer(caster) ? "" : "s");
}
dir = getdirtowards(caster->cell, targcell, target, B_FALSE);
dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS);
// lfs
if (target) {
knockback(target, dir, power, caster);
@ -704,7 +734,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
newlf = makezombie(o);
if (newlf) {
if (isplayer(caster) && skillcheck(caster, A_IQ, 20, power)) {
makefriendly(newlf);
makefriendly(newlf, PERMENANT);
}
donesomething = B_TRUE;
}
@ -813,21 +843,23 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
teleportto(caster, targcell, B_TRUE);
}
} else if (spellid == OT_S_BURNINGWAVE) {
cell_t *c;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, spellid, power)) return B_TRUE;
cell_t *retcell[MAXRETCELLS];
int nretcell;
int i;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_WALLSTOP, spellid, power)) return B_TRUE;
if (cansee(player, caster)) {
msg("%s shoots a wave of fire!",castername);
msg("%s shoot%s a wave of fire!",castername, isplayer(caster) ? "" : "s");
}
// create a line of fire towards the target cell
c = caster->cell;
while (c != targcell) {
int dir;
dir = getdirtowards(c, targcell, NULL, B_FALSE);
c = getcellindir(c, dir);
if (!c) break;
if (c->type->solid) break;
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, targcell->x, targcell->y, retcell, &nretcell);
// don't set caster's cell on fire!
for (i = 1; i < nretcell; i++) {
cell_t *c;
c = retcell[i];
// set on fire
addob(c->obpile, "medium fire");
if (c->lf) {
@ -841,7 +873,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_CLOUDKILL) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
if (targcell->type->solid) {
fizzle(caster);
@ -854,10 +886,48 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("A cloud of poison gas appears!");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (spellid == OT_S_CHARM) {
char targetname[BUFLEN];
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
return B_FALSE;
}
getlfname(target, targetname);
if (getallegiance(caster) == AL_PEACEFUL) {
fizzle(caster);
return B_FALSE;
}
if (getallegiance(target) == getallegiance(caster)) {
if (isplayer(caster)) {
msg("%s is already allied with you!",targetname);
}
return B_FALSE;
}
if (skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(caster) || cansee(player, target)) {
msg("%s resists.",targetname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
int howlong;
if (isplayer(caster) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
howlong = getspellduration(20,30,blessed) + (power*10);
addtempflag(target->flags, F_CHARMEDBY, caster->id, NA, NA, NULL, howlong);
}
} else if (spellid == OT_S_CONECOLD) {
char lfname[BUFLEN];
int acc;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}');
if (isplayer(caster) || cansee(player, caster)) {
@ -1042,8 +1112,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_DETECTLIFE) {
target = caster;
if (isplayer(caster)) {
int howlong;
int howlong,radius;
howlong = getspellduration(10,20,blessed) + (power*2);
radius = power * 10;
addtempflag(target->flags, F_DETECTLIFE, 10, NA, NA, NULL, howlong);
} else {
// monsters can't use this
@ -1068,9 +1139,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// monsters can't use this
}
*/
} else if (spellid == OT_S_DETECTOBS) {
target = caster;
if (isplayer(caster)) {
int howlong,radius;
howlong = getspellduration(25,35,blessed) + (power*10);
radius = power*10;
addtempflag(target->flags, F_DETECTOBS, radius, NA, NA, NULL, howlong);
} else {
// monsters can't use this
}
} else if (spellid == OT_S_DETONATE) {
// don't need line of fire!
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, B_FALSE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
explodecells(targcell, 20, B_TRUE, NULL, power / 4, B_TRUE);
@ -1081,7 +1162,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
float totalmass = 0;
object_t *o, *nexto;
if (!validatespellcell(caster, &targcell, TT_OBJECT, B_FALSE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_OBJECT, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
// how much metal is there?
for (o = targcell->obpile->first ; o ; o = nexto) {
@ -1194,7 +1275,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldist(caster->cell, targcell) <= range)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell, B_FALSE, NULL)) {
char lfname[BUFLEN];
// automatic hit
getlfname(targcell->lf, lfname);
@ -1216,7 +1297,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char numbuf[BUFLEN];
numtotext(power, numbuf);
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}');
if (isplayer(caster) || cansee(player, caster)) {
@ -1245,7 +1326,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FIREBALL) {
int failed = B_FALSE;
// ask for a target cell
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
if (targcell) {
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
int dir;
@ -1312,7 +1393,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FIREDART) {
char lfname[BUFLEN];
int acc;
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}');
if (isplayer(caster) || cansee(player, caster)) {
@ -1363,7 +1444,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell, B_FALSE, NULL)) {
char lfname[BUFLEN];
// automatic hit
getlfname(targcell->lf, lfname);
@ -1378,7 +1459,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FLAMEPILLAR) {
int failed = B_FALSE;
// ask for a target cell
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_WALLSTOP, spellid, power)) return B_TRUE;
if (targcell && haslos(caster, targcell)) {
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
flag_t *f;
@ -1565,7 +1646,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_HASTE) {
int howlong = 15;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
target = targcell->lf;
@ -1747,7 +1828,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char numbuf[BUFLEN];
numtotext(power, numbuf);
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, LOF_NEED, spellid, power)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}');
if (isplayer(caster) || cansee(player, caster)) {
@ -1950,7 +2031,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE;
}
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, LOF_WALLSTOP, spellid, power)) return B_TRUE;
// 4 is the same as ST_TITANIC strength
// 10 = gun speed
@ -2062,9 +2143,40 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(caster->flags, F_ARBOOST, power*3, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
} else if (spellid == OT_S_PULL) {
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_WALLSTOP, spellid, power)) return B_TRUE;
target = targcell->lf;
if (target) {
int failed = B_FALSE;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
failed = B_TRUE;
} else {
// they get pulled towards caster
failed = pullnextto(target, caster->cell);
}
if (isplayer(target) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if (failed) {
if (isplayer(target) || cansee(player, target)) {
char buf[BUFLEN];
getlfname(target, buf);
msg("%s %s pulled forward slightly.", buf, isplayer(target) ? "are" : "is");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
return B_FALSE;
}
} else {
fizzle(caster);
}
} else if (spellid == OT_S_PULLMETAL) {
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_OBJECT, B_TRUE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_OBJECT, B_TRUE, LOF_WALLSTOP, spellid, power)) return B_TRUE;
if (targcell->lf) {
object_t *o;
@ -2282,7 +2394,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int willannounce = B_FALSE;
char targname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_FALSE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
target = targcell->lf;
if (!target) {
@ -2305,7 +2417,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_KNOCK) {
object_t *o;
if (!validatespellcell(caster, &targcell,TT_DOOR, B_FALSE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_DOOR, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
o = hasobwithflag(targcell->obpile, F_DOOR);
if (o) {
int dooropen;
@ -2337,7 +2449,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// at power 3, you can control where the light appears
// at power 8, the light is permenant
if (power >= 3) {
if (!validatespellcell(caster, &targcell,TT_NONE, B_FALSE, spellid, power)) return B_TRUE;
// TODO: this actually means we can cast it through walls!!!
if (!validatespellcell(caster, &targcell,TT_NONE, B_FALSE, LOF_DONTNEED, spellid, power)) return B_TRUE;
} else {
targcell = caster->cell;
}
@ -2431,6 +2544,49 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(caster->flags, F_DTIMMUNE, DT_FALL, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
} else if (spellid == OT_S_PACIFY) {
char targetname[BUFLEN];
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
return B_FALSE;
}
getlfname(target, targetname);
if (skillcheck(targcell->lf, SC_RESISTMAG, 30 + power, 0)) {
if (isplayer(caster) || cansee(player, target)) {
msg("%s resists.",targetname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
int donesomething = B_FALSE;
// stop targetting anybody
if (killflagsofid(target->flags, F_TARGET)) {
donesomething = B_TRUE;
}
if (killflagsofid(target->flags, F_TARGETCELL)) {
donesomething = B_TRUE;
}
if (killflagsofid(target->flags, F_HOSTILE)) {
donesomething = B_TRUE;
}
if (donesomething) {
if (cansee(player, target)) {
msg("%s calms down.",targetname);
}
} else {
if (isplayer(caster)) {
msg("%s already seems calm enough.",targetname);
}
}
return B_FALSE;
}
} else if (spellid == OT_S_PASSWALL) {
int howlong = 7;
target = caster;
@ -2578,7 +2734,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_SPARK) {
object_t *o,*nexto;
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, B_FALSE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
if (haslos(player, targcell)) {
msg("A small spark of flame appears.");
@ -2837,9 +2993,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
o = relinkob(o, newloc->obpile);
}
if (o) {
if (isblind(caster)) {
youhear(caster->cell, "something hitting the ground.");
} else {
noise(caster->cell, NULL, "something hitting the ground.", NULL);
if (!isblind(caster)) {
msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : "");
}
} else {
@ -3111,7 +3266,7 @@ void pullobto(object_t *o, lifeform_t *lf) {
}
// where does it end up?
obloc = getoblocation(o);
dir = getdirtowards(lf->cell, obloc, NULL, B_FALSE);
dir = getdirtowards(lf->cell, obloc, NULL, B_FALSE, DT_COMPASS);
newcell = getcellindir(lf->cell, dir);
if (newcell) {
// move next to player
@ -3205,19 +3360,68 @@ lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **targe
return *target;
}
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid, int power) {
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlos, enum LOFTYPE needlof, enum OBTYPE spellid, int power) {
int maxrange = UNLIMITED;
int done = B_FALSE;
cell_t *where = NULL;
maxrange = getspellrange(spellid, power);
while (!done) {
if (*targcell) {
done = B_TRUE;
if (where) {
cell_t *newwhere = NULL;
// validate it
if (where && needlos && !haslos(caster, where)) {
msg("You cannot see there!"); more();
where = NULL;
}
if (where && needlof && !haslof(caster, where, needlof, &newwhere)) {
if (newwhere) {
// warn!
int ch;
ch = askchar("Your have no clear line of fire - really target here?","yn","n", B_TRUE);
if (ch == 'y') {
where = newwhere;
} else {
where = NULL;
}
} else {
where = NULL;
}
}
if (where && (maxrange != UNLIMITED) && (getcelldist(caster->cell, where) > maxrange)) {
// out of range
msg("Too far away - max range is %d.",maxrange); more();
where = NULL;
}
if (where && isplayer(caster) && (where == caster->cell)) {
// warn before targetting yourself!
if (getiqname(getattr(caster, A_IQ), NULL) >= IQ_AVERAGE) {
objecttype_t *sp;
sp = findot(spellid);
if (sp) {
if (hasflagval(sp->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL) ||
hasflagval(sp->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL)) {
int ch;
ch = askchar("Really target yourself","yn","n", B_TRUE);
if (ch != 'y') {
where = NULL;
}
}
}
}
}
// still got a target?
if (where) {
*targcell = where;
done = B_TRUE;
}
} else {
// ask for a target cell
if (isplayer(caster)) {
cell_t *where;
char buf[BUFLEN];
if (maxrange == UNLIMITED) {
objecttype_t *ot;
@ -3227,51 +3431,12 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i
sprintf(buf, "Where will you target your spell [max range %d]?",maxrange);
}
where = askcoords(buf, targtype);
if (where) {
//if (haslos(caster, where) || (where == caster->cell)) {
if (needlof && !haslof(caster, where)) {
// no line of sight
fizzle(caster);
return NULL;
} else if ((maxrange != UNLIMITED) && (getcelldist(caster->cell, where) > maxrange)) {
// out of range
fizzle(caster);
return NULL;
} else {
*targcell = where;
done = B_TRUE;
// warn before targetting yourself!
if (isplayer(caster) && (where == caster->cell)) {
if (getiqname(getattr(caster, A_IQ), NULL) >= IQ_AVERAGE) {
objecttype_t *sp;
sp = findot(spellid);
if (sp) {
if (hasflagval(sp->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL) ||
hasflagval(sp->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL)) {
int ch;
ch = askchar("Really target yourself","yn","n", B_TRUE);
if (ch != 'y') {
*targcell = NULL;
done = B_FALSE;
}
}
}
}
}
}
/*
} else {
msg("You can't see there!");
more();
*targcell = NULL;
done = B_FALSE;
if (!where) {
int ch;
ch = askchar("Abandon your spell?","yn","n", B_TRUE);
if (ch != 'y') {
where = NULL;
}
*/
} else {
// no line of sight or invalid cell
fizzle(caster);
return NULL;
}
} else {
// TODO: fill in monster code?

View File

@ -19,7 +19,7 @@ void pullobto(object_t *o, lifeform_t *lf);
void stopspell(lifeform_t *caster, enum OBTYPE spellid);
void stopallspells(lifeform_t *lf);
lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target);
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid, int power);
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlos, enum LOFTYPE needlof, enum OBTYPE spellid, int power);
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
#endif

23
text.c
View File

@ -32,16 +32,18 @@ char *capitaliseall(char *text) {
char *getattrname(enum ATTRIB att) {
switch (att) {
case A_NONE:
return "?attrib_none?";
case A_STR:
return "strength";
case A_IQ:
return "intelligence";
case A_DEX:
return "dexterity";
default:
break;
case A_CON:
return "constitution";
}
return "?unknown?";
return "?badattrib?";
}
char *getpossessive(char *text) {
@ -219,6 +221,21 @@ char *makeplural(char *text) {
return newtext;
}
int needses(char *text) {
if (text[strlen(text)-1] == 's') {
return B_TRUE;
}
if (strlen(text) >= 2) {
if ((text[strlen(text)-2] == 'c') &&
(text[strlen(text)-1] == 'h')) {
return B_TRUE;
}
}
return B_FALSE;
}
char *noprefix(char *obname) {
char *p;
p = strchr(obname, ' ');

1
text.h
View File

@ -10,6 +10,7 @@ char *gettimetextfuzzy(char *retbuf, int wantpm);
char *getweighttext(float weight, char *buf);
int isvowel(char c);
char *makeplural(char *text);
int needses(char *text);
char *noprefix(char *obname);
char *numtotext(int num, char *buf);
char *roman(int num);