* [+] 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

84
ai.c
View File

@ -165,6 +165,14 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi
// cast spell at the victim // cast spell at the victim
if (spelllf) *spelllf = victim; if (spelllf) *spelllf = victim;
if (spellcell) *spellcell = victim->cell; 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; return;
} }
if (goingtomove && (getcelldist(lf->cell, target->cell) == 1)) {
}
// can we attack with spells (ie. ones which target the victim)? // 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); 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; int spellfailed = B_FALSE;
lifeform_t *spelllf = NULL; lifeform_t *spelllf = NULL;
cell_t *spellcell = NULL; cell_t *spellcell = NULL;
@ -400,7 +416,7 @@ void aimove(lifeform_t *lf) {
} }
// if not adjacent, check for guns, wands, throwing // if not adjacent, check for guns, wands, throwing
if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell)) { if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell, B_FALSE, NULL)) {
// can we attack by firing something? // can we attack by firing something?
gun = getfirearm(lf); gun = getfirearm(lf);
if (goingtomove && gun && getammo(lf)) { if (goingtomove && gun && getammo(lf)) {
@ -422,8 +438,8 @@ void aimove(lifeform_t *lf) {
// can we attack by throwing something? // can we attack by throwing something?
if (goingtomove) { if (goingtomove) {
// TODO: or firing! check if we have a firearm first. //
o = getbestmissile(lf); o = getbestthrowmissile(lf);
if (o) { if (o) {
if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name); if (db) dblog(".oO { will throw %s at my target instead of moving }", o->type->name);
// try to throw it! // try to throw it!
@ -556,9 +572,10 @@ void aimove(lifeform_t *lf) {
// not attacking anyone in particular // not attacking anyone in particular
if (db) dblog(".oO { i do not have a target or can't move towards it. }"); 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 // are we hostile? if so, look for a target
f = hasflag(lf->flags, F_HOSTILE); switch (getallegiance(lf)) {
if (f) {
int i; int i;
int x,y;
case AL_HOSTILE:
if (db) dblog(".oO { i am hostile. looking for a target. }"); if (db) dblog(".oO { i am hostile. looking for a target. }");
// look around for a target // look around for a target
@ -587,12 +604,8 @@ void aimove(lifeform_t *lf) {
} }
} }
} }
} break;
case AL_FRIENDLY: // are we friendly? if so, look for a target
// 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. }"); if (db) dblog(".oO { i am friendly to the player. looking for a target. }");
// look around for a target // look around for a target
// TODO: use our vis rang einstead of 10! // TODO: use our vis rang einstead of 10!
@ -613,6 +626,9 @@ void aimove(lifeform_t *lf) {
} }
} }
} }
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 db = B_FALSE;
int ok = B_FALSE; int ok = B_FALSE;
int specialcase = B_FALSE; int specialcase = B_FALSE;
int specificcheckok = B_FALSE;
if (lfhasflag(lf, F_DEBUG)) { if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE; db = B_TRUE;
@ -801,6 +818,10 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if (ok) break; if (ok) break;
} }
} }
} else if (ot->id == OT_S_CHARM) {
if (getnearbypeaceful(lf)) {
ok = B_TRUE;
}
} else { } else {
dblog(".oO { cant cast %s - specialcase conditions not yet coded }", ot ? ot->name : "?unkownspell?"); dblog(".oO { cant cast %s - specialcase conditions not yet coded }", ot ? ot->name : "?unkownspell?");
return B_FALSE; return B_FALSE;
@ -812,45 +833,58 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
return B_FALSE; 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)) { if ((ot->id == OT_S_BLINDNESS) && isblind(victim)) {
return B_FALSE; specificcheckok = B_FALSE;
} }
if ((ot->id == OT_S_HASTE) && lfhasflag(lf, F_FASTACT)) { 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) {
return B_FALSE; specificcheckok = B_FALSE;
} }
if ((ot->id == OT_S_WEAKEN)) { if ((ot->id == OT_S_WEAKEN)) {
flag_t *lff; flag_t *lff;
for (lff = lf->flags->first; lff ; lff = lff->next) { for (lff = lf->flags->first; lff ; lff = lff->next) {
if ((lff->id == F_ATTRMOD) && (lff->val[0] == A_STR) && (lff->obfrom == OT_S_WEAKEN)) { if ((lff->id == F_ATTRMOD) && (lff->val[0] == A_STR) && (lff->obfrom == OT_S_WEAKEN)) {
specificcheckok = B_FALSE;
break;
}
}
}
if (!specificcheckok) {
dblog(".oO { cant cast %s - specific spell check failed }", ot ? ot->name : "?unkownspell?");
return B_FALSE; return B_FALSE;
} }
}
}
return B_TRUE; return B_TRUE;
} }

181
attack.c
View File

@ -84,6 +84,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
char attackername[BUFLEN]; char attackername[BUFLEN];
char victimname[BUFLEN]; char victimname[BUFLEN];
int fatal = B_FALSE; int fatal = B_FALSE;
int firstisbackstab = B_FALSE;
flag_t *unarmedflag = NULL; flag_t *unarmedflag = NULL;
object_t *wep; object_t *wep;
obpile_t *op = NULL; obpile_t *op = NULL;
@ -109,8 +110,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
return B_TRUE; return B_TRUE;
} }
// get names // get names
getlfname(lf, attackername); getlfname(lf, attackername);
@ -124,6 +123,25 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
getlfname(victim, victimname); 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); 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. // ie. if critical is 0, do this once.
// if critical is 1, do this twice. // if critical is 1, do this twice.
// etc. // etc.
dam[ndam] = 0; dam[0] = 0;
for (n = 0; n < critical+1; n++) { for (n = 0; n < critical+1; n++) {
if (unarmedflag) { if (unarmedflag) {
// this mosnter's unarmed attack will // this mosnter's unarmed attack will
// override normal damage calculation // override normal damage calculation
dam[ndam] += getdamrollfromflag(unarmedflag); dam[0] += getdamrollfromflag(unarmedflag);
} else { } 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; willheal = B_TRUE;
} }
if (!willheal) {
// modify for strength
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
dam[ndam] = (int)((float)dam[ndam] * getstrdammod(lf));
}
}
// damtype? // damtype?
damtype[ndam] = getdamtype(wep); damtype[0] = getdamtype(wep);
if (aidb) dblog(".oO { dealing %d %s damage }", dam[ndam], getdamname(damtype[ndam]));
ndam++;
// blessed vs undead etc?
if (!willheal) { if (!willheal) {
enum SKILLLEVEL slev;
skill_t *sk;
// blessed vs undead
if (isblessed(wep) && lfhasflagval(victim, F_DTVULN, DT_HOLY, NA, NA, NULL)) { if (isblessed(wep) && lfhasflagval(victim, F_DTVULN, DT_HOLY, NA, NA, NULL)) {
// a little extra damage // a little extra damage
dam[ndam] = (int) ( (float)dam[ndam] * 1.25 ); dam[0] = (int) ( (float)dam[0] * 1.25 );
}
// modify for strength
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
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]);
}
}
} }
// determine extra damage if (aidb) dblog(".oO { dealing %d %s damage }", dam[0], getdamname(damtype[0]));
ndam = 1;
// determine extra damage for flaming etc.
if (!willheal) {
getextradam(wep, &dam[0], &damtype[0], &ndam); getextradam(wep, &dam[0], &damtype[0], &ndam);
} }
} else { } else {
@ -243,9 +283,12 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
for (i = 0; i < ndam; i++) { for (i = 0; i < ndam; i++) {
int reduceamt; int reduceamt;
int backstab = B_FALSE;
if (firstisbackstab && (i == 0)) backstab = B_TRUE;
dblog("initial dam[%d] = %d",i,dam[i]); 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); dam[i] = (int)((float)dam[i] * 1.5);
dblog("heavy blow makes dam[%d] = %d",i,dam[i]); 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]); adjustdamlf(victim, &dam[i], damtype[i]);
dblog("adjusted for lf to dam[%d] = %d",i,dam[i]); dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
if (!backstab) {
// modify for defender's armour // modify for defender's armour
reduceamt = getarmourdamreduction(victim, wep, dam[i], damtype[i]); 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? // will this hit be fatal?
if (dam[i] >= victim->hp) { if (dam[i] >= victim->hp) {
@ -278,7 +323,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
strcpy(extradambuf, ""); strcpy(extradambuf, "");
} }
if (fatal) { if (backstab && (i == 0)) {
verb = strdup("backstab");
} else if (fatal) {
verb = getkillverb(victim, damtype[i], dam[i], victim->maxhp); verb = getkillverb(victim, damtype[i], dam[i], victim->maxhp);
} else { } else {
verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp); 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", warn("You %s %s%s%s",
verb, verb,
victimname, extradambuf, victimname, extradambuf,
fatal ? "!" : "."); (fatal || backstab) ? "!" : ".");
if (fatal && strstr(verb, "behead")) { if (fatal && strstr(verb, "behead")) {
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL); 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" // don't also say "the xx dies"
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
} }
if (!strcmp(verb, "backstab")) {
free(verb);
}
} else { } else {
if (cansee(player, lf) || isplayer(victim)) { if (cansee(player, lf) || isplayer(victim)) {
char withwep[BUFLEN]; char withwep[BUFLEN];
@ -303,7 +353,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
char nodamstr[BUFLEN]; char nodamstr[BUFLEN];
// capitalise first letter // capitalise first letter
sprintf(buf, "%s",attackername); strcpy(buf, attackername);
capitalise(buf); capitalise(buf);
if (wep && !unarmedflag && (lf->race->id != R_DANCINGWEAPON) && cansee(player, lf)) { 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, ""); strcpy(nodamstr, "");
} }
warn("%s %s%s %s%s%s.", buf, attackverb, warn("%s %s%s %s%s%s.", buf, attackverb,
attackverb[strlen(attackverb)-1] == 's' ? "es" : "s", needses(attackverb) ? "es" : "s",
victimname,withwep, nodamstr); 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 } // end foreach damtype
// special weapon effects // special weapon effects
if (dam[0]) { wepeffects(wep->flags, victim->cell, dam[0]);
wepeffects(wep->flags, victim->cell);
}
if (!isdead(victim)) { if (!isdead(victim)) {
if (unarmedflag) { if (unarmedflag) {
@ -415,9 +462,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
} }
// confer flags from attacker? // confer flags from attacker?
if (dam[0]) { wepeffects(lf->flags, victim->cell, dam[0]);
wepeffects(lf->flags, victim->cell);
}
// special lifeform-based effects // special lifeform-based effects
if ((lf->race->id == R_COCKATRICE) && dam[0]) { 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)) { if (lfhasflag(victim, F_DODGES)) {
flag_t *f;
cell_t *adj; cell_t *adj;
f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
adj = getrandomadjcell(victim->cell, WE_NOTSOLID); adj = getrandomadjcell(victim->cell, WE_NOTSOLID);
moveto(lf, adj, B_FALSE); 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"); msg("%s dodge%s!",victimname,isplayer(victim) ? "" : "s");
killflag(f); killflag(f);
}
} }
} }
@ -565,6 +612,11 @@ int attackob(lifeform_t *lf, object_t *o) {
dam[ndam] = getdamroll(wep, NULL); 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?
damtype[ndam] = getdamtype(wep); damtype[ndam] = getdamtype(wep);
ndam++; ndam++;
@ -598,7 +650,7 @@ int attackob(lifeform_t *lf, object_t *o) {
msg("%s %ss %s%s.", attackername, msg("%s %ss %s%s.", attackername,
getattackverb(lf, wep, damtype[i],dam[i],maxhp), obname,withwep); getattackverb(lf, wep, damtype[i],dam[i],maxhp), obname,withwep);
} else { } else {
youhear(lf->cell, "sounds of fighting"); noise(lf->cell, NULL, "sounds of fighting.", NULL);
} }
if ((i == 0) && unarmedflag && hasflag(o->flags, F_HARD)) { if ((i == 0) && unarmedflag && hasflag(o->flags, F_HARD)) {
@ -617,9 +669,7 @@ int attackob(lifeform_t *lf, object_t *o) {
} // end foreach damtype } // end foreach damtype
// special weapon effects // special weapon effects
if (dam[0]) { wepeffects(wep->flags, obloc, dam[0]);
wepeffects(wep->flags, obloc);
}
if (unarmedflag) { if (unarmedflag) {
// touch effects // touch effects
@ -857,6 +907,10 @@ char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp)
float pct; float pct;
pct = (int)(((float) dam / (float) maxhp) * 100.0); pct = (int)(((float) dam / (float) maxhp) * 100.0);
if (victim->race->id == R_DANCINGWEAPON) {
return "defeat";
}
if ((damtype == DT_BASH) && lfhasflag(victim, F_FROZEN)) { if ((damtype == DT_BASH) && lfhasflag(victim, F_FROZEN)) {
return "shatter"; return "shatter";
} }
@ -1189,6 +1243,11 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
acc -= 45; acc -= 45;
} }
// victim immobile or asleep?
if (isimmobile(victim)) {
acc += 50;
}
if (critical) { if (critical) {
if (rnd(1,20) == 20) *critical = 1; if (rnd(1,20) == 20) *critical = 1;
} }
@ -1213,7 +1272,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
return gothit; return gothit;
} }
void wepeffects(flagpile_t *fp, cell_t *where) { void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
flag_t *f; flag_t *f;
lifeform_t *victim; lifeform_t *victim;
lifeform_t *owner; lifeform_t *owner;
@ -1222,7 +1281,15 @@ void wepeffects(flagpile_t *fp, cell_t *where) {
if (!where) return; if (!where) return;
wep = fp->ob; wep = fp->ob;
if (wep) {
cell_t *c;
c = getoblocation(wep);
if (c && c->lf) {
owner = c->lf;
}
} else {
owner = fp->owner; owner = fp->owner;
}
victim = where->lf; victim = where->lf;
for (f = fp->first ; f ; f = f->next) { for (f = fp->first ; f ; f = f->next) {
@ -1237,6 +1304,7 @@ void wepeffects(flagpile_t *fp, cell_t *where) {
} }
} }
} else if ((f->id == F_REVENGE) && victim && !isdead(victim)) { } else if ((f->id == F_REVENGE) && victim && !isdead(victim)) {
if (dam) { // only works if we did damage
lifeform_t *owner; lifeform_t *owner;
owner = wep->pile->owner; owner = wep->pile->owner;
if (owner && victim) { if (owner && victim) {
@ -1276,13 +1344,16 @@ void wepeffects(flagpile_t *fp, cell_t *where) {
} }
} // end if dampct > 50 } // end if dampct > 50
} }
}
} else if ((f->id == F_HEAVYBLOW) && victim && owner) { } else if ((f->id == F_HEAVYBLOW) && victim && owner) {
int dir; int dir;
// knock back victim // 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); knockback(victim, dir , 2, owner);
f->known = B_TRUE; f->known = B_TRUE;
} else if ((f->id == F_HITCONFER) && victim ) { } else if ((f->id == F_HITCONFER) && victim ) {
// only works if we did damage
if (dam) {
enum FLAG fid; enum FLAG fid;
int min,max,howlong; int min,max,howlong;
fid = f->val[0]; fid = f->val[0];
@ -1324,7 +1395,30 @@ void wepeffects(flagpile_t *fp, cell_t *where) {
howlong = PERMENANT; howlong = PERMENANT;
} }
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); addtempflag(victim->flags, fid, val0, NA, NA, NULL, howlong);
}
} // end if passedcheck } // end if passedcheck
} // end (if victim doesn't already have the flag) } // end (if victim doesn't already have the flag)
@ -1332,6 +1426,7 @@ void wepeffects(flagpile_t *fp, cell_t *where) {
if ((f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) { if ((f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
killflag(f); killflag(f);
} }
}
} // end if (fid == hitconfer) } // end if (fid == hitconfer)
} }

View File

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

View File

@ -14,8 +14,7 @@ lf.c:
update gainlevel() question update gainlevel() question
update givejob() update givejob()
update modattr() update modattr()
io.c: io.c:
update announceflaggain() and loss() for this stat 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 // player flags which cause a redraw
if (isplayer(f->pile->owner)) { doredraw = flagcausesredraw(f->pile->owner, f->id);
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;
}
}
} else if (f->pile->ob) { } else if (f->pile->ob) {
if (announceobflaggain(f->pile->ob, f)) { if (announceobflaggain(f->pile->ob, f)) {
f->known = B_TRUE; 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 flagstacks(enum FLAG fid) {
int res = B_FALSE; int res = B_FALSE;
switch (fid) { switch (fid) {
@ -292,34 +300,8 @@ void killflag(flag_t *f) {
lf = f->pile->owner; lf = f->pile->owner;
// player flags which cause a redraw // flags which cause a redraw
if (lf) { doredraw = flagcausesredraw(f->pile->owner, f->id);
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;
}
}
}
// notify // notify
if ((gamemode == GM_GAMESTARTED)) { if ((gamemode == GM_GAMESTARTED)) {
@ -390,9 +372,9 @@ void killflagpile(flagpile_t *fp) {
free(fp); free(fp);
} }
void timeeffectsflag(flag_t *f) { void timeeffectsflag(flag_t *f, int howlong) {
if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) { if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) {
f->lifetime--; f->lifetime -= howlong;
if (f->lifetime <= 0) { if (f->lifetime <= 0) {
killflag(f); killflag(f);
return; return;
@ -505,7 +487,7 @@ void timeeffectsflags(flagpile_t *fp) {
flag_t *f,*nextf; flag_t *f,*nextf;
for (f = fp->first ; f ; f = nextf) { for (f = fp->first ; f ; f = nextf) {
nextf = f->next; 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); flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid);
flagpile_t *addflagpile(lifeform_t *owner, object_t *o); flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int flagcausesredraw(lifeform_t *lf, enum FLAG fid);
int flagstacks(enum FLAG fid); int flagstacks(enum FLAG fid);
flag_t *hasflag(flagpile_t *fp, int id); flag_t *hasflag(flagpile_t *fp, int id);
flag_t *hasflagknown(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 killflagpile(flagpile_t *fp);
void makeflagknown(flagpile_t *fp); void makeflagknown(flagpile_t *fp);
void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2); 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); void timeeffectsflags(flagpile_t *fp);

130
io.c
View File

@ -404,13 +404,21 @@ cell_t *askcoords(char *prompt, int targettype) {
sprintf(extrainfo, "level %d, ",c->lf->level); sprintf(extrainfo, "level %d, ",c->lf->level);
} }
*/ */
if (isfriendly(c->lf)) { switch (getallegiance(c->lf)) {
case AL_FRIENDLY:
if (!isplayer(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "ally"); strcat(extrainfo, "ally");
} else if (ispeaceful(c->lf)) { }
break;
case AL_PEACEFUL:
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "peaceful"); strcat(extrainfo, "peaceful");
break;
case AL_HOSTILE:
break;
} }
if (isfleeing(c->lf)) { if (isfleeing(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "fleeing"); strcat(extrainfo, "fleeing");
@ -437,6 +445,23 @@ cell_t *askcoords(char *prompt, int targettype) {
} }
wep = getweapon(c->lf); 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) { if (wep) {
char obname[BUFLEN]; char obname[BUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
@ -445,6 +470,7 @@ cell_t *askcoords(char *prompt, int targettype) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2); strcat(extrainfo, buf2);
} }
}
f = lfhasflag(c->lf, F_GRABBING); f = lfhasflag(c->lf, F_GRABBING);
if (f) { if (f) {
@ -690,6 +716,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
ot = findot(f->val[0]); ot = findot(f->val[0]);
if (ot) { if (ot) {
msg("You have learned the spell '%s'.", ot->name); msg("You have learned the spell '%s'.", ot->name);
donesomething = B_TRUE;
} }
} }
break; break;
@ -699,9 +726,18 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
ot = findot(f->val[0]); ot = findot(f->val[0]);
if (ot) { if (ot) {
msg("You have learned the ability '%s'.", ot->name); msg("You have learned the ability '%s'.", ot->name);
donesomething = B_TRUE;
} }
} }
break; 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: case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
msg("You feel immune to %s!", getdamnamenoun(f->val[0])); 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; donesomething = B_TRUE;
} }
break; 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: case F_DETECTMAGIC:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
msg("You feel sensitive to magical enchantments."); msg("You feel sensitive to magical enchantments.");
@ -779,7 +821,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
if (lf2) { if (lf2) {
getlfname(lf2, buf); getlfname(lf2, buf);
msg("%s turn%s to flee from %s!", lfname, isplayer(lf) ? "" : "s", 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; break;
case F_POISONED: case F_POISONED:
@ -952,7 +994,7 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
return B_FALSE; return B_FALSE;
} }
if (isdead(player)) return B_FALSE; if (isdead(lf) || isdead(player)) return B_FALSE;
getlfname(lf, lfname); getlfname(lf, lfname);
// player can't see? // player can't see?
@ -1034,6 +1076,15 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
} }
} }
break; 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: case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters lose it if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer immune to %s.", getdamnamenoun(f->val[0])); 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"); msg("%s stop%s fleeing.", lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE; donesomething = B_TRUE;
break; break;
case F_FRIENDLY:
msg("%s no longer looks quite so friendly!", lfname);
break;
case F_POISONED: case F_POISONED:
if (isplayer(lf)) { // don't know if monsters lose it if (isplayer(lf)) { // don't know if monsters lose it
msg("You feel less sick now."); msg("You feel less sick now.");
@ -1107,6 +1161,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; 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: case F_DETECTMAGIC:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
msg("You can no longer detect magical enchantments."); 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 (f) {
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) { if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
int dam; int dam;
@ -2299,6 +2359,9 @@ void describeob(object_t *o) {
case F_DETECTLIFE: case F_DETECTLIFE:
mvwprintw(mainwin, y, 0, "%s will detect nearby lifeforms.", buf); y++; mvwprintw(mainwin, y, 0, "%s will detect nearby lifeforms.", buf); y++;
break; break;
case F_DETECTOBS:
mvwprintw(mainwin, y, 0, "%s will detect nearby objects.", buf); y++;
break;
case F_DETECTMAGIC: case F_DETECTMAGIC:
mvwprintw(mainwin, y, 0, "%s will detect magical enchantemnts on objects.", buf); y++; mvwprintw(mainwin, y, 0, "%s will detect magical enchantemnts on objects.", buf); y++;
break; break;
@ -3591,7 +3654,7 @@ void donextguntarget(void) {
cell_t *c; cell_t *c;
c = player->los[i]; c = player->los[i];
if (c->lf && (c->lf != player) && (c->lf != targ)) { 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! // found one!
setguntarget(player, c->lf); setguntarget(player, c->lf);
done = B_TRUE; done = B_TRUE;
@ -3676,7 +3739,7 @@ void dorest(void) {
} }
if (strchr(validchars, 'h') && strchr(validchars, 'm')) { if (strchr(validchars, 'h') && strchr(validchars, 'm')) {
strcat(validchars, "b"); strcat(validchars, "bn");
strcpy(ques, "Rest until full HP, Mana, Both or none"); strcpy(ques, "Rest until full HP, Mana, Both or none");
ch = askchar(ques, validchars, "b", B_TRUE); ch = askchar(ques, validchars, "b", B_TRUE);
if (ch == 'b') { if (ch == 'b') {
@ -3739,7 +3802,7 @@ void doselguntarget(void) {
sprintf(buf, "Aim %s where?",gunname); sprintf(buf, "Aim %s where?",gunname);
where = askcoords(buf, TT_MONSTER); where = askcoords(buf, TT_MONSTER);
if (where) { if (where) {
if (where->lf && haslof(player, where)) { if (where->lf && haslof(player, where, LOF_NEED, NULL)) {
setguntarget(player, where->lf); setguntarget(player, where->lf);
} else { } else {
setguntarget(player, NULL); setguntarget(player, NULL);
@ -3807,13 +3870,22 @@ void dothrow(obpile_t *op) {
where = askcoords(buf2, TT_MONSTER); where = askcoords(buf2, TT_MONSTER);
if (where) { if (where) {
if (!haslof(player, where)) { cell_t *newwhere = NULL;
if (!haslof(player, where, LOF_WALLSTOP, &newwhere)) {
if (newwhere) {
// update destination cell.
where = newwhere;
} else {
if (reason == E_NOLOS) { if (reason == E_NOLOS) {
msg("You can't see there!"); msg("You can't see there!");
} else { // ie. E_NOLOF } else { // ie. E_NOLOF
msg("You don't have a clear line of fire to there."); msg("You don't have a clear line of fire to there.");
} }
} else if (getcelldist(player->cell, where) > maxdist) { return;
}
}
if (getcelldist(player->cell, where) > maxdist) {
msg("You can't throw %s that far!",buf); msg("You can't throw %s that far!",buf);
} else { } else {
throwat(player, o, where); throwat(player, o, where);
@ -4331,9 +4403,16 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
} }
// fill in the name of the completed choice // fill in the name of the completed choice
/*
sprintf(promptstr, "%s %s %s", sprintf(promptstr, "%s %s %s",
prompt->q[prompt->whichq], prompt->maycancel ? "[ESC=cancel, '=next page] " : "", prompt->q[prompt->whichq], prompt->maycancel ? "[ESC=cancel, '=next page] " : "",
prompt->choice[validone].text); 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); mvwprintw(mainwin, 0, 0, "%s", promptstr);
// move the cursor back // move the cursor back
@ -4935,6 +5014,7 @@ void nothinghappens(void) {
void drawstatus(void) { void drawstatus(void) {
char buf[BUFLEN]; char buf[BUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
char mpbuf[BUFLEN];
char waitbuf[BUFLEN]; char waitbuf[BUFLEN];
char pname[BUFLEN]; char pname[BUFLEN];
char maxmpstr[BUFLEN]; char maxmpstr[BUFLEN];
@ -5046,10 +5126,17 @@ void drawstatus(void) {
sprintf(maxmpstr, "(%d)",player->maxmp); 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->hp,player->maxhp,
player->mp, getmaxmp(player), maxmpstr, mpbuf,
countmoney(player), countmoney(player),
getarmourrating(player),
str, (str == player->baseatt[A_STR]) ? ' ' : '*', str, (str == player->baseatt[A_STR]) ? ' ' : '*',
dex, (dex == player->baseatt[A_DEX]) ? ' ' : '*', dex, (dex == player->baseatt[A_DEX]) ? ' ' : '*',
iq, (iq == player->baseatt[A_IQ]) ? ' ' : '*', 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)); mvwprintw(mainwin, y, 0, "%s cannot see.", you(lf));
y++; 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); f = lfhasknownflag(lf, F_DETECTAURAS);
if (f) { if (f) {
mvwprintw(mainwin, y, 0, "%s automatically detect blessings or curses.", you(lf)); 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)); mvwprintw(mainwin, y, 0, "%s automatically detect nearby metal.", you(lf));
y++; 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); f = lfhasknownflag(lf, F_EXTRAINFO);
if (f && (f->known)) { if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf)); mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf));

710
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); 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); skill_t *addskill(enum SKILL id, char *name, char *desc);
void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype); void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype);
int areallies(lifeform_t *lf1, lifeform_t *lf2);
int areenemies(lifeform_t *lf1, lifeform_t *lf2);
void autoskill(lifeform_t *lf); void autoskill(lifeform_t *lf);
void autotarget(lifeform_t *lf); void autotarget(lifeform_t *lf);
void autoweild(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 *findrace(enum RACE id);
race_t *findracebyname(char *name); race_t *findracebyname(char *name);
skill_t *findskill(enum SKILL id); skill_t *findskill(enum SKILL id);
skill_t *findskillbyname(char *name);
enum SKILLLEVEL findskilllevbyname(char *name);
int flee(lifeform_t *lf); int flee(lifeform_t *lf);
int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong); int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong);
void gainhp(lifeform_t *lf, int amt); void gainhp(lifeform_t *lf, int amt);
@ -47,12 +51,13 @@ void gainlevel(lifeform_t *lf);
void gainmp(lifeform_t *lf, int amt); void gainmp(lifeform_t *lf, int amt);
void gainxp(lifeform_t *lf, long amt); void gainxp(lifeform_t *lf, long amt);
int getactspeed(lifeform_t *lf); int getactspeed(lifeform_t *lf);
enum ALLEGIENCE getallegiance(lifeform_t *lf);
object_t *getarmour(lifeform_t *lf, enum BODYPART bp); object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
int getarmourrating(lifeform_t *lf); int getarmourrating(lifeform_t *lf);
int getattackspeed(lifeform_t *lf); int getattackspeed(lifeform_t *lf);
int getattr(lifeform_t *lf, enum ATTRIB attr); int getattr(lifeform_t *lf, enum ATTRIB attr);
int getevasion(lifeform_t *lf); int getevasion(lifeform_t *lf);
object_t *getbestmissile(lifeform_t *lf); object_t *getbestthrowmissile(lifeform_t *lf);
object_t *getbestweapon(lifeform_t *lf); object_t *getbestweapon(lifeform_t *lf);
object_t *getbestfirearm(lifeform_t *lf); object_t *getbestfirearm(lifeform_t *lf);
int getbodyparthitchance(enum BODYPART bp); int getbodyparthitchance(enum BODYPART bp);
@ -85,6 +90,7 @@ int getvisrange(lifeform_t *lf);
int getmovespeed(lifeform_t *lf); int getmovespeed(lifeform_t *lf);
char *getmoveverb(lifeform_t *lf); char *getmoveverb(lifeform_t *lf);
char *getmoveverbother(lifeform_t *lf); char *getmoveverbother(lifeform_t *lf);
lifeform_t *getnearbypeaceful(lifeform_t *lf);
char *getlfname(lifeform_t *lf, char *buf); char *getlfname(lifeform_t *lf, char *buf);
char *real_getlfname(lifeform_t *lf, char *buf, int usevis); char *real_getlfname(lifeform_t *lf, char *buf, int usevis);
char *getlfnamea(lifeform_t *lf, char *buf); char *getlfnamea(lifeform_t *lf, char *buf);
@ -113,6 +119,7 @@ long getxpforlev(int level);
void givejob(lifeform_t *lf, enum JOB jobid); void givejob(lifeform_t *lf, enum JOB jobid);
void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype); void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype);
int giveskill(lifeform_t *lf, enum SKILL id); 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 givestartobs(lifeform_t *lf, flagpile_t *fp);
void givestartskills(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); 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); int lockpick(lifeform_t *lf, object_t *target, object_t *device);
void loseobflags(lifeform_t *lf, object_t *o, int kind); void loseobflags(lifeform_t *lf, object_t *o, int kind);
int hasbp(lifeform_t *lf, enum BODYPART bp); 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); int haslos(lifeform_t *viewer, cell_t *dest);
void initjobs(void); void initjobs(void);
void initrace(void); void initrace(void);
@ -154,7 +161,7 @@ void killlf(lifeform_t *lf);
void killrace(race_t *race); void killrace(race_t *race);
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc); 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); 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 makenauseated(lifeform_t *lf, int amt, int howlong);
void makenoise(lifeform_t *lf, enum NOISETYPE nid); void makenoise(lifeform_t *lf, enum NOISETYPE nid);
lifeform_t *makezombie(object_t *o); 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); int modattr(lifeform_t *lf, enum ATTRIB attr, int amt);
void modhunger(lifeform_t *lf, int amt); void modhunger(lifeform_t *lf, int amt);
float modifybystat(float num, lifeform_t *lf, enum ATTRIB att); float modifybystat(float num, lifeform_t *lf, enum ATTRIB att);
void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext);
void outfitlf(lifeform_t *lf); void outfitlf(lifeform_t *lf);
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground); int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground);
void precalclos(lifeform_t *lf); 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 setguntarget(lifeform_t *lf, lifeform_t *targ);
void setrace(lifeform_t *lf, enum RACE rid); void setrace(lifeform_t *lf, enum RACE rid);
void setlastdam(lifeform_t *lf, char *buf); void setlastdam(lifeform_t *lf, char *buf);
void setlftarget(lifeform_t *lf, lifeform_t *victim);
int shoot(lifeform_t *lf); int shoot(lifeform_t *lf);
int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod); 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); 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 wear(lifeform_t *lf, object_t *o);
int weild(lifeform_t *lf, object_t *o); int weild(lifeform_t *lf, object_t *o);
int willflee(lifeform_t *lf); 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 ==== ====== NEW LOGFILE ====
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx xxx
findotn(): modname is 'wooden door'
checkobnames(): got exact match: 'wooden door'
xxx 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 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 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 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 9 possibilities.
findotn(): modname is 'zapper'
checkobnames(): got exact match: 'zapper'
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 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 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 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 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 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 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 9 possibilities.
findotn(): modname is 'teeth'
checkobnames(): got exact match: 'teeth'
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
-> possibility: xat, rarity=90 -> possibility: xat, rarity=90
-> possibility: giant newt, rarity=100
-> possibility: giant bat, rarity=90 -> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85 -> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90 -> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=95 -> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85 -> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 9 possibilities. got 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++) { for (i = 0; i < MAXDIR_ORTH; i++) {
a->nextmap[i] = -1; a->nextmap[i] = -1;
} }
a->beingcreated = B_TRUE;
return a; return a;
} }
@ -101,6 +102,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
if (lf) { if (lf) {
flag_t *f; flag_t *f;
lf->born = B_FALSE;
if (jobok) { if (jobok) {
// has a job? // has a job?
f = hasflag(lf->flags, F_STARTJOB); 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? // appears in groups?
f = hasflag(lf->flags, F_NUMAPPEAR); f = hasflag(lf->flags, F_NUMAPPEAR);
if (f) { if (f) {
@ -130,6 +140,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
//adjcell = c; //adjcell = c;
for ( ; amt > 0; amt--) { for ( ; amt > 0; amt--) {
int n; int n;
lifeform_t *newlf;
// find an adjacent cell to one of the newly added monsters, // find an adjacent cell to one of the newly added monsters,
// starting with the first one // starting with the first one
adjcell = NULL; adjcell = NULL;
@ -141,17 +152,25 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
if (!adjcell) break; if (!adjcell) break;
//lf = addlf(adjcell, r->id, getrandommonlevel(adjcell->map->depth)); //lf = addlf(adjcell, r->id, getrandommonlevel(adjcell->map->depth));
if (!addlf(adjcell, r->id, 1)) { newlf = addlf(adjcell, r->id, 1);
if (!newlf) {
break; 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; moncell[nmoncells] = adjcell;
nmoncells++; nmoncells++;
} }
free(moncell); free(moncell);
} }
lf->born = B_TRUE;
} // end if lf
} }
}
return 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, // if there's already someone there,
// then add an object. // then add an object.
if (c->lf || (rnd(1,2) == 1)) { if (c->lf || (rnd(1,100) <= obchance)) {
// object // object
addrandomob(c); addrandomob(c);
} else { } else {
@ -564,6 +583,8 @@ void createmap(map_t *map, int depth, int habitat, map_t *parentmap, objecttype_
//int db = B_TRUE; //int db = B_TRUE;
map->beingcreated = B_TRUE;
sprintf(buf, "Map %d",map->id); sprintf(buf, "Map %d",map->id);
map->name = strdup(buf); map->name = strdup(buf);
map->habitat = habitat; 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); c = getcellat(map, x, y);
if (c && isempty(c)) { if (c && isempty(c)) {
if (rnd(1,100) <= getobchance(map->habitat)) { 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 { } else {
*/ */
numobsmin = 0; 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 { } else {
*/ */
addrandomthing(c); // slightly more chance of objects in rooms
addrandomthing(c,60);
done = B_TRUE; done = B_TRUE;
//dblog("----> Success ob at (%d,%d).",c->x,c->y); //dblog("----> Success ob at (%d,%d).",c->x,c->y);
} else { } 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)); //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) { 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"); msg("You see %s explosion!", (range > 0) ? "a huge" : "an");
} }
} else { } else {
youhear(c, "an explosion!"); noise(c, NULL, "an explosion!", NULL);
} }
for (y = c->y - range ; y <= c->y + range ; y++) { 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 && (getcelldist(c, cc) <= (range+1))) {
if (cc->lf && !isdead(cc->lf)) { if (cc->lf && !isdead(cc->lf)) {
// move away from centre of explosion // move away from centre of explosion
knockback(cc->lf, getdiraway(cc, c, B_FALSE), 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; 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); map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt); lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt);
void addrandomob(cell_t *c); 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); int cellhaslos(cell_t *c1, cell_t *dest);
cell_t *getcellat(map_t *map, int x, int y); cell_t *getcellat(map_t *map, int x, int y);
int getcelldist(cell_t *src, cell_t *dst); int getcelldist(cell_t *src, cell_t *dst);

119
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); f = hasflag(o->flags, F_WALKDAM);
if (f) { if (f) {
// are we immune to this? // 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) { if (error) {
*error = E_AVOIDOB; *error = E_AVOIDOB;
rdata = o; rdata = o;
@ -255,7 +255,7 @@ void dorandommove(lifeform_t *lf, int badmovesok) {
// src is where something is // src is where something is
// dst is what we are going away from // dst is what we are going away from
// wantcheck is whether to check for dangerous things before considering a direction valid // wantcheck is whether to check for dangerous things before considering a direction valid
int getdiraway(cell_t *src, cell_t *dst, int wantcheck) { int getdiraway(cell_t *src, cell_t *dst, int wantcheck, int dirtype) {
int d; int d;
cell_t *c; cell_t *c;
int maxdist=-1,bestdir=D_NONE; int maxdist=-1,bestdir=D_NONE;
@ -290,8 +290,11 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck) {
} }
} }
if (ok) { if (ok) {
//thisdist = getcelldistorth(c, dst); if (dirtype == DT_ORTH) {
thisdist = getcelldistorth(c, dst);
} else {
thisdist = getcelldist(c, dst); thisdist = getcelldist(c, dst);
}
} else { } else {
thisdist = -1; 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; int d;
cell_t *c; cell_t *c;
int mindist=9999,bestdir=D_NONE; 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) { if (ok) {
int thisdist; int thisdist;
//thisdist = getcelldistorth(c, dst); if (dirtype == DT_ORTH) {
thisdist = getcelldistorth(c, dst);
} else {
thisdist = getcelldist(c, dst); thisdist = getcelldist(c, dst);
}
dist[d - DC_N] = thisdist; dist[d - DC_N] = thisdist;
if (thisdist < mindist) { if (thisdist < mindist) {
mindist = thisdist; mindist = thisdist;
@ -449,7 +455,7 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst ) {
} }
// move away from them // move away from them
dir = getdiraway(lf->cell, dst, B_TRUE); dir = getdiraway(lf->cell, dst, B_TRUE, DT_COMPASS);
if (dir == D_NONE) { if (dir == D_NONE) {
rv = B_TRUE; rv = B_TRUE;
} else { } else {
@ -606,15 +612,26 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if ((gamemode == GM_GAMESTARTED)) { if ((gamemode == GM_GAMESTARTED)) {
for (l = newcell->map->lf ; l ; l = l->next) { for (l = newcell->map->lf ; l ; l = l->next) {
if (l != lf) { if (l != lf) {
// cope with swapping locations with someone!
if (haslos(l, newcell)) { if (haslos(l, newcell)) {
interrupt(l); int dointerrupt = B_FALSE;
if (isplayer(l)) { if (isplayer(l)) {
if (areenemies(lf, l)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_RESTING)) { if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_RESTING)) {
char lfname2[BUFLEN]; char lfname2[BUFLEN];
getlfname(lf, lfname); getlfname(lf, lfname);
sprintf(lfname2, "%s",noprefix(lfname)); sprintf(lfname2, "%s",noprefix(lfname));
msg("%s %s comes into view.",isvowel(lfname2[0]) ? "An" : "A", lfname2); 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; return B_FALSE;
} }
@ -727,7 +767,7 @@ int movetowards(lifeform_t *lf, cell_t *dst) {
} }
// move towards them // 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) { if (dir != D_NONE) {
rv = trymove(lf, dir, B_TRUE); rv = trymove(lf, dir, B_TRUE);
} }
@ -828,6 +868,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
} }
where = getoblocation(o); where = getoblocation(o);
noise(where, lf, "a door opening", NULL);
if (player && haslos(player, where)) { if (player && haslos(player, where)) {
needredraw = B_TRUE; needredraw = B_TRUE;
drawscreen(); drawscreen();
@ -943,11 +984,12 @@ int tryrun(lifeform_t *lf, int dir) {
int pullnextto(lifeform_t *lf, cell_t *c) { int pullnextto(lifeform_t *lf, cell_t *c) {
int dir; int dir;
cell_t *dst = NULL; cell_t *dst = NULL;
cell_t *newdst = NULL;
dst = c; dst = c;
while (dst->lf) { 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) { if (dir == D_NONE) {
return B_TRUE; return B_TRUE;
} else { } else {
@ -957,11 +999,20 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
} }
} }
} }
// is the path clear? // is the path clear?
if (!dst || !haslof(lf, dst)) { if (!dst) {
return B_TRUE; 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)) { if (isplayer(lf) || cansee(player, lf)) {
char buf[BUFLEN]; char buf[BUFLEN];
getlfname(lf, buf); getlfname(lf, buf);
@ -1066,17 +1117,6 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
reason = E_OK; reason = E_OK;
moveto(lf, cell, onpurpose); moveto(lf, cell, onpurpose);
taketime(lf, getmovespeed(lf)); 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 { } else {
object_t *inway; object_t *inway;
int door, dooropen; int door, dooropen;
@ -1173,8 +1213,37 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} }
break; break;
case E_LFINWAY: case E_LFINWAY:
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! // attack!
return attacklf(lf, cell->lf); return attacklf(lf, cell->lf);
}
break;
case E_GRAVBOOSTED: case E_GRAVBOOSTED:
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You try to move but are unable to lift your feet!"); 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 (cell->lf) {
if (!isplayer(lf)) { // if we are a monster if (!isplayer(lf)) { // if we are a monster
// friendly monsters: don't hit other friendlies // 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; return B_FALSE;
}
/*
} else if (ispeaceful(lf)) { // peaceful mosnters: don't hit anyone } else if (ispeaceful(lf)) { // peaceful mosnters: don't hit anyone
return B_FALSE; return B_FALSE;
} else { // hostile/nonfriendly monsters - don't hit other monsters } 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_FALSE;
} }
} }
*/
} }
} }
return B_TRUE; 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 closedoor(lifeform_t *lf, object_t *o);
int diropposite(int dir); int diropposite(int dir);
void dorandommove(lifeform_t *lf, int badmovesok); void dorandommove(lifeform_t *lf, int badmovesok);
int getdiraway(cell_t *src, cell_t *dst, int wantcheck); int 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 getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher); int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher);
int moveawayfrom(lifeform_t *lf, cell_t *dst); int moveawayfrom(lifeform_t *lf, cell_t *dst);
void moveeffects(lifeform_t *lf); void moveeffects(lifeform_t *lf);

177
nexus.c
View File

@ -4,6 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include "ai.h" #include "ai.h"
#include "attack.h" #include "attack.h"
#include "io.h" #include "io.h"
@ -69,16 +70,33 @@ int main(int argc, char **argv) {
int newworld = B_FALSE; int newworld = B_FALSE;
object_t *o; object_t *o;
char welcomemsg[BUFLEN]; char welcomemsg[BUFLEN];
int ch;
FILE *playerfile = NULL;
atexit(cleanup); 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 // init params
if (init()) { if (init()) {
exit(1); exit(1);
} }
// load whatever maps are available // load whatever maps are available
loadall(); loadall();
@ -101,12 +119,29 @@ int main(int argc, char **argv) {
if (!player) { if (!player) {
char *user; char *user;
char pname[BUFLEN]; char pname[BUFLEN];
job_t *j; char buf[BUFLEN];
job_t *j = NULL;
char ch; char ch;
cell_t *where; cell_t *where;
// 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);
}
if (!j) {
// ask for race // ask for race
initprompt(&prompt, "Select your race:"); initprompt(&prompt, "Select your job:");
ch = 'a'; ch = 'a';
for (j = firstjob ; j ; j = j->next) { for (j = firstjob ; j ; j = j->next) {
addchoice(&prompt, ch++, j->name, NULL, j); addchoice(&prompt, ch++, j->name, NULL, j);
@ -116,6 +151,7 @@ int main(int argc, char **argv) {
getchoice(&prompt); getchoice(&prompt);
j = prompt.result; j = prompt.result;
} }
}
// find staircase // find staircase
where = findobinmap(firstmap, OT_STAIRSUP); where = findobinmap(firstmap, OT_STAIRSUP);
@ -135,6 +171,14 @@ int main(int argc, char **argv) {
} }
givejob(player, j->id); givejob(player, j->id);
if (playerfile) {
if (parseplayerfile(playerfile, player)) {
// error!
exit(0);
}
fclose(playerfile);
}
// player needs hunger // player needs hunger
addflag(player->flags, F_HUNGER, 0, NA, NA, NULL); addflag(player->flags, F_HUNGER, 0, NA, NA, NULL);
@ -325,6 +369,18 @@ void cleanup(void) {
// free races // 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) { void donextturn(map_t *map) {
lifeform_t *who; lifeform_t *who;
@ -512,6 +568,62 @@ int init(void) {
return B_FALSE; 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) { void initcommands(void) {
// Actions // Actions
addcommand(CMD_UP, '<', "Go up stairs."); addcommand(CMD_UP, '<', "Go up stairs.");
@ -577,6 +689,57 @@ int limit(int *what, int min, int max) {
return limited; 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) { float pctof(float pct, float num) {
return ((pct / 100.0) * num); return ((pct / 100.0) * num);
} }
@ -908,3 +1071,9 @@ void timeeffectsworld(map_t *map) {
if (db) dblog("cur time is %ld\n",curtime); 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 checkdeath(void);
void checkendgame(void); void checkendgame(void);
void cleanup(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); void donextturn(map_t *map);
celltype_t *findcelltype(int id); celltype_t *findcelltype(int id);
char *getdirname(int dir); char *getdirname(int dir);
void getrarity(int depth, int *min, int *max, int range); void getrarity(int depth, int *min, int *max, int range);
int init(void); 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); void initcommands(void);
int isplayerturn(void); int isplayerturn(void);
int limit(int *what, int min, int max); int limit(int *what, int min, int max);
int parseplayerfile(FILE *f, lifeform_t *lf);
float pctof(float pct, float num); float pctof(float pct, float num);
int rnd(int min, int max); int rnd(int min, int max);
int roll(char *string); int roll(char *string);
@ -22,3 +26,4 @@ int rollmpdice(lifeform_t *lf);
//void sortlf(map_t *map); //void sortlf(map_t *map);
void sortcommands(void); void sortcommands(void);
void timeeffectsworld(map_t *map); void timeeffectsworld(map_t *map);
void usage(char *progname);

158
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 *checkobnames(char *haystack, char *needle) {
objecttype_t *ot; objecttype_t *ot;
char *pluralname; char *pluralname;
int db = B_TRUE; int db = B_FALSE;
// search for exact match // search for exact match
if (!strcmp(haystack, needle)) { 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) { void explodeob(object_t *o, flag_t *f, int bigness) {
cell_t *c; cell_t *c;
int dam; int dam;
@ -1776,9 +1791,13 @@ objecttype_t *findotn(char *name) {
knowledge_t *k; knowledge_t *k;
char *modname; char *modname;
char *p; char *p;
int db = B_TRUE; int db = B_FALSE;
brand_t *om; brand_t *om;
if (!strlen(name)) {
return NULL;
}
modname = strdup(name); modname = strdup(name);
// make some replacements // make some replacements
@ -2126,6 +2145,8 @@ int getobvalue(object_t *o) {
} else if (o->type->obclass->id == OC_WAND) { } else if (o->type->obclass->id == OC_WAND) {
price *= 2.25; 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 selidx;
int amt; int amt;
flag_t *f; flag_t *f;
int db = B_TRUE; int db = B_FALSE;
char *pluralname; char *pluralname;
char brandname[BUFLEN]; char brandname[BUFLEN];
char cursestr[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); depth = rnd(1,MAXDEPTH);
} }
getrarity(depth, &raritymin, &raritymax, 25); getrarity(depth, &raritymin, &raritymax, RARITYVARIANCE);
while (!done) { while (!done) {
if (db) dblog("adding random object with rarity value between %d - %d",raritymin,raritymax); 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) // ie. 1 tonne object does 1000 damage (car)
dam = ceil((double)getobunitweight(o)); dam = ceil((double)getobunitweight(o));
// missile objects do extra damage // missile objects do extra damage
if (hasflag(o->flags, F_MISSILE)) { if (hasflag(o->flags, F_THROWMISSILE)) {
dam *= 2; dam *= 2;
} }
// max // max
@ -4025,7 +4046,6 @@ void initobjects(void) {
addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_STACKABLE, 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_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_ROCK, "Rocks/Gems", "Boring (or not so boring) rocks.", '*');
addoc(OC_FOOD, "Food", "Yum!", '%'); addoc(OC_FOOD, "Food", "Yum!", '%');
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, ""); 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_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, 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_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_OBHP, 80, 80, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "50-100 stones"); 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_NUMAPPEAR, 1, 10, NA, "");
addflag(lastot->flags, F_NOBLESS, 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_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); 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_GLYPH, B_TRUE, NA, NA, ",");
addflag(lastot->flags, F_STACKABLE, 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); 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); 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_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); 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); 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); 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); 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_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); 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_RARITY, H_DUNGEON, 40, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, 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_LINKSPELL, OT_S_DETECTLIFE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, 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); 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_LINKSPELL, OT_S_DETECTMAGIC, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, 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); 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_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, 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); 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_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, 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); 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_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
// l3 // l3
addot(OT_S_EXPLODEMETAL, "explode metal", "Causes all metal objects in a location explode.", MT_NOTHING, 0, OC_SPELL); 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); 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); 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_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
/////////////////// ///////////////////
// death // 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); 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_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, 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 // l3
addot(OT_S_DETECTAURA, "detect aura", "Senses holiness or evil near the caster.", MT_NOTHING, 0, OC_SPELL); 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_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
// TODO: hardcode how ai casts this // 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 // modification
/////////////////// ///////////////////
@ -4662,6 +4701,10 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, 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 // 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); 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); addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
@ -4712,6 +4755,8 @@ void initobjects(void) {
// divine powers // divine powers
addot(OT_A_DEBUG, "debug", "You can toggle debugging for a lifeform.", MT_NOTHING, 0, OC_ABILITY); 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); 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); addot(OT_A_LEARN, "learn", "Learn new skills.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); 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); 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 // manuals
addot(OT_MAN_ATHLETICS, "manual of athletics", "Teaches you the skill 'athletics'.", MT_PAPER, 3, OC_BOOK); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); addflag(lastot->flags, F_MANUALOF, SK_TECHUSAGE, NA, NA, NULL);
// weapon manuals // weapon manuals
@ -4820,6 +4871,8 @@ void initobjects(void) {
// divination // divination
addot(OT_SB_DETECTLIFE, "spellbook of detect life", "Teaches the spell 'detect life'.", MT_PAPER, 1.5, OC_BOOK); 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); 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); 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); 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); 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 // mental
addot(OT_SB_MINDSCAN, "spellbook of mind scan", "Teaches the spell 'mind scan'.", MT_PAPER, 1.5, OC_BOOK); 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); 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); 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); 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); 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); 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 // modification
addot(OT_SB_INSCRIBE, "spellbook of inscribe", "Teaches the spell 'inscribe'.", MT_PAPER, 1.5, OC_BOOK); 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); addflag(lastot->flags, F_LINKSPELL, OT_S_INSCRIBE, NA, NA, NULL);
@ -4922,7 +4981,8 @@ void initobjects(void) {
f2 = hasflag(spelltype->flags, F_SPELLLEVEL); f2 = hasflag(spelltype->flags, F_SPELLLEVEL);
if (f2) { if (f2) {
int rarity; 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); addflag(ot->flags, F_RARITY, H_ALL, rarity, NA, NULL);
} else { } else {
dblog("Spell %s has no spell level - can't determine rarity for spellbook.", spelltype->name); 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_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERUSECHARGE, 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_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_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, 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); 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_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "^"); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "^");
addflag(lastot->flags, F_SHARP, 1, 2, NA, NULL); 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); 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); 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); 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_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, 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_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 // armour - shields
addot(OT_BUCKLER, "buckler", "A small, unobtrusive wooden shield.", MT_WOOD, 3.00, OC_ARMOUR); 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); addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
@ -5879,6 +5940,7 @@ void initobjects(void) {
// missiles // missiles
addot(OT_DART, "dart", "A small, sharp projectile weapon.", MT_WOOD, 0.5, OC_MISSILE); 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_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_MISSILEDAM, 2, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, "");
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, 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); 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_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_MISSILEDAM, 2, NA, NA, "");
addflag(lastot->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, 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); 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_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_MISSILEDAM, 3, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, "");
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, 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_DAMTYPE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 4, NA, NULL); addflag(lastot->flags, F_DAM, 1, 4, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, 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_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, 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_DAMTYPE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 3, NA, NULL); addflag(lastot->flags, F_DAM, 1, 3, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, 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_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, 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); 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_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, 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_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_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, 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_DAMTYPE, DT_CHOP, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 6, 1, NULL); addflag(lastot->flags, F_DAM, 1, 6, 1, NULL);
addflag(lastot->flags, F_ACCURACY, 85, NA, NA, 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); 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); 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); 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_DAMTYPE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 3, NA, NULL); addflag(lastot->flags, F_DAM, 1, 3, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, 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_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, 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_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_DAMTYPE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL); addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, 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_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, 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_DAMTYPE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DAM, 1, 8, NA, NULL); addflag(lastot->flags, F_DAM, 1, 8, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 75, NA, 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_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL); addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL);
@ -6498,8 +6562,8 @@ int ismetal(enum MATERIAL mat) {
return metal; return metal;
} }
int ismissile(object_t *o) { int isthrowmissile(object_t *o) {
if (hasflag(o->flags, F_MISSILE)) { if (hasflag(o->flags, F_THROWMISSILE)) {
return B_TRUE; return B_TRUE;
} }
// special cases... // special cases...
@ -7355,17 +7419,23 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
return B_TRUE; return B_TRUE;
} else { } else {
if (f->val[1] != NA) { if (f->val[1] != NA) {
cell_t *newwhere = NULL;
if ((f->val[1] & TR_NEEDLOS) && !haslos(lf, where)) { if ((f->val[1] & TR_NEEDLOS) && !haslos(lf, where)) {
msg("You can't see there!"); msg("You can't see there!");
return B_TRUE; return B_TRUE;
} }
if ((f->val[1] & TR_NEEDLOF) && !haslof(lf, where)) { 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!"); msg("You have no line of fire to there!");
return B_TRUE; return B_TRUE;
} }
} }
} }
} }
}
f = hasflag(o->flags, F_OPERNEEDDIR); f = hasflag(o->flags, F_OPERNEEDDIR);
@ -7545,7 +7615,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
} }
// announce // announce
if (!seen) { if (!seen) {
youhear(where, "something spraying."); noise(where, NULL, "something spraying.", NULL);
} }
} else if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) { } else if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) {
object_t *oo,*nextoo; object_t *oo,*nextoo;
@ -8029,13 +8099,23 @@ int pour(lifeform_t *lf, object_t *o) {
dst->blessknown = B_TRUE; dst->blessknown = B_TRUE;
// remove bonuses // remove bonuses
killflagsofid(dst->flags, F_BONUS); killflagsofid(dst->flags, F_BONUS);
// remove temporary flags // remove temporary flags and modify some others
for (f = dst->flags->first ; f ; f = nextf) { for (f = dst->flags->first ; f ; f = nextf) {
nextf = f->next; nextf = f->next;
if (f->lifetime > 0) { if (f->lifetime > 0) {
killflag(f); 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); if (!isknown(dst)) makeknown(dst->type->id);
} else if (o->type->id == OT_POT_ACID) { } else if (o->type->id == OT_POT_ACID) {
@ -8706,8 +8786,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
char obname[BUFLEN]; char obname[BUFLEN];
getlfname(lf, lfname); getlfname(lf, lfname);
getobname(oo, obname,oo->amt); getobname(oo, obname,oo->amt);
msg("%s%s %s %s softly.",lfname,getpossessive(lfname),noprefix(obname), msg("A black aura breaks away from %s%s %s.",lfname,getpossessive(lfname),noprefix(obname));
(oo->amt == 1) ? "glows" : "glow");
seen = B_TRUE; seen = B_TRUE;
} }
// uncurse it // uncurse it
@ -9159,6 +9238,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
int acc; int acc;
int youhit; int youhit;
object_t *newob; object_t *newob;
cell_t *newloc;
int db = B_TRUE; int db = B_TRUE;
reason = E_OK; 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); 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); //taketime(thrower, SPEED_THROW);
// some obejcts will die when thrown. // 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); msg("%s", buf2);
} else { } else {
if (willshatter(o->material->id)) { if (willshatter(o->material->id)) {
youhear(where, "shattering glass."); noise(where, NULL, "shattering glass.", NULL);
} }
} }
sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea); 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); msg("%s shatters!",obcaps);
free(obcaps); free(obcaps);
} else { } else {
youhear(where, "shattering glass."); noise(where, NULL, "shattering glass.", NULL);
} }
shattered = B_TRUE; 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 (youhit && target) {
if (getobweight(o) >= getlfweight(target, B_NOOBS)) { if (getobweight(o) >= getlfweight(target, B_NOOBS)) {
int dir; 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); 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 // penalty for throwing non-missiles
if (missile && !firearm && !ismissile(missile)) { if (missile && !firearm && !isthrowmissile(missile)) {
acc -= 20; acc -= 20;
} }
return acc; return acc;

View File

@ -31,6 +31,7 @@ int countnames(char **list);
int countobs(obpile_t *op); int countobs(obpile_t *op);
int curseob(object_t *o); int curseob(object_t *o);
void damageallobs(object_t *exception, obpile_t *op, int howmuch, int damtype); 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 explodeob(object_t *o, flag_t *f, int bigness);
void extinguish(object_t *o); void extinguish(object_t *o);
material_t *findmaterial(int id); material_t *findmaterial(int id);
@ -127,7 +128,7 @@ int isknownot(objecttype_t *ot);
int isidentified(object_t *o); int isidentified(object_t *o);
int isimpassableob(object_t *o, lifeform_t *lf); int isimpassableob(object_t *o, lifeform_t *lf);
int ismetal(enum MATERIAL mat); int ismetal(enum MATERIAL mat);
int ismissile(object_t *o); int isthrowmissile(object_t *o);
int isoperable(object_t *o); int isoperable(object_t *o);
int isplainob(object_t *o); int isplainob(object_t *o);
int ispourable(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 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); 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 fscanf(f, "id:%d\n",&m->id); // map id
// load lifeforms // load lifeforms
@ -710,6 +711,7 @@ int savemap(map_t *m) {
for (i = 0; i < MAXDIR_ORTH; i++) { for (i = 0; i < MAXDIR_ORTH; i++) {
fprintf(f, "%d\n",m->nextmap[i] ); // map dimensons fprintf(f, "%d\n",m->nextmap[i] ); // map dimensons
} }
fprintf(f, "beingcreated:%d\n",m->beingcreated);
// save all non-player lifeforms (includes their objects) // save all non-player lifeforms (includes their objects)
fprintf(f, "lifeforms:\n"); fprintf(f, "lifeforms:\n");

319
spell.c
View File

@ -400,6 +400,36 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else { } else {
msg("There is nobody there!"); 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) { } else if (abilid == OT_A_HEAVYBLOW) {
object_t *wep; object_t *wep;
char dirch; char dirch;
@ -672,7 +702,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_AIRBLAST) { } else if (spellid == OT_S_AIRBLAST) {
int dir; int dir;
object_t *o,*nexto; 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; target = targcell->lf;
if (cansee(player, caster)) { 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"); 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 // lfs
if (target) { if (target) {
knockback(target, dir, power, caster); knockback(target, dir, power, caster);
@ -704,7 +734,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
newlf = makezombie(o); newlf = makezombie(o);
if (newlf) { if (newlf) {
if (isplayer(caster) && skillcheck(caster, A_IQ, 20, power)) { if (isplayer(caster) && skillcheck(caster, A_IQ, 20, power)) {
makefriendly(newlf); makefriendly(newlf, PERMENANT);
} }
donesomething = B_TRUE; donesomething = B_TRUE;
} }
@ -813,21 +843,23 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
teleportto(caster, targcell, B_TRUE); teleportto(caster, targcell, B_TRUE);
} }
} else if (spellid == OT_S_BURNINGWAVE) { } else if (spellid == OT_S_BURNINGWAVE) {
cell_t *c; cell_t *retcell[MAXRETCELLS];
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, spellid, power)) return B_TRUE; int nretcell;
int i;
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, LOF_WALLSTOP, spellid, power)) return B_TRUE;
if (cansee(player, caster)) { 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 // create a line of fire towards the target cell
c = caster->cell; calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, targcell->x, targcell->y, retcell, &nretcell);
while (c != targcell) {
int dir; // don't set caster's cell on fire!
dir = getdirtowards(c, targcell, NULL, B_FALSE); for (i = 1; i < nretcell; i++) {
c = getcellindir(c, dir); cell_t *c;
if (!c) break; c = retcell[i];
if (c->type->solid) break;
// set on fire // set on fire
addob(c->obpile, "medium fire"); addob(c->obpile, "medium fire");
if (c->lf) { if (c->lf) {
@ -841,7 +873,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else if (spellid == OT_S_CLOUDKILL) { } 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) { if (targcell->type->solid) {
fizzle(caster); fizzle(caster);
@ -854,10 +886,48 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("A cloud of poison gas appears!"); msg("A cloud of poison gas appears!");
if (seenbyplayer) *seenbyplayer = B_TRUE; 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) { } else if (spellid == OT_S_CONECOLD) {
char lfname[BUFLEN]; char lfname[BUFLEN];
int acc; 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 // animation
anim(caster->cell, targcell, '}'); anim(caster->cell, targcell, '}');
if (isplayer(caster) || cansee(player, caster)) { 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) { } else if (spellid == OT_S_DETECTLIFE) {
target = caster; target = caster;
if (isplayer(caster)) { if (isplayer(caster)) {
int howlong; int howlong,radius;
howlong = getspellduration(10,20,blessed) + (power*2); howlong = getspellduration(10,20,blessed) + (power*2);
radius = power * 10;
addtempflag(target->flags, F_DETECTLIFE, 10, NA, NA, NULL, howlong); addtempflag(target->flags, F_DETECTLIFE, 10, NA, NA, NULL, howlong);
} else { } else {
// monsters can't use this // 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 // 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) { } else if (spellid == OT_S_DETONATE) {
// don't need line of fire! // 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); 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; float totalmass = 0;
object_t *o, *nexto; 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? // how much metal is there?
for (o = targcell->obpile->first ; o ; o = nexto) { 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++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y); targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldist(caster->cell, targcell) <= range)) { 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]; char lfname[BUFLEN];
// automatic hit // automatic hit
getlfname(targcell->lf, lfname); getlfname(targcell->lf, lfname);
@ -1216,7 +1297,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char numbuf[BUFLEN]; char numbuf[BUFLEN];
numtotext(power, numbuf); 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 // animation
anim(caster->cell, targcell, '}'); anim(caster->cell, targcell, '}');
if (isplayer(caster) || cansee(player, caster)) { 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) { } else if (spellid == OT_S_FIREBALL) {
int failed = B_FALSE; int failed = B_FALSE;
// ask for a target cell // 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) {
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) { if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
int dir; int dir;
@ -1312,7 +1393,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FIREDART) { } else if (spellid == OT_S_FIREDART) {
char lfname[BUFLEN]; char lfname[BUFLEN];
int acc; 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 // animation
anim(caster->cell, targcell, '}'); anim(caster->cell, targcell, '}');
if (isplayer(caster) || cansee(player, caster)) { 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++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y); targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) { 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]; char lfname[BUFLEN];
// automatic hit // automatic hit
getlfname(targcell->lf, lfname); 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) { } else if (spellid == OT_S_FLAMEPILLAR) {
int failed = B_FALSE; int failed = B_FALSE;
// ask for a target cell // 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 && haslos(caster, targcell)) {
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) { if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
flag_t *f; flag_t *f;
@ -1565,7 +1646,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else if (spellid == OT_S_HASTE) { } else if (spellid == OT_S_HASTE) {
int howlong = 15; 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; target = targcell->lf;
@ -1747,7 +1828,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char numbuf[BUFLEN]; char numbuf[BUFLEN];
numtotext(power, numbuf); 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 // animation
anim(caster->cell, targcell, '}'); anim(caster->cell, targcell, '}');
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
@ -1950,7 +2031,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE; 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 // 4 is the same as ST_TITANIC strength
// 10 = gun speed // 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 = addtempflag(caster->flags, F_ARBOOST, power*3, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid; 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) { } else if (spellid == OT_S_PULLMETAL) {
int donesomething = B_FALSE; 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) { if (targcell->lf) {
object_t *o; object_t *o;
@ -2282,7 +2394,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int willannounce = B_FALSE; int willannounce = B_FALSE;
char targname[BUFLEN]; 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; target = targcell->lf;
if (!target) { if (!target) {
@ -2305,7 +2417,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else if (spellid == OT_S_KNOCK) { } else if (spellid == OT_S_KNOCK) {
object_t *o; 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); o = hasobwithflag(targcell->obpile, F_DOOR);
if (o) { if (o) {
int dooropen; 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 3, you can control where the light appears
// at power 8, the light is permenant // at power 8, the light is permenant
if (power >= 3) { 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 { } else {
targcell = caster->cell; 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 = addtempflag(caster->flags, F_DTIMMUNE, DT_FALL, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid; 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) { } else if (spellid == OT_S_PASSWALL) {
int howlong = 7; int howlong = 7;
target = caster; target = caster;
@ -2578,7 +2734,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_SPARK) { } else if (spellid == OT_S_SPARK) {
object_t *o,*nexto; object_t *o,*nexto;
int donesomething = B_FALSE; 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)) { if (haslos(player, targcell)) {
msg("A small spark of flame appears."); 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); o = relinkob(o, newloc->obpile);
} }
if (o) { if (o) {
if (isblind(caster)) { noise(caster->cell, NULL, "something hitting the ground.", NULL);
youhear(caster->cell, "something hitting the ground."); if (!isblind(caster)) {
} else {
msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : ""); msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : "");
} }
} else { } else {
@ -3111,7 +3266,7 @@ void pullobto(object_t *o, lifeform_t *lf) {
} }
// where does it end up? // where does it end up?
obloc = getoblocation(o); 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); newcell = getcellindir(lf->cell, dir);
if (newcell) { if (newcell) {
// move next to player // move next to player
@ -3205,44 +3360,44 @@ lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **targe
return *target; 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 maxrange = UNLIMITED;
int done = B_FALSE; int done = B_FALSE;
cell_t *where = NULL;
maxrange = getspellrange(spellid, power); maxrange = getspellrange(spellid, power);
while (!done) { while (!done) {
if (*targcell) {
done = B_TRUE;
} else {
// ask for a target cell
if (isplayer(caster)) {
cell_t *where;
char buf[BUFLEN];
if (maxrange == UNLIMITED) {
objecttype_t *ot;
ot = findot(spellid);
sprintf(buf, "Where will you target your %s?", ot->name);
} else {
sprintf(buf, "Where will you target your spell [max range %d]?",maxrange);
}
where = askcoords(buf, targtype);
if (where) { if (where) {
//if (haslos(caster, where) || (where == caster->cell)) { cell_t *newwhere = NULL;
if (needlof && !haslof(caster, where)) { // validate it
// no line of sight if (where && needlos && !haslos(caster, where)) {
fizzle(caster); msg("You cannot see there!"); more();
return NULL; where = NULL;
} else if ((maxrange != UNLIMITED) && (getcelldist(caster->cell, where) > maxrange)) { }
// out of range
fizzle(caster); if (where && needlof && !haslof(caster, where, needlof, &newwhere)) {
return NULL; 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 { } else {
*targcell = where; where = NULL;
done = B_TRUE; }
} 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! // warn before targetting yourself!
if (isplayer(caster) && (where == caster->cell)) {
if (getiqname(getattr(caster, A_IQ), NULL) >= IQ_AVERAGE) { if (getiqname(getattr(caster, A_IQ), NULL) >= IQ_AVERAGE) {
objecttype_t *sp; objecttype_t *sp;
sp = findot(spellid); sp = findot(spellid);
@ -3252,26 +3407,36 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i
int ch; int ch;
ch = askchar("Really target yourself","yn","n", B_TRUE); ch = askchar("Really target yourself","yn","n", B_TRUE);
if (ch != 'y') { if (ch != 'y') {
*targcell = NULL; where = NULL;
done = B_FALSE;
} }
} }
} }
} }
} }
// still got a target?
if (where) {
*targcell = where;
done = B_TRUE;
} }
/*
} else { } else {
msg("You can't see there!"); // ask for a target cell
more(); if (isplayer(caster)) {
*targcell = NULL; char buf[BUFLEN];
done = B_FALSE; if (maxrange == UNLIMITED) {
} objecttype_t *ot;
*/ ot = findot(spellid);
sprintf(buf, "Where will you target your %s?", ot->name);
} else { } else {
// no line of sight or invalid cell sprintf(buf, "Where will you target your spell [max range %d]?",maxrange);
fizzle(caster); }
return NULL; where = askcoords(buf, targtype);
if (!where) {
int ch;
ch = askchar("Abandon your spell?","yn","n", B_TRUE);
if (ch != 'y') {
where = NULL;
}
} }
} else { } else {
// TODO: fill in monster code? // 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 stopspell(lifeform_t *caster, enum OBTYPE spellid);
void stopallspells(lifeform_t *lf); void stopallspells(lifeform_t *lf);
lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target); 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); lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
#endif #endif

23
text.c
View File

@ -32,16 +32,18 @@ char *capitaliseall(char *text) {
char *getattrname(enum ATTRIB att) { char *getattrname(enum ATTRIB att) {
switch (att) { switch (att) {
case A_NONE:
return "?attrib_none?";
case A_STR: case A_STR:
return "strength"; return "strength";
case A_IQ: case A_IQ:
return "intelligence"; return "intelligence";
case A_DEX: case A_DEX:
return "dexterity"; return "dexterity";
default: case A_CON:
break; return "constitution";
} }
return "?unknown?"; return "?badattrib?";
} }
char *getpossessive(char *text) { char *getpossessive(char *text) {
@ -219,6 +221,21 @@ char *makeplural(char *text) {
return newtext; 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 *noprefix(char *obname) {
char *p; char *p;
p = strchr(obname, ' '); p = strchr(obname, ' ');

1
text.h
View File

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