- [+] implement getradiuscells()

- [+] evaporate spell - turn water into steam
- [+] monster generation bug? even on dlev10 i'm stil getting mostly
      kobolds
- [+] ai infinint eloop again - frost hawk trying to open door
- [+] another infinite loop - not falling through after spell failure.
* [+] reduce attack delay for most weapons.
- [+] letplayer see a tiny bit in the dark (1 cell ?)
- [+] beginner tracking not working - fixed.
- [+] only show "...but do no damage" if you have good knowledge about
      their race.
- [+] make gold lighter
* [+] footprints glyph shouldn't override pudles of water!
- [+] only show eviscerate etc if you have good knowledge?
- [+] don't start monsters on the stairs/magical barriers!!!
- [+] stone should be immune to more damage types
* [+] addexits adding way too many exits.
- [+] blessed identify should ID everything
- [+] blessed mending mends all
- [+] don't make noise when slowmoving.
- [+] eyebat dispersal big: The eyebat's strong scent leading north
      disappears!
- [+] go over footprint+scent+corpse and pickup:"You can't pick up
      footprints!"
* [+] doors can't do on top of each other!!!
* [+] low ground
- [+] make sure you can't have more than one "water" object in a cell.
* [+] make val2 of rarity be "common/uncommon/rare" etc
- [+] more monster types should appear in the forest.
- [+] when i go down stairs into a dark area, "it is pitch black!" is
      being cleared.
* [+] helm of the poltergeist
- [+] flying creatures get penalties in webs etc 
- [+] blind things shoudln't follow up/donw stairs
- [+] You shout a blood-curdling war cry!  The sawgrass turns to flee
      from you!
- [+] potions still worth too much.  minor healing was 420!!
- [+] AI should only go towards covetted object if it's closer or the
      same distanec as target.
- [+] branded objects should be worth LOTS - at the moment they're
      worth 1!!
* [+] maybe just adjust value of rarity?
- [+] don't roll spot checks while training!
* [+] replace f_nofeel with:
- [+] revenge did too much damage (50)
* [+] change how AR works
- [+] need to add: "really walk into a falling rock trap" ?
- [+] put only ONE staircase going up on dlev 0
- [+] why am i stopping sprinting after 1 move?
* [+] somehow make sure mosnters can't see footprints in a cell with
      mist
- [+] bones shouldn't be able to catch on fire.
- [+] when you levle up, gainskill BEFORE getting new spells
- [+] put out flaming objects after pickup
* [+] don't say "really target yourself?" when using a potion of sleep!!
- [+] enhance a random skill when levelling up? every 2 levels?
- [+] weaken koboldsa little - less change of javelin
- [+] don't drown instantly - take a few turns, depending on CON
* [+] create vault spell for debugging ???
- [+] doors in the middle of rooms.
- [+] highlight selected choice in askstr
- [+] flooded_room being created without walls!!!!!!
- [+] describe spell from levleup not working
* [+] GETROOMEDGE RETURNING NO CELLS for circularroom!!!!!
- [+] fire wizard not prompted to get firedart at l2..
Vaults
* [+] X corridor - 
- [+] crosshatch
- [+] should water be ~ instead ?? and change whatever is currently a
      tilde to something else...
Initial work on goal:
- [+] surround all stairs with barriers
- [+] start player NEAR stairs (randomadjcell from stairs, allowexpand)
+ methods of escape
- [+] knock scroll
- [+] digging (but it stops the dig from going any further)
This commit is contained in:
Rob Pearce 2011-06-09 08:58:35 +00:00
parent 3442dc293d
commit 27d22df11d
33 changed files with 1546 additions and 987 deletions

153
ai.c
View File

@ -556,10 +556,11 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
}
if (spellfailed) {
if (db) dblog(".oO { cast spell/ability tried but failed (2)! reason = %d }", reason);
// spell failed. we will keep going through aiturn.
} else {
// spell succesful
return B_FALSE;
}
return B_FALSE;
}
// see if we have a ranged attack. if so, adjust wantdist
@ -982,7 +983,7 @@ void aiturn(lifeform_t *lf) {
// instead of attacking our target.
if (!lfhasflag(lf, F_HIDING)) {
if (db) dblog(".oO { looking for covetted objects... }");
if (lookforobs(lf, B_COVETS)) {
if (lookforobs(lf)) {
if (db) dblog(".oO { found covetted object. returning. }");
return;
}
@ -991,34 +992,26 @@ void aiturn(lifeform_t *lf) {
///////////////////////////////////////////////
// attacks
///////////////////////////////////////////////
target = gettargetlf(lf);
// do we already have a target we are attacking?
f = hasflag(lf->flags, F_TARGETLF);
if (f) {
int targid;
int lastx,lasty;
if (db) dblog(".oO { i have a target... }");
targid = f->val[0];
lastx = f->val[1];
lasty = f->val[2];
target = findlf(lf->cell->map, targid);
if (target) {
if (db) dblog(".oO { my target is lfid %d (%s). }", targid, target->race->name);
// aquatic grabbers will try to drag their prey into the water
if (lfhasflagval(lf, F_GRABBING, target->id, NA, NA, NULL) && isaquatic(lf) ) {
if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) &&
!hasobwithflag(target->cell->obpile, F_DEEPWATER)) {
// move away!
if (!moveawayfrom(lf, target->cell, DT_ORTH)) {
return;
}
if (target) {
if (db) dblog(".oO { i have a target: lfid %d (%s). }", target->id, target->race->name);
// aquatic grabbers will try to drag their prey into the water
if (lfhasflagval(lf, F_GRABBING, target->id, NA, NA, NULL) && isaquatic(lf) ) {
if ( hasobwithflag(lf->cell->obpile, F_DEEPWATER) &&
!hasobwithflag(target->cell->obpile, F_DEEPWATER)) {
// move away!
if (!moveawayfrom(lf, target->cell, DT_ORTH)) {
return;
}
}
// try to move towards them.
if (!aimovetolf(lf, target, B_TRUE)) {
// success
return;
}
}
// try to move towards them.
if (!aimovetolf(lf, target, B_TRUE)) {
// success
return;
}
}
@ -1088,6 +1081,7 @@ void aiturn(lifeform_t *lf) {
///////////////////////////////////////////////
// look for any object which we want
/*
if (!isinbattle(lf)) {
if (db) dblog(".oO { looking for any ob which i want. }");
if (lookforobs(lf, B_ANY)) {
@ -1095,6 +1089,7 @@ void aiturn(lifeform_t *lf) {
return;
}
}
*/
@ -1547,6 +1542,16 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
}
lifeform_t *gettargetlf(lifeform_t *lf) {
flag_t *f;
lifeform_t *target = NULL;
f = hasflag(lf->flags, F_TARGETLF);
if (f) {
target = findlf(lf->cell->map, f->val[0]);
}
return target;
}
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op) {
object_t *o;
@ -1582,17 +1587,26 @@ object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op) {
// returns B_TRUE if we did something
int lookforobs(lifeform_t *lf, int covetsonly) {
int lookforobs(lifeform_t *lf) {
object_t *o;
enum OBTYPE oid[MAXPILEOBS];
int oidcovet[MAXPILEOBS];
int noids = 0;
enum FLAG wantflag[MAXPILEOBS];
int wantflagcovet[MAXPILEOBS];
int nwantflags = 0;
flag_t *f;
cell_t *c;
int n;
int i;
int db = B_FALSE;
lifeform_t *target;
int targdist = 999;
target = gettargetlf(lf);
if (target) {
targdist = getcelldist(lf->cell, target->cell);
}
if (wantdb && lfhasflag(lf, F_DEBUG)) {
db = B_TRUE;
@ -1604,31 +1618,45 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
noids = 0;
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_WANTS) {
if (!covetsonly || (f->val[1] == B_COVETS)) {
oid[noids] = f->val[0];
noids++;
}
oid[noids] = f->val[0];
oidcovet[noids] = (f->val[1] == B_COVETS) ? B_TRUE : B_FALSE;
noids++;
} else if (f->id == F_WANTSOBFLAG) {
if (!covetsonly || (f->val[1] == B_COVETS)) {
wantflag[nwantflags] = f->val[0];
nwantflags++;
}
wantflag[nwantflags] = f->val[0];
wantflagcovet[noids] = (f->val[1] == B_COVETS) ? B_TRUE : B_FALSE;
nwantflags++;
}
}
// current cell has an object we want?
o = hasobmulti(lf->cell->obpile, oid, noids);
if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) {
if (db) dblog(".oO { current cell has ob i want (%s) }",o->type->name);
// try to pick it up
if (!aipickup(lf, o)) return B_TRUE;
if (db) dblog(".oO { pickup of %s failed, trying to eat! }",o->type->name);
if (!eat(lf, o)) return B_TRUE;
if (db) dblog(".oO { eating %s failed }",o->type->name);
int getit = B_TRUE;
// if we are in battle only go for it if we covet it
if (target) {
int nn;
for (nn = 0; nn < noids; nn++) {
if (oid[nn] == o->id) break;
}
if (!oidcovet[nn]) getit = B_FALSE;
}
if (getit) {
if (db) dblog(".oO { current cell has ob i want (%s) }",o->type->name);
// try to pick it up
if (!aipickup(lf, o)) return B_TRUE;
if (db) dblog(".oO { pickup of %s failed, trying to eat! }",o->type->name);
if (!eat(lf, o)) return B_TRUE;
if (db) dblog(".oO { eating %s failed }",o->type->name);
}
}
// has an object with a flag we want?
for (n = 0; n < nwantflags; n++) {
o = hasobwithflag(lf->cell->obpile, wantflag[n]);
// if we are in battle only go for it if we covet it
if (target && !wantflagcovet[n]) continue;
if (o && !isdangerousob(o, lf, B_TRUE) && (canpickup(lf, o, 1) || caneat(lf,o)) ) {
if (db) dblog(".oO { current cell has ob with flag i want (%s) }",o->type->name);
// try to pick it up
@ -1643,7 +1671,8 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
if (lfhasflag(lf, F_HUMANOID) && hasbp(lf, BP_WEAPON)) {
f = hasflag(lf->flags, F_WANTSBETTERWEP);
if (f) {
if (!covetsonly || (f->val[1] == B_COVETS)) {
// if we are in battle only go for it if we covet it
if (!target || (f->val[1] == B_COVETS)) {
o = hasbetterweapon(lf, lf->cell->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name);
@ -1659,7 +1688,8 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
// current cell has better armour?
f = hasflag(lf->flags, F_WANTSBETTERARM);
if (f ) {
if (!covetsonly || (f->val[1] == B_COVETS)) {
// if we are in battle only go for it if we covet it
if (!target || (f->val[1] == B_COVETS)) {
o = hasbetterarmour(lf, lf->cell->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name);
@ -1679,14 +1709,36 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
c = lf->los[i];
if (!c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
int celldist;
celldist = getcelldist(lf->cell, c);
o = hasobmulti(c->obpile, oid, noids);
if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) {
if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
gothere = B_TRUE;
// if we are in battle only go for it if we covet it and
// it's closer than our target
if (target) {
int nn;
for (nn = 0; nn < noids; nn++) {
if (oid[nn] == o->id) break;
}
if (oidcovet[nn]) {
if (celldist <= targdist) {
if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
gothere = B_TRUE;
}
}
} else {
if (db) dblog(".oO { remote cell has ob i want (%s). setting f_targetcell. }",o->type->name);
gothere = B_TRUE;
}
}
if (!gothere) {
// has an object with a flag we want?
for (n = 0; n < nwantflags; n++) {
// if we are in battle only go for it if we covet it
if (target && !wantflagcovet[n]) continue;
o = hasobwithflag(c->obpile, wantflag[n]);
if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o)) {
if (db) dblog(".oO { remote cell has ob with flag i want (%s) }", o->type->name);
@ -1699,7 +1751,9 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
// remote cell has better weapon?
f = hasflag(lf->flags, F_WANTSBETTERWEP);
if (f) {
if (!covetsonly || (f->val[1] == B_COVETS)) {
// if we are in battle only go for it if we covet it
if (!target ||
((f->val[1] != B_COVETS) && (celldist <= targdist)) ) {
o = hasbetterweapon(lf, c->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name);
@ -1714,8 +1768,9 @@ int lookforobs(lifeform_t *lf, int covetsonly) {
// remote cell has better armour?
f = hasflag(lf->flags, F_WANTSBETTERARM);
if (f) {
if (!covetsonly || (f->val[1] == B_COVETS)) {
if (!target ||
((f->val[1] != B_COVETS) && (celldist <= targdist)) ) {
o = hasbetterarmour(lf, c->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) {
if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name);

3
ai.h
View File

@ -16,7 +16,8 @@ int aipickupok(lifeform_t *lf, object_t *o);
int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target);
int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG purpose);
void aiturn(lifeform_t *lf);
lifeform_t *gettargetlf(lifeform_t *lf);
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op);
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op);
int lookforobs(lifeform_t *lf, int covetsonly);
int lookforobs(lifeform_t *lf);
int useitemwithflag(lifeform_t *lf, enum FLAG whichflag);

View File

@ -573,6 +573,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
char extradambuf[BUFLEN];
char withwep[BUFLEN];
char *verb;
int needfree = B_FALSE;
strcpy(extradambuf, "");
@ -582,20 +583,28 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
strcpy(withwep, "");
}
strcpy(extradambuf, "");
if (dam[i] == 0) {
strcpy(extradambuf, " but do no damage");
if (getlorelevel(lf, victim->race->raceclass->id) >= PR_ADEPT) {
strcpy(extradambuf, " but do no damage");
}
} else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
sprintf(extradambuf, " [%d dmg]",dam[i]);
} else {
strcpy(extradambuf, "");
}
if (backstab && (i == 0)) {
verb = strdup("backstab");
needfree = B_TRUE;
} else if (fatal) {
verb = getkillverb(victim, wep, damtype[i], dam[i], victim->maxhp);
} else {
verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp);
if ((getlorelevel(lf, victim->race->raceclass->id) >= PR_BEGINNER) ||
!ismeleedam(damtype[i])) {
verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp);
} else {
verb = strdup("hit");
needfree = B_TRUE;
}
}
warn("You %s %s%s%s%s",
verb,
@ -610,7 +619,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// don't also say "the xx dies"
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
}
if (!strcmp(verb, "backstab")) {
if (needfree) {
free(verb);
}
} else {
@ -1001,13 +1010,20 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) {
int reduceamt = 0;
int ar;
int pctrange;
object_t *o;
ar = getarmourrating(lf);
//reducepct = getdamreducepct(ar);
//reduceamt = (int) ceil((reducepct / 100.0) * (float)dam);
reduceamt = ar/2;
//reduceamt = ar/2;
// between 25% and 75% of AR.
// ie. with AR of 20, all damage is reduced by 5-15.
pctrange = rnd(25,75);
reduceamt = pctof(pctrange, ar);
// special case
if (damtype == DT_PROJECTILE) {
@ -1573,6 +1589,24 @@ obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) {
}
*/
// ie. caused by hitting something with a melee weapon
int ismeleedam(enum DAMTYPE damtype) {
switch (damtype) {
case DT_PIERCE:
case DT_SLASH:
case DT_BASH:
case DT_BITE:
case DT_CHOP:
case DT_PROJECTILE:
case DT_UNARMED:
case DT_CRUSH:
return B_TRUE;
default:
break;
}
return B_FALSE;
}
int isphysicaldam(enum DAMTYPE damtype) {
switch (damtype) {
case DT_BASH:
@ -1748,7 +1782,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
if (dampct >= 50) {
getdamrange(damflag, NULL, &maxdam);
extradam = (int)(dampct * (float)maxdam);
extradam = (int)((dampct/100) * (float)maxdam);
if (extradam > 0) {
char buf[BUFLEN];
char buf2[BUFLEN];

View File

@ -20,6 +20,7 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag);
//int getunarmeddamroll(flag_t *f);
float getstrdammod(lifeform_t *lf);
//obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
int ismeleedam(enum DAMTYPE damtype);
int isphysicaldam(enum DAMTYPE damtype);
int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical);
void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam);

41
defs.h
View File

@ -421,6 +421,7 @@ enum CELLTYPE {
CT_DIRT,
CT_GRASS,
CT_LOOPCORRIDOR,
CT_LOWFLOOR,
// rooms
CT_ROOM,
};
@ -780,7 +781,6 @@ enum OBTYPE {
OT_VENDINGMACHINE,
OT_PORTAL,
// terrain
OT_WATERSHALLOW,
OT_WATERDEEP,
// traps
OT_TRAPARROW,
@ -978,6 +978,7 @@ enum OBTYPE {
OT_S_CUREPOISON,
OT_S_DETECTPOISON,
OT_S_DIG,
OT_S_EVAPORATE,
OT_S_WEB,
OT_S_ENDUREELEMENTS,
OT_S_ENTANGLE,
@ -1015,8 +1016,9 @@ enum OBTYPE {
OT_S_ENERGYBLAST,
OT_S_FLASH,
// -- divine powers
OT_S_WISH,
OT_S_CREATEVAULT,
OT_S_GIFT,
OT_S_WISH,
OT_A_DEBUG,
OT_A_ENHANCE,
OT_A_LEARN,
@ -1308,12 +1310,33 @@ enum BODYPART {
#define MAXBODYPARTS (12)
// depth on a human
#define DP_MAX DP_OVERHEAD4
#define DP_FIRST DP_TOE
enum DEPTH {
/*
DP_HEAD = 4,
DP_SHOULDERS = 3,
DP_WAIST = 2,
DP_FEET = 1,
DP_NONE = 0,
*/
DP_OVERHEAD4 = 15,
DP_OVERHEAD3 = 14,
DP_OVERHEAD2 = 13,
DP_OVERHEAD = 12,
DP_HEAD = 11,
DP_SHOULDERS = 10,
DP_CHEST = 9,
DP_BELLY = 8,
DP_WAIST = 7,
DP_THIGH = 6,
DP_KNEE = 5,
DP_CALF = 4,
DP_FEET = 3,
DP_ANKLE = 2,
DP_TOE = 1,
DP_NONE = 0,
};
// empty types
@ -1369,8 +1392,11 @@ enum FLAG {
// map flags
F_MAPCOORDS, // v0+v1 are x/y coords for this map area
F_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2
F_NEWWATERDEPTH, // temp flag for the spread of f_deepwater obs.
// v0+1 are x/y, v2 is new depth.
// object flags
F_DEAD, // object will be removed
F_ONEPERCELL, // only one of these objects can exist per cell
F_CREATEDBY, // object was made by lf id v0, text=real lfname
F_ENCHANTABLE, // object can get +1/-1 ect
F_STACKABLE, // can stack multiple objects togethr
@ -1389,6 +1415,7 @@ enum FLAG {
// (optional) text = lfid of lf who left this.
// should only be used for SCENT, not footprints.
F_NOFEEL, // when blind, don't show "you can feel xxx"
F_FEELTEXT, // when blind, show "you can feel"+f->text
// for items in shops
F_SHOPITEM, // causes shops to show this item as identified
F_VALUE, // how much an item is worth (over its base weight+material)
@ -1514,6 +1541,7 @@ enum FLAG {
F_REDUCEMOVEMENT, // time to move off here is multiplied by v0.
F_RESTRICTMOVEMENT, // must pass a diff=v0 STR check to move off it.
// if v1 is B_TRUE, then it takes 1 damage if you fail.
// if v2 is TRUE, it affects flying creatures
//
// for multiple objects, each one adds half its difficulty
@ -1770,7 +1798,10 @@ enum FLAG {
F_MOVESPEED, // override default move speed
F_ACTIONSPEED, // override default action speed
F_SPELLSPEED, // override default spellcast speed (ie. movespeed)
F_RARITY, // val[0] = habitat, val[1] = rarity
F_RARITY, // val[0] = habitat, val[1] = rarity%
// opt. val[2] = commonality (enum RARITY RR_xxx)
// NA means rr_common
F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max
F_MINIONS, // val0 % chance of appearing with v1-v2 lf of type text
F_HITDICE, // val0: # d4 to roll for maxhp per level. val1: +xx
@ -1967,6 +1998,8 @@ enum FLAG {
// vault flags
F_AUTODOORS, // automatically create at least one door
// v0 is pct chance of door (as opposed to empty
// doorway with no door).
F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms
F_VAULTATOB, // v0/1=x/y, v1=pctchance, text=obname
F_VAULTATLF, // v0/1=x/y, v1=pctchance, text=lfname
@ -2201,6 +2234,7 @@ typedef struct map_s {
int id;
int region;
int depth;
int nrooms; // how many rooms on this map
char *name; // name of this map
enum HABITAT habitat; // eg. dungeon, forest, etc
unsigned int seed;
@ -2296,6 +2330,7 @@ typedef struct celltype_s {
char *name; // name of cell type
int solid; // can you walk through it?
int transparent; // can you see through it?
int floorheight; // 0 is default. <0 is low.
struct material_s *material;
struct flagpile_s *flags;

4
flag.c
View File

@ -205,12 +205,12 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
if ((gamemode == GM_GAMESTARTED) && (redrawscreenatend || redrawstatatend || redolight)) {
if (redolight) {
dblog("CALCINGLIGHT from flag\n");
//dblog("CALCINGLIGHT from flag\n");
redrawscreenatend = B_TRUE;
calclight(redolight);
precalclos(player);
}
dblog("DRAWINGSCREEN from flag\n");
//dblog("DRAWINGSCREEN from flag\n");
if (redrawscreenatend) needredraw = B_TRUE;
if (redrawstatatend) statdirty = B_TRUE;

83
io.c
View File

@ -52,6 +52,7 @@ extern enum OBCLASS sortorder[];
extern knowledge_t *knowledge;
extern objecttype_t *objecttype;
extern command_t *firstcommand;
extern vault_t *firstvault;
extern skill_t *firstskill;
extern enum GAMEMODE gamemode;
@ -2624,6 +2625,24 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
return B_FALSE;
}
vault_t *askvault(char *prompttext) {
vault_t *v;
// make list of all vaults
initprompt(&prompt, prompttext);
for (v = firstvault ; v ; v = v->next) {
addchoice(&prompt, 'a', v->id, NULL, v);
}
if (prompt.nchoices == 0) {
msg("Error - no vaults found.");
return NULL;
}
getchoicestr(&prompt, B_FALSE, B_TRUE);
v = (vault_t *)prompt.result;
return v;
}
void centre(WINDOW *win, int y, char *format, ... ) {
int w;
char buf[BUFLEN];
@ -3394,9 +3413,7 @@ void describeob(object_t *o) {
// wait for key
getch();
real_clearmsg(B_TRUE);
needredraw = B_TRUE;
drawscreen();
restoregamewindows();
}
void describespell(objecttype_t *ot) {
@ -3449,8 +3466,7 @@ void describespell(objecttype_t *ot) {
// wait for key
getch();
real_clearmsg(B_TRUE);
needredraw = B_TRUE;
drawscreen();
restoregamewindows();
}
void doattackcell(char dirch) {
@ -4070,7 +4086,7 @@ void dolook(cell_t *where, int onpurpose) {
if (f) {
// doens't matter if you're blind
getobname(o, buf, o->amt);
msg("There is %s here%c", buf, f->text[0]);
msg("There %s %s here%c", (o->amt == 1) ? "is" : "are", buf, f->text[0]);
interrupt(player);
seensomething = B_TRUE;
} else {
@ -4091,7 +4107,16 @@ void dolook(cell_t *where, int onpurpose) {
if (numobs > 0) {
if (numobs == 1) {
if (!hasflag(firstob->flags, F_THEREISHERE)) {
getobname(firstob, buf, firstob->amt);
if (streq(seeverb, "feel")) {
f = hasflag(firstob->flags, F_FEELTEXT);
if (f) {
strcpy(buf, f->text);
} else {
getobname(firstob, buf, firstob->amt);
}
} else {
getobname(firstob, buf, firstob->amt);
}
msg("You %s %s here.", seeverb, buf);
}
} else if ((numobs > 1) && (numobs <= 3)) {
@ -4124,7 +4149,8 @@ void dolook(cell_t *where, int onpurpose) {
// if wantunknown is set, lsit spells we DONT know.
// otherwise list spells we DO know.
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid) {
// only include spells which cost <= mpcutoff
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid, int mpcutoff) {
char ch;
flag_t *f;
char buf[BUFLEN];
@ -4150,12 +4176,6 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
if ((i == SS_DIVINE) && !hasjob(lf, J_GOD)) {
continue;
}
// we can't cast spells from this school?
if (getschoolskill(i) != SK_NONE) {
if (!getskill(lf, getschoolskill(i))) {
continue;
}
}
for (lev = 0; lev <= MAXSPELLLEV; lev++) {
// get list of spells/abilities we can cast at will
for (ot = objecttype ; ot ; ot = ot->next) {
@ -4188,6 +4208,13 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
} // end if spell/ability
} // end foreach objecttype
// if we can't cast spells from this school, then just go to next spell.
if (getschoolskill(i) != SK_NONE) {
if (!getskill(lf, getschoolskill(i))) {
continue;
}
}
if (!lfhasflag(lf, F_NOSPELLS)) {
// get list of spells we can cast using mp
for (ot = objecttype ; ot ; ot = ot->next) {
@ -4222,7 +4249,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
} else {
getspellcosttext(lf, ot->id, power, mpdesc[nposs]);
}
if (lf->mp >= mpcost[nposs]) {
if (mpcost[nposs] <= mpcutoff) {
validspell[nposs] = B_TRUE;
} else {
validspell[nposs] = B_FALSE;
@ -4298,7 +4325,7 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) {
// init the prompt if required.
if (spellid == OT_NONE) {
makespellchoicelist(&prompt, player, "Use which spell/ability:","Describe which spell/ability:", SS_NONE, B_FALSE, B_TRUE);
makespellchoicelist(&prompt, player, "Use which spell/ability:","Describe which spell/ability:", SS_NONE, B_FALSE, B_TRUE, player->mp);
}
finished = B_FALSE;
@ -4366,7 +4393,7 @@ void domemmagic(void) {
char ch;
int slot;
objecttype_t *ot;
makespellchoicelist(&prompt, player, "Memorise which spell/ability:","Describe which spell/ability",SS_NONE, B_FALSE, B_TRUE);
makespellchoicelist(&prompt, player, "Memorise which spell/ability:","Describe which spell/ability",SS_NONE, B_FALSE, B_TRUE, player->maxmp);
if (prompt.nchoices <= 0) {
msg("You don't have any spells or abilities!");
return;
@ -4449,8 +4476,8 @@ int dopickup(obpile_t *op) {
if (o->amt == 1) {
// just get it
howmany = ALL;
retobs[0] = op->first;
retobscount[0] = op->first->amt;
retobs[0] = o;
retobscount[0] = o->amt;
nretobs = 1;
needtoask = B_FALSE;
}
@ -4507,6 +4534,7 @@ void doenter(lifeform_t *lf) {
enterob = hasob(lf->cell->obpile, OT_VENDINGMACHINE);
if (enterob) {
dovendingmachine(lf, enterob);
restoregamewindows();
return;
}
enterob = hasob(lf->cell->obpile, OT_PORTAL);
@ -4518,7 +4546,6 @@ void doenter(lifeform_t *lf) {
// try to go down
dostairs(D_DOWN);
}
restoregamewindows();
}
void doexplain(char *question) {
@ -5465,6 +5492,7 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
curs_set(1);
sel = -1;
while (sel == -1) {
int foundfirstvalid = B_FALSE;
int atbottom;
// show choices which match our input string
if (showall) {
@ -5474,6 +5502,7 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
nextpage = -1;
nvalid = 0;
foundfirstvalid = B_FALSE;
atbottom = B_FALSE;
for (i = 0; i < prompt->nchoices; i++) {
if (showall) {
@ -5503,6 +5532,8 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
matched = strpixmatch(prompt->choice[i].text, inpstring);
if (matched) {
prompt->choice[i].valid = B_TRUE;
nvalid++;
if (showall) {
// if we haven't printed the heading yet...
if (gotheadings && !doneheading) {
@ -5516,12 +5547,14 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
}
// only print if we're not off the bottom
if ((i >= first) && !atbottom) {
if (nvalid && !foundfirstvalid) setcol(mainwin, C_BOLDGREEN);
mvwprintw(mainwin, y, 0, "%s%s", gotheadings ? " " : "", prompt->choice[i].desc);
y++;
if (nvalid && !foundfirstvalid) unsetcol(mainwin, C_BOLDGREEN);
foundfirstvalid = B_TRUE;
}
}
prompt->choice[i].valid = B_TRUE;
nvalid++;
} else {
prompt->choice[i].valid = B_FALSE;
}
@ -5628,15 +5661,15 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
inpstring[strlen(inpstring)-1] = '\0';
}
} else if (ch == 10) { // enter
// exactly one valid choice?
if (nvalid == 1) {
// valid choices?
if (nvalid) {
for (i = 0; i < prompt->nchoices; i++) {
if (prompt->choice[i].valid) {
sel = i;
break;
}
}
} else if (nvalid == 0) {
} else if (nvalid == 0) { // no choices?
// cancel
sel = -1;
break;

4
io.h
View File

@ -23,6 +23,7 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts);
char askchar(char *prompt, char *validchars, char *def, int showchars);
cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange, enum LOFTYPE loftype, int wanttrail);
char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def);
vault_t *askvault(char *prompttext);
void centre(WINDOW *win, int y, char *format, ... );
int chartodir(char ch);
char checkforkey(void);
@ -33,6 +34,7 @@ void clearretobs(void);
void cls(void);
int contains(enum OBCLASS *array, int nargs, enum OBCLASS want);
void describeob(object_t *o);
void describespell(objecttype_t *ot);
void doattackcell(char dirch);
void doclose(void);
void docomms(void);
@ -86,7 +88,7 @@ void initgfx(void);
void initprompt(prompt_t *p, char *q1);
int keycodetokey(int keycode);
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints);
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid);
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid, int mpcutoff);
void more(void);
void warn(char *format, ... );
void msg(char *format, ... );

344
lf.c
View File

@ -656,6 +656,19 @@ int canlearn(lifeform_t *lf, enum SKILL skid) {
return B_FALSE;
}
int canopendoors(lifeform_t *lf) {
if (lf) {
if (!lfhasflag(lf, F_HUMANOID)) {
return B_FALSE;
}
if (lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
return B_FALSE;
}
}
return B_TRUE;
}
int canpickup(lifeform_t *lf, object_t *o, int amt) {
reason = E_OK;
@ -1132,7 +1145,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
// cast the spell
addflag(lf->flags, F_CASTINGSPELL, sid, NA, NA, NULL);
rv = dospelleffects(lf, sid, power, targlf, targob, targcell, B_UNCURSED, NULL);
rv = dospelleffects(lf, sid, power, targlf, targob, targcell, B_UNCURSED, NULL, B_FALSE);
f = lfhasflag(lf, F_CASTINGSPELL);
if (f) {
killflag(f);
@ -1183,19 +1196,37 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
// will you drown?
if (depth >= DP_HEAD) {
if (!slev && !lfhasflag(lf, F_BREATHWATER)) {
// you drown.
if (isplayer(lf)) {
msg("You drown.");
didsomething = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s drowns.",lfname);
didsomething = B_TRUE;
int damamt;
// take drowning damage. generally you'll die
// in around 3-4 turns.
damamt = lf->maxhp / (getattr(lf, A_CON) / 3);
if (damamt >= lf->hp) {
if (isplayer(lf)) {
msg("You drown.");
didsomething = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s drowns.",lfname);
didsomething = B_TRUE;
}
addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
lf->hp = 0;
setlastdam(lf, "drowning");
} else {
if (isplayer(lf)) {
msg("You are drowning!");
didsomething = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s is drowning!",lfname);
didsomething = B_TRUE;
}
losehp(lf, damamt, DT_DIRECT, NULL, "drowning");
}
addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
lf->hp = 0;
setlastdam(lf, "drowning");
}
}
@ -1598,9 +1629,6 @@ void die(lifeform_t *lf) {
strcpy(corpseprefix, "");
switch (lf->lastdamtype) {
case DT_FIRE:
strcat(corpseprefix, "flaming ");
break;
case DT_COLD:
strcat(corpseprefix, "frozen ");
break;
@ -1798,8 +1826,8 @@ void dumplev(void) {
// NOTE: this code copied from getrandomrace(), which is used by addmonster().
for (i = 1; i <= 25; i++) {
int min,max,prevmin,prevmax;
getrarity(i-1, &prevmin, &prevmax, RARITYVARIANCELF, B_FALSE);
getrarity(i, &min, &max, RARITYVARIANCELF, B_FALSE);
getrarityrange(i-1, &prevmin, &prevmax, RARITYVARIANCELF, B_FALSE);
getrarityrange(i, &min, &max, RARITYVARIANCELF, B_FALSE);
fprintf(logfile, "Dlev %d (rar >= %d): ",i,min);
for (r = firstrace ; r; r = r->next) {
int rarity = 0;
@ -1835,8 +1863,8 @@ void dumplev(void) {
// NOTE: this code copied from getrandomrace(), which is used by addmonster().
for (i = 1; i <= 25; i++) {
int min,max,prevmin,prevmax;
getrarity(i-1, &prevmin, &prevmax, RARITYVARIANCEOB, B_FALSE);
getrarity(i, &min, &max, RARITYVARIANCEOB, B_FALSE);
getrarityrange(i-1, &prevmin, &prevmax, RARITYVARIANCEOB, B_FALSE);
getrarityrange(i, &min, &max, RARITYVARIANCEOB, B_FALSE);
fprintf(logfile, "Dlev %d (rar >= %d): ",i,min);
for (ot = objecttype ; ot; ot = ot->next) {
int rarity = 0;
@ -2148,6 +2176,22 @@ int eat(lifeform_t *lf, object_t *o) {
return B_FALSE;
}
void enhancerandomskill(lifeform_t *lf) {
flag_t *f;
enum SKILL poss[MAXSKILLS];
int nposs = 0;
int sel;
for (f = lf->flags->first ; f ; f = f->next) {
if ((f->id == F_HASSKILL) && (f->val[1] != PR_MASTER)) {
poss[nposs] = f->val[0];
nposs++;
}
}
sel = rnd(0,nposs-1);
giveskill(lf, poss[sel]);
}
void enhanceskills(lifeform_t *lf) {
enum SKILL whichsk;
flag_t *f;
@ -2178,49 +2222,6 @@ void enhanceskills(lifeform_t *lf) {
more();
}
// give job-based level rewards
f = levelabilityready(lf);
while (f) {
if (f->id == F_LEVABIL) {
addflag(lf->flags, F_CANWILL, f->val[1], f->val[2], f->val[2], f->text);
} else if (f->id == F_LEVFLAG) {
addflag(lf->flags, f->val[1], f->val[2], NA, NA, f->text);
} else if (f->id == F_LEVSKILL) {
giveskill(lf, f->val[1]);
} else if (f->id == F_LEVSPELL) {
addflag(lf->flags, F_CANCAST, f->val[1], NA, NA, NULL);
} else if (f->id == F_LEVSPELLSCHOOL) { // select a spell from school
if (isplayer(lf)) {
makespellchoicelist(&prompt, player, "Learn which new spell:","Describe which spell:", f->val[1], B_TRUE, B_FALSE);
if (prompt.nchoices > 0) {
objecttype_t *ot;
getchoicestr(&prompt, B_TRUE, B_TRUE);
ot = prompt.result;
if (ot) {
addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL);
}
} else {
msg("There are no new spells for you to learn at this time.");
}
} else {
makespellchoicelist(&prompt, player, "xx","xx:", f->val[1], B_FALSE, B_FALSE);
if (prompt.nchoices > 0) {
objecttype_t *ot;
// pick one randomly
ot = (objecttype_t *)prompt.choice[rnd(0,prompt.nchoices)].data;
if (ot) {
addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL);
}
}
}
}
f->lifetime = LEVABILITYDONE; // mark as done.
// get next one
f = levelabilityready(lf);
}
// now refresh them all for next level.
refreshlevelabilities(lf);
// increase str/int etc if we can
f = lfhasflag(lf, F_STATGAINREADY);
@ -2254,6 +2255,11 @@ void enhanceskills(lifeform_t *lf) {
f = lfhasflag(lf, F_STATGAINREADY);
}
// enhance a random skill every 2 levels (ie. 3/5/7/etc)
if (((lf->level + 1) % 2) == 0) {
enhancerandomskill(lf);
}
// now ask about learning/enhancing skills
if (isplayer(lf)) {
char eorl = 'e';
@ -2364,21 +2370,64 @@ void enhanceskills(lifeform_t *lf) {
statdirty = B_TRUE;
} else {
// monsters will just enhance a random skill, they never learn new ones.
enum SKILL poss[MAXSKILLS];
int nposs = 0;
int sel;
for (f = lf->flags->first ; f ; f = f->next) {
if ((f->id == F_HASSKILL) && (f->val[1] != PR_MASTER)) {
poss[nposs] = f->val[0];
nposs++;
}
}
sel = rnd(0,nposs-1);
giveskill(lf, poss[sel]);
enhancerandomskill(lf);
lf->skillpoints--;
} // end if isplayer
// give job-based level rewards
f = levelabilityready(lf);
while (f) {
if (f->id == F_LEVABIL) {
addflag(lf->flags, F_CANWILL, f->val[1], f->val[2], f->val[2], f->text);
} else if (f->id == F_LEVFLAG) {
addflag(lf->flags, f->val[1], f->val[2], NA, NA, f->text);
} else if (f->id == F_LEVSKILL) {
giveskill(lf, f->val[1]);
} else if (f->id == F_LEVSPELL) {
addflag(lf->flags, F_CANCAST, f->val[1], NA, NA, NULL);
} else if (f->id == F_LEVSPELLSCHOOL) { // select a spell from school
if (isplayer(lf)) {
int done = B_FALSE;
while (!done) {
makespellchoicelist(&prompt, player, "Learn which new spell:","Describe which spell:", f->val[1], B_TRUE, B_FALSE, player->maxmp);
if (prompt.nchoices > 0) {
objecttype_t *ot;
getchoicestr(&prompt, B_TRUE, B_TRUE);
ot = prompt.result;
if (ot) {
if (prompt.whichq == 0) { // learn the spell
addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL);
done = B_TRUE;
} else {
describespell(ot);
}
}
} else {
msg("There are no new spells for you to learn at this time.");
done = B_TRUE;
}
}
} else {
// monster gets random spell
makespellchoicelist(&prompt, lf, "xx","xx:", f->val[1], B_TRUE, B_FALSE, lf->maxmp);
if (prompt.nchoices > 0) {
objecttype_t *ot;
// pick one randomly
ot = (objecttype_t *)prompt.choice[rnd(0,prompt.nchoices)].data;
if (ot) {
addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL);
}
}
}
}
f->lifetime = LEVABILITYDONE; // mark as done.
// get next one
f = levelabilityready(lf);
}
// now refresh them all for next level.
refreshlevelabilities(lf);
killflagsofid(lf->flags, F_HASNEWLEVEL);
// ready for another level?
@ -2949,6 +2998,7 @@ int getactspeed(lifeform_t *lf) {
return speed;
}
// only include allies which will follow you up/down stairs etc
void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies) {
int d;
for (d = DC_N; d <= DC_NW; d++) {
@ -2956,7 +3006,7 @@ void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies) {
c = getcellindir(lf->cell, d);
if (c && c->lf) {
if (areallies(lf, c->lf) || areenemies(lf, c->lf)) {
if (!isimmobile(c->lf)) {
if (!isimmobile(c->lf) && cansee(c->lf, lf)) {
adjally[*nadjallies] = c->lf;
(*nadjallies)++;
}
@ -3105,7 +3155,9 @@ int getattackspeed(lifeform_t *lf) {
w = getweapon(lf);
if (w) {
speed *= ((float)getobattackdelay(w) / 100.0);
int del;
del = getobattackdelay(w);
speed = pctof(del, speed);
}
return (int)speed;
@ -3852,7 +3904,7 @@ int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions) {
}
int getnightvisrange(lifeform_t *lf) {
int range = -1; // default
int range = 1; // default
flag_t *f;
f = lfhasflag(lf, F_SEEINDARK);
@ -4172,6 +4224,7 @@ int getvisrange(lifeform_t *lf) {
int getmovespeed(lifeform_t *lf) {
int speed = 0;
flag_t *f;
object_t *o;
f = lfhasflag(lf, F_MOVESPEED);
if (f) {
@ -4216,6 +4269,14 @@ int getmovespeed(lifeform_t *lf) {
if (speed < 1) speed = 1;
// reducemovement flags?
o = hasobwithflag(lf->cell->obpile, F_REDUCEMOVEMENT);
if (o) {
f = hasflag(o->flags, F_REDUCEMOVEMENT);
speed += (f->val[0] * SPEEDUNIT);
}
// water
adjustspeedforwater(lf, &speed);
@ -4625,6 +4686,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
int db = B_FALSE;
int depth;
int raritymin,raritymax;
enum RARITY wantrr = RR_COMMON;
// determine rarity of lf to generate
if (forcedepth != NA) {
@ -4633,9 +4695,15 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
depth = getmapdifficulty(c ? c->map : NULL);
}
getrarity(depth, &raritymin, &raritymax, RARITYVARIANCELF, B_TRUE);
getrarityrange(depth, &raritymin, &raritymax, RARITYVARIANCELF, B_TRUE);
if (db) dblog("finding random lf with rarity val %d-%d\n",raritymin,raritymax);
// pick rr...
wantrr = RR_COMMON;
while ((wantrr < RR_VERYRARE) && onein(3)) {
wantrr++;
}
if (db) dblog("finding random lf with rarity val %d-%d and rr <= %d\n",raritymin,raritymax, wantrr);
// try to find a lf of this type which will
@ -4658,7 +4726,9 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
if (rarflag) {
if ((rarflag->val[1] >= raritymin) && (rarflag->val[1] <= raritymax)) {
valid = B_TRUE;
if ((rarflag->val[2] == NA) || (rarflag->val[2] <= wantrr)) {
valid = B_TRUE;
}
}
}
@ -5337,6 +5407,7 @@ int giveskill(lifeform_t *lf, enum SKILL id) {
}
if (isplayer(lf) && (gamemode == GM_GAMESTARTED)) {
msg("You have learned the %s %s skill!", getskilllevelname(f->val[1]), getskillname(sk->id));
more();
}
statdirty = B_TRUE; // in case skill changes your stats
} else {
@ -5381,11 +5452,12 @@ int giveskill(lifeform_t *lf, enum SKILL id) {
if (f->val[1] == PR_NOVICE) {
msg("You now make basic maps of your surroundings.");
} else if (f->val[1] == PR_BEGINNER) {
msg("Your map will now show the location of staircases.");
msg("Your map now shows the location of staircases.");
} else if (f->val[1] == PR_ADEPT) {
msg("Your map will now show the location of doors.");
msg("Your map now shows the location of doors.");
} else if (f->val[1] == PR_SKILLED) {
msg("You will no longer forget your surroundings.");
//msg("You will no longer forget your surroundings.");
addflag(lf->flags, F_PHOTOMEM, B_TRUE, NA, NA, NULL);
} else if (f->val[1] == PR_EXPERT) {
msg("Your map will now show the location of objects.");
}
@ -6074,6 +6146,11 @@ int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest) {
cell_t *retcell[MAXRETCELLS];
reason = E_OK;
if (loftype == LOF_DONTNEED) {
return B_TRUE;
}
if (newdest) *newdest = src;
//if (!viewer) return B_FALSE;
@ -6409,7 +6486,8 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL);
@ -6453,6 +6531,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TECHUSAGE, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_SKILLED, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL);
@ -6470,7 +6549,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTATT, A_DEX, DX_AVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_ENLIGHTENED, NA, NULL);
// skills
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_SKILLED, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, PR_NOVICE, NA, NULL);
@ -6521,6 +6600,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL);
@ -6556,6 +6636,8 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_LONGBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
@ -6579,6 +6661,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_LOCKPICKING, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SPOTHIDDEN, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL);
@ -6622,6 +6705,8 @@ void initjobs(void) {
// can detect magic objects
addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DEMONS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SPELLCASTING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL);
@ -6682,6 +6767,7 @@ void initrace(void) {
// races / monsters
addrace(R_HUMAN, "human", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 75, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 2, 2, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
@ -6887,6 +6973,7 @@ void initrace(void) {
addrace(R_GIANTHILL, "hill giant", 160, 'H', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 55, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 19, NA, NA, NULL);
@ -7020,6 +7107,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NUMAPPEAR, 2, 3, NA, "");
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 72, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 72, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 8, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL);
@ -7043,6 +7131,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 68, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 68, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL);
@ -7071,6 +7160,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 65, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL);
@ -7094,6 +7184,7 @@ void initrace(void) {
addrace(R_GOBLIN, "goblin", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 87, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 87, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 1, 3, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
@ -7121,6 +7212,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 75, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 3, 5, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
@ -7147,6 +7239,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 70, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 3, 7, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
@ -7176,6 +7269,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 63, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 63, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 5, 6, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
@ -7202,6 +7296,7 @@ void initrace(void) {
addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 73, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 73, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 1, 2, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL);
@ -7231,6 +7326,7 @@ void initrace(void) {
lastrace->baseid = R_HOBGOBLIN;
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 60, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 1, 2, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 2, 3, NA, NULL);
@ -7275,10 +7371,10 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_DEX, DX_NIMBLE, NA, NULL);
addflag(lastrace->flags, F_STARTOBDT, 20, DT_PIERCE, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 25, OC_POTION, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-3 darts");
addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "javelin");
addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "buckler");
addflag(lastrace->flags, F_STARTOB, 10, NA, NA, "javelin");
addflag(lastrace->flags, F_STARTOB, 15, NA, NA, "buckler");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-10 gold coins");
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "shouts^a shout");
@ -7314,6 +7410,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 72, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 72, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, ST_MIGHTY, NA, NULL);
@ -8280,7 +8377,7 @@ void initrace(void) {
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 90, NA, "");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 80, NA, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, 80, NA, "");
addflag(lastrace->flags, F_HITDICE, 2, 1, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d4");
@ -9576,31 +9673,28 @@ void adjustspeedforwater(lifeform_t *lf, int *speed) {
flag_t *f;
if (!isairborne(lf)) {
for (o = lf->cell->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_REDUCEMOVEMENT);
f = hasflag(o->flags, F_DEEPWATER);
if (f) {
if (hasflag(o->flags, F_DEEPWATER)) {
int modamt = 0;
// water
if (isaquatic(lf)) {
modamt = 0;
} else {
switch (getskill(lf, SK_SWIMMING)) {
default:
case PR_NOVICE:
case PR_INEPT: modamt = f->val[0]; break; // normal penalty
case PR_BEGINNER: modamt = f->val[0] - 2; break;
case PR_ADEPT: modamt = 0; break;
case PR_SKILLED: modamt = -1; break;
case PR_EXPERT: modamt = -2; break;
case PR_MASTER: modamt = -2; break;
}
}
limit(&modamt, 0, 5);
*speed += (modamt * SPEEDUNIT);
int modamt;
modamt = (f->val[0] / 5); // ie. 0 - 4
if (modamt > 4) modamt = 4;
// water
if (isaquatic(lf)) {
modamt = 0;
} else {
// something else
*speed += (f->val[0] * SPEEDUNIT);
switch (getskill(lf, SK_SWIMMING)) {
default:
case PR_NOVICE:
case PR_INEPT: break; // normal penalty
case PR_BEGINNER: modamt -= 2; if (modamt < 0) modamt = 0; break; // bit less
case PR_ADEPT: modamt = 0; break; // nothing
case PR_SKILLED: modamt = -1; break; // faster
case PR_EXPERT: modamt = -2; break; // faster
case PR_MASTER: modamt = -2; break; // faster
}
}
limit(&modamt, 0, 5);
*speed += (modamt * SPEEDUNIT);
}
}
}
@ -9981,8 +10075,7 @@ int isswimming(lifeform_t *lf) {
if (gamemode != GM_GAMESTARTED) {
return B_FALSE;
}
if (!isairborne(lf) &&
hasobwithflag(lf->cell->obpile, F_DEEPWATER) &&
if (!isairborne(lf) && (getcellwaterdepth(lf->cell, lf) >= DP_WAIST) &&
getskill(lf, SK_SWIMMING)) {
return B_TRUE;
}
@ -10254,7 +10347,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
msg("%s releases a cloud of purple spores!", lfname);
drawscreen();
}
spellcloud(lf->cell, 3, '\0', C_MAGENTA, OT_S_SLEEP, 8);
spellcloud(lf->cell, 3, '\0', C_MAGENTA, OT_S_SLEEP, 8, B_TRUE);
}
@ -10568,6 +10661,7 @@ int modattr(lifeform_t *lf, enum ATTRIB attr, int amt) {
}
}
msg("%s %s %s!", lfname, verb, adverb);
more();
}
return B_FALSE;
}
@ -11532,12 +11626,12 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) {
// immune to fear?
if (lfhasflag(lf, F_UNDEAD)) return B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) {
return B_FALSE;
}
// not intelligent enough to be scared?
if (getiqname(getattr(scarer, A_IQ), NULL) <= IQ_VEGETABLE) {
if (getiqname(getattr(lf, A_IQ), NULL) <= IQ_VEGETABLE) {
return B_FALSE;
}
@ -12068,7 +12162,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
othermod += 5;
}
if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) {
othermod += 20;
othermod += 25;
}
} else if (ct == SC_FALL) {
if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) {
@ -12211,8 +12305,7 @@ int slipon(lifeform_t *lf, object_t *o) {
char obname[BUFLEN];
char lfname[BUFLEN];
if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET) ||
lfhasflag(lf, F_NONCORPOREAL) || isairborne(lf)) {
if (lfhasflag(lf, F_NONCORPOREAL) || isairborne(lf)) {
return B_TRUE;
}
@ -12841,7 +12934,7 @@ void turneffectslf(lifeform_t *lf) {
f = lfhasflag(l, F_HIDING);
if (f && !lfhasflagval(lf, F_SPOTTED, l->id, NA, NA, NULL) && !isinbattle(lf)) {
// can you see their cell?
if (haslos(lf, l->cell)) {
if (!lfhasflag(lf, F_TRAINING) && haslos(lf, l->cell)) {
int bonus = 0;
int dist;
if (!lfhasflag(l, F_SILENTMOVE) && !lfhasflag(lf, F_DEAF)) {
@ -13242,7 +13335,7 @@ int touch(lifeform_t *lf, object_t *o) {
// not wearing gloves?
if (!getequippedob(lf->pack, BP_HANDS)) {
// default power of 4
dospelleffects(lf, OT_S_FREEZEOB, 4, NULL, o, NULL, B_UNCURSED, NULL);
dospelleffects(lf, OT_S_FREEZEOB, 4, NULL, o, NULL, B_UNCURSED, NULL, B_FALSE);
// we use val[0] here rather than timeleft, because we don't
// want to decrement it each turn.
@ -13310,6 +13403,11 @@ int touch(lifeform_t *lf, object_t *o) {
gloves = getequippedob(lf->pack, BP_HANDS);
if (gloves) {
takedamage(gloves, 2, DT_FIRE);
if (!hasflag(gloves->flags, F_DEAD)) {
// if your gloves weren't destroyed the fire
// will go out.
killflagsofid(o->flags, F_ONFIRE);
}
} else {
// otherwise YOU get damaged.
if (isplayer(lf)) {
@ -13559,7 +13657,7 @@ int usestairs(lifeform_t *lf, object_t *o) {
// move player to new map
moveto(lf, newcell, B_TRUE, B_TRUE);
if ((dir == D_UP) && !isairborne(lf)) {
stopsprinting(adjally[n]); // you can sprint down stairs, but not up
stopsprinting(lf); // you can sprint down stairs, but not up
taketime(lf, getmovespeed(lf)*2); // takes longer to climb
} else {
taketime(lf, getmovespeed(lf));

2
lf.h
View File

@ -27,6 +27,7 @@ int candrink(lifeform_t *lf, object_t *o);
int caneat(lifeform_t *lf, object_t *o);
int canhear(lifeform_t *lf, cell_t *c);
int canlearn(lifeform_t *lf, enum SKILL skid);
int canopendoors(lifeform_t *lf);
int canpickup(lifeform_t *lf, object_t *o, int amt);
int canpolymorphto(enum RACE rid);
int canpush(lifeform_t *lf, object_t *o, int dir);
@ -51,6 +52,7 @@ void dumplev(void);
void dumplf(void);
void dumpxp(void);
int eat(lifeform_t *lf, object_t *o);
void enhancerandomskill(lifeform_t *lf);
void enhanceskills(lifeform_t *lf);
object_t *eyesshaded(lifeform_t *lf);
int fall(lifeform_t *lf, lifeform_t *fromlf, int announce);

360
map.c
View File

@ -126,7 +126,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
}
if ((raceid == R_NONE) || (raceid == R_RANDOM)) {
r = getrandomrace(c, 0);
r = getrandomrace(c, NA);
} else {
r = findrace(raceid);
}
@ -342,7 +342,7 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) {
int rv = TT_NONE;
// if there's already someone there,
// then add an object.
if (c->lf || (rnd(1,100) <= obchance)) {
if (!cellwalkable(NULL, c, NULL) || (rnd(1,100) <= obchance)) {
object_t *o;
// object
o = addrandomob(c);
@ -359,44 +359,86 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) {
return rv;
}
// populates retcell[] with all cells within given radius of centre
void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells) {
int (*distfunc)(cell_t *, cell_t *);
int x,y;
cell_t *c;
*ncells = 0;
if (!c) {
return;
}
if (dirtype == DT_ORTH) {
distfunc = getcelldistorth;
} else {
distfunc = getcelldist;
}
for (y = centre->y - radius; y <= centre->y + radius; y++) {
for (x = centre->x - radius; x <= centre->x + radius; x++) {
c = getcellat(centre->map, x,y);
if (c && haslof(centre, c, needlof, NULL) && (distfunc(centre, c) <= radius) &&
(wantcentre || (c != centre)) ) {
retcell[*ncells] = c;
(*ncells)++;
}
}
}
}
// whichside should be D_ORTH
// for now, this function will NOT include room corners
void getroomedge(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells) {
void getroomedge(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid) {
int x,y;
cell_t *c;
*ncells = 0;
if (whichside == D_N) {
y = miny;
for (x = minx+1; x <= maxx-1; x++) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
c = getcellat(map, x, y);
if (!onlywantsolid || c->type->solid) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
}
}
} else if (whichside == D_S) {
y = maxy;
for (x = minx+1; x <= maxx-1; x++) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
c = getcellat(map, x, y);
if (!onlywantsolid || c->type->solid) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
}
}
} else if (whichside == D_W) {
x = minx;
for (y = miny+1; y <= maxy-1; y++) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
c = getcellat(map, x, y);
if (!onlywantsolid || c->type->solid) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
}
}
} else if (whichside == D_E) {
x = maxx;
for (y = miny+1; y <= maxy-1; y++) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
c = getcellat(map, x, y);
if (!onlywantsolid || c->type->solid) {
retcell[*ncells] = getcellat(map, x, y);
(*ncells)++;
}
}
}
}
void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) {
int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct) {
int i,d;
cell_t *poss[MAXCANDIDATES], *cell[MAXCANDIDATES]; // TODO: should this be maxroomw * maxroomh ?
int ncells = 0, npossible = 0;
int doorsadded = 0;
int db = B_FALSE;
// for each side, make list of all possible door locations
// then pick one randomly.
@ -404,7 +446,7 @@ void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) {
// place a door.
for (d = D_N; d <= D_W; d++) {
npossible = 0;
getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells);
getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells, B_TRUE);
for (i = 0; i < ncells; i++) {
cell_t *newcell;
// is there empty space on the other side of this wall segment?
@ -418,7 +460,7 @@ void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) {
// walls to either side of the potential door location, then
// always add a door
if ((countcellexits(newcell) == 1) && wallstoleftright(newcell, d)) {
if (onein(2)) {
if (rnd(1,100) <= doorpct) {
makedoor(cell[i]);
} else {
setcelltype(cell[i], getemptycelltype(map->habitat));
@ -436,7 +478,13 @@ void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) {
if (npossible > 0) {
int sel;
sel = rnd(0,npossible-1);
makedoor(poss[sel]);
if (rnd(1,100) <= doorpct) {
makedoor(poss[sel]);
} else {
setcelltype(poss[sel], getemptycelltype(map->habitat));
}
doorsadded++;
}
} // end foreach direction
@ -474,16 +522,20 @@ void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) {
for (i = 0; i < ndodoors; i++) {
int sel;
d = dodoor[i];
getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells);
getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells, B_TRUE);
sel = rnd(0,ncells-1);
if (onein(2)) {
if (rnd(1,100) <= doorpct) {
makedoor(cell[sel]);
doorsadded++;
} else {
setcelltype(cell[sel], getemptycelltype(map->habitat));
doorsadded++;
}
}
}
if (db) dblog("autodoors() added %d doors to roomid %d", doorsadded, roomid);
return doorsadded;
}
@ -614,6 +666,103 @@ int cellhaslos(cell_t *c1, cell_t *dest) {
return B_TRUE;
}
void clearcell(cell_t *c) {
// kill everything there
if (c->lf) {
killlf(c->lf);
}
while (c->obpile->first) {
killob(c->obpile->first);
}
c->known = B_FALSE;
c->knownglyph.ch = ' ';
c->knownglyph.colour = C_GREY;
}
// returns true if something happened
int dowaterspread(cell_t *c) {
float thisdepth,surrounddepth = DP_NONE;
int i;
int nsurroundwithwater = 0,nsurround = 0;
int db = B_FALSE;
if (!c || c->type->solid || hascloseddoor(c)) {
return B_FALSE;
}
// calculate depth of this cell
thisdepth = getcellwaterdepth(c, NULL);
// calculate average depth of surrounding cells
for (i = DC_N; i <= DC_NW; i++) {
cell_t *newc;
newc = getcellindir(c, i);
if (newc && !newc->type->solid && !hascloseddoor(newc)) {
float newcdepth;
int ok = B_FALSE;
if (newc->type->floorheight == c->type->floorheight) {
ok = B_TRUE;
} else if (newc->type->floorheight < c->type->floorheight) {
// ie. downhill. don't include these
ok = B_FALSE;
} else if (newc->type->floorheight > c->type->floorheight) {
// ie. uphill.
ok = B_TRUE;
}
if (ok) {
newcdepth = getcellwaterdepth(newc, NULL);
nsurround++; // ie. a non-solid cell
surrounddepth += newcdepth;
if (newcdepth > DP_NONE) {
nsurroundwithwater++; // ie. a non-solid cell _with water_
}
}
}
}
// if there was water here or around us...
if (nsurroundwithwater || thisdepth) {
float newdepth;
//surrounddepth /= ((float)nsurround);
surrounddepth /= ((float)nsurroundwithwater);
limitf(&surrounddepth,(float)DP_NONE, (float)DP_MAX);
if (thisdepth == surrounddepth) {
// if there are any nonsolid surrounding cells _without_ water, and
// there is water here, our depth drops.
if ((thisdepth > 0) && (nsurround - nsurroundwithwater >= 2)) {
newdepth = thisdepth - 1;
} else {
newdepth = thisdepth;
}
} else if (surrounddepth > thisdepth) {
// surrounding cells are deeper - they flow into here
newdepth = (thisdepth + surrounddepth) * 0.8;
} else if (thisdepth > surrounddepth) {
// surrounding cells are shallower - this cell will go down.
newdepth = (thisdepth + surrounddepth) * 0.2;
}
addflag(c->map->flags, F_NEWWATERDEPTH, c->x, c->y, (int)newdepth, NULL);
if (db) {
dblog("%s %d,%d: goes from %d to %d (surrounddepth is %d)\n",
thisdepth ? "water depth at" : "NEW WATER AT ",
c->x, c->y,
(int)thisdepth, (int)newdepth, (int)surrounddepth);
}
return B_TRUE;
}
return B_FALSE;
}
cell_t *getcellat(map_t *map, int x, int y) {
if (!isonmap(map, x, y)) return NULL;
return map->cell[y*map->w + x];
@ -665,7 +814,7 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
object_t *o;
// draw highest object in sort order
o = gettopobject(c);
o = gettopobject(c, B_TRUE);
if (o && !hasflag(o->flags, F_NOGLYPH)) {
// return the object's glyph
*g = *(getglyph(o));
@ -708,6 +857,17 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
}
}
enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf) {
object_t *o;
o = hasobwithflag(c->obpile, F_DEEPWATER);
if (o) {
return getobdepth(o, lf);
}
return DP_NONE;
}
int getdoorlockdiff(int depth) {
return 19 + depth;
}
@ -768,7 +928,9 @@ int getmapdifficulty(map_t *m) {
return diff;
}
object_t *gettopobject(cell_t *where) {
// forglyph will be true if we are using this function for the purpose
// of figuring out which glyph to draw
object_t *gettopobject(cell_t *where, int forglyph) {
object_t *o,*oo = NULL;
enum LFSIZE largest = SZ_MINI;
int c;
@ -779,6 +941,7 @@ object_t *gettopobject(cell_t *where) {
// ignore hidden traps, but not secret doors
if (hasflag(o->flags, F_SECRET) && !isdoor(o, NULL)) {
} else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) {
} else if (forglyph && hasflag(o->flags, F_NOGLYPH)) {
} else {
f = hasflag(o->flags, F_IMPASSABLE);
if (f && (f->val[0] > largest)) {
@ -801,6 +964,7 @@ object_t *gettopobject(cell_t *where) {
if (o->type->obclass->id == sortorder[c]) {
if (hasflag(o->flags, F_SECRET)) {
} else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) {
} else if (forglyph && hasflag(o->flags, F_NOGLYPH)) {
} else {
return o;
}
@ -894,8 +1058,8 @@ int calcroompos(map_t *map, int w, int h, int *bx, int *by) {
cell_t *cell;
// try placing room at all positions
for (y = 0; y < map->h; y++) {
for (x = 0; x < map->w; x++) {
for (y = 1; y < map->h; y++) {
for (x = 1; x < map->w; x++) {
// would the room fit here?
if ( ((x + (w-1)) <= (map->w-1)) &&
((y + (h-1)) <= (map->h-1))) {
@ -1222,42 +1386,50 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
}
if (!roomvault[i]) {
// just do a normal room
createroom(map, i, NA, NA, NULL, NULL, &roomw[i],&roomh[i]);
createroom(map, i, NA, NA, NULL, NULL, &roomw[i],&roomh[i], 50, B_FALSE);
roomvault[i] = B_FALSE;
}
}
}
// add staircases - dungeons always have an up and down stairs
// add staircases.
// first dungeon level has 1 up stairs, 3 down.
// subsequent levels always have 3 up and down stairs
for (i = 0; i < 3; i++) {
// add up stairs
c = NULL;
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM);
}
o = addob(c->obpile, "staircase going up");
linkstairs(o);
// first dungeon level has barriers over the exit stairs
if ((map->region == RG_FIRSTDUNGEON) && (map->depth == 1)) {
if (c->lf) killlf(c->lf);
addob(c->obpile, "magical barrier");
/*
int d;
// surround stairs with barriers
for (d = DC_N; d <= DC_NW; d++) {
cell_t *newc;
newc = getcellindir(c, d);
if (newc && !newc->type->solid) {
// kill lfs there
if (newc->lf) killlf(newc->lf);
// add a barrier
addob(newc->obpile, "magical barrier");
}
// UP STAIRS
if ((map->region == RG_FIRSTDUNGEON) && (map->depth == 1) && (i > 0)) {
// first dungeon level, already added 1 up stairs
} else {
c = NULL;
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM);
}
o = addob(c->obpile, "staircase going up");
linkstairs(o);
// first dungeon level has barriers over the exit stairs
if ((map->region == RG_FIRSTDUNGEON) && (map->depth == 1)) {
if (c->lf) killlf(c->lf);
addob(c->obpile, "magical barrier");
/*
int d;
// surround stairs with barriers
for (d = DC_N; d <= DC_NW; d++) {
cell_t *newc;
newc = getcellindir(c, d);
if (newc && !newc->type->solid) {
// kill lfs there
if (newc->lf) killlf(newc->lf);
// add a barrier
addob(newc->obpile, "magical barrier");
}
}
*/
}
*/
}
// DOWN STAIRS
c = NULL;
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM);
@ -1460,11 +1632,13 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
map->depth = depth;
map->region = region;
sprintf(buf, "Region %d (#%d)",map->region, map->id);
map->name = strdup(buf);
map->habitat = habitat;
map->nrooms = 0;
// link to other maps if required.
// default to no links
for (i = D_UP; i <= D_DOWN; i++) {
@ -1588,16 +1762,14 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
map->nextmap[D_DOWN] = firstdungeon->id;
// add stairs going down to dungeon
for (i = 0; i < 3; i++) {
cell_t *c;
object_t *o;
c = NULL;
while (!c || !cellwalkable(NULL, c, NULL)) {
c = getrandomcell(map);
}
o = addob(c->obpile, "staircase going down");
linkstairs(o);
cell_t *c;
object_t *o;
c = NULL;
while (!c || !cellwalkable(NULL, c, NULL)) {
c = getrandomcell(map);
}
o = addob(c->obpile, "staircase going down");
linkstairs(o);
}
// join up any unlinked staircases in this map.
@ -1670,8 +1842,10 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
f = hasflag(v->flags, F_VAULTRANDOMMAP);
if (f) {
// just make a normal room to start with.
if (createroom(map, roomid, f->val[0], f->val[1], &minx, &miny, &w, &h)) {
// just make a normal room to start with. but make sure :
// - it is surrounded with walls!
// - we don't do autodoors (will handle this further down)
if (createroom(map, roomid, f->val[0], f->val[1], &minx, &miny, &w, &h, 0, B_TRUE)) {
return B_TRUE;
}
maxx = minx + w - 1;
@ -1694,7 +1868,9 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
cell_t *cell;
celltype_t *ct;
cell = getcellat(map, x, y);
clearcell(cell);
// set cell type
ct = getvaultcelltype(v, x-minx,y-miny);
setcelltype(cell, ct ? ct->id : getemptycelltype(cell->map->habitat));
@ -1713,21 +1889,25 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
addvaultcontents(map, v, minx, miny, maxx, maxy);
// auto add doors if required
if (hasflag(v->flags, F_AUTODOORS)) {
autodoors(map, roomid, minx, miny, maxx, maxy);
f = hasflag(v->flags, F_AUTODOORS);
if (f) {
autodoors(map, roomid, minx, miny, maxx, maxy, f->val[0]);
}
linkexits(map, roomid, minx, miny, maxx,maxy);
map->nrooms++;
return B_FALSE;
}
// make sure exits/doors in a given room link up to the rest of the map.
void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
int x,y,i;
cell_t *poss[MAXCANDIDATES],*c;
int nposs = 0;
int db = B_FALSE;
int nadded = 0;
if (db) dblog("linkexits for roomid %d", roomid);
@ -1802,6 +1982,7 @@ void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
// now create a path
if (db) dblog(" Linking %s (distance %d).", getdirname(whichway), bestdist);
nadded++;
c = getcellindir(poss[i], whichway);
while (c && !cellwalkable(NULL, c, NULL)) {
setcelltype(c, getemptycelltype(c->map->habitat));
@ -1811,10 +1992,11 @@ void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
} // end if ncorridors = 0
} // end for each door
if (db) dblog("linkexits complete.");
return nadded;
}
// room w/h are returned in *w and *h if given.
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth) {
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls) {
int x,y;
cell_t *cell;
int minx,miny;
@ -1858,21 +2040,32 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *
for (y = miny; y <= maxy; y++) {
for (x = minx; x <= maxx; x++) {
cell = getcellat(map, x, y);
// make it a border or room
if ((y == miny) || (y == maxy) ||
(x == minx) || (x == maxx)) {
if (cell->type->solid) {
setcelltype(cell, CT_ROOMWALL);
if (cell) {
// kill contents
clearcell(cell);
// make it a border or room
if ((y == miny) || (y == maxy) ||
(x == minx) || (x == maxx)) {
// ie. if you haven't forced walls then if this room overlaps
// with another one, no walls will be created.
if (forcewalls || (!forcewalls && cell->type->solid)) {
setcelltype(cell, CT_ROOMWALL);
}
//}
} else {
setcelltype(cell, CT_ROOM);
}
} else {
setcelltype(cell, CT_ROOM);
cell->roomid = roomid;
}
cell->roomid = roomid;
}
}
// add doors
autodoors(map, roomid, minx, miny, maxx, maxy);
if (doorpct) {
autodoors(map, roomid, minx, miny, maxx, maxy, doorpct);
}
map->nrooms++;
return B_FALSE;
}
@ -2613,6 +2806,18 @@ object_t *hasenterableobject(cell_t *c) {
return hasobwithflag(c->obpile, F_CLIMBABLE);
}
object_t *hascloseddoor(cell_t *c) {
object_t *o;
int isopen;
for (o = c->obpile->first ; o ; o = o->next) {
if (isdoor(o, &isopen)) {
if (!isopen) {
return o;
}
}
}
return NULL;
}
lifeform_t *haslf(cell_t *c) {
if (c->lf && !isdead(c->lf)) {
@ -2962,6 +3167,11 @@ void makedoor(cell_t *cell) {
map_t *m;
char doorbuf[BUFLEN];
// can't have more than one door in a cell
if (hasobwithflag(cell->obpile, F_DOOR)) {
return;
}
m = cell->map;
setcelltype(cell, getemptycelltype(m->habitat));
@ -3073,7 +3283,7 @@ void setcellknown(cell_t *cell, int forcelev) {
cell->knownglyph = cell->type->glyph;
// high cartography skill lets us remember certain objects...
if (slev >= PR_EXPERT) {
o = gettopobject(cell);
o = gettopobject(cell, B_TRUE);
if (o) {
cell->knownglyph = *(getglyph(o));
}

15
map.h
View File

@ -6,20 +6,24 @@ map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded);
object_t *addrandomob(cell_t *c);
int addrandomthing(cell_t *c, int obchance, int *nadded);
void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy);
int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct);
int cellhaslos(cell_t *c1, cell_t *dest);
void clearcell(cell_t *c);
int dowaterspread(cell_t *c);
cell_t *getcellat(map_t *map, int x, int y);
int getcelldist(cell_t *src, cell_t *dst);
int getcelldistorth(cell_t *src, cell_t *dst);
void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer);
enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf);
int getdoorlockdiff(int depth);
int getdoorsecretdiff(int depth);
enum CELLTYPE getemptycelltype(enum HABITAT hab);
enum CELLTYPE getwallcelltype(enum HABITAT hab);
flag_t *getmapcoords(map_t *m, int *x, int *y);
int getmapdifficulty(map_t *m);
void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells);
object_t *gettopobject(cell_t *where);
void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells);
void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid);
object_t *gettopobject(cell_t *where, int forglyph);
void calclight(map_t *map);
int calcroompos(map_t *map, int w, int h, int *bx, int *by);
int countadjcellsoftype(cell_t *cell, int id);
@ -28,7 +32,7 @@ int countcellexits(cell_t *cell);
void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir);
void createforest(map_t *map, int depth, map_t *parentmap, int exitdir);
void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap, int exitdir);
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth);
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls);
int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth);
int dirtox(int dt, int dir);
int dirtoy(int dt, int dir);
@ -60,6 +64,7 @@ void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells);
int getslipperyness(cell_t *c, object_t **slipob);
cell_t *getstairdestination(object_t *o);
object_t *hasenterableobject(cell_t *c);
object_t *hascloseddoor(cell_t *c);
lifeform_t *haslf(cell_t *c);
int hasknownobject(cell_t *c);
int hasobject(cell_t *c);
@ -76,7 +81,7 @@ int isnewcellok(cell_t *cell, char *err);
int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m);
int iswallindir(cell_t *cell, int dir);
void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy);
int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy);
int linkstairs(object_t *o);
void makedoor(cell_t *cell);
void makelit(cell_t *c, enum LIGHTLEV how, int howlong);

63
move.c
View File

@ -70,16 +70,29 @@ int ispossiblemove(lifeform_t *lf, int dir) {
return B_TRUE;
}
break;
case E_DOORINWAY:
case E_CANTMOVE:
case E_GRABBEDBY:
case E_TOOHEAVY:
case E_LFINWAY:
return B_TRUE;
case E_DOORINWAY:
if (canopendoors(lf)) {
return B_TRUE;
}
break;
case E_OBINWAY:
inway = (object_t *)rdata;
if (inway && ispushable(inway)) {
return B_TRUE;
// player can always try pushing...
if (isplayer(lf)) {
return B_TRUE;
} else {
// for ai, move is only 'possible' if
// we are strong enough to push the object.
if (canpush(lf, inway, dir)) {
return B_TRUE;
}
}
}
break;
default:
@ -153,7 +166,15 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
}
}
for (o = cell->obpile->first ; o ; o = o->next) {
if (hasflag(o->flags, F_TRAP) && canseeob(lf, o)) {
if (error) {
*error = E_AVOIDOB;
rdata = o;
}
return B_TRUE;
}
f = hasflag(o->flags, F_DEEPWATER);
if (f) {
// non swimming creature in water?
@ -250,7 +271,6 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
if (error) *error = E_LFINWAY;
return B_FALSE;
}
for (o = cell->obpile->first ; o ; o = o->next) {
if (isimpassableob(o, lf)) {
if (lf) {
@ -261,6 +281,7 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
// ok but still set error
*error = E_OBINWAY;
} else {
// not ok
rdata = o;
if (error) {
if (isdoor(o, NULL)) {
@ -907,7 +928,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
}
// did you just enter the water?
if (!prewater) {
if (getskill(lf, SK_SWIMMING)) {
if ((getobdepth(o, lf) >= DP_WAIST) && getskill(lf, SK_SWIMMING)) {
if (isplayer(lf)) {
msg("You start swimming.");
didmsg = B_TRUE;
@ -1169,7 +1190,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
// make some noise
// (stealth check to avoid this)
if (!lfhasflag(lf, F_SILENTMOVE)) {
if (!lfhasflag(lf, F_SILENTMOVE) && !lfhasflag(lf, F_SNEAK)) {
if (!skillcheck(lf, SC_STEALTH, 20, 0)) {
if (isairborne(lf)) {
makenoise(lf, N_FLY);
@ -1276,7 +1297,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
return B_TRUE;
}
if (lf && lfhasflagval(lf, F_NOBODYPART, BP_HANDS, NA, NA, NULL)) {
if (!canopendoors(lf)) {
if (isplayer(lf)) {
msg("You have no hands with which to open the door!");
}
@ -1363,8 +1384,8 @@ int opendoor(lifeform_t *lf, object_t *o) {
}
where = getoblocation(o);
if (!haslos(player, where)) {
// don't anonuce this is we can see it.
// normally 'noise()' takes case of this by
// don't anonuce this if we can see it.
// normally 'noise()' takes care of this by
// checking if we have LOS to the lifeform making
// sound, but in this case it's the door making
// the sound, not the lf.
@ -1604,6 +1625,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
for (o = lf->cell->obpile->first ; o ; o = nexto) {
nexto = o->next;
if ((o->type->id == OT_WEB) && (lf->race->baseid == R_SPIDER)) {
continue;
}
@ -1615,7 +1637,19 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
if (f) {
char lfname[BUFLEN];
int diff;
int checkmod = 0;
int getsweaker;
if (isairborne(lf) && (f->val[2] != B_TRUE)) {
continue;
}
if ((o->type->id == OT_WEB) && isairborne(lf)) {
checkmod -= 5;
}
getlfname(lf,lfname);
getobname(o, buf, o->amt);
@ -1631,7 +1665,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
diff = (o->amt - 1) * ((float)f->val[0] / 4.0);
}
getsweaker = f->val[1];
if (skillcheck(lf, SC_STR, diff, 0)) {
if (skillcheck(lf, SC_STR, diff, checkmod)) {
if (isplayer(lf)) {
msg("You tear free from %s!", buf);
if (didmsg) *didmsg = B_TRUE;
@ -1696,11 +1730,12 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
if (!lfhasflag(lf, F_SNEAK)) {
slip = getslipperyness(lf->cell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
if (didmsg) *didmsg = B_TRUE;
// don't move
reason = E_OK;
return B_TRUE;
if (!slipon(lf, slipob)) {
if (didmsg) *didmsg = B_TRUE;
// don't move
reason = E_OK;
return B_TRUE;
}
}
}
}

91
nexus.c
View File

@ -74,6 +74,8 @@ long timeleft = 0;
extern int statdirty;
extern int noredraw;
int needredraw = B_TRUE;
int numdraws = 0;
@ -290,11 +292,11 @@ int main(int argc, char **argv) {
// pre-calc line-of-sight for player
precalclos(player);
// don't want any mosnters starting within los of player
// don't want any mosnters starting within los/lof of player
for (y = 0; y < player->cell->map->h; y++) {
for (x = 0; x < player->cell->map->w; x++) {
c = getcellat(player->cell->map, x, y);
if (c && c->lf && haslos(player, c)) {
if (c && c->lf && (haslos(player, c) || haslof(player->cell, c, LOF_WALLSTOP, NULL))) {
if (!isplayer(c->lf) && !ispetof(c->lf, player)) {
killlf(c->lf);
}
@ -372,7 +374,7 @@ int main(int argc, char **argv) {
return B_FALSE;
}
celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat) {
celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight) {
celltype_t *a;
// add to the end of the list
@ -398,6 +400,7 @@ celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, i
a->solid = solid;
a->transparent = transparent;
a->material = findmaterial(mat);
a->floorheight = floorheight;
a->flags = addflagpile(NULL, NULL);
@ -630,7 +633,6 @@ void donextturn(map_t *map) {
}
if (hasflag(player->flags, F_ASLEEP)) {
// ooo is this right ?
needredraw = B_FALSE;
/*
} else if (isdead(who) || cansee(player, who)) {
@ -708,7 +710,7 @@ enum COLOUR getpctcol(float num, float max) {
return C_ORANGE;
}
void getrarity(int depth, int *min, int *max, int range, int oodok) {
void getrarityrange(int depth, int *min, int *max, int range, int oodok) {
int mid;
int num;
@ -750,15 +752,16 @@ int init(void) {
initrace();
// cell types
addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE);
addcelltype(CT_WALLGLASS, "glass wall", '#', C_CYAN, B_SOLID, B_TRANS, MT_GLASS);
addcelltype(CT_WALLMETAL, "metal wall", '#', C_WHITE, B_SOLID, B_OPAQUE, MT_METAL);
addcelltype(CT_ROOMWALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE);
addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT);
addcelltype(CT_DIRT, "dirt", '.', C_BROWN, B_EMPTY, B_TRANS, MT_STONE);
addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
addcelltype(CT_WALLGLASS, "glass wall", '#', C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0);
addcelltype(CT_WALLMETAL, "metal wall", '#', C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0);
addcelltype(CT_ROOMWALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT, 0);
addcelltype(CT_DIRT, "dirt", '.', C_BROWN, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -1);
gamemode = GM_VALIDATION;
if (validateobs()) {
@ -905,6 +908,23 @@ int limit(int *what, int min, int max) {
return limited;
}
int limitf(float *what, float min, float max) {
int limited = B_FALSE;
if (min != NA) {
if (*what < min) {
*what = min;
limited = B_TRUE;
}
}
if (max != NA) {
if (*what > max) {
*what = max;
limited = B_TRUE;
}
}
return limited;
}
int onein(int howmany) {
if (rnd(1,howmany) == 1) return B_TRUE;
return B_FALSE;
@ -1256,6 +1276,7 @@ void timeeffectsworld(map_t *map) {
timeleft += firstlftime;
// now do effects based on time...
while (timeleft >= TICK_INTERVAL) {
flag_t *f, *nextf;
timeleft -= TICK_INTERVAL;
@ -1279,10 +1300,50 @@ void timeeffectsworld(map_t *map) {
c->lit = c->origlit;
}
}
}
// water spreads...
if (dowaterspread(c) && haslos(player, c)) {
needredraw = B_TRUE;
}
} // end if c
}
} // end for (y...
// now finish off water spread
noredraw = B_TRUE;
for (f = map->flags->first ; f ; f = nextf) {
nextf = f->next;
if (f->id == F_NEWWATERDEPTH) {
cell_t *c;
c = getcellat(map, f->val[0], f->val[1]);
if (c) {
if (f->val[2] > DP_NONE) {
o = hasobwithflag(c->obpile, F_DEEPWATER);
if (!o) {
o = addob(c->obpile, "water");
}
if (o) {
flag_t *dflag;
dflag = hasflag(o->flags, F_DEEPWATER);
// adjust depth
dflag->val[0] = f->val[2];
}
} else {
// water depth is now zero.
o = hasobwithflag(c->obpile, F_DEEPWATER);
if (o) {
killob(o);
addob(c->obpile, "large puddle of water");
}
}
}
killflag(f);
continue;
}
}
noredraw = B_FALSE;
// now handle effects on lifeforms and/or their objects
for (l = map->lf ; l ; l = l->next) {
timeeffectslf(l);

View File

@ -1,6 +1,6 @@
#include "defs.h"
celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat);
celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight);
command_t *addcommand(enum COMMAND id, char c, char *desc);
void checkdeath(void);
void checkendgame(void);
@ -12,13 +12,14 @@ void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, in
void donextturn(map_t *map);
char *getdirname(int dir);
enum COLOUR getpctcol(float num, float max);
void getrarity(int depth, int *min, int *max, int range, int oodok);
void getrarityrange(int depth, int *min, int *max, int range, int oodok);
int init(void);
void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels);
void initbresnham(int x1, int y1, int x2, int y2, int *xinc1, int *yinc1, int *dinc1, int *xinc2, int *yinc2, int *dinc2, int *numpixels, int *d);
void initcommands(void);
int isplayerturn(void);
int limit(int *what, int min, int max);
int limitf(float *what, float min, float max);
int onein(int howmany);
int parseplayerfile(FILE *f, lifeform_t *lf);
float pctof(float pct, float num);

977
objects.c

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,7 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
int getobaccuracy(object_t *wep, lifeform_t *weilder);
int getobbonus(object_t *o);
skill_t *getobskill(object_t *o);
int getobspellpower(object_t *o, lifeform_t *lf);
int getobvalue(object_t *o);
//int getobtypevalue(objecttype_t *ot);
char *getaccuracyname(int accpct);
@ -103,7 +104,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, int depthmod);
int getobrarity(object_t *o);
int getobrarity(object_t *o, enum RARITY *rr);
enum SPELLSCHOOL getschool(enum OBTYPE sid);
char *getschoolname(enum SPELLSCHOOL sch);
char *getschoolnameshort(enum SPELLSCHOOL sch);
@ -134,6 +135,7 @@ int isblessed(object_t *o);
int isblessknown(object_t *o);
int iscorpse(object_t *o);
int iscursed(object_t *o);
int isdamaged(object_t *o);
int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown);
int isdeadob(object_t *o);
int isdrinkable(object_t *o);
@ -190,7 +192,7 @@ int obpropsmatch(object_t *a, object_t *b);
int obotpropsmatch(object_t *a, objecttype_t *b);
int operate(lifeform_t *lf, object_t *o, cell_t *where);
int pilehasletter(obpile_t *op, char let);
void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potlessed, int *seen);
void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE potlessed, int *seen);
int pour(lifeform_t *lf, object_t *o);
void quaff(lifeform_t *lf, object_t *o);
int readsomething(lifeform_t *lf, object_t *o);

253
spell.c
View File

@ -1185,7 +1185,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
case OC_RING:
break;
default:
msg("This doesn't seem to be a standard kind of item.");
msg("Your knowledge doesn't extend to this kind of item.");
return B_TRUE;
}
@ -1252,7 +1252,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// returns TRUE on error
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer) {
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer, int frompot) {
char buf[BUFLEN];
char castername[BUFLEN];
int rv = B_FALSE;
@ -1382,7 +1382,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
cell_t *nextc;
if (targcell) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS);
} else {
int dirch;
@ -1511,7 +1511,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_BLADEBURN) {
object_t *wep;
enum DAMTYPE dt;
if (!validatespellcell(caster, &targcell, TT_PLAYER | TT_ALLY, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_PLAYER | TT_ALLY, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -1540,7 +1540,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_BLINDNESS) {
int failed = B_FALSE;
// ask for target
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (isblind(target)) {
@ -1596,7 +1596,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
cell_t *retcell[MAXRETCELLS];
int nretcell;
int i;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (cansee(player, caster)) {
msg("%s shoot%s a wave of fire!",castername, isplayer(caster) ? "" : "s");
@ -1645,7 +1645,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_CALLLIGHTNING) {
int failed = B_FALSE;
// ask for a target cell
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (target) {
@ -1679,7 +1679,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// if no target object...
if (!targob) {
// ask for a target cell (to take objects from)
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE;
if (targcell->obpile->first) {
// select object from cell...
@ -1777,7 +1777,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
range = getspellrange(spellid, power);
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// create a line of fire towards the target cell
animline(caster->cell, targcell, B_FALSE, '/', '\\', C_WHITE);
@ -1854,7 +1854,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} // end while narccells
} else if (spellid == OT_S_CLOUDKILL) {
int radius;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (targcell->type->solid) {
fizzle(caster);
@ -1871,7 +1871,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_CHARM) {
char targetname[BUFLEN];
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
@ -1943,7 +1943,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_CHARMANIMAL) {
char targetname[BUFLEN];
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
@ -2016,7 +2016,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_CHILL) {
char lfname[BUFLEN];
int exposedlimbs,dam;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -2100,7 +2100,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
cell_t *retcell[MAXRETCELLS];
int nretcell,i;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}', C_GREY);
if (isplayer(caster) || cansee(player, caster)) {
@ -2143,7 +2143,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!targcell) {
if ((power >= 5) && isplayer(caster)) {
// control location
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE;
// make sure it's empty
if (!cellwalkable(NULL, targcell, NULL)) {
targcell = NULL;
@ -2235,8 +2235,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
return B_TRUE;
}
} else if (spellid == OT_S_CREATEVAULT) {
vault_t *v;
// ask for a vaulttype
v = askvault("Create which vault?");
if (createvault(caster->cell->map, caster->cell->map->nrooms, v, NULL, NULL)) {
msg("Couldn't create a vault.");
} else {
msg("BAM! A vault has appeared nearby.");
needredraw = B_TRUE;
}
} else if (spellid == OT_S_CUREPOISON) {
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -2315,7 +2327,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int ndigs;
// don't need line of fire OR sight!
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE;
// calculate a line from caster to the target cell
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y,
@ -2457,18 +2469,56 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} // end if isplayer
} else if (spellid == OT_S_DETONATE) {
// don't need line of fire!
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_DOOR, spellid, power, frompot)) return B_TRUE;
explodecells(targcell, 20, B_TRUE, NULL, power / 4, DT_ORTH, B_TRUE);
if (haslos(player, targcell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (spellid == OT_S_EVAPORATE) {
cell_t *cell[MAXCANDIDATES];
int i,ncells;
int nseen = 0;
int nsteamseen = 0;
// don't need line of fire!
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE;
getradiuscells(targcell, power, DT_ORTH, LOF_NEED, B_TRUE, cell, &ncells);
for (i = 0; i < ncells; i++) {
object_t *o,*nexto;
for (o = cell[i]->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (o->material->id == MT_WATER) {
int cellseen = B_FALSE;
if (haslos(player, cell[i])) {
cellseen = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
// if 20kilos or more, make steam
if (getobweight(o) >= 25) {
addob(cell[i]->obpile, "cloud of steam");
if (cellseen) nsteamseen++;
}
nseen++;
removeob(o, ALL);
}
}
}
if (nsteamseen) {
msg("A huge cloud of steam appears!");
} else if (nseen) {
msg("Some nearby water evaporates!");
} else {
fizzle(caster);
}
} else if (spellid == OT_S_EXPLODEMETAL) {
float totalmass = 0;
object_t *o, *nexto;
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE;
// how much metal is there?
for (o = targcell->obpile->first ; o ; o = nexto) {
@ -2499,7 +2549,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *o, *nexto;
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_MONSTER|TT_OBJECT, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER|TT_OBJECT, spellid, power, frompot)) return B_TRUE;
if (!targcell) {
if (isplayer(caster)) {
fizzle(caster);
@ -2558,13 +2608,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
c = getrandomcell(targcell->map);
}
if (haslos(player, targcell)) {
if (haslos(player, targcell) && canseeob(player, o)) {
msg("%s disappear%s!", buf, (o->amt == 1) ? "s" : "");
if (seenbyplayer) *seenbyplayer = B_TRUE;
donesomething = B_TRUE;
}
moveob(o, c->obpile, o->amt);
if (haslos(player, c)) {
if (haslos(player, c) && canseeob(player, o)) {
msg("%s appear%s nearby!", buf, (o->amt == 1) ? "s" : "");
}
}
@ -2574,7 +2624,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
rv = B_FALSE;
} else if (spellid == OT_S_DRAINLIFE) {
char lfname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = haslf(targcell);
if (target) {
@ -2644,7 +2694,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FEAR) {
char targname[BUFLEN];
// ask for target
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -2674,7 +2724,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_FEEBLEMIND) {
// ask for target
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if ((getattr(target, A_IQ) <= 3) || skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
@ -2719,23 +2769,33 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FLOOD) {
int failed = B_FALSE;
// ask for a target cell
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE;
if (targcell) {
if (!targcell->type->solid) {
// create water there
object_t *o;
o = addob(targcell->obpile, "deep water");
o = addob(targcell->obpile, "water");
if (o) {
enum OBTYPE badoid[2];
int i,amt;
int depth;
depth = DP_SHOULDERS + power;
amt = ((power+1) * (power+1)) - 1;
//amt = power;
badoid[0] = OT_WATERDEEP;
badoid[1] = OT_NONE;
for (i = 0; i < amt; i++) {
cell_t *c;
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_WALLSTOP, badoid);
if (c) {
addob(c->obpile, "deep water");
object_t *water;
water = addob(c->obpile, "water");
if (water) {
flag_t *f;
f = hasflag(water->flags, F_DEEPWATER);
if (f) f->val[0] = depth;
}
} else {
break;
}
@ -2760,7 +2820,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char numbuf[BUFLEN];
numtotext(power, numbuf);
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}', C_CYAN);
if (isplayer(caster) || cansee(player, caster)) {
@ -2789,7 +2849,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FIREBALL) {
int failed = B_FALSE;
// ask for a target cell
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (targcell) {
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
int dir;
@ -2881,7 +2941,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_FIREDART) {
char lfname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}', C_RED);
if (isplayer(caster) || cansee(player, caster)) {
@ -2941,7 +3001,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FLAMEPILLAR) {
int failed = B_FALSE;
// ask for a target cell
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (targcell) {
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
flag_t *f;
@ -3006,7 +3066,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_ENDUREELEMENTS) {
flag_t *f;
// always targetted at caster
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -3022,7 +3082,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
flag_t *f;
object_t *o;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
@ -3171,7 +3231,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_FROSTBITE) {
char lfname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -3219,7 +3279,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_GREASE) {
int radius;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (targcell->type->solid) {
fizzle(caster);
@ -3249,7 +3309,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
limit(&power, NA, 10);
}
// ask for a target cell
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (targcell) {
if (!targcell->type->solid) {
object_t *o;
@ -3300,7 +3360,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_HASTE) {
int howlong = 15;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
@ -3325,7 +3385,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if ((spellid == OT_S_HEALING) || (spellid == OT_S_HEALINGMIN) || (spellid == OT_S_HEALINGMAJ)) {
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -3406,7 +3466,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_HOLDPORTAL) {
object_t *o;
if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power, frompot)) return B_TRUE;
o = hasobwithflag(targcell->obpile, F_DOOR);
if (!o) {
@ -3427,7 +3487,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *wep;
enum DAMTYPE dt;
char obname[BUFLEN];
if (!validatespellcell(caster, &targcell, TT_PLAYER | TT_ALLY, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_PLAYER | TT_ALLY, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -3464,7 +3524,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *o;
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// create icicle
o = addob(targcell->obpile, "huge icicle");
@ -3579,7 +3639,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char numbuf[BUFLEN];
numtotext(power, numbuf);
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}', C_CYAN);
if (isplayer(caster) || cansee(player, caster)) {
@ -3750,7 +3810,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_MINDSCAN) {
int failed = B_FALSE;
if (isplayer(caster)) {
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (targcell && haslos(caster, targcell) && haslf(targcell)) {
char targname[BUFLEN];
@ -3794,7 +3854,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE;
}
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// 4 is the same as ST_TITANIC strength
// 10 = gun speed
@ -3802,7 +3862,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_PARALYZE) {
int howlong;
int saved = B_FALSE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (lfhasflag(target, F_PARALYZED)) {
@ -3837,7 +3897,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_PAIN) {
int failed = B_FALSE;
// ask for target
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (lfhasflag(target, F_PAIN)) {
@ -3873,7 +3933,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster);
}
} else if (spellid == OT_S_PETRIFY) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
// some thigns can't be stoned
@ -3903,7 +3963,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
addflag(target->flags, F_BEINGSTONED, 2, NA, NA, NULL);
} else if (spellid == OT_S_POISONBOLT) {
char lfname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// animation
anim(caster->cell, targcell, '}', C_GREEN);
@ -3930,7 +3990,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_POSSESSION) {
char targname[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
@ -4048,7 +4108,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(caster->flags, F_MAGICARMOUR, power*4, NA, NA, "psychic barrier", FROMSPELL);
f->obfrom = spellid;
} else if (spellid == OT_S_PULL) {
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
@ -4080,7 +4140,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_PULLMETAL) {
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power, frompot)) return B_TRUE;
if (targcell->lf) {
object_t *o;
@ -4299,7 +4359,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (caster->race->id == R_GHOST) {
targcell = caster->cell;
} else {
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
}
target = targcell->lf;
@ -4323,7 +4383,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (spellid == OT_S_JOLT) {
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = haslf(targcell);
if (target) {
@ -4343,7 +4403,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_KNOCK) {
object_t *o;
if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_DOOR, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
@ -4404,7 +4464,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// at power 8, the light is permenant
if (power >= 3) {
// TODO: this actually means we can cast it through walls!!!
if (!validatespellcell(caster, &targcell,TT_NONE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_NONE, spellid, power, frompot)) return B_TRUE;
} else {
targcell = caster->cell;
}
@ -4467,7 +4527,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int nretcells;
int i;
int nhits = power;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// create a line of fire towards the target cell
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, targcell->x, targcell->y, retcell, &nretcells);
@ -4667,7 +4727,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_GRAVBOOST) {
// ask for target
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (target) {
int howlong = 15;
@ -4710,7 +4770,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
limit(&power, NA, 10);
}
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_OBJECT, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_OBJECT, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
@ -4829,7 +4889,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_PACIFY) {
char targetname[BUFLEN];
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
@ -4883,7 +4943,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_POLYMORPH) {
race_t *r = NULL;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
@ -4939,7 +4999,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// random race, but not the same!
r = target->race;
while ((r == target->race) || !canpolymorphto(r->id)) {
r = getrandomrace(NULL, 0);
r = getrandomrace(NULL, NA);
}
}
}
@ -5050,7 +5110,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *o,*nexto;
int ndone = 0;
if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power, frompot)) return B_TRUE;
if (!targcell) {
fizzle(caster);
@ -5105,7 +5165,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_LESSENPOISON) {
flag_t *f;
int ndone = 0;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
@ -5207,7 +5267,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f->obfrom = spellid;
} else if (spellid == OT_S_SLEEP) {
int howlong;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (lfhasflag(target, F_ASLEEP) || !cansleep(target)) {
@ -5238,7 +5298,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
limit(&power, NA, 10);
}
// ask for a target cell
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (targcell) {
if (!targcell->type->solid) {
int radius;
@ -5263,7 +5323,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_SLOW) {
int howlong = 15;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
@ -5288,7 +5348,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int ndone = 0;
int powerleft = power;
// ask for a target cell
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE;
if (targcell) {
object_t *o;
enum OBTYPE badoid[2];
@ -5329,7 +5389,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_SPARK) {
object_t *o,*nexto;
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power, frompot)) return B_TRUE;
if (haslos(player, targcell)) {
msg("A small spark of flame appears.");
@ -5349,7 +5409,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_STENCH) {
int howlong;
if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
@ -5815,7 +5875,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
}
} else if (spellid == OT_S_TWIDDLE) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target || (target == caster)) {
@ -5918,7 +5978,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int seen = B_FALSE;
flag_t *f;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// get vert distance
@ -6031,7 +6091,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char lfname[BUFLEN];
cell_t *retcell[MAXRETCELLS];
int nretcell,i;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// animation
//anim(caster->cell, targcell, '}', C_BLUE);
if (isplayer(caster) || cansee(player, caster)) {
@ -6079,7 +6139,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
flag_t *f;
int ndone = 0;
if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_OBJECT, spellid, power, frompot)) return B_TRUE;
if (!targcell) {
fizzle(caster);
@ -6131,7 +6191,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_WEAKEN) {
// ask for target
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
@ -6172,7 +6232,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int i;
numtotext(power, numbuf);
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
// animation
anim(caster->cell, targcell, '^', C_GREY);
if (isplayer(caster) || cansee(player, caster)) {
@ -6223,7 +6283,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE;
// ask for target
if (spellid == OT_S_GIFT) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
} else {
target = caster;
@ -6502,8 +6562,14 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
int spelllev;
enum SKILLLEVEL spellskill,schoolskill;
enum SPELLSCHOOL school;
int db = B_FALSE;
int max = 10;
flag_t *f;
objecttype_t *ot;
ot = findot(spellid);
if (db) dblog("getspellpower for lf %s, spell %s", lf->race->name, ot->name);
// first: can we WILL this to occur? if so, we might have a set
// spellpower
@ -6511,6 +6577,9 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
if (f && strlen(f->text)) {
texttospellopts(f->text, &power, NULL, NULL, NULL);
if (power > 0) {
if (db) {
dblog("-->power = %d (from canwill)", power);
}
return power;
}
}
@ -6518,6 +6587,9 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
// player can only ever cast spells up to your level.
if (isplayer(lf) && !hasjob(lf, J_GOD)) {
if (getspelllevel(spellid) > lf->level) {
if (db) {
dblog("-->power = 0 (spell level > lf level)", power);
}
return 0;
}
}
@ -6545,6 +6617,9 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
break;
default:
if (spellskill == PR_INEPT) {
if (db) {
dblog("-->power = 0 (inept in SORCERY)");
}
return 0;
}
break;
@ -6553,10 +6628,12 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
if (hasjob(lf, J_DRUID)) {
power = (lf->level/3) + statmod;
if (db) dblog("-->(druid) basepower from level+iq is %d", power);
} else {
// every 6 levels you get 1 more power
// ie. at level 30 you get +5 power
power = (lf->level/6) + statmod;
if (db) dblog("-->basepower from level+iq is %d", power);
}
switch (school) {
@ -6564,6 +6641,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
case SS_MENTAL:
break;
default:
if (db) dblog("--> + %d from skill in Sorcery", spellskill);
power += spellskill;
break;
}
@ -6579,6 +6657,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
}
if (divamt > 0) {
if (db) dblog("--> divided by %d (based on spelllevel %d)", divamt, spelllev);
power /= divamt;
}
}
@ -6586,12 +6665,16 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
// specialised school skill - apply this AFTER dividing by spell level
schoolskill = getskill(lf, getschoolskill(school));
if (schoolskill != PR_INEPT) {
power += ((float)schoolskill * 1.5);
float addamt;
addamt = (float)schoolskill * 1.5;
if (db) dblog("--> + %0.1f from skill in %s", addamt, getschoolname(school));
power += addamt;
}
// enforce maximum
max = getspellmaxpower(spellid);
if (power > max) power = max;
if (db) dblog("==> final power: %d", power);
return power;
}
@ -6782,7 +6865,7 @@ int schoolappearsinbooks(enum SPELLSCHOOL ss) {
return B_TRUE;
}
void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power) {
void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot) {
int x,y;
if (ch != '\0') {
if (haslos(player, srcloc)) {
@ -6798,7 +6881,7 @@ void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYP
haslof(srcloc, c, LOF_WALLSTOP, NULL)) {
if (getcelldistorth(srcloc, c) <= radius) {
// fall asleep
dospelleffects(NULL, sid, power, c->lf, NULL, c, B_UNCURSED, NULL);
dospelleffects(NULL, sid, power, c->lf, NULL, c, B_UNCURSED, NULL, frompot);
}
}
}
@ -6940,7 +7023,7 @@ lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **targe
return *target;
}
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power) {
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power, int frompot) {
int maxrange = UNLIMITED;
int done = B_FALSE;
cell_t *where = NULL;
@ -6972,7 +7055,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e
cell_t *newwhere = NULL;
// validate it
if (where && needlos && !haslos(caster, where) && (where != caster->cell)) {
if (isplayer(caster)) {
if (isplayer(caster) && !frompot) {
msg("You cannot see there!"); more();
}
where = NULL;
@ -6981,7 +7064,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e
// line of fire interrupted?
if (where && needlof && !haslof(caster->cell, where, needlof, &newwhere)) {
if (newwhere) {
if (isplayer(caster)) {
if (isplayer(caster) && !frompot) {
// warn!
int ch;
ch = askchar("Your have no clear line of fire - really target here?","yn","n", B_TRUE);
@ -6999,13 +7082,13 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e
}
if (where && (maxrange != UNLIMITED) && (getcelldist(caster->cell, where) > maxrange)) {
// out of range
if (isplayer(caster)) {
if (isplayer(caster) && !frompot) {
msg("Too far away - max range is %d.",maxrange); more();
}
where = NULL;
}
if (where && where->lf && haslos(caster, where) && isplayer(caster) && areallies(caster, where->lf)) {
if (!frompot && where && where->lf && haslos(caster, where) && isplayer(caster) && areallies(caster, where->lf)) {
// warn before targetting yourself!
if (getiqname(getattr(caster, A_IQ), NULL) >= IQ_AVERAGE) {
objecttype_t *sp;

View File

@ -3,7 +3,7 @@
#include "defs.h"
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target, flag_t *cwflag);
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer);
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer, int frompot);
objecttype_t *findspelln(char *buf);
void fizzle(lifeform_t *caster);
//int getiqreq(enum OBTYPE oid);
@ -22,12 +22,12 @@ int getspellrange(enum OBTYPE spellid, int power);
char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf);
void pullobto(object_t *o, lifeform_t *lf);
int schoolappearsinbooks(enum SPELLSCHOOL ss);
void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power);
void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot);
void stopspell(lifeform_t *caster, enum OBTYPE spellid);
void stopallspells(lifeform_t *lf);
int summonlfs(lifeform_t *caster, enum RACECLASS wantrc, enum LFSIZE wantsize, int howmany, int lifetime);
lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target);
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power);
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power, int frompot);
//lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
#endif

30
text.c
View File

@ -289,6 +289,36 @@ char *gettimetextfuzzy(char *retbuf, int wantpm) {
return retbuf;
}
char *getwaterdepthname(enum DEPTH d) {
switch (d) {
case DP_NONE:
return "shallow";
case DP_TOE:
return "toe-deep";
case DP_ANKLE:
return "ankle-deep";
case DP_FEET:
return "foot-deep";
case DP_CALF:
return "calf-deep";
case DP_KNEE:
return "knee-deep";
case DP_THIGH:
return "thigh-deep";
case DP_WAIST:
return "waist-deep";
case DP_BELLY:
return "belly-deep";
case DP_CHEST:
return "chest-deep";
case DP_SHOULDERS:
return "shoulder-deep";
default:
return "very deep";
}
return "?unknowndepth?";
}
char *getweighttext(float weight, char *buf) {
if (weight == 0) {
sprintf(buf, "nothing");

1
text.h
View File

@ -14,6 +14,7 @@ char *getrarityname(enum RARITY rr);
char *getsizetext(enum LFSIZE sz);
char *gettimetext(char *retbuf);
char *gettimetextfuzzy(char *retbuf, int wantpm);
char *getwaterdepthname(enum DEPTH d);
char *getweighttext(float weight, char *buf);
char *is(lifeform_t *lf);
int isvowel(char c);

View File

@ -8,7 +8,7 @@ random(4,4)
@end
@flags
autodoors
autodoors:25
autopop
scatter(1,1,-2,-2) ob:boulder:25%
scatter(1,1,-2,-2) ob:25-75 stones:50%

View File

@ -12,12 +12,12 @@
@end
@legend
#:ob:stone wall
#:cell:rock wall
+:ob:wooden door
@end
@flags
autodoors
autodoors:50
autopop
@end

View File

@ -8,11 +8,11 @@ random(4,4)
@end
@flags
autodoors
autodoors:75
autopop
! tables & chairs
scatter(1,1,-2,-2) ob:wooden table:20%
scatter(1,1,-2,-2) ob:wooden chair:20%
scatter(1,1,-2,-2) ob:wooden footstool:20%
scatter(1,1,-2,-2) ob:random food:5-10
scatter(1,1,-2,-2) ob:steak knife:1-5
! mayrotate

View File

@ -1,4 +1,5 @@
! a room filled with deep water
! a room completely filled with deep water
! the water will explode outwards when you open the door
@id:flooded_room
@map
random(5,5)
@ -8,11 +9,10 @@ random(5,5)
@end
@flags
autodoors
! 100% chance of doors - don't want the water escaping
autodoors:100
autopop
! sometimes there will be a walkway around the edge
box(1,1,-2,-2) ob:shallow water:50
fill(2,2,-3,-3) ob:deep water:100
fill(1,1,-2,-2) ob:very deep water:100
scatter(1,1,-2,-2) mon:piranha:3:100
@end

View File

@ -8,10 +8,10 @@ random(5,5)
@end
@flags
autodoors
autodoors:50
autopop
! sometimes there will be a walkway around the edge
fill(2,2,-3,-3) ob:shallow water:100
fill(2,2,-3,-3) cell:low rock floor:100
fill(2,2,-3,-3) ob:waist-deep water:100
scatter(2,2,-3,-3) mon:piranha:50%:100
@end

View File

@ -8,7 +8,8 @@ random(5,5)
@end
@flags
autodoors
! don't want cockatrice escaping
autodoors:100
scatter(1,1,-2,-2) ob:statue:25%
scatter(1,1,-2,-2) mon:cockatrice:1
scatter(1,1,-2,-2) ob:1-10 stones:1-5

View File

@ -8,7 +8,7 @@ random(4,4)
@end
@flags
autodoors
autodoors:100
! every cell in here has 1-3 objects and a monster
scatter(1,1,-2,-2) mon:random:100%
scatter(1,1,-2,-2) ob:random:100%

View File

@ -8,7 +8,7 @@ random(4,4)
@end
@flags
autodoors
autodoors:50
autopop
! add mud to 50% of room cells
scatter(1,1,-2,-2) ob:pool of mud:50%

View File

@ -7,8 +7,8 @@ random(5,5)
@end
@flags
autodoors
autodoors:50
autopop
scatter(1,1,-2,-2) cell:stone wall:25%
scatter(1,1,-2,-2) cell:rock wall:25%
@end

View File

@ -8,7 +8,7 @@ random(5,5)
@end
@flags
autodoors
autodoors:50
autopop
scatter(1,1,-2,-2) cell:glass wall:25%
@end

View File

@ -8,7 +8,7 @@ random(3,3)
@end
@flags
autodoors
autodoors:100
! half the cells are trapped!
scatter(1,1,-2,-2) ob:random trap:50%
! corpses

View File

@ -8,7 +8,7 @@
@end
@legend
#:ob:metal wall
#:cell:metal wall
$:ob:25-200 gold
! 30% chance of a door on each side
+:ob:secret locked iron door:30