This commit is contained in:
parent
4f89ab33f8
commit
020f47b808
127
ai.c
127
ai.c
|
@ -18,7 +18,8 @@ extern enum ERROR reason;
|
|||
|
||||
int wantdb = B_TRUE;
|
||||
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf) {
|
||||
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
|
||||
flag_t *f;
|
||||
enum OBTYPE poss[MAXPILEOBS];
|
||||
int nposs = 0;
|
||||
|
@ -29,25 +30,51 @@ enum OBTYPE aigetattackspell(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
for (f = lf->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_CANWILL) {
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
} else if (f->id == F_CANCAST) {
|
||||
if ((f->id == F_CANCAST) || (f->id == F_CANWILL)) {
|
||||
objecttype_t *ot;
|
||||
ot = findot(f->val[0]);
|
||||
if (cancast(lf, f->val[0], NULL)) {
|
||||
if (hasflag(ot->flags, F_AICASTATVICTIM) || hasflag(ot->flags, F_AICASTATSELF) || hasflag(ot->flags, F_AICASTANYWHERE)) {
|
||||
int ok = B_FALSE;
|
||||
if (hasflag(ot->flags, F_AICASTATVICTIM)) {
|
||||
int range;
|
||||
range = getspellrange(f->val[0]);
|
||||
if ((range == UNLIMITED) || (getcelldist(lf->cell, victim->cell) <= range)) {
|
||||
if (db) {
|
||||
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?");
|
||||
}
|
||||
//TODO :ooo only add if we have an AICAST flag!
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else if (hasflag(ot->flags, F_AICASTATSELF) || hasflag(ot->flags, F_AICASTANYWHERE)) {
|
||||
if (db) {
|
||||
dblog(".oO { spell possibility: %s }", ot ? ot->name : "?unkownspell?");
|
||||
}
|
||||
ok = B_TRUE;
|
||||
} else if (hasflag(ot->flags, F_AICASTATADJVICTIM) &&
|
||||
(getcelldist(lf->cell,victim->cell) == 1)) {
|
||||
if (ot->id == OT_A_GRAB) {
|
||||
if (lfhasflag(lf, F_GRABBING) || lfhasflag(lf, F_GRABBEDBY) ||
|
||||
lfhasflag(victim, F_GRABBING) || lfhasflag(victim, F_GRABBEDBY)) {
|
||||
} else {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else if (hasflag(ot->flags, F_AICASTNEXTTOVICTIM) &&
|
||||
(getcelldist(lf->cell,victim->cell) == 1)) {
|
||||
ok = B_TRUE;
|
||||
} else {
|
||||
if (db) {
|
||||
dblog(".oO { cant cast %s - dont know where to target it }", ot ? ot->name : "?unkownspell?");
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (aispellok(lf, ot, victim)) {
|
||||
poss[nposs] = f->val[0];
|
||||
nposs++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (db) {
|
||||
if (ot) {
|
||||
|
@ -77,6 +104,18 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi
|
|||
if (spelllf) *spelllf = victim;
|
||||
if (spellcell) *spellcell = victim->cell;
|
||||
if (spellob) *spellob = NULL;
|
||||
} else if (hasflag(spelltype->flags, F_AICASTNEXTTOVICTIM)) {
|
||||
if (getcelldist(lf->cell, victim->cell) <= 1) {
|
||||
if (spelllf) *spelllf = NULL;
|
||||
if (spellcell) *spellcell = lf->cell;
|
||||
if (spellob) *spellob = NULL;
|
||||
}
|
||||
} else if (hasflag(spelltype->flags, F_AICASTATADJVICTIM)) {
|
||||
if (getcelldist(lf->cell, victim->cell) <= 1) {
|
||||
if (spelllf) *spelllf = victim;
|
||||
if (spellcell) *spellcell = victim->cell;
|
||||
if (spellob) *spellob = NULL;
|
||||
}
|
||||
} else if (hasflag(spelltype->flags, F_AICASTATSELF)) {
|
||||
if (spelllf) *spelllf = lf;
|
||||
if (spellcell) *spellcell = lf->cell;
|
||||
|
@ -181,6 +220,18 @@ void aimove(lifeform_t *lf) {
|
|||
if (!weild(lf, bestgun)) return;
|
||||
}
|
||||
|
||||
// do we have better ammo?
|
||||
if (curgun) {
|
||||
object_t *curammo;
|
||||
curammo = getammo(lf);
|
||||
if (!curammo) {
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
testammo(lf, o); // doesn't take any time.
|
||||
if (getammo(lf)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do we have better armour?
|
||||
for (bp = BP_RIGHTHAND ; bp < MAXBODYPARTS; bp++) {
|
||||
object_t *curarm;
|
||||
|
@ -228,7 +279,7 @@ void aimove(lifeform_t *lf) {
|
|||
|
||||
// reset F_TARGET lifetime to full.
|
||||
f->lifetime = AI_FOLLOWTIME;
|
||||
if (db) dblog(".oO { i can see my target (at %d,%d). will move towards it. }",target->cell->x,target->cell->y);
|
||||
if (db) dblog(".oO { i can see my target (at %d,%d). might move towards it. }",target->cell->x,target->cell->y);
|
||||
// remember last known loc
|
||||
f->val[1] = target->cell->x;
|
||||
f->val[2] = target->cell->y;
|
||||
|
@ -236,8 +287,13 @@ void aimove(lifeform_t *lf) {
|
|||
goingtomove = B_TRUE;
|
||||
|
||||
|
||||
// drink boost potions
|
||||
if (!useitemwithflag(lf, F_AIBOOSTITEM)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// can we attack with spells (ie. ones which target the victim)?
|
||||
spell = aigetattackspell(lf);
|
||||
spell = aigetattackspell(lf, target);
|
||||
if (spell != OT_NONE) {
|
||||
int spellfailed = B_FALSE;
|
||||
lifeform_t *spelllf = NULL;
|
||||
|
@ -288,27 +344,42 @@ void aimove(lifeform_t *lf) {
|
|||
aigetspelltarget(lf, st, target, &spelllf, &spellcell, &spellob);
|
||||
}
|
||||
|
||||
|
||||
if (!spellfailed && !castspell(lf, spell, spelllf, spellob, spellcell)) {
|
||||
if (spellfailed) {
|
||||
if (db) dblog(".oO { cast spell/ability failed (1)! }");
|
||||
} else {
|
||||
if (getschool(spell) == SS_ABILITY) {
|
||||
spellfailed = useability(lf, spell, spelllf, spellcell);
|
||||
} else {
|
||||
spellfailed = castspell(lf, spell, spelllf, spellob, spellcell);
|
||||
}
|
||||
}
|
||||
if (spellfailed) {
|
||||
if (db) dblog(".oO { cast spell/ability tried but failed (2)! }");
|
||||
} else {
|
||||
// spell succesful
|
||||
return;
|
||||
} else {
|
||||
if (db) dblog(".oO { cast spell failed! }");
|
||||
}
|
||||
}
|
||||
|
||||
// if not adjacent, check for guns, wands, throwing
|
||||
if (goingtomove && (getcelldist(lf->cell, target->cell) > 1)) {
|
||||
if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell)) {
|
||||
// can we attack by firing something?
|
||||
gun = getfirearm(lf);
|
||||
if (goingtomove && gun && getammo(lf)) {
|
||||
if (db) {
|
||||
char gunname[BUFLEN];
|
||||
getobname(gun, gunname, gun->amt);
|
||||
dblog(".oO { will fire my gun (%s) at target. }",gunname);
|
||||
}
|
||||
setguntarget(lf, target);
|
||||
if (!shoot(lf)) {
|
||||
// succesful
|
||||
return;
|
||||
} else {
|
||||
if (db) dblog(".oO { shoot gun failed! }");
|
||||
if (db) dblog(".oO { shoot gun failed! reason = %d }", reason);
|
||||
}
|
||||
} else {
|
||||
if (db) dblog(".oO { not firing out gun }");
|
||||
}
|
||||
|
||||
// can we attack by throwing something?
|
||||
|
@ -500,6 +571,12 @@ void aimove(lifeform_t *lf) {
|
|||
// need to heal?
|
||||
if ((lf->hp < lf->maxhp) ||
|
||||
((lf->mp < lf->maxmp) && lfhasflag(lf, F_RESTHEALMPAMT)) ) {
|
||||
if (lf->hp < (lf->maxhp/2)) {
|
||||
if (!useitemwithflag(lf, F_AIHEALITEM)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (db) dblog(".oO { resting }");
|
||||
rest(lf, B_TRUE);
|
||||
}
|
||||
|
@ -523,6 +600,21 @@ int aipickup(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
|
||||
|
||||
int aispellok(lifeform_t *lf, objecttype_t *st, lifeform_t *victim) {
|
||||
if ((st->id == OT_S_BLINDNESS) && isblind(victim)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
if ((st->id == OT_S_PAIN) && lfhasflag(victim, F_PAIN)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
if ((st->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op) {
|
||||
object_t *o;
|
||||
|
||||
|
@ -709,4 +801,3 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
3
ai.h
3
ai.h
|
@ -1,10 +1,11 @@
|
|||
#include "defs.h"
|
||||
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf);
|
||||
enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim);
|
||||
void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob);
|
||||
object_t * aigetwand(lifeform_t *lf);
|
||||
void aimove(lifeform_t *lf);
|
||||
int aipickup(lifeform_t *lf, object_t *o);
|
||||
int aispellok(lifeform_t *lf, objecttype_t *st, lifeform_t *victim);
|
||||
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op);
|
||||
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op);
|
||||
int lookforobs(lifeform_t *lf, int covetsonly);
|
||||
|
|
293
attack.c
293
attack.c
|
@ -8,6 +8,8 @@
|
|||
#include "flag.h"
|
||||
#include "io.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
#include "move.h"
|
||||
#include "nexus.h"
|
||||
#include "objects.h"
|
||||
#include "text.h"
|
||||
|
@ -15,6 +17,47 @@
|
|||
extern lifeform_t *player;
|
||||
|
||||
|
||||
int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) {
|
||||
object_t *armour;
|
||||
int adam;
|
||||
int damtaken = 0;
|
||||
if ((damtype == DT_ACID) || hasflag(wep->flags, F_ARMOURPIERCE)) {
|
||||
// ALL of damage reduction goes towards armour
|
||||
adam = dam;
|
||||
} else {
|
||||
// some of damage reduction goes towards armour
|
||||
adam = (dam / 2);
|
||||
}
|
||||
// pick a random piece of armour
|
||||
armour = getrandomarmour(lf);
|
||||
if (armour) {
|
||||
damtaken = takedamage(armour,adam, damtype);
|
||||
}
|
||||
return damtaken;
|
||||
}
|
||||
|
||||
void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *dam, enum DAMTYPE damtype) {
|
||||
int db = B_FALSE;
|
||||
|
||||
// armour can't stop armour-piercing weapons
|
||||
if (hasflag(wep->flags, F_ARMOURPIERCE)) {
|
||||
reduceamt = 0;
|
||||
}
|
||||
|
||||
if (db) {
|
||||
if (reduceamt > 0) {
|
||||
dblog("Armour reduces dam by %d to %d.",reduceamt,dam);
|
||||
} else {
|
||||
dblog("No armour dam reduction.");
|
||||
}
|
||||
}
|
||||
if (dam && (reduceamt >= 0)) {
|
||||
*dam -= reduceamt;
|
||||
if (*dam < 0) *dam = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int attackcell(lifeform_t *lf, cell_t *c) {
|
||||
// anyone there? if so just attack.
|
||||
if (c->lf) {
|
||||
|
@ -45,10 +88,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
object_t *wep;
|
||||
obpile_t *op = NULL;
|
||||
int attacktime;
|
||||
int acc;
|
||||
int hit = B_FALSE;
|
||||
int critical = 0;
|
||||
char wepname[BUFLEN];
|
||||
int ev;
|
||||
//int acc;
|
||||
//int ev;
|
||||
int i;
|
||||
int willheal = B_FALSE;
|
||||
|
||||
|
@ -61,7 +105,16 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
|
||||
// get names
|
||||
getlfname(lf, attackername);
|
||||
|
||||
if (lf == victim) {
|
||||
if (isplayer(lf)) {
|
||||
strcpy(victimname, "yourself");
|
||||
} else {
|
||||
strcpy(victimname, "itself");
|
||||
}
|
||||
} else {
|
||||
getlfname(victim, victimname);
|
||||
}
|
||||
|
||||
|
||||
if (aidb) dblog(".oO { trying to attack %s }", victimname);
|
||||
|
@ -89,25 +142,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
|
||||
taketime(lf, attacktime);
|
||||
|
||||
acc = getlfaccuracy(lf);
|
||||
|
||||
// modify for defender's evasion
|
||||
ev = getevasion(victim);
|
||||
acc -= ev;
|
||||
|
||||
// metal weapon versus magnetic shield?
|
||||
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
|
||||
acc -= 45;
|
||||
}
|
||||
|
||||
if (acc < 0) acc = 0;
|
||||
if (acc > 100) acc = 100;
|
||||
|
||||
if (aidb) dblog(".oO { my modified chance to hit is %d %% }", acc);
|
||||
|
||||
// did you hit?
|
||||
ndam = 0;
|
||||
if (rnd(1,100) <= acc) {
|
||||
if (rolltohit(lf, victim, &critical)) {
|
||||
int n;
|
||||
hit = B_TRUE;
|
||||
if (aidb) dblog(".oO { i hit! }");
|
||||
|
||||
|
@ -122,7 +160,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
o = addob(lf->pack, "glowing flask");
|
||||
if (o) {
|
||||
getobname(o, buf, o->amt);
|
||||
msglower("%c - %s.",o->letter, buf);
|
||||
msgnocap("%c - %s.",o->letter, buf);
|
||||
} else {
|
||||
// add to the ground
|
||||
o = addob(lf->cell->obpile, "glowing flask");
|
||||
|
@ -143,12 +181,18 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
|
||||
// determine damage
|
||||
//if (unarmed && (unarmedflag->val[0] != NA)) {
|
||||
// ie. if critical is 0, do this once.
|
||||
// if critical is 1, do this twice.
|
||||
// etc.
|
||||
dam[ndam] = 0;
|
||||
for (n = 0; n < critical+1; n++) {
|
||||
if (unarmedflag) {
|
||||
// this mosnter's unarmed attack will
|
||||
// override normal damage calculation
|
||||
dam[ndam] = getdamrollfromflag(unarmedflag);
|
||||
dam[ndam] += getdamrollfromflag(unarmedflag);
|
||||
} else {
|
||||
dam[ndam] = getdamroll(wep, victim);
|
||||
dam[ndam] += getdamroll(wep, victim);
|
||||
}
|
||||
}
|
||||
if (aidb) dblog("rolled dam[%d] = %d",ndam,dam[ndam]);
|
||||
|
||||
|
@ -175,7 +219,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
}
|
||||
|
||||
// determine extra damage
|
||||
getextradam(wep, &dam[ndam], &damtype[ndam]);
|
||||
getextradam(wep, &dam[0], &damtype[0], &ndam);
|
||||
}
|
||||
} else {
|
||||
hit = B_FALSE;
|
||||
|
@ -185,24 +229,26 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
|
||||
|
||||
if (ndam > 0) {
|
||||
flag_t *f;
|
||||
for (i = 0; i < ndam; i++) {
|
||||
float reducepct;
|
||||
int ar;
|
||||
int reduceamt;
|
||||
|
||||
dblog("initial dam[%d] = %d",i,dam[i]);
|
||||
|
||||
if (lfhasflag(lf, F_HEAVYBLOW)) {
|
||||
dam[i] = (int)((float)dam[i] * 1.5);
|
||||
dblog("heavy blow makes dam[%d] = %d",i,dam[i]);
|
||||
}
|
||||
|
||||
// modify based on resistances
|
||||
adjustdamlf(victim, &dam[i], damtype[i]);
|
||||
dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
|
||||
|
||||
// modify for defender's armour
|
||||
ar = getarmourrating(victim);
|
||||
reducepct = getdamreducepct(ar);
|
||||
reduceamt = (int) ceil((reducepct / 100.0) * (float)dam[i]);
|
||||
reduceamt = getarmourdamreduction(victim, wep, dam[i], damtype[i]);
|
||||
|
||||
applyarmourdamreduction(victim, wep, reduceamt, &dam[i], damtype[i]);
|
||||
|
||||
dam[i] -= reduceamt;
|
||||
if (dam[i] < 0) dam[i] = 0;
|
||||
dblog("reduced by armour to dam[%d] = %d",i,dam[i]);
|
||||
|
||||
// will this hit be fatal?
|
||||
|
@ -287,7 +333,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
if (wep && !unarmedflag) {
|
||||
char wepname[BUFLEN];
|
||||
getobname(wep, wepname, 1);
|
||||
sprintf(buf, "%s^weilding %s",attackername, wepname);
|
||||
sprintf(buf, "%s^%s %s",attackername,
|
||||
(lf == victim) ? "using" : "weilding",
|
||||
wepname);
|
||||
} else {
|
||||
strcpy(buf, attackername);
|
||||
}
|
||||
|
@ -296,20 +344,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
|
||||
// victim's armour loses hp
|
||||
if (reduceamt) {
|
||||
object_t *armour;
|
||||
int adam;
|
||||
if (damtype[i] == DT_ACID) {
|
||||
// ALL of damage reduction goes towards armour
|
||||
adam = reduceamt;
|
||||
} else {
|
||||
// some of damage reduction goes towards armour
|
||||
adam = (reduceamt / 2);
|
||||
}
|
||||
// pick a random piece of armour
|
||||
armour = getrandomarmour(victim);
|
||||
if (armour) {
|
||||
takedamage(armour,adam, damtype[i]);
|
||||
}
|
||||
applyarmourdamage(victim, wep, reduceamt, damtype[i]);
|
||||
}
|
||||
}
|
||||
} // end foreach damtype
|
||||
|
@ -319,7 +354,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
|
||||
if (!isdead(victim)) {
|
||||
if (unarmedflag) {
|
||||
flag_t *f;
|
||||
f = lfhasflag(lf, F_FREEZINGTOUCH);
|
||||
if (f) {
|
||||
// victim turns to ice for a while!
|
||||
|
@ -327,6 +361,45 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
killflag(f);
|
||||
}
|
||||
}
|
||||
|
||||
f = lfhasflag(lf, F_QUICKBITE);
|
||||
if (f) {
|
||||
if (isbleeding(victim)) {
|
||||
int dam;
|
||||
char lfname[BUFLEN];
|
||||
dam = rolldie(f->val[0], f->val[1]) + f->val[2];
|
||||
getlfname(lf, lfname);
|
||||
losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE);
|
||||
if (isplayer(victim) || haslos(player, victim->cell)) {
|
||||
msg("%s bites %s!", lfname, victimname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f = lfhasflag(lf, F_PACKATTACK);
|
||||
if (f) {
|
||||
int dir;
|
||||
cell_t *c;
|
||||
int nmatched = 0;
|
||||
// count adjacent allies of name xx
|
||||
for (dir = DC_N; dir <= DC_NW; dir++) {
|
||||
c = getcellindir(victim->cell, dir);
|
||||
if (c && c->lf) {
|
||||
if (strcasestr(c->lf->race->name, f->text)) {
|
||||
nmatched++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nmatched >= f->val[2]) {
|
||||
char damstring[BUFLEN];
|
||||
sprintf(damstring, "a %s pack", f->text);
|
||||
losehp(victim, f->val[0], f->val[1], lf, damstring);
|
||||
if (isplayer(victim) || haslos(player, victim->cell)) {
|
||||
msg("The %s pack attacks %s!", f->text, victimname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else { // miss!
|
||||
if (aidb) dblog(".oO { i missed! }");
|
||||
|
@ -349,6 +422,18 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
|
|||
msg("%s misses %s.", buf, victimname);
|
||||
}
|
||||
}
|
||||
|
||||
if (lfhasflag(victim, F_DODGES)) {
|
||||
flag_t *f;
|
||||
cell_t *adj;
|
||||
|
||||
f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
|
||||
adj = getrandomadjcell(victim->cell, WE_NOTSOLID);
|
||||
moveto(lf, adj);
|
||||
msg("%s dodge%s!",victimname,isplayer(victim) ? "" : "s");
|
||||
killflag(f);
|
||||
|
||||
}
|
||||
}
|
||||
fightback(victim, lf);
|
||||
}
|
||||
|
@ -445,7 +530,8 @@ int attackob(lifeform_t *lf, object_t *o) {
|
|||
// don't need to check for blessed vs mosnters
|
||||
|
||||
// determine extra damage
|
||||
getextradam(wep, &dam[ndam], &damtype[ndam]);
|
||||
getextradam(wep, &dam[0], &damtype[0], &ndam);
|
||||
|
||||
|
||||
for (i = 0; i < ndam; i++) {
|
||||
// announce the hit
|
||||
|
@ -473,6 +559,16 @@ int attackob(lifeform_t *lf, object_t *o) {
|
|||
youhear(lf->cell, "sounds of fighting");
|
||||
}
|
||||
|
||||
if ((i == 0) && unarmedflag) {
|
||||
char buf[BUFLEN];
|
||||
sprintf(buf, "punching %s", obname);
|
||||
if ( losehp(lf, 1, DT_BASH, lf, buf)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("Ow!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// object loses hp
|
||||
takedamage(o, dam[i], damtype[i]);
|
||||
|
||||
|
@ -481,6 +577,21 @@ int attackob(lifeform_t *lf, object_t *o) {
|
|||
// special weapon effects
|
||||
wepeffects(wep, obloc);
|
||||
|
||||
// weapon gets damaged ?
|
||||
if (!unarmedflag && wep && (ndam > 0)) {
|
||||
switch (damtype[0]) {
|
||||
case DT_PIERCE:
|
||||
case DT_SLASH:
|
||||
// weapon gets duller
|
||||
if (rnd(1,2)) makeduller(wep, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// hitting an object with our hands will hurt
|
||||
|
||||
// get rid of temp unarmed object pile
|
||||
if (op) {
|
||||
killobpile(op);
|
||||
|
@ -489,6 +600,20 @@ int attackob(lifeform_t *lf, object_t *o) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
// returns the amount of damage the armour blocked...
|
||||
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) {
|
||||
int reduceamt = 0;
|
||||
float reducepct;
|
||||
int ar;
|
||||
|
||||
ar = getarmourrating(lf);
|
||||
reducepct = getdamreducepct(ar);
|
||||
reduceamt = (int) ceil((reducepct / 100.0) * (float)dam);
|
||||
|
||||
if (reduceamt < 0) reduceamt = 0;
|
||||
return reduceamt;
|
||||
}
|
||||
|
||||
|
||||
// returns a const char *
|
||||
char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
|
@ -597,6 +722,12 @@ char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) {
|
|||
} else {
|
||||
return "freeze";
|
||||
}
|
||||
} else if (damtype == DT_UNARMED) {
|
||||
if (rnd(1,2) == 1) {
|
||||
return "punch";
|
||||
} else {
|
||||
return "hit";
|
||||
}
|
||||
} else if (damtype == DT_TOUCH) {
|
||||
return "touch";
|
||||
}
|
||||
|
@ -635,12 +766,13 @@ enum DAMTYPE getdamtype(object_t *wep) {
|
|||
return dt;
|
||||
}
|
||||
|
||||
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype) {
|
||||
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) {
|
||||
flag_t *f;
|
||||
for (f = wep->flags->first ; f ; f = f->next) {
|
||||
if (f->id == F_ONFIRE) {
|
||||
*dam = rnd(5,10); // TODO: don't hardcode?
|
||||
*damtype = DT_FIRE;
|
||||
*(dam + *ndam) = rolldie(2,8);
|
||||
*(damtype + *ndam) = DT_FIRE;
|
||||
(*ndam)++;
|
||||
}
|
||||
}
|
||||
return *dam;
|
||||
|
@ -667,7 +799,7 @@ char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp)
|
|||
if (lfhasflagval(victim, F_NOBODYPART, BP_HEAD, NA, NA, NULL)) {
|
||||
return "bisect";
|
||||
} else {
|
||||
if (rnd(1,3)) {
|
||||
if (rnd(1,3) == 1) {
|
||||
return "behead";
|
||||
} else {
|
||||
return "bisect";
|
||||
|
@ -771,9 +903,8 @@ int getdamroll(object_t *o, lifeform_t *victim) {
|
|||
}
|
||||
|
||||
} else {
|
||||
// TODO wepaon does damage based on weight
|
||||
// weapon does no damage
|
||||
dam = 0;
|
||||
// TODO wepaon does bashing damage based on weight
|
||||
dam = rnd(1,2);
|
||||
}
|
||||
|
||||
// modify for bonus
|
||||
|
@ -938,10 +1069,58 @@ obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) {
|
|||
return op;
|
||||
}
|
||||
|
||||
int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
|
||||
int acc,ev;
|
||||
object_t *wep;
|
||||
obpile_t *op = NULL;
|
||||
int gothit;
|
||||
|
||||
if (critical) {
|
||||
*critical = 0;
|
||||
}
|
||||
|
||||
acc = getlfaccuracy(lf);
|
||||
wep = getattackwep(lf, &op, NULL);
|
||||
|
||||
// modify for defender's evasion
|
||||
ev = getevasion(victim);
|
||||
acc -= ev;
|
||||
|
||||
// metal weapon versus magnetic shield?
|
||||
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
|
||||
acc -= 45;
|
||||
}
|
||||
|
||||
if (critical) {
|
||||
if (rnd(1,20) == 20) *critical = 1;
|
||||
}
|
||||
|
||||
if (acc < 0) acc = 0;
|
||||
if (acc > 100) acc = 100;
|
||||
|
||||
//if (aidb) dblog(".oO { my modified chance to hit is %d %% }", acc);
|
||||
if (rnd(1,100) <= acc) {
|
||||
gothit = B_TRUE;
|
||||
} else {
|
||||
if (critical && *critical) {
|
||||
// turn a miss into a hit
|
||||
gothit = B_TRUE;
|
||||
} else {
|
||||
gothit = B_FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (op) killobpile(op);
|
||||
return gothit;
|
||||
}
|
||||
|
||||
void wepeffects(object_t *wep, cell_t *where) {
|
||||
flag_t *f;
|
||||
lifeform_t *victim;
|
||||
lifeform_t *owner;
|
||||
|
||||
owner = wep->pile->owner;
|
||||
victim = where->lf;
|
||||
|
||||
if (!where) return;
|
||||
|
@ -1024,6 +1203,12 @@ void wepeffects(object_t *wep, cell_t *where) {
|
|||
}
|
||||
} // end if dampct > 50
|
||||
}
|
||||
} else if ((f->id == F_HEAVYBLOW) && victim && owner) {
|
||||
int dir;
|
||||
// knock back victim
|
||||
dir = getdirtowards(owner->cell, victim->cell, victim, B_FALSE);
|
||||
knockback(victim, dir , 2, owner);
|
||||
f->known = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
6
attack.h
6
attack.h
|
@ -1,12 +1,15 @@
|
|||
#include "defs.h"
|
||||
|
||||
int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype);
|
||||
void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *dam, enum DAMTYPE damtype);
|
||||
int attackcell(lifeform_t *lf, cell_t *c);
|
||||
int attacklf(lifeform_t *lf, lifeform_t *victim);
|
||||
int attackob(lifeform_t *lf, object_t *o);
|
||||
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype);
|
||||
char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp);
|
||||
object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag);
|
||||
enum DAMTYPE getdamtype(object_t *wep);
|
||||
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype);
|
||||
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam);
|
||||
char *getkillverb(lifeform_t *victim, enum DAMTYPE damtype, int dam, int maxhp);
|
||||
void getdamrange(flagpile_t *fp, int *min, int *max);
|
||||
void getdamrangeunarmed(flag_t *f, int *min, int *max);
|
||||
|
@ -15,4 +18,5 @@ int getdamroll(object_t *o, lifeform_t *victim);
|
|||
int getdamrollfromflag(flag_t *f);
|
||||
float getstrdammod(lifeform_t *lf);
|
||||
obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
|
||||
int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical);
|
||||
void wepeffects(object_t *wep, cell_t *where);
|
||||
|
|
278
defs.h
278
defs.h
|
@ -25,6 +25,16 @@ enum ATTRIB {
|
|||
};
|
||||
#define MAXATTS 3
|
||||
|
||||
enum CHECKTYPE {
|
||||
SC_STR,
|
||||
SC_DEX,
|
||||
SC_IQ,
|
||||
//////////
|
||||
SC_DODGE,
|
||||
SC_SLIP,
|
||||
SC_MORALE,
|
||||
};
|
||||
|
||||
enum BURDENED {
|
||||
BR_NONE = 0,
|
||||
BR_BURDENED = 1,
|
||||
|
@ -68,6 +78,7 @@ enum LFCONDITION {
|
|||
#define IFKNOWN (-9772) // used by f_xxconfer. only confer a flag if item is known.
|
||||
#define IFACTIVE (-9771) // used by f_prodeuceslight. only does so if object is activated
|
||||
|
||||
#define NOCONDITION (0)
|
||||
#define IFMONSTER (-9769) // used in v2 of f_ifpct job flags
|
||||
#define IFPLAYER (-9768) // used in v2 of f_ifpct job flags
|
||||
|
||||
|
@ -102,7 +113,7 @@ enum LFCONDITION {
|
|||
|
||||
#define MAXRANDOMOBCANDIDATES 100
|
||||
#define MAXRANDOMLFCANDIDATES 100
|
||||
#define MAXCANDIDATES 50
|
||||
#define MAXCANDIDATES 200
|
||||
|
||||
//#define MAX_MAPW 80
|
||||
//#define MAX_MAPH 50
|
||||
|
@ -128,7 +139,7 @@ enum LFCONDITION {
|
|||
#define DEF_SPARSENESS 20
|
||||
//#define DEF_SPARSENESS 0
|
||||
//#define DEF_LOOPPCT 70
|
||||
#define DEF_LOOPPCT 85
|
||||
#define DEF_LOOPPCT 95
|
||||
//#define DEF_LOOPPCT 0
|
||||
#define MINROOMS 5
|
||||
#define MAXROOMS 10
|
||||
|
@ -240,21 +251,25 @@ enum CELLTYPE {
|
|||
CT_LOOPCORRIDOR,
|
||||
};
|
||||
|
||||
|
||||
enum SPELLSCHOOL {
|
||||
SS_DIVINE = 2,
|
||||
SS_ABILITY = 0,
|
||||
SS_ALLOMANCY = 1,
|
||||
SS_DEATH = 3,
|
||||
SS_ELEMENTAL = 4,
|
||||
SS_DIVINATION = 5,
|
||||
SS_GRAVITY = 6,
|
||||
SS_LIFE = 7,
|
||||
SS_MODIFICATION = 8,
|
||||
SS_MENTAL = 9,
|
||||
SS_SUMMONING = 10,
|
||||
SS_TRANSLOCATION = 11,
|
||||
SS_WILD = 12,
|
||||
SS_LAST = 13,
|
||||
SS_NONE,
|
||||
SS_DIVINE,
|
||||
SS_ABILITY,
|
||||
SS_ALLOMANCY,
|
||||
SS_AIR,
|
||||
SS_DEATH,
|
||||
SS_DIVINATION,
|
||||
SS_FIRE,
|
||||
SS_ICE,
|
||||
SS_GRAVITY,
|
||||
SS_LIFE,
|
||||
SS_MODIFICATION,
|
||||
SS_MENTAL,
|
||||
SS_SUMMONING,
|
||||
SS_TRANSLOCATION,
|
||||
SS_WILD,
|
||||
SS_LAST,
|
||||
};
|
||||
|
||||
enum STRBRACKET {
|
||||
|
@ -318,15 +333,17 @@ enum DAMTYPE {
|
|||
DT_MAGIC = 17,
|
||||
DT_TOUCH = 18,
|
||||
DT_POISONGAS = 19,
|
||||
DT_NONE = 20, // for direclty dealt damage, not really any type
|
||||
DT_UNARMED = 20,
|
||||
DT_NONE = 21, // for direclty dealt damage, not really any type
|
||||
};
|
||||
#define MAXDAMTYPE 21
|
||||
#define MAXDAMTYPE 22
|
||||
|
||||
// Object Classes
|
||||
enum OBCLASS {
|
||||
OC_MONEY,
|
||||
OC_WEAPON,
|
||||
OC_ARMOUR,
|
||||
OC_MISSILE,
|
||||
OC_RING,
|
||||
OC_SCROLL,
|
||||
OC_POTION,
|
||||
|
@ -374,21 +391,33 @@ enum RACE {
|
|||
// monsters
|
||||
R_BUGBEAR,
|
||||
R_EYEBAT,
|
||||
R_GIANT,
|
||||
R_GIANTHILL,
|
||||
R_GIANTFIRE,
|
||||
R_GIANTFIREFC,
|
||||
R_GIANTFIRETITAN,
|
||||
R_GNOLL,
|
||||
R_GNOLLHM,
|
||||
R_GNOLLMR,
|
||||
R_GOBLIN,
|
||||
R_GOBLINGUARD,
|
||||
R_GOBLINCHAMP,
|
||||
R_GOBLINWAR,
|
||||
R_GOBLINSHOOTER,
|
||||
R_GOBLINHEXER,
|
||||
R_HOBGOBLIN,
|
||||
R_HOBGOBLINWAR,
|
||||
R_KOBOLD,
|
||||
R_LIZARDMAN,
|
||||
R_LURKINGHORROR,
|
||||
R_OGRE,
|
||||
R_OGRESAVAGE,
|
||||
R_OGREWARHULK,
|
||||
R_OOZEGREY,
|
||||
R_ORC,
|
||||
R_ORCWARRIOR,
|
||||
R_ORK,
|
||||
R_POLTERGEIST,
|
||||
R_SHADOWCAT,
|
||||
R_SLIME,
|
||||
R_SPRITEFIRE,
|
||||
R_TROGLODYTE,
|
||||
R_TROLL,
|
||||
R_XAT,
|
||||
// small animals
|
||||
|
@ -397,6 +426,7 @@ enum RACE {
|
|||
R_RAT,
|
||||
R_WOLF,
|
||||
// insects
|
||||
R_BUTTERFLY,
|
||||
R_GLOWBUG,
|
||||
R_GIANTFLY,
|
||||
R_GIANTBLOWFLY,
|
||||
|
@ -452,6 +482,7 @@ enum OBTYPE {
|
|||
OT_NONE,
|
||||
// dungeon features
|
||||
OT_BOULDER,
|
||||
OT_STATUE,
|
||||
OT_WOODENDOOR,
|
||||
OT_WOODENTABLE,
|
||||
OT_WOODENBARREL,
|
||||
|
@ -469,6 +500,7 @@ enum OBTYPE {
|
|||
OT_BERRY,
|
||||
OT_NUT,
|
||||
OT_BANANA,
|
||||
OT_BANANASKIN, // not really food
|
||||
OT_APPLE,
|
||||
OT_MUSHROOM,
|
||||
OT_BREADSTALE,
|
||||
|
@ -501,6 +533,7 @@ enum OBTYPE {
|
|||
OT_POT_ELEMENTENDURE,
|
||||
OT_POT_ELEMENTIMMUNE,
|
||||
OT_POT_ETHEREALNESS,
|
||||
OT_POT_EXPERIENCE,
|
||||
OT_POT_GASEOUSFORM,
|
||||
OT_POT_HEALING,
|
||||
OT_POT_HEALINGMIN,
|
||||
|
@ -521,6 +554,7 @@ enum OBTYPE {
|
|||
OT_SCR_DETECTLIFE,
|
||||
OT_SCR_DETECTMAGIC,
|
||||
OT_SCR_FLAMEPILLAR,
|
||||
OT_SCR_FLAMEBURST,
|
||||
OT_SCR_IDENTIFY,
|
||||
OT_SCR_KNOCK,
|
||||
OT_SCR_LIGHT,
|
||||
|
@ -535,18 +569,28 @@ enum OBTYPE {
|
|||
// SPELLBOOKS
|
||||
// allomancy can't be learned from books
|
||||
// -- death
|
||||
OT_SB_ANIMATEDEAD,
|
||||
OT_SB_PAIN,
|
||||
OT_SB_INFINITEDEATH,
|
||||
OT_SB_WEAKEN,
|
||||
OT_SB_BLINDNESS,
|
||||
// -- divination
|
||||
OT_SB_DETECTAURA,
|
||||
OT_SB_DETECTLIFE,
|
||||
OT_SB_IDENTIFY,
|
||||
OT_SB_MAPPING,
|
||||
// -- elemental
|
||||
// -- elemental - air
|
||||
OT_SB_CLOUDKILL,
|
||||
// -- elemental - fire
|
||||
OT_SB_SPARK,
|
||||
OT_SB_FIREDART,
|
||||
OT_SB_CONECOLD,
|
||||
OT_SB_FIREBALL,
|
||||
OT_SB_FLAMEPILLAR,
|
||||
OT_SB_FLAMEBURST,
|
||||
OT_SB_BURNINGWAVE,
|
||||
// -- elemental - ice
|
||||
OT_SB_CONECOLD,
|
||||
OT_SB_FREEZEOB,
|
||||
// -- gravity
|
||||
OT_SB_GRAVBOOST,
|
||||
OT_SB_HASTE,
|
||||
|
@ -559,12 +603,13 @@ enum OBTYPE {
|
|||
OT_SB_MINDSCAN,
|
||||
OT_SB_TELEKINESIS,
|
||||
// -- modification
|
||||
OT_SB_FREEZEOB,
|
||||
OT_SB_GASEOUSFORM,
|
||||
OT_SB_KNOCK,
|
||||
OT_SB_INSCRIBE,
|
||||
OT_SB_LIGHT,
|
||||
OT_SB_DARKNESS,
|
||||
OT_SB_PASSWALL,
|
||||
OT_SB_PETRIFY,
|
||||
OT_SB_POLYMORPH,
|
||||
OT_SB_POLYMORPHRND,
|
||||
// -- summoning
|
||||
|
@ -586,19 +631,29 @@ enum OBTYPE {
|
|||
OT_S_MAGSHIELD,
|
||||
OT_S_METALHEAL,
|
||||
// -- death
|
||||
OT_S_ANIMATEDEAD,
|
||||
OT_S_PAIN,
|
||||
OT_S_INFINITEDEATH,
|
||||
OT_S_WEAKEN,
|
||||
OT_S_BLINDNESS,
|
||||
// -- divination
|
||||
OT_S_DETECTAURA,
|
||||
OT_S_DETECTLIFE,
|
||||
OT_S_DETECTMAGIC,
|
||||
OT_S_IDENTIFY,
|
||||
OT_S_MAPPING,
|
||||
// -- elemental
|
||||
// -- elemental - air
|
||||
OT_S_CLOUDKILL,
|
||||
// -- elemental - fire
|
||||
OT_S_SPARK,
|
||||
OT_S_FIREDART,
|
||||
OT_S_CONECOLD,
|
||||
OT_S_FIREBALL,
|
||||
OT_S_FLAMEPILLAR,
|
||||
OT_S_FLAMEBURST,
|
||||
OT_S_BURNINGWAVE,
|
||||
// -- elemental - ice
|
||||
OT_S_CONECOLD,
|
||||
OT_S_FREEZEOB,
|
||||
// -- gravity
|
||||
OT_S_GRAVBOOST,
|
||||
OT_S_HASTE,
|
||||
|
@ -609,15 +664,17 @@ enum OBTYPE {
|
|||
OT_S_TURNUNDEAD,
|
||||
// -- mental
|
||||
OT_S_MINDSCAN,
|
||||
OT_S_SLEEP,
|
||||
OT_S_TELEKINESIS,
|
||||
// -- modification
|
||||
OT_S_ENCHANT,
|
||||
OT_S_FREEZEOB,
|
||||
OT_S_GASEOUSFORM,
|
||||
OT_S_INSCRIBE,
|
||||
OT_S_KNOCK,
|
||||
OT_S_LIGHT,
|
||||
OT_S_DARKNESS,
|
||||
OT_S_PASSWALL,
|
||||
OT_S_PETRIFY,
|
||||
OT_S_POLYMORPH,
|
||||
OT_S_POLYMORPHRND,
|
||||
// -- summoning
|
||||
|
@ -638,10 +695,12 @@ enum OBTYPE {
|
|||
OT_S_WISH,
|
||||
OT_S_GIFT,
|
||||
// abilities
|
||||
OT_A_GRAB,
|
||||
OT_A_JUMP,
|
||||
OT_A_SPRINT,
|
||||
OT_A_DEBUG,
|
||||
OT_A_EMPLOY,
|
||||
OT_A_HEAVYBLOW,
|
||||
// wands
|
||||
OT_WAND_COLD,
|
||||
OT_WAND_DETONATION,
|
||||
|
@ -653,6 +712,7 @@ enum OBTYPE {
|
|||
OT_WAND_POLYMORPH,
|
||||
OT_WAND_SLOW,
|
||||
OT_WAND_WEAKNESS,
|
||||
OT_WAND_WONDER,
|
||||
// tech/tools
|
||||
OT_BLINDFOLD,
|
||||
OT_POCKETWATCH,
|
||||
|
@ -682,11 +742,13 @@ enum OBTYPE {
|
|||
OT_CALTROP,
|
||||
OT_BROKENGLASS,
|
||||
OT_ICECHUNK,
|
||||
OT_ICESHEET,
|
||||
OT_PUDDLEWATER,
|
||||
OT_PUDDLEWATERL,
|
||||
OT_SLIMEPOOL,
|
||||
OT_VOMITPOOL,
|
||||
OT_BLOODSTAIN,
|
||||
OT_BLOODSPLASH,
|
||||
OT_BLOODPOOL,
|
||||
OT_SOGGYPAPER,
|
||||
OT_FLESHCHUNK,
|
||||
|
@ -701,6 +763,11 @@ enum OBTYPE {
|
|||
OT_POISONPUFF,
|
||||
// armour - body
|
||||
OT_ARMOURLEATHER,
|
||||
OT_ARMOURRING,
|
||||
OT_ARMOURSCALE,
|
||||
OT_ARMOURCHAIN,
|
||||
OT_ARMOURSPLINT,
|
||||
OT_ARMOURPLATE,
|
||||
OT_FLAKJACKET,
|
||||
OT_OVERALLS,
|
||||
OT_COTTONSHIRT,
|
||||
|
@ -720,6 +787,7 @@ enum OBTYPE {
|
|||
OT_SHOESLEATHER,
|
||||
OT_BOOTSLEATHER,
|
||||
OT_BOOTSRUBBER,
|
||||
OT_BOOTSSPIKED,
|
||||
// armour - hands
|
||||
OT_GLOVESCLOTH,
|
||||
OT_GLOVESLEATHER,
|
||||
|
@ -736,6 +804,8 @@ enum OBTYPE {
|
|||
OT_SUNGLASSES,
|
||||
// armour - shields
|
||||
OT_BUCKLER,
|
||||
OT_SHIELD,
|
||||
OT_SHIELDLARGE,
|
||||
// rings
|
||||
OT_RING_INVULN,
|
||||
OT_RING_MPREGEN,
|
||||
|
@ -752,6 +822,14 @@ enum OBTYPE {
|
|||
OT_ACIDATTACK,
|
||||
OT_TOUCHPARALYZE,
|
||||
OT_TOUCHPARALYZE2,
|
||||
// missiles / ammo
|
||||
OT_ARROW,
|
||||
OT_BOLT,
|
||||
OT_DART,
|
||||
OT_NANODART,
|
||||
OT_JAVELIN,
|
||||
OT_BULLET,
|
||||
OT_RUBBERBULLET,
|
||||
// stabbing weapons
|
||||
OT_DAGGER,
|
||||
OT_COMBATKNIFE,
|
||||
|
@ -761,6 +839,7 @@ enum OBTYPE {
|
|||
OT_QUICKBLADE,
|
||||
// chopping weapons
|
||||
OT_AXE,
|
||||
OT_HANDAXE,
|
||||
OT_BATTLEAXE,
|
||||
OT_GREATAXE,
|
||||
// slashing weapons
|
||||
|
@ -770,6 +849,7 @@ enum OBTYPE {
|
|||
OT_SHORTSWORD,
|
||||
OT_SCIMITAR,
|
||||
OT_LONGSWORD,
|
||||
OT_GREATSWORD,
|
||||
OT_ORNSWORD,
|
||||
// polearms
|
||||
OT_SPEAR,
|
||||
|
@ -778,6 +858,8 @@ enum OBTYPE {
|
|||
OT_STICK,
|
||||
OT_SPANNER,
|
||||
OT_CLUB,
|
||||
OT_FLAIL,
|
||||
OT_FLAILHEAVY,
|
||||
OT_MACE,
|
||||
OT_MORNINGSTAR,
|
||||
OT_GREATCLUB,
|
||||
|
@ -785,9 +867,9 @@ enum OBTYPE {
|
|||
// projectile weapons
|
||||
OT_REVOLVER,
|
||||
OT_SLING,
|
||||
// ammo
|
||||
OT_BULLET,
|
||||
OT_RUBBERBULLET,
|
||||
OT_BOW,
|
||||
OT_LONGBOW,
|
||||
OT_CROSSBOWHAND,
|
||||
// holy weapons
|
||||
OT_HANDOFGOD,
|
||||
|
||||
|
@ -822,14 +904,15 @@ enum NOISETYPE {
|
|||
};
|
||||
|
||||
enum LFSIZE {
|
||||
SZ_MINI, // ie. fly
|
||||
SZ_TINY, // ie. mouse
|
||||
SZ_SMALL, // ie. cat
|
||||
SZ_MEDIUM, // ie. wolf/dog
|
||||
SZ_HUMAN, // ie. human-sized
|
||||
SZ_LARGE, // ie. bear/horse
|
||||
SZ_HUGE, // ie. elephant, dragon
|
||||
SZ_ENORMOUS, // ie. ??? kraken?
|
||||
SZ_MINI = 0, // ie. fly
|
||||
SZ_TINY = 1, // ie. mouse
|
||||
SZ_SMALL = 2, // ie. cat
|
||||
SZ_MEDIUM = 3, // ie. wolf/dog
|
||||
SZ_HUMAN = 4, // ie. human-sized
|
||||
SZ_LARGE = 5, // ie. bear/horse
|
||||
SZ_HUGE = 6, // ie. elephant, dragon, giant
|
||||
SZ_ENORMOUS = 7, // ie. ??? kraken, titan
|
||||
SZ_MAX = 100
|
||||
};
|
||||
|
||||
|
||||
|
@ -854,7 +937,8 @@ enum FLAG {
|
|||
F_UNIQUE, // only one may appear
|
||||
F_GLYPH, // override the glyph with the first char of text
|
||||
F_NOPICKUP, // cannot pick this up
|
||||
F_IMPASSABLE, // cannot walk past this
|
||||
F_IMPASSABLE, // cannot walk past this if your size if v0 or smaller
|
||||
F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it
|
||||
F_BLOCKSVIEW, // cannot see past this
|
||||
F_BLOCKSTHROW, // cannot throw past this
|
||||
F_DIETEXT, // text when the object dies
|
||||
|
@ -918,15 +1002,22 @@ enum FLAG {
|
|||
F_STAIRDIR, // val0 = direcion
|
||||
F_OPPOSITESTAIRS, // val0 = opposite kind of stairs
|
||||
F_MAPLINK, // val0 = map to link to. optional v1/v2 = x/y
|
||||
|
||||
// ob interaction flags
|
||||
F_SHARP, // does damage when you step on it. v0/1 are min/max dam
|
||||
F_SLIPPERY, // you might slip when stepping on it. v0 is amt
|
||||
F_SLIPMOVE, // if someone slips on this, it will move to an adj cell
|
||||
F_FLAMMABLE, // object will catch alight if burnt
|
||||
// object mods/effects
|
||||
F_ONFIRE, // burning, also deals extra fire damage
|
||||
F_HEADLESS, // for corpses
|
||||
F_HEADLESS, // for corpses. can go on LFs too.
|
||||
// weapon flags
|
||||
F_OBATTACKDELAY, // how long weapon takes to attack
|
||||
F_DAMTYPE, // val0 = damage type
|
||||
F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod
|
||||
F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier)
|
||||
F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better)
|
||||
F_ARMOURPIERCE, // goes through armour
|
||||
F_TWOHANDED, // weapon uses two hands to weild
|
||||
F_FIREARM, // this weapon is equipped in bp_secweapon, not _weapon.
|
||||
F_FIRESPEED, // how fast this weapon shoots projectimes
|
||||
|
@ -934,7 +1025,7 @@ enum FLAG {
|
|||
F_RANGE, // range of projectile firing weapon
|
||||
F_FLAMESTRIKE, // causes fires where you hit
|
||||
F_BALANCE, // heals target if their maxhp < your maxhp
|
||||
F_REVENGE, // causes damage based on your max hp
|
||||
F_REVENGE, // causes damage based on your hp
|
||||
// tech flags
|
||||
F_RNDCHARGES, // ob starts with between val0 and val1 charges
|
||||
// this will cause F_CHARGES to be filled in
|
||||
|
@ -944,7 +1035,6 @@ enum FLAG {
|
|||
F_REFILLWITH, // pour obj id val0 onto this to refill its charges
|
||||
// ob appearance flags
|
||||
F_SHINY,
|
||||
F_SHARP, // does damage when you step on it. v0/1 are min/max dam
|
||||
// armour flags
|
||||
F_ARMOURRATING, // val0 * 2 = pct of damage reduced
|
||||
F_SHIELD, // this is a shield - use special bodyhitchance code
|
||||
|
@ -967,8 +1057,13 @@ enum FLAG {
|
|||
F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2
|
||||
//F_SPELLLETTER, // text[0] = letter to cast this spell
|
||||
F_AICASTATVICTIM, // hints for AI to cast spells
|
||||
F_AICASTATADJVICTIM, // hints for AI to cast spells
|
||||
F_AICASTATSELF, // hints for AI to cast spells
|
||||
F_AICASTNEXTTOVICTIM, // hints for AI to cast spells
|
||||
F_AICASTANYWHERE, // hints for AI to cast spells
|
||||
F_AIBOOSTITEM, // ai will use this item to boost/buff itself
|
||||
F_AIHEALITEM, // ai will use this item when low on hp
|
||||
F_AIFLEEITEM, // ai will use this item when fleeing
|
||||
// lifeform flags
|
||||
F_DEBUG, // debugging enabled
|
||||
F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3
|
||||
|
@ -990,6 +1085,7 @@ enum FLAG {
|
|||
F_STARTSTR, // val0 = start str bracket (ie. STR_STRONG)
|
||||
F_CORPSETYPE, // text field specifies what corpse obtype to leave
|
||||
F_NOCORPSE, // monster's body crumbles to dust after death
|
||||
F_LFSUFFIX, // text = suffix. eg. "skeleton"
|
||||
F_VISRANGE, // how far you can see (in the light)
|
||||
F_VISRANGEMOD, // modifications to visrange
|
||||
F_GUNTARGET, // current projectile weapon target
|
||||
|
@ -1005,6 +1101,8 @@ enum FLAG {
|
|||
F_WANTSBETTERWEP, // lf will look for better weapons, val1=covets
|
||||
F_WANTSBETTERARM, // lf will look for better armour, val1=covets
|
||||
F_FLEEONDAM, // lf will run away instead of counterattacking
|
||||
F_FLEEONHPPCT, // lf will run away if its hp drop to v0% or lower
|
||||
F_NOFLEE, // lf will not run away
|
||||
F_TARGET, // lf will attack lfid v0. lastknown x/y is v1/v2
|
||||
F_TARGETCELL, // lf will go towards this place. val0=x,val1=y
|
||||
F_FLEEFROM, // lf will run away from this lf id
|
||||
|
@ -1044,10 +1142,18 @@ enum FLAG {
|
|||
F_INDUCEFEAR, // causes fear when you attack it
|
||||
F_AUTOCREATEOB, // produces obtype 'text' wherever it walks, v0=radius
|
||||
// (only if ob of that type not already there)
|
||||
F_PACKATTACK, // deal v0 extra damage of type v1 if there are
|
||||
// v2 or more monsters matching f->text next
|
||||
// to the victim
|
||||
F_PHALANX, // gain v0 AR if v2 or more adj monsters matching f->text
|
||||
// INTRINSICS
|
||||
F_ASLEEP, // is asleep
|
||||
F_BLIND, // cannot see anything
|
||||
F_CANCAST, // can cast the spell val0 (need MP)
|
||||
F_CANWILL, // can cast the spell val0 without using MP
|
||||
// v1 is counter untiluse
|
||||
// v2 is what you need to use it
|
||||
// ie. when v1 == v2, ability is ready.
|
||||
F_DETECTAURAS, // autodetect bless/curse
|
||||
F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0
|
||||
F_DETECTMAGIC, // autodetect magic/special objects
|
||||
|
@ -1058,12 +1164,19 @@ enum FLAG {
|
|||
F_FASTMOVE, // modifier for move speed
|
||||
F_FOODPOISONED, // has food poisoning
|
||||
F_FREEZINGTOUCH,// next thing touched turns to ice!
|
||||
F_GRABBEDBY,// you've been grabbed by lf id v0
|
||||
F_GRABBING, // you are grabbing lf id v0
|
||||
F_HEAVYBLOW, // next attack is a heavy blow
|
||||
F_QUICKBITE, // deals v0 d d1 + d2 damage when you hit a bleeding victim
|
||||
// (bypasses armour)
|
||||
F_GRAVBOOSTED,// cannot walk or throw stuff
|
||||
F_PAIN, // take damage if you walk
|
||||
F_PARALYZED,// cannot do anything
|
||||
F_FROZEN, // made of ice
|
||||
F_INVULNERABLE,// immune to most damage
|
||||
F_LEVITATING, // like flying but uncontrolled
|
||||
F_MAGSHIELD,// magnetic shield
|
||||
F_NAUSEATED, // lf has a stench penalty of v0 (-v0*10 to hit).
|
||||
F_NONCORPOREAL,// can walk through walls
|
||||
F_OMNIPOTENT, // knows extra info
|
||||
F_PHOTOMEM, // you don't forget your surroundings
|
||||
|
@ -1071,6 +1184,9 @@ enum FLAG {
|
|||
F_RESISTMAG, // immune to most magic effects
|
||||
F_MPREGEN, // regenerate MP at val0 per turn
|
||||
F_SEEINDARK, // nightvis range is val0
|
||||
F_SEEWITHOUTEYES, // doesn't need eyes to see
|
||||
F_STABILITY, // doesn't slip over
|
||||
F_STENCH, // creatures within v0 gain f_nauseated = v1
|
||||
F_PRODUCESLIGHT, // produces light of val0 radius.
|
||||
// (but not for obs in pack)
|
||||
// if val2 is true, will only make light if ob
|
||||
|
@ -1081,6 +1197,8 @@ enum FLAG {
|
|||
F_CANSEETHROUGHMAT, //val0=kind of material you can see through
|
||||
F_SPRINTING, // you are sprinting
|
||||
F_TIRED, // you are too tired to sprint
|
||||
F_DODGES, // you dodge missed attacks
|
||||
F_NOTIME, // this lf's actions don't take time
|
||||
// COMBAT
|
||||
F_HASATTACK, // objecttype id to use when attacking unarmed
|
||||
// if val0-3 are filled in, they override the object's
|
||||
|
@ -1096,8 +1214,11 @@ enum FLAG {
|
|||
|
||||
// for jobs
|
||||
F_IFPCT, // only add the NEXT job flag if rnd(1,100) <= v0.
|
||||
// if v2=IFMONSTER, also only add the next one for non-players
|
||||
// if v2=IFPLAYER, also only add the next one for players
|
||||
F_ELSE,
|
||||
F_IFPLAYER,
|
||||
F_IFMONSTER,
|
||||
F_ENDIFPLAYER,
|
||||
F_ENDIFMONSTER,
|
||||
|
||||
//
|
||||
F_NULL = -1
|
||||
|
@ -1126,8 +1247,16 @@ enum HUNGER {
|
|||
#define B_FALSE (0)
|
||||
#define B_TRUE (-1)
|
||||
|
||||
#define B_TEMP (-1)
|
||||
#define B_PERM (-2)
|
||||
//#define B_TEMP (-1)
|
||||
//#define B_PERM (-2)
|
||||
//#define B_NOT (-3)
|
||||
|
||||
enum LIGHTLEV {
|
||||
L_DARK = -1,
|
||||
L_NOTLIT = 0,
|
||||
L_TEMP = 1,
|
||||
L_PERM = 2,
|
||||
};
|
||||
|
||||
#define B_DIEONFAIL (-1)
|
||||
#define B_BLUNTONFAIL (-2)
|
||||
|
@ -1200,8 +1329,58 @@ enum ERROR {
|
|||
E_NOMP = 27,
|
||||
E_AVOIDOB = 28,
|
||||
E_FROZEN = 29,
|
||||
E_TOOBIG = 30,
|
||||
E_NOTREADY = 31,
|
||||
E_BLIND = 32,
|
||||
E_GRABBEDBY = 33,
|
||||
E_CANTMOVE = 34,
|
||||
};
|
||||
|
||||
|
||||
enum COMMAND {
|
||||
CMD_AIM,
|
||||
CMD_CLOSE,
|
||||
CMD_DOWN,
|
||||
CMD_DROP,
|
||||
CMD_DROPMULTI,
|
||||
CMD_EAT,
|
||||
CMD_FIRE,
|
||||
CMD_FIRENEW,
|
||||
CMD_FORCEATTACK,
|
||||
CMD_HELP,
|
||||
CMD_INFOARMOUR,
|
||||
CMD_INFOKNOWLEDGE,
|
||||
CMD_INFOPLAYER,
|
||||
CMD_INV,
|
||||
CMD_LOOKAROUND,
|
||||
CMD_LOOKHERE,
|
||||
CMD_MAGIC,
|
||||
CMD_MSGHIST,
|
||||
CMD_OPERATE,
|
||||
CMD_PICKLOCK,
|
||||
CMD_PICKUP,
|
||||
CMD_POUR,
|
||||
CMD_QUAFF,
|
||||
CMD_QUIT,
|
||||
CMD_READ,
|
||||
CMD_REST,
|
||||
CMD_RESTFULL,
|
||||
CMD_SAVEQUIT,
|
||||
CMD_TAKEOFF,
|
||||
CMD_UP,
|
||||
CMD_WEAR,
|
||||
CMD_WEILD,
|
||||
};
|
||||
|
||||
// command types
|
||||
typedef struct command_s {
|
||||
enum COMMAND id;
|
||||
char ch;
|
||||
char *desc;
|
||||
struct command_s *next, *prev;
|
||||
} command_t;
|
||||
|
||||
|
||||
typedef struct map_s {
|
||||
int id;
|
||||
int depth;
|
||||
|
@ -1223,7 +1402,7 @@ typedef struct cell_s {
|
|||
int roomid;
|
||||
struct celltype_s *type;
|
||||
struct obpile_s *obpile;
|
||||
int lit;
|
||||
enum LIGHTLEV lit;
|
||||
|
||||
char *writing;
|
||||
|
||||
|
@ -1252,6 +1431,7 @@ typedef struct celltype_s {
|
|||
|
||||
typedef struct race_s {
|
||||
enum RACE id;
|
||||
enum RACE baseid;
|
||||
struct material_s *material;
|
||||
char *name;
|
||||
char glyph;
|
||||
|
@ -1409,10 +1589,12 @@ enum OBMOD {
|
|||
OM_FEEBLENESS,
|
||||
OM_FLIGHT,
|
||||
OM_GIANTSTRENGTH,
|
||||
OM_IMPACT,
|
||||
OM_INTELLIGENCE,
|
||||
OM_KNOWLEDGE,
|
||||
OM_LEVITATION,
|
||||
OM_MAGRESIST,
|
||||
OM_SHARPNESS,
|
||||
OM_PYROMANIA,
|
||||
OM_REVENGE,
|
||||
OM_SLOTH,
|
||||
|
|
|
@ -8,3 +8,8 @@ in objcets.c:
|
|||
in attack.c
|
||||
update getattackverb if required
|
||||
update getkillverb if required
|
||||
|
||||
update attackob() to say whether dealing this damtype to an object
|
||||
will dull a weapon.
|
||||
ie. hitting a door with DT_CHOP won't damage the weapon
|
||||
ie. hitting a door with DT_SLASH _will_ damage the weapon
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
1. add it normally.
|
||||
|
||||
2. if monsters should drink it, add a flag:
|
||||
f_aiboostitem
|
||||
f_aihealitem
|
||||
f_aifleeitem
|
|
@ -9,6 +9,7 @@ objects.c:
|
|||
(optional) add a scroll to do the same effect, use F_LINKSPELL
|
||||
(optional) add a potion to do the same effect
|
||||
(optional) add a spellbook to learn it
|
||||
assign AI hint flags so it knows how to cast it
|
||||
|
||||
spell.c:
|
||||
implement the effects
|
||||
|
@ -18,3 +19,7 @@ spell.c:
|
|||
target having antimagic - use hasmr(victim)
|
||||
blindness if the effect is vision-based
|
||||
|
||||
ai.c
|
||||
update aigetspelltarget();
|
||||
update aigetattackspell();
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Converting dndv4 monsters:
|
||||
hp / 8
|
||||
ac / 2 (sometimes use evasion instead though)
|
|
@ -0,0 +1,9 @@
|
|||
hay
|
||||
pebbles
|
||||
torch
|
||||
boulder / monolith / statue
|
||||
shackles
|
||||
chain
|
||||
bone
|
||||
skeleton
|
||||
scrap of material
|
|
@ -0,0 +1,10 @@
|
|||
helpless/feeble = 0
|
||||
weak/vweak = 1
|
||||
avg/strong = 2
|
||||
mighty = 3
|
||||
titanic = 4
|
||||
|
||||
gun = 10
|
||||
|
||||
only apply damage to armour if speed >= 3
|
||||
(or armour piercing)
|
|
@ -0,0 +1,24 @@
|
|||
#Slow the target down
|
||||
#Summon a cloud of toxic gas
|
||||
#Summon huge swarm of butterflies
|
||||
#Turn target to stone
|
||||
#Cause darkness
|
||||
#Fireball
|
||||
swap places ?
|
||||
Make all inanimate objects in range vanish
|
||||
Makes leaves grow from target
|
||||
Shoots forth semi-precious gems (this is actually an attack, they shoot out really fast)
|
||||
Cause a funky light show
|
||||
|
||||
Turn target into a giant
|
||||
+ str?
|
||||
Shrink wand user to halfling size
|
||||
+ acc?
|
||||
|
||||
Makes user invisible
|
||||
Summon a mouse, elephant, or rhino
|
||||
Cause grass to grow
|
||||
Lightning Bolt
|
||||
Summon a great wind (ie. airblast spellO)
|
||||
Cause heavy rainfall
|
||||
Make the wand wielder believe that something else happened
|
11
flag.c
11
flag.c
|
@ -92,6 +92,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
if (gamestarted) {
|
||||
if (f->pile->owner) {
|
||||
if (announceflaggain(f->pile->owner, f)) {
|
||||
interrupt(f->pile->owner);
|
||||
f->known = B_TRUE;
|
||||
if (f->obfrom) { // ooooooo it's getting -1 ?!?!?!?
|
||||
object_t *ob;
|
||||
|
@ -238,14 +239,18 @@ flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, ch
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void killflagsofid(flagpile_t *fp, enum FLAG fid) {
|
||||
// returns true if we did something
|
||||
int killflagsofid(flagpile_t *fp, enum FLAG fid) {
|
||||
flag_t *f,*nextf;
|
||||
int donesomething = B_FALSE;
|
||||
for (f = fp->first ; f ; f = nextf) {
|
||||
nextf = f->next;
|
||||
if (f->id == fid) {
|
||||
killflag(f);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
return donesomething;
|
||||
}
|
||||
|
||||
void killflag(flag_t *f) {
|
||||
|
@ -273,7 +278,9 @@ void killflag(flag_t *f) {
|
|||
// notify
|
||||
if (gamestarted) {
|
||||
if (f->pile->owner) {
|
||||
announceflagloss(f->pile->owner, f);
|
||||
if (announceflagloss(f->pile->owner, f)) {
|
||||
interrupt(f->pile->owner);
|
||||
}
|
||||
} else if (f->pile->ob) {
|
||||
announceobflagloss(f->pile->ob, f);
|
||||
}
|
||||
|
|
2
flag.h
2
flag.h
|
@ -14,7 +14,7 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown);
|
|||
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text);
|
||||
flag_t *hasflagvalknown(flagpile_t *fp, int id, int val1, int val2, int val3, char *text);
|
||||
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown);
|
||||
void killflagsofid(flagpile_t *fp, enum FLAG fid);
|
||||
int killflagsofid(flagpile_t *fp, enum FLAG fid);
|
||||
void killflag(flag_t *f);
|
||||
void killflagpile(flagpile_t *fp);
|
||||
void makeflagknown(flagpile_t *fp);
|
||||
|
|
8
io.h
8
io.h
|
@ -6,9 +6,10 @@ void addmsghist(char *text);
|
|||
void addpromptq(prompt_t *p, char *q);
|
||||
void anim(cell_t *src, cell_t *dst, char ch);
|
||||
void animradial(cell_t *src, int radius, char ch);
|
||||
void animradialorth(cell_t *src, int radius, char ch);
|
||||
//void announceob(enum OBTYPE oid);
|
||||
int announceflaggain(lifeform_t *lf, flag_t *f);
|
||||
void announceflagloss(lifeform_t *lf, flag_t *f);
|
||||
int announceflagloss(lifeform_t *lf, flag_t *f);
|
||||
int announceobflaggain(object_t *o, flag_t *f);
|
||||
void announceobflagloss(object_t *o, flag_t *f);
|
||||
object_t *askobject(obpile_t *op, char *title, int *count, int opts);
|
||||
|
@ -36,6 +37,7 @@ void doenter(lifeform_t *lf);
|
|||
void doexplain(void);
|
||||
void dofinaloblist(obpile_t *op);
|
||||
void dofire(void);
|
||||
void dohelp(void);
|
||||
void doinventory(obpile_t *op);
|
||||
void doknowledgelist(void);
|
||||
void dolook(cell_t *where);
|
||||
|
@ -57,6 +59,7 @@ void dothrow(obpile_t *op);
|
|||
void dovendingmachine(lifeform_t *lf, object_t *vm);
|
||||
int dowear(obpile_t *op);
|
||||
int doweild(obpile_t *op);
|
||||
void downline(int *y, int h, char *heading, char *subheading);
|
||||
void drawunviscell(cell_t *cell, int x, int y);
|
||||
void drawcellwithcontents(cell_t *cell, int x, int y);
|
||||
void drawcursor(void);
|
||||
|
@ -69,13 +72,14 @@ char getchoice(prompt_t *prompt);
|
|||
char getchoicestr(prompt_t *prompt);
|
||||
int getkey(void);
|
||||
void handleinput(void);
|
||||
void doheading(WINDOW *win, int *y, int x, char *what);
|
||||
void initgfx(void);
|
||||
void initprompt(prompt_t *p, char *q1);
|
||||
int keycodetokey(int keycode);
|
||||
void more(void);
|
||||
void warn(char *format, ... );
|
||||
void msg(char *format, ... );
|
||||
void msglower(char *format, ... );
|
||||
void msgnocap(char *format, ... );
|
||||
void msg_real(char *format, ... );
|
||||
void nothinghappens(void);
|
||||
void dblog(char *format, ... );
|
||||
|
|
16
lf.h
16
lf.h
|
@ -14,7 +14,6 @@ int calcxprace(enum RACE rid);
|
|||
int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost);
|
||||
int caneat(lifeform_t *lf, object_t *o);
|
||||
int canhear(lifeform_t *lf, cell_t *c);
|
||||
int cannotmove(lifeform_t *lf);
|
||||
int canpickup(lifeform_t *lf, object_t *o, int amt);
|
||||
int canpush(lifeform_t *lf, object_t *o, int dir);
|
||||
int canquaff(lifeform_t *lf, object_t *o);
|
||||
|
@ -45,7 +44,6 @@ object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
|
|||
int getarmourrating(lifeform_t *lf);
|
||||
int getattackspeed(lifeform_t *lf);
|
||||
int getattr(lifeform_t *lf, enum ATTRIB attr);
|
||||
int getdexmod(lifeform_t *lf);
|
||||
int getevasion(lifeform_t *lf);
|
||||
object_t *getbestmissile(lifeform_t *lf);
|
||||
object_t *getbestweapon(lifeform_t *lf);
|
||||
|
@ -59,6 +57,7 @@ lifeform_t *getguntarget(lifeform_t *lf);
|
|||
int getguntargetid(lifeform_t *lf);
|
||||
//int gethealtime(lifeform_t *lf);
|
||||
int gethearingrange(lifeform_t *lf);
|
||||
int gethppct(lifeform_t *lf);
|
||||
enum HUNGER gethungerlevel(int hunger);
|
||||
char * gethungername(enum HUNGER hunger, char *buf);
|
||||
int gethungerval(lifeform_t *lf);
|
||||
|
@ -68,6 +67,7 @@ enum LFCONDITION getlfcondition(lifeform_t *lf);
|
|||
int getnightvisrange(lifeform_t *lf);
|
||||
char *getlfconditionname(enum LFCONDITION cond);
|
||||
char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer);
|
||||
char getlfglyph(lifeform_t *lf);
|
||||
enum MATERIAL getlfmaterial(lifeform_t *lf);
|
||||
float getmaxcarryweight(lifeform_t *lf);
|
||||
float getmaxliftweight(lifeform_t *lf);
|
||||
|
@ -119,6 +119,7 @@ enum BURDENED isburdened(lifeform_t *lf);
|
|||
int isdead(lifeform_t *lf);
|
||||
int isfleeing(lifeform_t *lf);
|
||||
int isfreebp(lifeform_t *lf, enum BODYPART bp);
|
||||
int isfriendly(lifeform_t *lf);
|
||||
int isgenius(lifeform_t *lf);
|
||||
int isimmobile(lifeform_t *lf);
|
||||
flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt);
|
||||
|
@ -133,7 +134,10 @@ void killlf(lifeform_t *lf);
|
|||
void killrace(race_t *race);
|
||||
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc);
|
||||
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam);
|
||||
void makefriendly(lifeform_t *lf);
|
||||
void makenauseated(lifeform_t *lf, int amt, int howlong);
|
||||
void makenoise(lifeform_t *lf, enum NOISETYPE nid);
|
||||
lifeform_t *makezombie(object_t *o);
|
||||
void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how);
|
||||
int modattr(lifeform_t *lf, enum ATTRIB attr, int amt);
|
||||
void modhunger(lifeform_t *lf, int amt);
|
||||
|
@ -148,7 +152,6 @@ int rolldex(enum DEXBRACKET bracket);
|
|||
int rolliq(enum IQBRACKET bracket);
|
||||
int rollstr(enum STRBRACKET bracket);
|
||||
int rollstat(lifeform_t *lf, enum ATTRIB attr);
|
||||
int savingthrow(lifeform_t *lf, enum ATTRIB attr, int mod);
|
||||
int scare(lifeform_t *lf, lifeform_t *scarer, int howlong);
|
||||
int setammo(lifeform_t *lf, object_t *o);
|
||||
void setattr(lifeform_t *lf, enum ATTRIB attr, int val);
|
||||
|
@ -156,7 +159,10 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ);
|
|||
void setrace(lifeform_t *lf, enum RACE rid);
|
||||
void setlastdam(lifeform_t *lf, char *buf);
|
||||
int shoot(lifeform_t *lf);
|
||||
int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod);
|
||||
int slipon(lifeform_t *lf, object_t *o);
|
||||
void sortlf(map_t *map, lifeform_t *lf);
|
||||
int stone(lifeform_t *lf);
|
||||
void stopresting(lifeform_t *lf);
|
||||
void stoprunning(lifeform_t *lf);
|
||||
int testammo(lifeform_t *lf, object_t *o);
|
||||
|
@ -167,9 +173,11 @@ void timeeffectslf(lifeform_t *lf);
|
|||
void turneffectslf(lifeform_t *lf);
|
||||
int touch(lifeform_t *lf, object_t *o);
|
||||
int unweild(lifeform_t *lf, object_t *o);
|
||||
int useability(lifeform_t *lf, enum OBTYPE aid);
|
||||
int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where);
|
||||
int useitemwithflag(lifeform_t *lf, enum FLAG whichflag);
|
||||
int usestairs(lifeform_t *lf, object_t *o);
|
||||
int validateraces(void);
|
||||
int wear(lifeform_t *lf, object_t *o);
|
||||
int weild(lifeform_t *lf, object_t *o);
|
||||
int willflee(lifeform_t *lf);
|
||||
int youhear(cell_t *c, char *text);
|
||||
|
|
133
map.c
133
map.c
|
@ -31,7 +31,7 @@ cell_t *addcell(map_t *m, int x, int y) {
|
|||
cell->obpile = addobpile(NOOWNER, cell);
|
||||
cell->lf = NULL;
|
||||
cell->roomid = -1;
|
||||
cell->lit = B_FALSE;
|
||||
cell->lit = L_NOTLIT;
|
||||
cell->writing = NULL;
|
||||
cell->known = B_FALSE;
|
||||
return cell;
|
||||
|
@ -73,7 +73,7 @@ map_t *addmap(void) {
|
|||
}
|
||||
|
||||
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok) {
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
|
||||
lifeform_t *lf = NULL;
|
||||
race_t *r;
|
||||
int db = B_FALSE;
|
||||
|
@ -96,7 +96,6 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok) {
|
|||
//lf = addlf(c, r->id, getrandommonlevel(c->map->depth));
|
||||
lf = addlf(c, r->id, 1);
|
||||
if (lf) {
|
||||
int amt;
|
||||
flag_t *f;
|
||||
|
||||
if (jobok) {
|
||||
|
@ -112,23 +111,41 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok) {
|
|||
// appears in groups?
|
||||
f = hasflag(lf->flags, F_NUMAPPEAR);
|
||||
if (f) {
|
||||
// override amount
|
||||
amt = rnd(f->val[0], f->val[1]);
|
||||
} else {
|
||||
amt = 1;
|
||||
}
|
||||
if (amt > 1) {
|
||||
cell_t *adjcell;
|
||||
cell_t **moncell;
|
||||
int nmoncells = 1;
|
||||
|
||||
moncell = malloc( amt * sizeof(cell_t *));
|
||||
moncell[0] = c;
|
||||
nmoncells = 1;
|
||||
amt--; // we've already added one
|
||||
adjcell = c;
|
||||
|
||||
//adjcell = c;
|
||||
for ( ; amt > 0; amt--) {
|
||||
// add more in adjacent cells
|
||||
adjcell = getrandomadjcell(adjcell, WE_NOTSOLID);
|
||||
int n;
|
||||
// find an adjacent cell to one of the newly added monsters,
|
||||
// starting with the first one
|
||||
adjcell = NULL;
|
||||
for (n = 0; n < nmoncells; n++) {
|
||||
adjcell = getrandomadjcell(moncell[n], WE_NOTSOLID);
|
||||
if (adjcell) break;
|
||||
}
|
||||
// did we find one?
|
||||
if (!adjcell) break;
|
||||
|
||||
//lf = addlf(adjcell, r->id, getrandommonlevel(adjcell->map->depth));
|
||||
lf = addlf(adjcell, r->id, 1);
|
||||
if (!lf) break;
|
||||
if (!addlf(adjcell, r->id, 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
moncell[nmoncells] = adjcell;
|
||||
nmoncells++;
|
||||
}
|
||||
free(moncell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +174,7 @@ void addrandomthing(cell_t *c) {
|
|||
addrandomob(c);
|
||||
} else {
|
||||
// monster
|
||||
addmonster(c, R_RANDOM, B_TRUE);
|
||||
addmonster(c, R_RANDOM, B_TRUE, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,7 +358,7 @@ void calclight(map_t *map) {
|
|||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
c = getcellat(map, x,y);
|
||||
if (c && (c->lit != B_PERM)) c->lit = B_FALSE;
|
||||
if (c && (c->lit == L_PERM) && (c->lit != L_DARK)) c->lit = B_FALSE;
|
||||
}
|
||||
}
|
||||
for (y = 0; y < map->h; y++) {
|
||||
|
@ -351,22 +368,22 @@ void calclight(map_t *map) {
|
|||
int radius;
|
||||
object_t *o;
|
||||
// lit based on depth
|
||||
if (map->depth <= 5) {
|
||||
c->lit = B_PERM;
|
||||
if ((map->depth <= 5) && (c->lit != L_DARK)) {
|
||||
c->lit = L_PERM;
|
||||
}
|
||||
// has lightproducing lf? (ie.hasflag f_produceslight)
|
||||
if (c->lf) {
|
||||
if (lfhasflag(c->lf, F_PRODUCESLIGHT)) {
|
||||
sumflags(c->lf->flags, F_PRODUCESLIGHT, &radius, NULL, NULL);
|
||||
|
||||
makelitradius(c, radius, B_TEMP);
|
||||
makelitradius(c, radius, L_TEMP);
|
||||
}
|
||||
// objects in hands or on body...
|
||||
for (o = c->lf->pack->first ; o ; o = o->next) {
|
||||
if (obproduceslight(o) && isequipped(o)) {
|
||||
sumflags(o->flags, F_PRODUCESLIGHT, &radius, NULL, NULL);
|
||||
|
||||
makelitradius(c, radius, B_TEMP);
|
||||
makelitradius(c, radius, L_TEMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,7 +391,7 @@ void calclight(map_t *map) {
|
|||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
if (obproduceslight(o)) {
|
||||
sumflags(o->flags, F_PRODUCESLIGHT, &radius, NULL, NULL);
|
||||
makelitradius(c, radius, B_TEMP);
|
||||
makelitradius(c, radius, L_TEMP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,11 +421,20 @@ int calcroompos(map_t *map, int w, int h, int *bx, int *by) {
|
|||
for (ry = y; (ry < y+h) && (!notpossible); ry++) {
|
||||
for (rx = x; (rx < x+w) && (!notpossible); rx++) {
|
||||
cell = getcellat(map, rx,ry);
|
||||
// is this cell adjacent to an empty cell?
|
||||
// is this cell adjacent to an empty cell and not a
|
||||
// corner (ie. a valid door location)
|
||||
if (countcellexits(cell)) {
|
||||
score++;
|
||||
if ( ((ry == y) && (rx == x)) ||
|
||||
((ry == y) && (rx == (x+w-1))) ||
|
||||
((ry == y+h-1) && (rx == x)) ||
|
||||
((ry == y+h-1) && (rx == (x+w-1))) ) {
|
||||
// corner.
|
||||
} else {
|
||||
// not corner
|
||||
valid = B_TRUE;
|
||||
}
|
||||
}
|
||||
// is this cell empty itself?
|
||||
if (!cell->type->solid) score += 3;
|
||||
// avoid being adjacent to other room walls
|
||||
|
@ -1235,7 +1261,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
// N
|
||||
npossible = 0;
|
||||
y = miny;
|
||||
for (x = minx; x <= maxx; x++) {
|
||||
for (x = minx+1; x <= maxx-1; x++) {
|
||||
cell = getcellat(map, x, y);
|
||||
newcell = getcellindir(cell, D_N);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
|
@ -1267,7 +1293,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
// S
|
||||
npossible = 0;
|
||||
y = maxy;
|
||||
for (x = minx; x <= maxx; x++) {
|
||||
for (x = minx+1; x <= maxx-1; x++) {
|
||||
cell = getcellat(map, x, y);
|
||||
newcell = getcellindir(cell, D_S);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
|
@ -1299,7 +1325,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
// W
|
||||
npossible = 0;
|
||||
x = minx;
|
||||
for (y = miny; y <= maxy; y++) {
|
||||
for (y = miny+1; y <= maxy-1; y++) {
|
||||
cell = getcellat(map, x, y);
|
||||
newcell = getcellindir(cell, D_W);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
|
@ -1329,7 +1355,7 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
// E
|
||||
npossible = 0;
|
||||
x = maxx;
|
||||
for (y = miny; y <= maxy; y++) {
|
||||
for (y = miny+1; y <= maxy-1; y++) {
|
||||
cell = getcellat(map, x, y);
|
||||
newcell = getcellindir(cell, D_E);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
|
@ -1793,6 +1819,25 @@ cell_t *getrandomroomcell(map_t *map, int roomid) {
|
|||
return c;
|
||||
}
|
||||
|
||||
// returns how slippery this cell is
|
||||
int getslipperyness(cell_t *c, object_t **slipob) {
|
||||
object_t *o;
|
||||
int totalslip = 0;
|
||||
if (slipob) *slipob = NULL;
|
||||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
int thisslip;
|
||||
sumflags(o->flags, F_SLIPPERY, &thisslip, NULL, NULL);
|
||||
if (thisslip > 0) {
|
||||
if (slipob && (*slipob == NULL)) {
|
||||
*slipob = o;
|
||||
}
|
||||
}
|
||||
thisslip *= o->amt;
|
||||
totalslip += thisslip;
|
||||
}
|
||||
return totalslip;
|
||||
}
|
||||
|
||||
object_t *hasenterableobject(cell_t *c) {
|
||||
return hasobwithflag(c->obpile, F_CLIMBABLE);
|
||||
}
|
||||
|
@ -1872,31 +1917,7 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) {
|
|||
}
|
||||
if (glyph) {
|
||||
// select glyph based on size
|
||||
switch(getlfsize(c->lf)) {
|
||||
case SZ_ENORMOUS:
|
||||
*glyph = '6';
|
||||
break;
|
||||
case SZ_HUGE:
|
||||
*glyph = '5';
|
||||
break;
|
||||
case SZ_LARGE:
|
||||
*glyph = '4';
|
||||
break;
|
||||
case SZ_HUMAN:
|
||||
*glyph = '3';
|
||||
break;
|
||||
case SZ_MEDIUM:
|
||||
*glyph = '2';
|
||||
break;
|
||||
case SZ_SMALL:
|
||||
*glyph = '1';
|
||||
break;
|
||||
case SZ_MINI:
|
||||
case SZ_TINY:
|
||||
default:
|
||||
*glyph = '0';
|
||||
break;
|
||||
}
|
||||
*glyph = '0' + ((int) getlfsize(c->lf));
|
||||
}
|
||||
return TT_MONSTER;
|
||||
}
|
||||
|
@ -1928,8 +1949,12 @@ int isinscanrange(cell_t *c, void **thing, char *desc, char *glyph) {
|
|||
}
|
||||
|
||||
int islit(cell_t *c) {
|
||||
if (c->lit) {
|
||||
switch (c->lit) {
|
||||
case L_TEMP:
|
||||
case L_PERM:
|
||||
return B_TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -2009,16 +2034,16 @@ void makedoor(cell_t *cell) {
|
|||
}
|
||||
|
||||
|
||||
void makelit(cell_t *c, int how) {
|
||||
if (how == B_FALSE) {
|
||||
c->lit = how;
|
||||
} else if (c->lit != B_PERM) { // don't override permenant light with temp light!
|
||||
void makelit(cell_t *c, enum LIGHTLEV how) {
|
||||
// don't override permenant light with temp light!
|
||||
if ((c->lit == L_PERM) && (how == L_TEMP)) {
|
||||
return;
|
||||
} else {
|
||||
c->lit = how;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void makelitradius(cell_t *c, int radius, int how) {
|
||||
void makelitradius(cell_t *c, int radius, enum LIGHTLEV how) {
|
||||
int x,y;
|
||||
cell_t *c2;
|
||||
|
||||
|
|
7
map.h
7
map.h
|
@ -2,7 +2,7 @@
|
|||
|
||||
cell_t *addcell(map_t *map, int x, int y);
|
||||
map_t *addmap(void);
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok);
|
||||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt);
|
||||
void addrandomob(cell_t *c);
|
||||
void addrandomthing(cell_t *c);
|
||||
int cellhaslos(cell_t *c1, cell_t *dest);
|
||||
|
@ -35,6 +35,7 @@ cell_t *getrandomcell(map_t *map);
|
|||
cell_t *getrandomcelloftype(map_t *map, int id);
|
||||
int getrandomdir(int dirtype);
|
||||
cell_t *getrandomroomcell(map_t *map, int roomid);
|
||||
int getslipperyness(cell_t *c, object_t **slipob);
|
||||
object_t *hasenterableobject(cell_t *c);
|
||||
lifeform_t *haslf(cell_t *c);
|
||||
int hasobject(cell_t *c);
|
||||
|
@ -49,7 +50,7 @@ int isnewcellok(cell_t *cell, char *err);
|
|||
int isonmap(map_t *map, int x, int y);
|
||||
int iswallindir(cell_t *cell, int dir);
|
||||
void makedoor(cell_t *cell);
|
||||
void makelit(cell_t *c, int how);
|
||||
void makelitradius(cell_t *c, int radius, int how);
|
||||
void makelit(cell_t *c, enum LIGHTLEV how);
|
||||
void makelitradius(cell_t *c, int radius, enum LIGHTLEV how);
|
||||
void setcelltype(cell_t *cell, int id);
|
||||
void updateknowncells(void);
|
||||
|
|
314
move.c
314
move.c
|
@ -36,6 +36,7 @@ int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
|||
|
||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||
cell_t *cell;
|
||||
flag_t *f;
|
||||
|
||||
// default
|
||||
if (error) {
|
||||
|
@ -53,9 +54,27 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
// TODO: check if we are burdened, paralyzed, etc
|
||||
// check if we are paralyzed, frozen, etc
|
||||
if (isimmobile(lf)) {
|
||||
if (error) *error = E_CANTMOVE;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
|
||||
f = lfhasflag(lf, F_GRABBEDBY);
|
||||
if (f) {
|
||||
lifeform_t *lf2;
|
||||
lf2 = findlf(NULL, f->val[0]);
|
||||
if (lf2 && (lf2 != cell->lf)) {
|
||||
if (error) {
|
||||
rdata = lf2;
|
||||
*error = E_GRABBEDBY;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return cellwalkable(lf, cell, error);
|
||||
}
|
||||
|
||||
|
@ -69,9 +88,9 @@ int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
|||
rdata = NULL;
|
||||
}
|
||||
|
||||
// check for dangerous objects
|
||||
// check for _known_ dangerous objects
|
||||
iq = getiqname(getattr(lf, A_IQ), NULL);
|
||||
if (iq >= IQ_AVERAGE) {
|
||||
if ((iq >= IQ_AVERAGE) && !isblind(lf)) {
|
||||
flag_t *f;
|
||||
object_t *o;
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
|
@ -121,8 +140,15 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
|||
}
|
||||
}
|
||||
|
||||
// must check for lf before checking for impassable objects,
|
||||
// so that we are able to attack monsters embedded in walls.
|
||||
if (cell->lf && (cell->lf != lf)) {
|
||||
if (error) *error = E_LFINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
if (isimpassableob(o, lf)) {
|
||||
if (lf) {
|
||||
if ((lf->race->material->id == MT_GAS) ||
|
||||
(lf->race->material->id == MT_SLIME)) {
|
||||
|
@ -142,13 +168,40 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cell->lf && (cell->lf != lf)) {
|
||||
if (error) *error = E_LFINWAY;
|
||||
return B_FALSE;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
int diropposite(int dir) {
|
||||
switch (dir) {
|
||||
case D_N:
|
||||
return D_S;
|
||||
case D_E:
|
||||
return D_W;
|
||||
case D_S:
|
||||
return D_N;
|
||||
case D_W:
|
||||
return D_E;
|
||||
case DC_N:
|
||||
return DC_S;
|
||||
case DC_NE:
|
||||
return DC_SW;
|
||||
case DC_E:
|
||||
return DC_W;
|
||||
case DC_SE:
|
||||
return DC_NW;
|
||||
case DC_S:
|
||||
return DC_N;
|
||||
case DC_SW:
|
||||
return DC_NE;
|
||||
case DC_W:
|
||||
return DC_E;
|
||||
case DC_NW:
|
||||
return DC_SE;
|
||||
}
|
||||
// should never happen!
|
||||
return dir;
|
||||
}
|
||||
|
||||
void dorandommove(lifeform_t *lf, int badmovesok) {
|
||||
int dir;
|
||||
int tries = 0;
|
||||
|
@ -226,7 +279,7 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck) {
|
|||
}
|
||||
}
|
||||
if (ok) {
|
||||
thisdist = getcelldist(c, dst);
|
||||
thisdist = getcelldistorth(c, dst);
|
||||
} else {
|
||||
thisdist = -1;
|
||||
}
|
||||
|
@ -239,12 +292,14 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck) {
|
|||
}
|
||||
|
||||
// TODO: handle ties
|
||||
|
||||
if (bestdir != D_NONE) {
|
||||
reason = E_OK;
|
||||
}
|
||||
return bestdir;
|
||||
}
|
||||
|
||||
|
||||
int getdirtowards(cell_t *src, cell_t *dst, int wantcheck) {
|
||||
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck) {
|
||||
int d;
|
||||
cell_t *c;
|
||||
int mindist=9999,bestdir=D_NONE;
|
||||
|
@ -260,21 +315,21 @@ int getdirtowards(cell_t *src, cell_t *dst, int wantcheck) {
|
|||
}
|
||||
|
||||
if (wantcheck) {
|
||||
if (src->lf && canandwillmove(src->lf, d, NULL)) {
|
||||
if (srclf && canandwillmove(srclf, d, NULL)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!src->lf) {
|
||||
} else if (!srclf) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (src->lf && cellwalkable(src->lf, c, NULL)) {
|
||||
if (srclf && cellwalkable(srclf, c, NULL)) {
|
||||
ok = B_TRUE;
|
||||
} else if (!src->lf) {
|
||||
} else if (!srclf) {
|
||||
ok = B_TRUE;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
int thisdist;
|
||||
thisdist = getcelldist(c, dst);
|
||||
thisdist = getcelldistorth(c, dst);
|
||||
if (thisdist < mindist) {
|
||||
mindist = thisdist;
|
||||
bestdir = d;
|
||||
|
@ -287,13 +342,66 @@ int getdirtowards(cell_t *src, cell_t *dst, int wantcheck) {
|
|||
return bestdir;
|
||||
}
|
||||
|
||||
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher) {
|
||||
int i;
|
||||
char lfname[BUFLEN];
|
||||
int seen;
|
||||
|
||||
int moveawayfrom(lifeform_t *lf, cell_t *dst) {
|
||||
getlfname(lf,lfname);
|
||||
if (haslos(player, lf->cell)) {
|
||||
seen = B_TRUE;
|
||||
} else {
|
||||
seen = B_FALSE;
|
||||
}
|
||||
|
||||
if (dir == D_NONE) {
|
||||
// failed!
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// if levitating (not flying), knocked back further.
|
||||
if (lfhasflag(lf, F_LEVITATING)) {
|
||||
howfar *= 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < howfar; i++) {
|
||||
if (canmove(lf, dir, &reason)) {
|
||||
if ((i == 0) && seen) {
|
||||
msg("%s %s knocked backwards!",lfname,isplayer(lf) ? "are" : "is");
|
||||
}
|
||||
trymove(lf, dir);
|
||||
}
|
||||
if (reason != E_OK) {
|
||||
// failed to move
|
||||
switch (reason) {
|
||||
case E_WALLINWAY:
|
||||
msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s");
|
||||
losehp(lf, rnd(1,6), DT_BASH, pusher, "slamming into a wall");
|
||||
// stop moving
|
||||
i = howfar;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int moveawayfrom(lifeform_t *lf, cell_t *dst ) {
|
||||
int dir;
|
||||
int rv = B_TRUE;
|
||||
|
||||
if (isblind(lf)) {
|
||||
dorandommove(lf, B_TRUE);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// move towards them
|
||||
dir = getdiraway(lf->cell, dst, B_TRUE);
|
||||
if (dir != D_NONE) {
|
||||
if (dir == D_NONE) {
|
||||
rv = B_TRUE;
|
||||
} else {
|
||||
rv = trymove(lf, dir);
|
||||
}
|
||||
return rv;
|
||||
|
@ -310,6 +418,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
int didmsg = B_FALSE;
|
||||
flag_t *f;
|
||||
|
||||
getlfname(lf, lfname);
|
||||
|
||||
// update current cell
|
||||
lf->cell->lf = NULL;
|
||||
|
||||
|
@ -335,6 +445,14 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
bleed(lf);
|
||||
}
|
||||
}
|
||||
if (lfhasflag(lf, F_PAIN)) {
|
||||
losehp(lf, rolldie(2,4)+2, DT_DIRECT, NULL, "extreme pain");
|
||||
if (isplayer(lf)) {
|
||||
msg("Your body is wracked with pain!");
|
||||
} else if (haslos(player, lf->cell)) {
|
||||
msg("%s convulses in pain!",lfname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check ground objects
|
||||
|
@ -346,10 +464,32 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
object_t *boots;
|
||||
// has boots on?
|
||||
boots = getequippedob(lf->pack, BP_FEET);
|
||||
if (boots) {
|
||||
// crunch the broken glass
|
||||
if (!boots) {
|
||||
// take damage
|
||||
getobname(o, obname, 1);
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("Ow - you step on %s!",obname);
|
||||
didmsg = B_TRUE;
|
||||
} else if (haslos(player, newcell)) {
|
||||
msg("%s steps on %s!",lfname, obname);
|
||||
didmsg = B_TRUE;
|
||||
}
|
||||
sprintf(buf, "stepping on %s", obname);
|
||||
losehp(lf, rnd(f->val[0],f->val[1]), DT_SLASH, NULL, buf);
|
||||
}
|
||||
}
|
||||
|
||||
f = hasflag(o->flags, F_CRUSHABLE);
|
||||
if (f) {
|
||||
enum LFSIZE crushsize;
|
||||
crushsize = f->val[0];
|
||||
|
||||
if (getlfsize(lf) >= crushsize) {
|
||||
// crunch it broken glass
|
||||
getobname(o, obname, 1);
|
||||
|
||||
// special case
|
||||
if (o->type->id == OT_BROKENGLASS) {
|
||||
if (o->amt > 1) {
|
||||
char *newname;
|
||||
// we want 'xx steps on some pieces of broken glass'
|
||||
|
@ -359,33 +499,19 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
strcpy(obname, newname);
|
||||
free(newname);
|
||||
}
|
||||
if (lf->controller == C_PLAYER) {
|
||||
}
|
||||
|
||||
if (isplayer(lf)) {
|
||||
msg("You crush %s underfoot.",obname);
|
||||
didmsg = B_TRUE;
|
||||
} else if (haslos(player, newcell)) {
|
||||
getlfname(lf, lfname);
|
||||
capitalise(lfname);
|
||||
msg("%s crushes %s.",lfname, obname);
|
||||
didmsg = B_TRUE;
|
||||
}
|
||||
// kill object
|
||||
removeob(o, o->amt);
|
||||
} else {
|
||||
// take damage
|
||||
getobname(o, obname, 1);
|
||||
if (lf->controller == C_PLAYER) {
|
||||
msg("Ow - you step on %s!",obname);
|
||||
didmsg = B_TRUE;
|
||||
} else if (haslos(player, newcell)) {
|
||||
getlfname(lf, lfname);
|
||||
capitalise(lfname);
|
||||
msg("%s steps on %s!",lfname, obname);
|
||||
didmsg = B_TRUE;
|
||||
}
|
||||
sprintf(buf, "stepping on %s", obname);
|
||||
losehp(lf, rnd(f->val[0],f->val[1]), DT_SLASH, NULL, buf);
|
||||
}
|
||||
}
|
||||
} // end if crushable
|
||||
} // end foreach object in cell
|
||||
} // end if !flying
|
||||
|
||||
|
@ -434,7 +560,7 @@ int moveto(lifeform_t *lf, cell_t *newcell) {
|
|||
object_t *o;
|
||||
char obname[BUFLEN];
|
||||
for (o = newcell->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
if (isimpassableob(o, lf)) {
|
||||
getobname(o, obname, o->amt);
|
||||
if (isplayer(lf)) {
|
||||
msg("You seep around %s.", obname);
|
||||
|
@ -447,7 +573,7 @@ int moveto(lifeform_t *lf, cell_t *newcell) {
|
|||
object_t *o;
|
||||
char obname[BUFLEN];
|
||||
for (o = newcell->obpile->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
if (isimpassableob(o, lf)) {
|
||||
getobname(o, obname, o->amt);
|
||||
if (isplayer(lf)) {
|
||||
msg("You seep under %s.", obname);
|
||||
|
@ -476,8 +602,14 @@ int moveto(lifeform_t *lf, cell_t *newcell) {
|
|||
int movetowards(lifeform_t *lf, cell_t *dst) {
|
||||
int dir;
|
||||
int rv = B_TRUE;
|
||||
|
||||
if (isblind(lf)) {
|
||||
dorandommove(lf, B_TRUE);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// move towards them
|
||||
dir = getdirtowards(lf->cell, dst, B_TRUE);
|
||||
dir = getdirtowards(lf->cell, dst, lf, B_TRUE);
|
||||
if (dir != D_NONE) {
|
||||
rv = trymove(lf, dir);
|
||||
}
|
||||
|
@ -606,8 +738,11 @@ int closedoor(lifeform_t *lf, object_t *o) {
|
|||
cell_t *cell;
|
||||
char buf[BUFLEN];
|
||||
char obname[BUFLEN];
|
||||
object_t *oo;
|
||||
flag_t *f;
|
||||
|
||||
cell = getoblocation(o);
|
||||
|
||||
getobname(o, obname, 1);
|
||||
|
||||
if (!isdoor(o, NULL)) {
|
||||
|
@ -624,6 +759,29 @@ int closedoor(lifeform_t *lf, object_t *o) {
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (cell->lf) {
|
||||
if (lf && isplayer(lf)) {
|
||||
char inwayname[BUFLEN];
|
||||
getlfname(cell->lf, inwayname);
|
||||
msg("%s is in the way!", haslos(lf, cell) ? inwayname : "Something");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// impassable object other than the door?
|
||||
for (oo = cell->obpile->first ; oo ; oo = oo->next) {
|
||||
if (oo != o) {
|
||||
if (hasflag(oo->flags, F_IMPASSABLE)) {
|
||||
if (lf && isplayer(lf)) {
|
||||
char inwayname[BUFLEN];
|
||||
getobname(oo, inwayname, oo->amt);
|
||||
msg("%s is in the way!", haslos(lf, cell) ? inwayname : "Something");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
f = hasflag(o->flags, F_OPEN);
|
||||
if (!f) {
|
||||
if (lf && (lf->controller == C_PLAYER)) {
|
||||
|
@ -672,7 +830,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
|
|||
dst = c;
|
||||
|
||||
while (dst->lf) {
|
||||
dir = getdirtowards(dst, lf->cell, B_FALSE);
|
||||
dir = getdirtowards(dst, lf->cell, lf, B_FALSE);
|
||||
if (dir == D_NONE) {
|
||||
return B_TRUE;
|
||||
} else {
|
||||
|
@ -701,6 +859,15 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
|
|||
// teleport somewhere, along with puffs of smoke etc
|
||||
int teleportto(lifeform_t *lf, cell_t *c) {
|
||||
char buf[BUFLEN];
|
||||
|
||||
// can't teleport on top of something else
|
||||
if (c->lf) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You feel a wrenching sensation.");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (!isplayer(lf) && haslos(player, lf->cell)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s disappears in a cloud of smoke!", buf);
|
||||
|
@ -731,7 +898,8 @@ int trymove(lifeform_t *lf, int dir) {
|
|||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
if (canandwillmove(lf, dir, &errcode)) {
|
||||
object_t *o;
|
||||
object_t *o,*slipob;
|
||||
int slip;
|
||||
|
||||
// check for cursed objects + animals
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
|
@ -743,12 +911,11 @@ int trymove(lifeform_t *lf, int dir) {
|
|||
char lfname[BUFLEN];
|
||||
getlfname(lf,lfname);
|
||||
getobname(o, buf, o->amt);
|
||||
msg("%s shies away from %s!", lfname, buf);
|
||||
msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf);
|
||||
o->blessknown = B_TRUE;
|
||||
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
reason = E_OK;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -756,9 +923,28 @@ int trymove(lifeform_t *lf, int dir) {
|
|||
}
|
||||
}
|
||||
|
||||
// slipping on blood before moving?
|
||||
slip = getslipperyness(lf->cell, &slipob);
|
||||
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
|
||||
slipon(lf, slipob);
|
||||
// don't move
|
||||
reason = E_OK;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// move to new cell
|
||||
reason = E_OK;
|
||||
moveto(lf, cell);
|
||||
taketime(lf, getmovespeed(lf));
|
||||
|
||||
// slip on blood in new cell?
|
||||
slip = getslipperyness(cell, &slipob);
|
||||
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
|
||||
slipon(lf, slipob);
|
||||
// don't move
|
||||
reason = E_OK;
|
||||
return B_FALSE;
|
||||
}
|
||||
} else {
|
||||
object_t *inway;
|
||||
int door, dooropen;
|
||||
|
@ -855,18 +1041,39 @@ int trymove(lifeform_t *lf, int dir) {
|
|||
case E_LFINWAY:
|
||||
// attack!
|
||||
return attacklf(lf, cell->lf);
|
||||
break;
|
||||
case E_GRAVBOOSTED:
|
||||
if (isplayer(lf)) {
|
||||
msg("You try to move but are unable to lift your feet!");
|
||||
taketime(lf, getmovespeed(lf));
|
||||
} else if (haslos(player, lf->cell)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(lf, lfname);
|
||||
msg("%s tries to move but is unable to lift its feet!",lfname);
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
break;
|
||||
case E_CANTMOVE:
|
||||
if (isplayer(lf)) {
|
||||
msg("You cannot move!");
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
break;
|
||||
case E_GRABBEDBY:
|
||||
if (isplayer(lf)) {
|
||||
char lfname[BUFLEN];
|
||||
if (rdata) {
|
||||
getlfname((lifeform_t *)rdata, lfname);
|
||||
} else {
|
||||
sprintf(lfname, "whatever is holding you");
|
||||
}
|
||||
msg("You cannot get away from %s!",lfname);
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
break;
|
||||
case E_TOOHEAVY:
|
||||
if (isplayer(lf)) {
|
||||
msg("Your load is too heavy to move with!");
|
||||
taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
taketime(lf, getmovespeed(lf));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -895,6 +1102,15 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
|||
if (celldangerous(lf, cell, error)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// don't attack other monsters
|
||||
if (cell->lf) {
|
||||
if (!isplayer(lf)) {
|
||||
if (!isplayer(cell->lf) && !isfriendly(cell->lf)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
|
4
move.h
4
move.h
|
@ -6,9 +6,11 @@ int celldangerous(lifeform_t *lf, cell_t *cell, enum ERROR *error);
|
|||
int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error);
|
||||
int closedoorat(lifeform_t *lf, cell_t *c);
|
||||
int closedoor(lifeform_t *lf, object_t *o);
|
||||
int diropposite(int dir);
|
||||
void dorandommove(lifeform_t *lf, int badmovesok);
|
||||
int getdiraway(cell_t *src, cell_t *dst, int wantcheck);
|
||||
int getdirtowards(cell_t *src, cell_t *dst, int wantcheck);
|
||||
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck);
|
||||
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher);
|
||||
int moveawayfrom(lifeform_t *lf, cell_t *dst);
|
||||
int movelf(lifeform_t *lf, cell_t *newcell);
|
||||
int moveto(lifeform_t *lf, cell_t *newcell);
|
||||
|
|
138
nexus.c
138
nexus.c
|
@ -21,6 +21,7 @@ objectclass_t *objectclass = NULL,*lastobjectclass = NULL;
|
|||
objecttype_t *objecttype = NULL,*lastobjecttype = NULL;
|
||||
obmod_t *firstobmod = NULL,*lastobmod = NULL;
|
||||
celltype_t *firstcelltype = NULL,*lastcelltype = NULL;
|
||||
command_t *firstcommand = NULL,*lastcommand = NULL;
|
||||
race_t *firstrace = NULL,*lastrace = NULL;
|
||||
job_t *firstjob = NULL,*lastjob = NULL;
|
||||
map_t *firstmap = NULL,*lastmap = NULL;
|
||||
|
@ -144,7 +145,6 @@ int main(int argc, char **argv) {
|
|||
more();
|
||||
}
|
||||
|
||||
|
||||
// start game - this will cause debug messages to now
|
||||
// go to the log file instead of stdout.
|
||||
gamestarted = B_TRUE;
|
||||
|
@ -243,6 +243,32 @@ celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transpare
|
|||
return a;
|
||||
}
|
||||
|
||||
command_t *addcommand(enum COMMAND id, char ch, char *desc) {
|
||||
command_t *a;
|
||||
|
||||
// add to the end of the list
|
||||
if (firstcommand == NULL) {
|
||||
firstcommand = malloc(sizeof(command_t));
|
||||
a = firstcommand;
|
||||
a->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
a = lastcommand;
|
||||
a->next = malloc(sizeof(command_t));
|
||||
a->next->prev = a;
|
||||
a = a->next;
|
||||
}
|
||||
lastcommand = a;
|
||||
a->next = NULL;
|
||||
|
||||
// set props
|
||||
a->id = id;
|
||||
a->ch = ch;
|
||||
a->desc = strdup(desc);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void checkdeath(void) {
|
||||
lifeform_t *lf, *nextlf;
|
||||
int x,y;
|
||||
|
@ -330,7 +356,7 @@ void donextturn(map_t *map) {
|
|||
|
||||
if (donormalmove) {
|
||||
// paralyzed etc?
|
||||
if (cannotmove(who)) {
|
||||
if (isimmobile(who)) {
|
||||
rest(who, B_FALSE);
|
||||
donormalmove = B_FALSE;
|
||||
}
|
||||
|
@ -359,7 +385,10 @@ void donextturn(map_t *map) {
|
|||
}
|
||||
}
|
||||
|
||||
if (isdead(who) || haslos(player, who->cell)) {
|
||||
if (hasflag(player->flags, F_RESTING)) {
|
||||
// ooo is this right ?
|
||||
needredraw = B_FALSE;
|
||||
} else if (isdead(who) || haslos(player, who->cell)) {
|
||||
needredraw = B_TRUE;
|
||||
}
|
||||
|
||||
|
@ -415,7 +444,8 @@ void getrarity(int depth, int *min, int *max, int range) {
|
|||
int mid;
|
||||
mid = 100 - (depth * 3);
|
||||
*min = mid - range; if (*min < 0) *min = 0;
|
||||
*max = mid + range; if (*max > 100) *max = 100;
|
||||
//*max = mid + range; if (*max > 100) *max = 100;
|
||||
*max = 100;
|
||||
|
||||
if (*min > 75) *min = 75;
|
||||
if (*max < 25) *max = 25;
|
||||
|
@ -426,6 +456,8 @@ int init(void) {
|
|||
srand(time(NULL));
|
||||
|
||||
|
||||
|
||||
initcommands();
|
||||
initobjects();
|
||||
initjobs();
|
||||
initrace();
|
||||
|
@ -453,6 +485,47 @@ int init(void) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
void initcommands(void) {
|
||||
// Actions
|
||||
addcommand(CMD_UP, '<', "Go up stairs.");
|
||||
addcommand(CMD_DOWN, '>', "Go down stairs, enter a shop/portal.");
|
||||
addcommand(CMD_REST, '.', "Rest once.");
|
||||
addcommand(CMD_PICKUP, ',', "Pick up something from the ground.");
|
||||
addcommand(CMD_CLOSE, 'c', "Close a door.");
|
||||
addcommand(CMD_DROP, 'd', "Drop an item.");
|
||||
addcommand(CMD_DROPMULTI, 'D', "Drop multiple items.");
|
||||
addcommand(CMD_EAT, 'e', "Eat something.");
|
||||
addcommand(CMD_MAGIC, 'm', "Use magic or abilities.");
|
||||
addcommand(CMD_OPERATE, 'o', "Operate a tool/wand/device.");
|
||||
addcommand(CMD_PICKLOCK, 'p', "Pick a lock.");
|
||||
addcommand(CMD_POUR, 'P', "Pour a potion onto something.");
|
||||
addcommand(CMD_QUAFF, 'q', "Quaff (drink) a potion.");
|
||||
addcommand(CMD_READ, 'r', "Read a scroll/book.");
|
||||
addcommand(CMD_RESTFULL, 'R', "Rest until healed.");
|
||||
addcommand(CMD_TAKEOFF, 'T', "Take off an item of clothing/jewelery.");
|
||||
addcommand(CMD_WEILD, 'w', "Weild a weapon.");
|
||||
addcommand(CMD_WEAR, 'W', "Wear an item of clothing/jewelery.");
|
||||
// Firearms
|
||||
addcommand(CMD_FIRE, 'f', "Fire your firearm/bow at your current target.");
|
||||
addcommand(CMD_FIRENEW, 'F', "Fire your firearm/bow at a new target.");
|
||||
addcommand(CMD_AIM, 'a', "Aim your current firearm/bow at a new target.");
|
||||
// Information
|
||||
addcommand(CMD_HELP, '?', "Display this text.");
|
||||
addcommand(CMD_INFOPLAYER, '@', "Display player stats.");
|
||||
addcommand(CMD_INFOARMOUR, ']', "Display player armour.");
|
||||
addcommand(CMD_FORCEATTACK, 'A', "Force an attack in a given direction.");
|
||||
addcommand(CMD_LOOKHERE, ':', "Look at current cell.");
|
||||
addcommand(CMD_LOOKAROUND, '/', "Look at a remote cell.");
|
||||
addcommand(CMD_INFOKNOWLEDGE, '\\', "Display known items.");
|
||||
addcommand(CMD_MSGHIST, '|', "Display message history.");
|
||||
addcommand(CMD_INV, 'i', "Display your inventory.");
|
||||
// GAME FUNCTIONS
|
||||
addcommand(CMD_QUIT, 'Q', "Quit the game.");
|
||||
addcommand(CMD_SAVEQUIT, 'S', "Save and quit the game.");
|
||||
|
||||
sortcommands();
|
||||
}
|
||||
|
||||
int isplayerturn(void) {
|
||||
if (!player) return B_FALSE;
|
||||
|
||||
|
@ -462,6 +535,19 @@ int isplayerturn(void) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int limit(int *what, int min, int max) {
|
||||
int limited = B_FALSE;
|
||||
if (*what < min) {
|
||||
*what = min;
|
||||
limited = B_TRUE;
|
||||
}
|
||||
if (*what > max) {
|
||||
*what = max;
|
||||
limited = B_TRUE;
|
||||
}
|
||||
return limited;
|
||||
}
|
||||
|
||||
float pctof(float pct, float num) {
|
||||
return ((pct / 100.0) * num);
|
||||
}
|
||||
|
@ -619,6 +705,50 @@ dblog("doing sort...");
|
|||
}
|
||||
*/
|
||||
|
||||
void sortcommands(void) {
|
||||
command_t *c;
|
||||
int donesomething = B_TRUE;
|
||||
while (donesomething) {
|
||||
donesomething = B_FALSE;
|
||||
for (c = firstcommand ; c->next ; c = c->next) {
|
||||
// move up one position if required.
|
||||
if (c->ch > c->next->ch) {
|
||||
command_t *temp;
|
||||
|
||||
// remember next element
|
||||
temp = c->next;
|
||||
|
||||
// remove this element from list
|
||||
if (c->prev == NULL) {
|
||||
// first
|
||||
firstcommand = c->next;
|
||||
c->next->prev = NULL;
|
||||
} else {
|
||||
// not first
|
||||
c->prev->next = c->next;
|
||||
c->next->prev = c->prev;
|
||||
}
|
||||
|
||||
// re-add element afterwards
|
||||
c->next = temp->next;
|
||||
c->prev = temp;
|
||||
temp->next = c;
|
||||
if (c->next == NULL) {
|
||||
lastcommand = c;
|
||||
} else {
|
||||
c->next->prev = c;
|
||||
}
|
||||
|
||||
// mark as done.
|
||||
donesomething = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void timeeffectsworld(map_t *map) {
|
||||
lifeform_t *l;
|
||||
int db = B_FALSE;
|
||||
|
|
4
nexus.h
4
nexus.h
|
@ -1,6 +1,7 @@
|
|||
#include "defs.h"
|
||||
|
||||
celltype_t *addcelltype(int id, char *name, char glyph, int solid, int transparent, enum MATERIAL mat);
|
||||
command_t *addcommand(enum COMMAND id, char c, char *desc);
|
||||
void checkdeath(void);
|
||||
void checkendgame(void);
|
||||
void cleanup(void);
|
||||
|
@ -9,11 +10,14 @@ celltype_t *findcelltype(int id);
|
|||
char *getdirname(int dir);
|
||||
void getrarity(int depth, int *min, int *max, int range);
|
||||
int init(void);
|
||||
void initcommands(void);
|
||||
int isplayerturn(void);
|
||||
int limit(int *what, int min, int max);
|
||||
float pctof(float pct, float num);
|
||||
int rnd(int min, int max);
|
||||
int rolldie(int ndice, int sides);
|
||||
int rollhitdice(lifeform_t *lf);
|
||||
int rollmpdice(lifeform_t *lf);
|
||||
//void sortlf(map_t *map);
|
||||
void sortcommands(void);
|
||||
void timeeffectsworld(map_t *map);
|
||||
|
|
13
objects.h
13
objects.h
|
@ -8,6 +8,7 @@ material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
|
|||
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph);
|
||||
object_t *addob(obpile_t *where, char *name);
|
||||
object_t *addobject(obpile_t *where, char *name, int canstack);
|
||||
int addobburst(cell_t *where, int range, int dirtype, char *name);
|
||||
obmod_t *addobmod(enum OBMOD id, char *suffix, enum BODYPART bp);
|
||||
obpile_t *addobpile(lifeform_t *owner, cell_t *where);
|
||||
objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid);
|
||||
|
@ -20,6 +21,7 @@ void brightflash(cell_t *centre, int range, lifeform_t *immunelf);
|
|||
object_t *canstackob(obpile_t *op, object_t *match);
|
||||
object_t *canstacknewot(obpile_t *op, objecttype_t *match);
|
||||
int changemat(object_t *o, enum MATERIAL mat);
|
||||
objecttype_t *checkobnames(char *haystack, char *needle);
|
||||
void copyobprops(object_t *dst, object_t *src);
|
||||
int countnames(char **list);
|
||||
int countobs(obpile_t *op);
|
||||
|
@ -41,6 +43,7 @@ int geteffecttime(int min, int max, enum BLESSTYPE isblessed);
|
|||
objecttype_t *getlinkspell(object_t *o);
|
||||
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt);
|
||||
int getobaccuracy(object_t *wep);
|
||||
int getobbonus(object_t *o);
|
||||
int getobvalue(object_t *o);
|
||||
//int getobtypevalue(objecttype_t *ot);
|
||||
char *getaccuracyname(int accpct);
|
||||
|
@ -55,6 +58,7 @@ char getglyph(object_t *o);
|
|||
char *genhiddenname(enum OBCLASS id);
|
||||
char *gethiddenname(object_t *o);
|
||||
int getobattackdelay(object_t *o);
|
||||
float getobhppct(object_t *o);
|
||||
int getletindex(char let);
|
||||
int getmaterialvalue(enum MATERIAL mat );
|
||||
int getmaxthrowrange(lifeform_t *lf, object_t *o);
|
||||
|
@ -63,9 +67,10 @@ int getnumshards(object_t *o);
|
|||
int getnutritionbase(object_t *o);
|
||||
int getnutrition(object_t *o);
|
||||
char *getobdesc(object_t *o, char *buf);
|
||||
char *getobextrainfo(object_t *o, char *buf);
|
||||
cell_t *getoblocation(object_t *o);
|
||||
char *getobname(object_t *o, char *buf, int count);
|
||||
char *real_getobname(object_t *o, char *buf, int count, int wantcondition, int adjustforblind, int wantblesscurse);
|
||||
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse);
|
||||
float getobpileweight(obpile_t *op);
|
||||
char *getobconditionname(object_t *o, char *buf);
|
||||
char *getobhurtname(object_t *o, enum DAMTYPE damtype);
|
||||
|
@ -76,6 +81,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
|
|||
char *getrandomob(map_t *map, char *buf);
|
||||
char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf);
|
||||
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf);
|
||||
enum SPELLSCHOOL getschool(enum OBTYPE sid);
|
||||
char *getschoolname(enum SPELLSCHOOL sch);
|
||||
int getshatterdam(object_t *o);
|
||||
int getthrowdam(object_t *o);
|
||||
|
@ -88,6 +94,7 @@ object_t *hasobwithflag(obpile_t *op, enum FLAG flagid);
|
|||
object_t *hasobwithflagval(obpile_t *op, enum FLAG flagid, int val0, int val1, int val2, char *text);
|
||||
object_t *hasobid(obpile_t *op, int id);
|
||||
void identify(object_t *o);
|
||||
void ignite(object_t *o);
|
||||
void initobjects(void);
|
||||
flag_t *isarmour(object_t *o);
|
||||
int isactivated(object_t *o);
|
||||
|
@ -107,6 +114,7 @@ int isfirearm(object_t *o);
|
|||
int isflammable(object_t *o);
|
||||
int isknown(object_t *o);
|
||||
int isidentified(object_t *o);
|
||||
int isimpassableob(object_t *o, lifeform_t *lf);
|
||||
int ismetal(enum MATERIAL mat);
|
||||
int ismissile(object_t *o);
|
||||
int isoperable(object_t *o);
|
||||
|
@ -123,6 +131,7 @@ void killobpile(obpile_t *o);
|
|||
void killoc(objectclass_t *oc);
|
||||
void killot(objecttype_t *ot);
|
||||
lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level);
|
||||
void makeduller(object_t *o, int howmuch);
|
||||
void makeknown(enum OBTYPE otid);
|
||||
object_t *moveob(object_t *src, obpile_t *dst, int howmany);
|
||||
void modbonus(object_t *o, int amt);
|
||||
|
@ -141,7 +150,7 @@ int pilehasletter(obpile_t *op, char let);
|
|||
void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, int *seen);
|
||||
int pour(lifeform_t *lf, object_t *o);
|
||||
void quaff(lifeform_t *lf, object_t *o);
|
||||
void readsomething(lifeform_t *lf, object_t *o);
|
||||
int readsomething(lifeform_t *lf, object_t *o);
|
||||
void removedeadobs(obpile_t *op);
|
||||
int removeob(object_t *o, int howmany);
|
||||
object_t *relinkob(object_t *src, obpile_t *dst);
|
||||
|
|
570
spell.c
570
spell.c
|
@ -4,6 +4,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "attack.h"
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "io.h"
|
||||
|
@ -21,30 +22,79 @@ extern WINDOW *msgwin;
|
|||
|
||||
extern job_t *firstjob;
|
||||
|
||||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid) {
|
||||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target) {
|
||||
char username[BUFLEN];
|
||||
char buf[BUFLEN];
|
||||
flag_t *f;
|
||||
|
||||
getlfname(user, username);
|
||||
|
||||
if (abilid == OT_A_JUMP) {
|
||||
if (abilid == OT_A_GRAB) {
|
||||
char dirch;
|
||||
flag_t *f;
|
||||
|
||||
f = lfhasflag(user, F_GRABBING);
|
||||
if (f) {
|
||||
if (isplayer(user)) msg("You are already holding someone!");
|
||||
return B_TRUE;
|
||||
}
|
||||
f = lfhasflag(user, F_GRABBEDBY);
|
||||
if (f) {
|
||||
if (isplayer(user)) msg("You are already being held by someone!");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// ask for direction
|
||||
if (!targcell) {
|
||||
dirch = askchar("Grab in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE);
|
||||
if (dirch == '.') {
|
||||
if (isplayer(user)) msg("You can't grab yourself!");
|
||||
return B_TRUE;
|
||||
} else {
|
||||
int dir;
|
||||
dir = chartodir(dirch);
|
||||
if (dir == D_NONE) {
|
||||
if (isplayer(user)) msg("Cancelled.");
|
||||
return B_TRUE ;
|
||||
} else {
|
||||
targcell = getcellindir(user->cell, dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target = targcell->lf;
|
||||
if (!target) {
|
||||
if (isplayer(user)) msg("There is nobody there to grab!");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
addflag(user->flags, F_GRABBING, target->id, NA, NA, NULL);
|
||||
addflag(target->flags, F_GRABBEDBY, user->id, NA, NA, NULL);
|
||||
} else if (abilid == OT_A_JUMP) {
|
||||
lifeform_t *victim = NULL;
|
||||
char victimname[BUFLEN];
|
||||
int dodged = B_FALSE;
|
||||
cell_t *where = NULL, *origcell;
|
||||
cell_t *origcell;
|
||||
if (!targcell) {
|
||||
sprintf(buf, "Jump where (max distance 2)?");
|
||||
while (!where) {
|
||||
while (!targcell) {
|
||||
// ask where
|
||||
where = askcoords(buf, TT_NONE);
|
||||
if (!where) {
|
||||
targcell = askcoords(buf, TT_NONE);
|
||||
if (!targcell) {
|
||||
return B_TRUE;
|
||||
} else if (getcelldist(user->cell, where) > 2) {
|
||||
where = NULL;
|
||||
} else if (getcelldist(user->cell, targcell) > 2) {
|
||||
targcell = NULL;
|
||||
if (isplayer(user)) {
|
||||
sprintf(buf, "You can't jump that far! Jump where (max distance 2)?");
|
||||
} else if (!haslos(user, where)) {
|
||||
where = NULL;
|
||||
}
|
||||
} else if (!haslos(user, targcell)) {
|
||||
targcell = NULL;
|
||||
if (isplayer(user)) {
|
||||
sprintf(buf, "You can't see where to land! Jump where (max distance 2)?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isburdened(user)) {
|
||||
if (isplayer(user)) {
|
||||
|
@ -63,7 +113,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) {
|
|||
origcell = user->cell;
|
||||
|
||||
// did you land on anyone?
|
||||
victim = haslf(where);
|
||||
victim = haslf(targcell);
|
||||
if (victim) {
|
||||
cell_t *c;
|
||||
int acc;
|
||||
|
@ -86,7 +136,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) {
|
|||
dodged = B_TRUE;
|
||||
}
|
||||
}
|
||||
movelf(user, where);
|
||||
movelf(user, targcell);
|
||||
|
||||
// announce
|
||||
if (isplayer(user)) {
|
||||
|
@ -140,11 +190,16 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) {
|
|||
msg("You are too tired to sprint right now.");
|
||||
}
|
||||
return B_TRUE;
|
||||
} else if (lfhasflag(user, F_SPRINTING)) {
|
||||
if (isplayer(user)) {
|
||||
msg("You are already sprinting!");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
// TODO: calculate time based on:
|
||||
// constitution (or max hp?)
|
||||
// running speed
|
||||
howlong = 3;
|
||||
howlong = 5;
|
||||
addtempflag(user->flags, F_SPRINTING, B_TRUE, NA, NA, NULL, howlong);
|
||||
} else if (abilid == OT_A_DEBUG) {
|
||||
cell_t *where;
|
||||
|
@ -191,7 +246,60 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid) {
|
|||
} else {
|
||||
msg("There is nobody there!");
|
||||
}
|
||||
} else if (abilid == OT_A_HEAVYBLOW) {
|
||||
object_t *wep;
|
||||
char dirch;
|
||||
char targetname[BUFLEN];
|
||||
flag_t *f;
|
||||
|
||||
wep = getweapon(user);
|
||||
if (!wep) {
|
||||
if (isplayer(user)) msg("You need a bashing weapon to perform a heavy blow!");
|
||||
return B_TRUE;
|
||||
} else if (getdamtype(wep) != DT_BASH) {
|
||||
if (isplayer(user)) msg("You need a bashing weapon to perform a heavy blow!");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
// ask for direction
|
||||
if (!targcell) {
|
||||
dirch = askchar("Attack in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE);
|
||||
if (dirch == '.') {
|
||||
// yourself!
|
||||
targcell = user->cell;
|
||||
} else {
|
||||
int dir;
|
||||
dir = chartodir(dirch);
|
||||
if (dir == D_NONE) {
|
||||
if (isplayer(user)) msg("Cancelled.");
|
||||
return B_TRUE ;
|
||||
} else {
|
||||
targcell = getcellindir(user->cell, dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target = targcell->lf;
|
||||
if (!target) {
|
||||
if (isplayer(user)) msg("There is nobody there to attack!");
|
||||
return B_TRUE;
|
||||
}
|
||||
getlfname(target, targetname);
|
||||
|
||||
f = addflag(wep->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL);
|
||||
attackcell(user, targcell);
|
||||
killflag(f);
|
||||
}
|
||||
|
||||
// expire ability
|
||||
f = lfhasflagval(user, F_CANWILL, abilid, NA, NA, NULL);
|
||||
if (f) {
|
||||
if (f->val[2] != NA) {
|
||||
// ie. it will go to 0 next turn.
|
||||
f->val[1] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -207,6 +315,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
// default to unseen
|
||||
if (seenbyplayer) *seenbyplayer = B_FALSE;
|
||||
|
||||
|
||||
// reverse some spells if cursed
|
||||
|
||||
if (blessed == B_CURSED) {
|
||||
switch (spellid) {
|
||||
case OT_S_LIGHT:
|
||||
spellid = OT_S_DARKNESS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (spellid == OT_S_ABSORBMETAL) {
|
||||
int i;
|
||||
float totalmass = 0;
|
||||
|
@ -290,6 +411,33 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_ANIMATEDEAD) {
|
||||
int i;
|
||||
object_t *o,*nexto;
|
||||
int donesomething = B_FALSE;
|
||||
// animate corpses within los of caster
|
||||
for (i = 0; i < caster->nlos; i++) {
|
||||
targcell = caster->los[i];
|
||||
for (o = targcell->obpile->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
if (o->type->id == OT_CORPSE) {
|
||||
lifeform_t *newlf;
|
||||
newlf = makezombie(o);
|
||||
if (newlf) {
|
||||
if (isplayer(caster) && skillcheck(caster, A_IQ, 20, 0)) {
|
||||
makefriendly(newlf);
|
||||
}
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (donesomething) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_ANIMATEMETAL) {
|
||||
object_t *o;
|
||||
o = getweapon(caster);
|
||||
|
@ -331,6 +479,40 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_BLINDNESS) {
|
||||
int failed = B_FALSE;
|
||||
// ask for target
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
|
||||
if (isblind(target)) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
if (hasmr(target) || skillcheck(caster, A_IQ, 24, 0)) {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
|
||||
if (target) {
|
||||
if (failed) {
|
||||
if (isplayer(target)) {
|
||||
msg("Your vision darkens for a moment.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, target->cell)) {
|
||||
char targetname[BUFLEN];
|
||||
getlfname(target, targetname);
|
||||
msg("%s seems to lose its vision for a moment.", targetname);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
} else {
|
||||
int howlong = 7;
|
||||
howlong = getspellduration(5,10,blessed);
|
||||
addtempflag(target->flags, F_BLIND, B_TRUE, NA, NA, NULL, howlong);
|
||||
}
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_BLINK) {
|
||||
if (hasmr(caster)) {
|
||||
if (isplayer(caster)) {
|
||||
|
@ -356,10 +538,50 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
teleportto(caster, targcell);
|
||||
}
|
||||
} else if (spellid == OT_S_BURNINGWAVE) {
|
||||
cell_t *c;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
|
||||
if (haslos(player, caster->cell)) {
|
||||
msg("%s shoots a wave of fire!",castername);
|
||||
}
|
||||
|
||||
// create a line of fire towards the target cell
|
||||
c = caster->cell;
|
||||
while (c != targcell) {
|
||||
int dir;
|
||||
dir = getdirtowards(c, targcell, NULL, B_FALSE);
|
||||
c = getcellindir(c, dir);
|
||||
if (!c) break;
|
||||
if (c->type->solid) break;
|
||||
// set on fire
|
||||
addob(c->obpile, "medium fire");
|
||||
if (c->lf) {
|
||||
char buf[BUFLEN];
|
||||
getlfname(c->lf,buf);
|
||||
msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s");
|
||||
losehp(c->lf, rolldie(2,10), DT_FIRE, caster, "a wave of fire");
|
||||
}
|
||||
}
|
||||
|
||||
} else if (spellid == OT_S_CLOUDKILL) {
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_FALSE, spellid)) return B_TRUE;
|
||||
|
||||
if (targcell->type->solid) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
addobburst(targcell, 1, DT_COMPASS, "cloud of gas");
|
||||
|
||||
if (haslos(player, targcell)) {
|
||||
msg("A cloud of poison gas appears!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_CONECOLD) {
|
||||
char lfname[BUFLEN];
|
||||
int acc;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
// animation
|
||||
anim(caster->cell, targcell, '}');
|
||||
if (isplayer(caster) || haslos(player, caster->cell)) {
|
||||
|
@ -385,6 +607,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
msg("A blast of coldness misses %s.",lfname);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object_t *o, *nexto;
|
||||
for (o = targcell->obpile->first; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
takedamage(o, 0, DT_COLD);
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_CREATEMONSTER) {
|
||||
cell_t *where;
|
||||
|
@ -445,9 +673,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
|
||||
if (blessed) {
|
||||
//newlf = addlf(where, r->id, getrandommonlevel(where->map->depth));
|
||||
newlf = addmonster(where, r->id, randomjobsok);
|
||||
newlf = addmonster(where, r->id, randomjobsok, 1);
|
||||
} else {
|
||||
newlf = addmonster(where, R_RANDOM, randomjobsok);
|
||||
newlf = addmonster(where, R_RANDOM, randomjobsok, 1);
|
||||
}
|
||||
if (newlf) {
|
||||
// assign job if required
|
||||
|
@ -477,6 +705,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_DARKNESS) {
|
||||
// centre on the caster
|
||||
if (isplayer(caster) || haslos(player, caster->cell)) {
|
||||
msg("A cloud of darkness descends!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
makelitradius(caster->cell, 10, L_DARK);
|
||||
} else if (spellid == OT_S_DETECTAURA) {
|
||||
if (isplayer(caster)) {
|
||||
object_t *o;
|
||||
|
@ -552,7 +787,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
*/
|
||||
} else if (spellid == OT_S_DETONATE) {
|
||||
// don't need line of fire!
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, B_FALSE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, B_FALSE, spellid)) return B_TRUE;
|
||||
|
||||
explodecells(targcell, 20, B_TRUE, NULL, 0, B_TRUE);
|
||||
|
||||
|
@ -563,7 +798,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
float totalmass = 0;
|
||||
object_t *o, *nexto;
|
||||
|
||||
if (!validatespellcell(caster, &targcell, TT_OBJECT, B_FALSE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_OBJECT, B_FALSE, spellid)) return B_TRUE;
|
||||
|
||||
// how much metal is there?
|
||||
for (o = targcell->obpile->first ; o ; o = nexto) {
|
||||
|
@ -686,7 +921,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else if (spellid == OT_S_ENERGYBOLT) {
|
||||
char lfname[BUFLEN];
|
||||
int acc;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
// animation
|
||||
anim(caster->cell, targcell, '}');
|
||||
if (isplayer(caster) || haslos(player, caster->cell)) {
|
||||
|
@ -716,7 +951,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else if (spellid == OT_S_FIREBALL) {
|
||||
int failed = B_FALSE;
|
||||
// ask for a target cell
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
if (targcell && haslof(caster, targcell)) { // need line of FIRE for this, not just sight
|
||||
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
|
||||
int dir;
|
||||
|
@ -783,7 +1018,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else if (spellid == OT_S_FIREDART) {
|
||||
char lfname[BUFLEN];
|
||||
int acc;
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
// animation
|
||||
anim(caster->cell, targcell, '}');
|
||||
if (isplayer(caster) || haslos(player, caster->cell)) {
|
||||
|
@ -809,11 +1044,44 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
msg("A dart of flame misses %s.",lfname);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object_t *o, *nexto;
|
||||
for (o = targcell->obpile->first; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
takedamage(o, 0, DT_FIRE);
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_FLAMEBURST) {
|
||||
int range = 1;
|
||||
int x,y;
|
||||
// announce
|
||||
if (isplayer(caster) || haslos(player, caster->cell)) {
|
||||
msg("%s emit%s a blast of fire!",castername,isplayer(caster) ? "" : "s");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
|
||||
animradialorth(caster->cell, range, '}');
|
||||
|
||||
for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) {
|
||||
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
|
||||
targcell = getcellat(caster->cell->map, x,y);
|
||||
if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) {
|
||||
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell)) {
|
||||
char lfname[BUFLEN];
|
||||
// automatic hit
|
||||
getlfname(targcell->lf, lfname);
|
||||
if (haslos(caster, targcell)) {
|
||||
msg("%s burn%s!",lfname,isplayer(targcell->lf) ? "" : "s");
|
||||
}
|
||||
losehp(targcell->lf, rolldie(2,8)+3, DT_MAGIC, caster, "a burst of fire");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_FLAMEPILLAR) {
|
||||
int failed = B_FALSE;
|
||||
// ask for a target cell
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
if (targcell && haslos(caster, targcell)) {
|
||||
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
|
||||
// create flame there
|
||||
|
@ -853,14 +1121,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else {
|
||||
int amt;
|
||||
char obname[BUFLEN];
|
||||
getobname(o, obname, o->amt);
|
||||
msg("Your %s glows %s for a moment.", noprefix(obname), (blessed == B_CURSED) ? "black" : "green");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
if (blessed == B_CURSED) {
|
||||
amt = -1;
|
||||
} else {
|
||||
amt = 1;
|
||||
}
|
||||
modbonus(o, amt);
|
||||
getobname(o, obname, o->amt);
|
||||
msg("Your %s glows %s for a moment.", noprefix(obname), (blessed == B_CURSED) ? "black" : "green");
|
||||
}
|
||||
} else {
|
||||
// monsters can't id things!
|
||||
|
@ -976,7 +1245,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
} else if (spellid == OT_S_HASTE) {
|
||||
int howlong = 15;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
|
||||
target = targcell->lf;
|
||||
|
||||
|
@ -1001,6 +1270,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
addtempflag(target->flags, F_FASTMOVE, 5, NA, NA, NULL, howlong);
|
||||
}
|
||||
} else if (spellid == OT_S_HEALING) {
|
||||
int donesomething = B_FALSE;
|
||||
flag_t *f;
|
||||
target = caster;
|
||||
|
||||
if (hasmr(target)) {
|
||||
|
@ -1011,6 +1282,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// cure certain bad effects
|
||||
if (killflagsofid(target->flags, F_PAIN)) {
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
|
||||
if (target->hp < target->maxhp) {
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
|
@ -1035,12 +1312,23 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
msg("%s looks healthier!", buf);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
f = lfhasflag(target, F_FOODPOISONED);
|
||||
if (f) {
|
||||
killflag(f);
|
||||
donesomething = B_TRUE;
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
|
||||
if (!donesomething) {
|
||||
if (isplayer(target)) {
|
||||
nothinghappens();
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_HEALINGMIN) {
|
||||
int donesomething = B_FALSE;
|
||||
flag_t *f;
|
||||
target = caster;
|
||||
if (hasmr(target)) {
|
||||
if (isplayer(target) || haslos(player, target->cell)) {
|
||||
|
@ -1050,6 +1338,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// cure bad effects instead of healing
|
||||
if (killflagsofid(target->flags, F_PAIN)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
if (target->hp < target->maxhp) {
|
||||
switch (blessed) {
|
||||
case B_BLESSED:
|
||||
|
@ -1071,7 +1365,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
msg("%s looks a little healthier!", buf);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
f = lfhasflag(target, F_FOODPOISONED);
|
||||
if (f) {
|
||||
killflag(f);
|
||||
donesomething = B_TRUE;
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
|
||||
if (!donesomething) {
|
||||
if (isplayer(target)) {
|
||||
nothinghappens();
|
||||
}
|
||||
|
@ -1102,9 +1405,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
// charges
|
||||
charges = getcharges(o);
|
||||
if (charges == -1) {
|
||||
msglower("%c - %s.",o->letter, buf);
|
||||
msgnocap("%c - %s.",o->letter, buf);
|
||||
} else {
|
||||
msglower("%c - %s (%d charges left).",o->letter, buf, charges);
|
||||
msgnocap("%c - %s (%d charges left).",o->letter, buf, charges);
|
||||
}
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
|
@ -1140,7 +1443,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
char lfname[BUFLEN];
|
||||
int acc;
|
||||
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
// animation
|
||||
anim(caster->cell, targcell, '}');
|
||||
if (isplayer(caster) || haslos(player, caster->cell)) {
|
||||
|
@ -1339,12 +1642,71 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, B_TRUE, spellid)) return B_TRUE;
|
||||
|
||||
// 4 is the same as ST_TITANIC strength
|
||||
fireat(caster, targob, targcell, 4 , NULL);
|
||||
} else if (spellid == OT_S_PAIN) {
|
||||
int failed = B_FALSE;
|
||||
// ask for target
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
|
||||
if (lfhasflag(target, F_PAIN)) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// make this a constitution skill check ?
|
||||
//if (hasmr(target) || skillcheck(caster, A_IQ, -5)) {
|
||||
if (hasmr(target)) {
|
||||
failed = B_TRUE;
|
||||
}
|
||||
|
||||
if (target) {
|
||||
if (failed) {
|
||||
if (isplayer(target)) {
|
||||
msg("Your skin hurts for a moment.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, target->cell)) {
|
||||
char targetname[BUFLEN];
|
||||
getlfname(target, targetname);
|
||||
msg("%s winces in pain, then recovers.", targetname);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
} else {
|
||||
int howlong = 7;
|
||||
howlong = getspellduration(3,5,blessed);
|
||||
addtempflag(target->flags, F_PAIN, B_TRUE, NA, NA, NULL, howlong);
|
||||
}
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_PETRIFY) {
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
|
||||
// savingthrow
|
||||
if (skillcheck(target, SC_IQ, 30, 0)) {
|
||||
if (haslos(player, target->cell)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(target, lfname);
|
||||
msg("%s glows grey momentarily.", lfname);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (!stone(target)) {
|
||||
// successful
|
||||
if (haslos(player, target->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
// failed!
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_PULLMETAL) {
|
||||
if (!validatespellcell(caster, &targcell,TT_OBJECT, B_TRUE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell,TT_OBJECT, B_TRUE, spellid)) return B_TRUE;
|
||||
|
||||
if (targcell->lf) {
|
||||
object_t *o;
|
||||
|
@ -1378,7 +1740,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
|
||||
if (hasmr(target)) {
|
||||
failed = B_TRUE;
|
||||
} else if (metalweight <= getmaxliftweight(caster)) {
|
||||
} else if (getobpileweight(caster->pack) + metalweight <= getmaxcarryweight(caster)) {
|
||||
// they get pulled towards caster
|
||||
failed = pullnextto(target, caster->cell);
|
||||
} else {
|
||||
|
@ -1419,7 +1781,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
} else if (haslos(player, caster->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
if (getobweight(targob) < getmaxliftweight(caster) ) {
|
||||
if (getobpileweight(caster->pack) + getobweight(targob) <= getmaxcarryweight(caster)) {
|
||||
// move it to the player
|
||||
pullobto(targob, caster);
|
||||
} else {
|
||||
|
@ -1551,7 +1913,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
}
|
||||
} else if (spellid == OT_S_KNOCK) {
|
||||
object_t *o;
|
||||
if (!validatespellcell(caster, &targcell,TT_DOOR, B_FALSE)) return B_TRUE;
|
||||
if (!validatespellcell(caster, &targcell,TT_DOOR, B_FALSE, spellid)) return B_TRUE;
|
||||
o = hasobwithflag(targcell->obpile, F_DOOR);
|
||||
if (o) {
|
||||
int dooropen;
|
||||
|
@ -1566,6 +1928,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
takedamage(o, 999, DT_DIRECT);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (targcell->lf && (targcell->lf != caster)) {
|
||||
int dir;
|
||||
target = targcell->lf;
|
||||
dir = getdirtowards(caster->cell, targcell, target, B_FALSE);
|
||||
knockback(target, dir, 2, caster);
|
||||
if (haslos(caster, target->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
|
@ -1576,7 +1946,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
msg("The area is lit by a magical light!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
makelitradius(caster->cell, 10, B_PERM);
|
||||
makelitradius(caster->cell, 10, L_PERM);
|
||||
|
||||
// blind anyone with nightvis who sees it
|
||||
// (player last)
|
||||
|
@ -1585,8 +1955,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
if (lfhasflag(l, F_SEEINDARK)) {
|
||||
// if you don't have eyes, your'e safe!
|
||||
if (!lfhasflagval(l, F_NOBODYPART, BP_EYES, NA, NA, NULL)) {
|
||||
// blind for 5-10 turns
|
||||
addtempflag(l->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(5,10));
|
||||
// blind for 1-3 turns
|
||||
addtempflag(l->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(1,3));
|
||||
}
|
||||
}
|
||||
// undead will flee from light
|
||||
|
@ -1724,10 +2094,34 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
|
||||
// become the new race!
|
||||
setrace(target, r->id);
|
||||
|
||||
if (haslos(player, target->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_SLEEP) {
|
||||
int howlong;
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
|
||||
if (hasmr(target)) {
|
||||
if (isplayer(target)) {
|
||||
msg("You yawn.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, target->cell)) {
|
||||
getlfname(target, buf);
|
||||
msg("%s yawns.", buf);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
howlong = getspellduration(5,15,blessed);
|
||||
addtempflag(target->flags, F_ASLEEP, B_TRUE, NA, NA, NULL, howlong);
|
||||
if (isplayer(target) || haslos(player, target->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_SLOW) {
|
||||
int howlong = 15;
|
||||
if (!validatespelllf(caster, &target)) return B_TRUE;
|
||||
|
@ -1747,12 +2141,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
howlong = rnd(5,25);
|
||||
addtempflag(target->flags, F_SLOWACT, 5, NA, NA, NULL, howlong);
|
||||
addtempflag(target->flags, F_SLOWMOVE, 5, NA, NA, NULL, howlong);
|
||||
/*
|
||||
if (!isplayer(target) && haslos(player, target->cell)) {
|
||||
getlfname(target, buf);
|
||||
msg("%s seems to slow down.",buf);
|
||||
if (isplayer(target) || haslos(player, target->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_SPARK) {
|
||||
object_t *o,*nexto;
|
||||
int donesomething = B_FALSE;
|
||||
if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, B_FALSE, spellid)) return B_TRUE;
|
||||
|
||||
if (haslos(player, targcell)) {
|
||||
msg("A small spark appears.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
|
||||
for (o = targcell->obpile->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
if (isflammable(o)) {
|
||||
takedamage(o, 0, DT_FIRE);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
if (targcell->lf) {
|
||||
losehp(targcell->lf, 0, DT_FIRE, caster, "a spark");
|
||||
}
|
||||
*/
|
||||
} else if (spellid == OT_S_TELEPORT) {
|
||||
cell_t *c = NULL;
|
||||
|
||||
|
@ -1981,7 +2392,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target,
|
|||
if (!hasflag(o->flags, F_IMPASSABLE) && canpickup(target, o, ALL)) {
|
||||
relinkob(o, target->pack); // move to pack
|
||||
if (isplayer(target)) {
|
||||
msglower("%c - %s.", o->letter, obname);
|
||||
msgnocap("%c - %s.", o->letter, obname);
|
||||
} else {
|
||||
msg("%s is gifted with %s.", lfname, obname);
|
||||
}
|
||||
|
@ -2051,6 +2462,49 @@ int getspellduration(int min,int max,int blessed) {
|
|||
return howlong;
|
||||
}
|
||||
|
||||
int getspelllevel(enum OBTYPE spellid) {
|
||||
flag_t *f;
|
||||
objecttype_t *ot;
|
||||
int level = 0;
|
||||
ot = findot(spellid);
|
||||
if (!ot) {
|
||||
return 0;
|
||||
}
|
||||
f = hasflag(ot->flags, F_SPELLLEVEL);
|
||||
if (f) {
|
||||
level = f->val[0];
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
enum SPELLSCHOOL getspellschool(enum OBTYPE spellid) {
|
||||
flag_t *f;
|
||||
objecttype_t *ot;
|
||||
ot = findot(spellid);
|
||||
if (!ot) {
|
||||
return SS_NONE;
|
||||
}
|
||||
f = hasflag(ot->flags, F_SPELLSCHOOL);
|
||||
if (f) {
|
||||
return f->val[0];
|
||||
}
|
||||
return SS_NONE;
|
||||
}
|
||||
|
||||
int getspellrange(enum OBTYPE spellid) {
|
||||
objecttype_t *st;
|
||||
int range = UNLIMITED;
|
||||
st = findot(spellid);
|
||||
if (st) {
|
||||
flag_t *f;
|
||||
f = hasflag(st->flags, F_RANGE);
|
||||
if (f) {
|
||||
range = f->val[0];
|
||||
}
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
// magically propel an object into lf's hands.
|
||||
// if it's too big it'll hit them!
|
||||
void pullobto(object_t *o, lifeform_t *lf) {
|
||||
|
@ -2079,7 +2533,7 @@ void pullobto(object_t *o, lifeform_t *lf) {
|
|||
}
|
||||
// where does it end up?
|
||||
obloc = getoblocation(o);
|
||||
dir = getdirtowards(lf->cell, obloc, B_FALSE);
|
||||
dir = getdirtowards(lf->cell, obloc, NULL, B_FALSE);
|
||||
newcell = getcellindir(lf->cell, dir);
|
||||
if (newcell) {
|
||||
// move next to player
|
||||
|
@ -2101,26 +2555,37 @@ void pullobto(object_t *o, lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
|
||||
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof) {
|
||||
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid) {
|
||||
int maxrange = UNLIMITED;
|
||||
|
||||
maxrange = getspellrange(spellid);
|
||||
|
||||
if (*targcell == NULL) {
|
||||
// ask for a target cell
|
||||
if (isplayer(caster)) {
|
||||
cell_t *where;
|
||||
char buf[BUFLEN];
|
||||
if (maxrange == UNLIMITED) {
|
||||
sprintf(buf, "Where will you target your spell?");
|
||||
where = askcoords(buf, targtype);
|
||||
if (where && haslos(caster, where)) {
|
||||
if (needlof) {
|
||||
if (haslof(caster, where)) {
|
||||
*targcell = where;
|
||||
} else {
|
||||
sprintf(buf, "Where will you target your spell [max range %d]?",maxrange);
|
||||
}
|
||||
where = askcoords(buf, targtype);
|
||||
|
||||
if (where && haslos(caster, where)) {
|
||||
if (needlof && !haslof(caster, where)) {
|
||||
// no line of sight
|
||||
fizzle(caster);
|
||||
return NULL;
|
||||
} else if ((maxrange != UNLIMITED) && (getcelldist(caster->cell, where) > maxrange)) {
|
||||
// out of range
|
||||
fizzle(caster);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
*targcell = where;
|
||||
}
|
||||
} else {
|
||||
// no line of sight or invalid cell
|
||||
fizzle(caster);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -2183,6 +2648,7 @@ int getmpcost(enum OBTYPE oid) {
|
|||
return cost;
|
||||
}
|
||||
|
||||
|
||||
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **target) {
|
||||
if (*target) {
|
||||
return *target;
|
||||
|
|
7
spell.h
7
spell.h
|
@ -2,14 +2,17 @@
|
|||
#define __SPELLS_H
|
||||
#include "defs.h"
|
||||
|
||||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid);
|
||||
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target);
|
||||
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer);
|
||||
void fizzle(lifeform_t *caster);
|
||||
int getiqreq(enum OBTYPE oid);
|
||||
int getmpcost(enum OBTYPE oid);
|
||||
int getspellduration(int min,int max,int blessed);
|
||||
int getspelllevel(enum OBTYPE spellid);
|
||||
enum SPELLSCHOOL getspellschool(enum OBTYPE spellid);
|
||||
int getspellrange(enum OBTYPE spellid);
|
||||
void pullobto(object_t *o, lifeform_t *lf);
|
||||
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof);
|
||||
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid);
|
||||
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
|
||||
#endif
|
||||
|
||||
|
|
10
text.c
10
text.c
|
@ -110,7 +110,7 @@ char *gettimetextfuzzy(char *retbuf, int wantpm) {
|
|||
} else if (mins <= 35) {
|
||||
sprintf(retbuf, "around half past %d", hours);
|
||||
} else if (mins <= 45) {
|
||||
sprintf(retbuf, "comung up to %d o'clock", (hours == 12) ? 1 : (hours+1));
|
||||
sprintf(retbuf, "coming up to %d o'clock", (hours == 12) ? 1 : (hours+1));
|
||||
} else {
|
||||
sprintf(retbuf, "nearly %d o'clock", (hours == 12) ? 1 : (hours+1));
|
||||
}
|
||||
|
@ -189,6 +189,10 @@ char *makeplural(char *text) {
|
|||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "scroll ", "scrolls ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "splash ", "splashes ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "suit ", "suits ", &rv);
|
||||
if (rv) return newtext;
|
||||
newtext = strrep(newtext, "vial ", "vials ", &rv);
|
||||
if (rv) return newtext;
|
||||
|
||||
|
@ -200,6 +204,10 @@ char *makeplural(char *text) {
|
|||
// default
|
||||
lastlet = text[strlen(text)-1];
|
||||
switch (lastlet) {
|
||||
case 'y': // change to 'ies'
|
||||
text[strlen(text)-1] = '\0';
|
||||
asprintf(&newtext, "%sies",text);
|
||||
break;
|
||||
case 's':
|
||||
case 'o': // append "es"
|
||||
asprintf(&newtext, "%ses",text);
|
||||
|
|
Loading…
Reference in New Issue