* [+] check darkmantle code now that i can se ab it in dark

- [+] don't drip blood from melting damge
* [+] climbing
- [+] LOTS of bugs with holes
- [+] cope with walking diagonally off world map
- [+] can no longer walk off the world map!!!
* [+] BUG: worldmap 0,-1 had a link to dungeon!
- [+] Dig down into a pit - CRASH. fixing previous one might fix this?
* [+] CRASH:
* [+] walking onto water:
- [+] boots of stealth / elven boots - make footstep volume = 1
* [+] f_freezingtouch
This commit is contained in:
Rob Pearce 2011-06-23 05:57:55 +00:00
parent 57d783ab71
commit cf328f849f
15 changed files with 576 additions and 258 deletions

View File

@ -761,8 +761,16 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (isunarmed) {
f = lfhasflag(lf, F_FREEZINGTOUCH);
if (f) {
int diff;
diff = f->val[2];
if (isimmuneto(victim->flags, DT_COLD) || skillcheck(victim, SC_RESISTMAG, diff, 0)) {
if (isplayer(victim)) {
msg("You feel mildly chilly.");
}
} else {
// victim turns to ice for a while!
freezelf(victim, lf, rnd(5,10));
}
killflag(f);
}
}
@ -1074,6 +1082,24 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
return B_FALSE;
}
int damtypecausesbleed(enum DAMTYPE dt) {
switch (dt) {
case DT_PIERCE:
case DT_SLASH:
case DT_BASH:
case DT_BITE:
case DT_CHOP:
case DT_PROJECTILE:
case DT_EXPLOSIVE:
case DT_UNARMED:
case DT_FALL:
return B_TRUE;
default:
break;
}
return B_FALSE;
}
// returns the amount of damage the armour blocked...
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) {
int reduceamt = 0;

View File

@ -6,6 +6,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force);
int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag);
int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag);
void confereffects(flagpile_t *fp, lifeform_t *victim);
int damtypecausesbleed(enum DAMTYPE dt);
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype);
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
//object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag);

16
defs.h
View File

@ -43,6 +43,7 @@ enum SKILL {
SK_BACKSTAB,
SK_CARTOGRAPHY,
SK_CHANNELING,
SK_CLIMBING,
SK_COOKING,
SK_FIRSTAID,
SK_LISTEN,
@ -90,7 +91,7 @@ enum SKILL {
SK_SS_TRANSLOCATION,
SK_SS_WILD,
};
#define MAXSKILLS 49
#define MAXSKILLS 50
// proficiency levels
enum SKILLLEVEL {
@ -145,6 +146,7 @@ enum CHECKTYPE {
SC_IQ,
SC_CON,
//////////
SC_CLIMB,
SC_DISARM,
SC_DODGE,
SC_SHIELDBLOCK,
@ -1089,6 +1091,7 @@ enum OBTYPE {
OT_LOCKPICK,
OT_PANPIPES,
OT_PICKAXE,
OT_ROPE,
OT_TORCH,
OT_TOWEL,
// tech
@ -1106,6 +1109,7 @@ enum OBTYPE {
OT_MOTIONSCANNER,
OT_NVGOGGLES,
OT_PAPERCLIP,
OT_PORTLADDER,
OT_SLEEPINGBAG,
OT_TELEPAD,
OT_TENT,
@ -1518,6 +1522,7 @@ enum FLAG {
F_LIGHTSOURCE, // a light source like a torch, lantern etc
F_CHARGELOWMSG, // text = msg when charges are nearly out
F_CHARGEOUTMSG, // text = msg when charges are gone
F_HELPSCLIMB, // object gives v0 bonus to sc_climb checks.
// technology flags
F_TECHLEVEL, // v0 is a PR_xxx enum for tech usage skill
// what can you do with this object?
@ -1751,6 +1756,7 @@ enum FLAG {
// v0 is spell id
F_AVOIDCURSEDOB, // for AI animals - they will avoid walking on obid 'text'
// (text is a long)
F_FALLDISTANCE, // how many floors this lf has fallen through.
// ABILITY/SPELL FLAGS / ability flags / spell flags
F_FAILEDINSPECT, // lf has failed an inspect check for item id v0
F_BOOSTSPELL, // v0 is active boost spell, v1 is ongoing mpcost, v2 is power
@ -1822,7 +1828,6 @@ enum FLAG {
// this lf's spell casting at all.
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
F_BEHEADED, // use special corpse drop code
F_SILENTMOVE, // lf makes no noise when walking/flying
F_MOVESPEED, // override default move speed
F_ACTIONSPEED, // override default action speed
F_SPELLSPEED, // override default spellcast speed (ie. movespeed)
@ -1925,6 +1930,7 @@ enum FLAG {
// v1 = power
// text = what from.eg'a bad egg'
F_FREEZINGTOUCH,// next thing touched turns to ice!
// v2 is save difficulty
F_GRABBEDBY,// you've been grabbed by lf id v0
F_GRABBING, // you are grabbing lf id v0
F_HEAVYBLOW, // next attack is a heavy blow
@ -1958,11 +1964,12 @@ enum FLAG {
// text must have at least TWO words
F_RISEASGHOST, // become a ghost when you die.
F_SEEINDARK, // nightvis range is val0
F_TREMORSENSE, // doesn't need eyes to see, can see in dark with v0
F_TRUESTRIKE, // your attacks ALWAYS hit. turnsleft=v0
F_SEEINVIS, // can see invisible things
F_SILENTMOVE, // lf makes no noise when walking/flying
F_STABILITY, // doesn't slip over
F_STENCH, // creatures within v0 gain f_nauseated = v1
F_TREMORSENSE, // doesn't need eyes to see, can see in dark with v0
F_TRUESTRIKE, // your attacks ALWAYS hit. turnsleft=v0
F_PRODUCESLIGHT, // produces light of val0 radius.
// (but not for obs in pack)
// if val2 is true, will only make light if ob
@ -2670,6 +2677,7 @@ enum BRAND {
BR_SHADOWS,
BR_SLOTH,
BR_SPEED,
BR_STEALTH,
BR_POWER,
BR_SWIFTNESS,
BR_TELEKINESIS,

31
io.c
View File

@ -1417,6 +1417,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
}
break;
case F_SILENTMOVE:
if (isplayer(lf)) { // don't know if monsters get it
msg("You now move silently.");
donesomething = B_TRUE;
}
break;
case F_SLOWACT:
msg("%s %s",lfname, isplayer(lf) ? "feel sluggish." : "looks sluggish.");
donesomething = B_TRUE;
@ -1902,6 +1908,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
}
break;
case F_SILENTMOVE:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You no longer move silently.");
donesomething = B_TRUE;
}
break;
case F_SLOWACT:
msg("%s %s",lfname, isplayer(lf) ? "no longer feel sluggish." : "no longer looks sluggish.");
donesomething = B_TRUE;
@ -2849,6 +2861,7 @@ void describeob(object_t *o) {
// weight
y = 4;
if (o->material->id != MT_NOTHING) {
if (o->material->id == MT_FOOD) {
sprintf(buf, "%s food product%s, ",(o->amt == 1) ? "It is a" : "They are",
(o->amt == 1) ? "" : "s");
@ -2891,6 +2904,7 @@ void describeob(object_t *o) {
}
y++;
}
}
if (isedible(o)) {
int basenutr;
@ -3049,6 +3063,13 @@ void describeob(object_t *o) {
y++;
}
f = hasflag(o->flags, F_HELPSCLIMB);
if (f) {
mvwprintw(mainwin, y, 0, "It can be used to assist in climbing.");
y++;
}
// skip line
y++;
@ -3364,6 +3385,9 @@ void describeob(object_t *o) {
case F_SEEINDARK:
mvwprintw(mainwin, y, 0, "%s allows you to see in the dark.", buf); y++;
break;
case F_SILENTMOVE:
mvwprintw(mainwin, y, 0, "%s allows you to move silently.", buf); y++;
break;
case F_SLOWACT:
mvwprintw(mainwin, y, 0, "%s will slow down your actions.", buf); y++;
break;
@ -3952,7 +3976,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) {
ch = f->val[0];
if (strlen(f->text)) {
o = addobject(op, f->text, B_FALSE); // no stacking!
o = addobject(op, f->text, B_FALSE, B_FALSE); // no stacking!
// remember letter
o->letter = ch;
// make object fully known
@ -8325,6 +8349,11 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
f = lfhasflag(lf, F_SILENTMOVE);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s move%s silently.", you(lf), isplayer(lf) ? "" : "s");
y++;
}
f = lfhasflag(lf, F_STABILITY);
if (f && (f->known)) {

234
lf.c
View File

@ -49,11 +49,13 @@ extern int obdb;
extern enum ERROR reason;
// for xplist
race_t **raceposs;
int *xpposs;
int xplistlen;
int notime = B_FALSE; // prevent taketime from doing anything
void autoweild(lifeform_t *lf) {
object_t *bestwep,*bestfirearm;
@ -1923,6 +1925,15 @@ int digdown(lifeform_t *lf, object_t *o) {
// TODO: check if the floor is solid?
if (o) {
if (lfhasflag(lf, F_LEVITATING)) {
if (isplayer(lf)) {
msg("You can't reach the ground from up here!");
}
return B_TRUE;
}
}
if (isplayer(lf)) {
msg("You dig a hole in the floor.");
} else if (cansee(player, lf)) {
@ -1932,7 +1943,9 @@ int digdown(lifeform_t *lf, object_t *o) {
addob(lf->cell->obpile, "hole in the ground");
// takes a lot of time
if (o) {
taketime(lf, getactspeed(lf) * 9);
}
return B_FALSE;
}
@ -1948,14 +1961,15 @@ int digup(lifeform_t *lf, object_t *o) {
return B_TRUE;
}
// TODO: check if the roof is solid?
// if digging with an object, you must be able to reach the roof
if (o) {
if (!isairborne(lf)) {
if (isplayer(lf)) {
msg("You can't reach the roof!");
}
return B_TRUE;
}
}
if (isplayer(lf)) {
msg("You dig a hole in the roof.");
@ -1969,7 +1983,9 @@ int digup(lifeform_t *lf, object_t *o) {
addob(lf->cell->obpile, "hole in the roof");
// takes a LOT of time since gravity is against us
if (o) {
taketime(lf, getactspeed(lf) * 18);
}
return B_FALSE;
}
@ -3170,8 +3186,8 @@ 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) {
// include allies or enemies which will follow you up/down stairs etc
void getadjallies(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *nadjallies) {
int d;
for (d = DC_N; d <= DC_NW; d++) {
cell_t *c;
@ -3179,6 +3195,13 @@ void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies) {
if (c && c->lf) {
if (areallies(lf, c->lf) || areenemies(lf, c->lf)) {
if (!isimmobile(c->lf) && cansee(c->lf, lf)) {
int ok = B_TRUE;
// if this was a pit, only flying things will follow
if (stairob && hasflag(stairob->flags, F_PIT)) {
if (!lfhasflag(c->lf, F_FLYING)) {
ok = B_FALSE;
}
}
adjally[*nadjallies] = c->lf;
(*nadjallies)++;
}
@ -6565,6 +6588,11 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
if (!islit(dest)) {
return B_FALSE;
}
} else {
// inside our nightvis range and magically dark
if (dest->lit == L_PERMDARK) {
return B_FALSE;
}
}
}
@ -6723,6 +6751,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_LOCKPICKING, PR_NOVICE, NA, NULL);
mayusespellschool(lastjob->flags, SS_ALLOMANCY, F_CANCAST);
addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STEALTH, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, NA, NA, NULL);
@ -6752,6 +6781,7 @@ void initjobs(void) {
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_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LOCKPICKING, NA, NA, NULL);
@ -6797,6 +6827,7 @@ void initjobs(void) {
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_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
@ -6845,6 +6876,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANWILL, OT_A_JUMP, 3, 3, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_METALWORK, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, NA, NA, NULL);
@ -6901,6 +6933,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "5 potions of rum");
// skills
addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_SKILLED, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CLIMBING, PR_BEGINNER, NA, NULL);
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);
@ -6927,6 +6960,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "5 lockpicks");
addflag(lastjob->flags, F_MPDICE, 1, NA, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CLIMBING, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_STEALTH, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LISTEN, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_BACKSTAB, PR_BEGINNER, NA, NULL);
@ -10622,17 +10656,9 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
}
// occasionally drop blood
switch (damtype) {
case DT_POISON:
case DT_POISONGAS:
case DT_WATER:
break;
default:
if (onein(3)) {
if (damtypecausesbleed(damtype) && onein(3)) {
bleed(lf);
}
break;
}
if (hasflag(lf->flags, F_DEBUG)) {
msg("[%s takes %d dam]",lfname, amt);
@ -12339,6 +12365,7 @@ void initskills(void) {
addskill(SK_BACKSTAB, "Backstab", "Lets you inflict massive damage with stabs when unseen.", 50);
addskill(SK_CARTOGRAPHY, "Cartography", "Your ability to create and interpret maps.", 0); // untrainable
addskill(SK_CHANNELING, "Channeling", "Lets you make better use of magical items.", 0); // untrainable
addskill(SK_CLIMBING, "Climbing", "Helps you to climb walls, mountains or other terrain.", 50);
addskill(SK_COOKING, "Cooking", "Your ability to combine foods into nutritious meals.", 50);
addskill(SK_FIRSTAID, "First Aid", "Increases your healing rate and reduces duration of poison.", 0); // untrainable
addskill(SK_LISTEN, "Listen", "How good you are at hearing and interpreting sounds.", 100);
@ -12507,6 +12534,9 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
attrib += (getattr(lf, A_DEX)/4);
}
break;
case SC_CLIMB:
attrib = (getskill(lf, SK_CLIMBING)*2);
break;
case SC_DODGE:
// getevasion returns 0-100 (ie. pct chance)
// convert this to 0-20
@ -12535,7 +12565,15 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
levmod = (lf->level / 3);
// other modifiers
if (ct == SC_SLIP) {
if (ct == SC_CLIMB) {
object_t *o;
for (o = lf->pack->first ; o ; o = o->next) {
f = hasflag(o->flags, F_HELPSCLIMB);
if (f && isknown(o)) {
othermod += f->val[0];
}
}
} else if (ct == SC_SLIP) {
if (getequippedob(lf->pack, BP_FEET)) {
othermod += 5;
}
@ -13001,8 +13039,7 @@ void taketime(lifeform_t *lf, long howlong) {
int db = B_FALSE;
map_t *map;
if (lfhasflag(lf, F_NOTIME)) {
if (notime || lfhasflag(lf, F_NOTIME)) {
return;
}
@ -13061,6 +13098,10 @@ int throwat(lifeform_t *thrower, object_t *o, cell_t *where) {
void timeeffectslf(lifeform_t *lf) {
object_t *o, *nexto;
flag_t *f,*nextf;
int dir;
// make SURE we don't take any time!
notime = B_TRUE;
// decrement flags
timeeffectsflags(lf->flags);
@ -13082,6 +13123,7 @@ void timeeffectslf(lifeform_t *lf) {
}
if (isdead(lf)) {
killflagsofid(lf->flags, F_NOTIME);
return;
}
@ -13121,19 +13163,78 @@ void timeeffectslf(lifeform_t *lf) {
}
// holes in the floor/roof
o = hasobwithflagval(lf->cell->obpile, F_PIT, D_DOWN, NA, NA, NULL);
if (o) {
if (!isairborne(lf)) {
usestairs(lf, o, B_FALSE);
for (dir = D_UP; dir <= D_DOWN; dir++) {
int donesomething = B_TRUE;
o = hasobwithflagval(lf->cell->obpile, F_PIT, dir, NA, NA, NULL);
while (o && donesomething) {
int willfall = B_FALSE;
donesomething = B_FALSE;
if ((dir == D_DOWN) && !isairborne(lf)) {
willfall = B_TRUE;
} else if ((dir == D_UP) && lfhasflag(lf, F_LEVITATING)) {
willfall = B_TRUE;
}
}
o = hasobwithflagval(lf->cell->obpile, F_PIT, D_UP, NA, NA, NULL);
if (o) {
if (lfhasflag(lf, F_LEVITATING)) {
if (willfall) {
usestairs(lf, o, B_FALSE);
donesomething = B_TRUE;
o = hasobwithflagval(lf->cell->obpile, F_PIT, dir, NA, NA, NULL);
}
}
}
notime = B_FALSE;
}
// return B_TRUE on failure.
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat) {
// if you have a rope or there's an adjacent wall, you can try
// to climb up
int adjwalls;
char lfname[BUFLEN];
getlfname(lf, lfname);
adjwalls = countadjwalls(where);
if (adjwalls || hasobwithflag(lf->pack, F_HELPSCLIMB)) {
if (isplayer(lf)) {
msg("You start climbing...");
} else if (cansee(player, lf)) {
msg("%s starts climbing...", lfname);
}
taketime(lf, getactspeed(lf));
// base difficulty of 20
if (skillcheck(lf, SC_CLIMB, 20, (countadjwalls(where)+1)/2)) {
// you made it!
if (isplayer(lf)) {
msg("You reach %s.", towhat);
} else if (cansee(player, lf)) {
msg("%s reaches %s.", towhat);
}
// train climbing
practice(lf, SK_CLIMBING, 1);
// continue...
} else {
// you fall.
if (isplayer(lf)) {
msg("You fall to the ground!");
} else if (cansee(player, lf)) {
msg("%s falls to the ground!", lfname);
}
fall(lf, NULL, B_FALSE); // this will take some time.
losehp(lf, roll("1d6"), DT_FALL, NULL, "a fall while climbing");
return B_TRUE;
}
} else { // no rope or adjacent walls
if (isplayer(lf)) {
msg("You can't reach the roof!");
}
return B_TRUE;
}
// success
return B_FALSE;
}
//////////////////////////////////
@ -13967,6 +14068,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
flag_t *f;
map_t *curmap;
map_t *newmap;
cell_t *obcell;
cell_t *newcell;
int dir;
int newdepth;
@ -13985,20 +14087,21 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
getlfname(lf, lfname);
getobname(o, obname, 1);
obcell = getoblocation(o);
if (initiatemove(lf, NULL, NULL)) {
// failed?
return B_FALSE;
}
curmap = lf->cell->map;
curmap = obcell->map;
f = hasflag(o->flags, F_CLIMBABLE);
assert(f);
dir = f->val[0];
if (f->val[1] == NA) {
// use same region
newregion = lf->cell->map->region;
newregion = obcell->map->region;
} else {
newregion = findregion(f->val[1]);
}
@ -14032,14 +14135,16 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
// can only go up if you have a rope or are flying/levitating
if (lfhasflag(lf, F_LEVITATING) || lfhasflag(lf, F_FLYING)) {
// ok.
} else { // TODO: if has rope???
if (isplayer(lf)) {
msg("You can't reach the roof!");
}
} else {
char buf[BUFLEN];
sprintf(buf, "the %s", noprefix(obname));
if (tryclimb(lf, obcell, buf)) {
// failed
return B_TRUE;
}
}
}
}
// announce
curs_set(1);
@ -14070,9 +14175,9 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
}
// find adjacent allies or enemies which will follow you
// (but not into/out of pits)
if (isplayer(lf) || !hasflag(o->flags, F_PIT)) {
getadjallies(lf, adjally, &nadjallies);
// (getadjallies will handle following through pits)
if (isplayer(lf)) {
getadjallies(lf, o, adjally, &nadjallies);
}
// do stairs go somewhere?
@ -14100,9 +14205,11 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
// previous/next levels in the same region.
// if not, we need to call linkstairs() on the staircase first.
/*
if (newmap->region->id != curmap->region->id) {
linkstairs(o);
}
*/
// at this point, stairs should have a destination
newcell = getstairdestination(o);
}
@ -14112,10 +14219,29 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
curs_set(0);
if (newcell) {
int n;
// if we just climbed up through a hole, and are not flying, we want to
// end up adjacent to the hole in the ground. otherwise we'll just fall
// straight back down!
if (hasflag(o->flags, F_PIT) && (dir == D_UP) && !isairborne(lf)) {
cell_t *noholecell;
noholecell = real_getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL);
if (noholecell) {
// go here instead
newcell = noholecell;
} else {
// alert
if (isplayer(lf)) {
msg("You can't find anywhere safe to get out.");
}
}
}
// check noone is in the way
if (newcell->lf) {
cell_t *c;
// if they are, move them
// if they are, find somewhere to move them.
c = getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) {
// move them there
@ -14168,24 +14294,56 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
if (falling) {
if (dir == D_DOWN) {
if (hasobwithflagval(lf->cell->obpile, F_PIT, D_DOWN, NA, NA, NULL)) {
flag_t *ff;
// inc fall distance
ff = lfhasflag(lf, F_FALLDISTANCE);
if (ff) {
ff->val[0]++;
} else {
addflag(lf->flags, F_FALLDISTANCE, 1, NA, NA, NULL);
}
} else {
int howfar;
if (isplayer(lf)) {
msg("You slam into the ground!");
} else if (cansee(player, lf)){
msg("%s slams into the ground!", lfname);
}
// take fall damage
losehp(lf, roll("2d6"), DT_FALL, NULL, "falling");
// how far did you fall?
sumflags(lf->flags, F_FALLDISTANCE, &howfar, NULL, NULL);
howfar++;
// take fall damage. 2d6 per level.
losehp(lf, rolldie(howfar*2, 6), DT_FALL, NULL, "falling");
killflagsofid(lf->flags, F_FALLDISTANCE);
// fall over
fall(lf, NULL, B_FALSE);
}
} else {
// TODO: if you are outside, DIE!
if (hasobwithflagval(lf->cell->obpile, F_PIT, D_UP, NA, NA, NULL)) {
flag_t *ff;
// inc fall distance
ff = lfhasflag(lf, F_FALLDISTANCE);
if (ff) {
ff->val[0]++;
} else {
addflag(lf->flags, F_FALLDISTANCE, 1, NA, NA, NULL);
}
} else {
int howfar;
if (isplayer(lf)) {
msg("You slam into the roof!");
} else if (cansee(player, lf)){
msg("%s slams into the roof!", lfname);
}
// take hitting roof damage
losehp(lf, roll("1d4"), DT_FALL, NULL, "slamming into the roof");
// how far did you fall?
sumflags(lf->flags, F_FALLDISTANCE, &howfar, NULL, NULL);
howfar++;
// take hitting roof damage (less than floor). 1d4 per level.
losehp(lf, rolldie(howfar, 4), DT_FALL, NULL, "slamming into the roof");
killflagsofid(lf->flags, F_FALLDISTANCE);
}
}
}

3
lf.h
View File

@ -79,7 +79,7 @@ void gainmp(lifeform_t *lf, int amt);
void gainxp(lifeform_t *lf, long amt);
void genxplist(void);
int getactspeed(lifeform_t *lf);
void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies);
void getadjallies(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *nadjallies);
enum ALLEGIENCE getallegiance(lifeform_t *lf);
int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs);
object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
@ -295,6 +295,7 @@ int takeoff(lifeform_t *lf, object_t *o);
void taketime(lifeform_t *lf, long howlong);
int throwat(lifeform_t *thrower, object_t *o, cell_t *where);
void timeeffectslf(lifeform_t *lf);
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat);
void turneffectslf(lifeform_t *lf);
int touch(lifeform_t *lf, object_t *o);
void unpoison(lifeform_t *lf);

121
map.c
View File

@ -389,6 +389,20 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) {
return rv;
}
map_t *getmapindir(map_t *src, int dir) {
map_t *other = NULL;
if (src->nextmap[dir] != -1) {
other = findmap(src->nextmap[dir]);
} else {
if (dir == D_DOWN) {
other = findregionmap(src->region->id, src->depth+1);
} else {
other = findregionmap(src->region->id, src->depth-1);
}
}
return other;
}
// 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 *);
@ -1276,6 +1290,20 @@ int countadjcellsoftype(cell_t *cell, int id) {
return count;
}
int countadjwalls(cell_t *cell) {
int d;
int walls = 0;
for (d = DC_N; d <= DC_NW; d++) {
cell_t *newcell;
newcell = getcellindir(cell, d);
if (!newcell || newcell->type->solid) {
walls++;
}
}
return walls;
}
int countcellexits(cell_t *cell) {
int d;
int exits = 0;
@ -1751,7 +1779,6 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
map_t *m;
char buf[BUFLEN];
int i,x,y;
int firstworldmap = B_FALSE;
enum HABITAT habitat;
regionthing_t *thing[MAXOUTLINETHINGS];
int nthings = 0;
@ -1760,10 +1787,11 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
// note: we might override this later based on our region outline
habitat = region->rtype->defaulthabitat;
/*
if ((region->rtype->id == RG_WORLDMAP) && (depth == 1)) {
firstworldmap = B_TRUE;
}
*/
map->beingcreated = B_TRUE;
map->depth = depth;
@ -1777,6 +1805,9 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
// link to other maps if required.
// default to no links
for (i = D_N; i <= D_W; i++) {
map->nextmap[i] = -1;
}
for (i = D_UP; i <= D_DOWN; i++) {
map->nextmap[i] = -1;
}
@ -1795,17 +1826,27 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
}
}
// did we come from a previous map?
if (parentmap) {
parentmap->nextmap[exitdir] = map->id;
for (i = 0; i < MAXDIR_ORTH; i++) {
if (parentmap && (i == diropposite(exitdir)) ) {
map->nextmap[diropposite(exitdir)] = parentmap->id;
}
/*
if (map->region->rtype->id == RG_WORLDMAP) {
map_t *adjmap;
for (i = D_N; i <= D_W; i++) {
// is there a map this dir from us???
adjmap = findmapcoords(, x, y);
if (i == diropposite(exitdir) ) {
map->nextmap[i] = parentmap->id;
} else {
map->nextmap[i] = -1;
}
}
}
*/
map->w = MAX_MAPW;
map->h = MAX_MAPH;
@ -1818,7 +1859,8 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
srand(map->seed);
// set map coords
if (firstworldmap) {
// first world map??
if (map == firstmap) {
addflag(map->flags, F_MAPCOORDS, 0, 0, NA, NULL);
} else {
// set mapcoords if not already done.
@ -1947,7 +1989,8 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
}
}
// link up holes - this will add matching holes on adjacent maps
// link up holes - this will create NEW holes in THIS map connecting to
// EXISTING unlinked holes in adjacent maps
linkholes(map);
// add random objects and monsters
@ -2175,8 +2218,8 @@ void createpit(map_t *map, int depth, map_t *parentmap, int exitdir) {
c = getrandomcell(map);
// clear it
setcelltype(c, CT_CORRIDOR);
// put an exit here
o = addob(c->obpile, "hole in the roof");
// put an exit here - don't link it yet - this will happen back in createmap().
o = addobject(c->obpile, "hole in the roof", B_FALSE, B_FALSE);
assert(o);
}
@ -2622,10 +2665,10 @@ map_t *findsurfaceexitmap(map_t *m) {
if (c) {
for (o = c->obpile->first ; o ; o = o->next) {
if (hasflagval(o->flags, F_CLIMBABLE, D_UP, NA, NA, NULL)) {
cell_t *c;
c = getstairdestination(o);
if (c) {
return c->map;
cell_t *newc;
newc = getstairdestination(o);
if (newc) {
return newc->map;
}
}
}
@ -3449,22 +3492,25 @@ int iswallindir(cell_t *cell, int dir) {
return B_FALSE;
}
// search for unlinked pits/holes in roof in adjacent maps
// if we find any, add a matching end as close as we can in this map.
// search for unlinked pits/holes in roof in ADJACENT maps
// if we find any, add a matching end as close as we can in THIS map.
void linkholes(map_t *map) {
map_t *adjmap;
cell_t *c;
object_t *o, *newob;
int x,y;
// check previous map for pits.
adjmap = findregionmap(map->region->id, map->depth-1);
int dir;
for (dir = D_UP ; dir <= D_DOWN; dir++) {
adjmap = getmapindir(map, dir);
if (adjmap) {
for (y = 0; y < adjmap->h; y++) {
for (x = 0; x < adjmap->w; x++) {
c = getcellat(adjmap, x, y);
if (c) {
// does the adjacent map have an unlinked pit going to us?
for (o = c->obpile->first ; o ; o = o->next) {
if (hasflagval(o->flags, F_PIT, D_DOWN, NA, NA, NULL) &&
if (hasflagval(o->flags, F_PIT, diropposite(dir), NA, NA, NULL) &&
!hasflag(o->flags, F_MAPLINK)) {
cell_t *c2;
objecttype_t *ot;
@ -3472,9 +3518,13 @@ void linkholes(map_t *map) {
// make a link to it in this map, as close as possible to same pos
c2 = getcellat(map, x, y);
if (c2->type->solid) {
c2 = real_getrandomadjcell(c2, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, &ot->id);
// this will automatically avoid lifeforms since we're using
// we_walkable rather than we_notwall. this saves problems
// with someine coming up underneath you!
c2 = real_getrandomadjcell(c2, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, &ot->id);
}
newob = addob(c2->obpile, ot->name);
// note we specifically say DONT link the new hole!
newob = addobject(c2->obpile, ot->name, B_FALSE, B_FALSE);
// link them!
linkstairs(newob);
}
@ -3484,12 +3534,12 @@ void linkholes(map_t *map) {
}
}
}
}
// link the staircase 'o' to a free one in adjacent maps.
// returns TRUE if it failed because othermap doesn't exist.
int linkstairs(object_t *o) {
map_t *othermap;
int othermapid;
object_t *o2;
map_t *stairmap;
cell_t *staircell;
@ -3522,13 +3572,7 @@ int linkstairs(object_t *o) {
// if so, find the first map in that region (ie depth 1)
othermap = findregionmap(f->val[1], 1);
} else {
othermapid = stairmap->nextmap[f->val[0]];
othermap = findmap(othermapid);
if (!othermap) {
// find next map based on depth...
othermap = findregionmap(stairmap->region->id, stairmap->depth+dir);
}
othermap = getmapindir(stairmap, f->val[0]);
}
if (othermap) {
// find an empty staircase in other map
@ -3536,23 +3580,8 @@ int linkstairs(object_t *o) {
c2 = othermap->cell[n];
o2 = hasob(c2->obpile, otherstairtype->id);
if (o2) {
int ok = B_FALSE;
// does it go nowhere?
if (!hasflag(o2->flags, F_MAPLINK)) {
if (othermap->region->id == stairmap->region->id) {
ok = B_TRUE;
} else {
/*
// handle cross-region stairs!
f = hasflag(o2->flags, F_CLIMBABLE);
if (f->val[1] == stairmap->region->id) {
ok = B_TRUE;
}
*/
ok = B_TRUE;
}
if (ok) {
char obid[BUFLEN];
// link it to here!
sprintf(obid, "%ld", o->id);
@ -3561,11 +3590,12 @@ int linkstairs(object_t *o) {
sprintf(obid, "%ld", o2->id);
addflag(o->flags, F_MAPLINK, othermap->id, NA, NA, obid);
found = B_TRUE;
// now mark that we are not a new staircase to a new region anymore
f->val[1] = NA;
break;
}
}
}
}
if (!found) {
dblog("ERROR - stairs link to existing map %d, but it has no free stairs.",othermap->id);
msg("ERROR - stairs link to existing map %d, but it has no free stairs.",othermap->id);
@ -3883,3 +3913,8 @@ int wallstoleftright(cell_t *c, int dir) {
}
return B_FALSE;
}

2
map.h
View File

@ -24,6 +24,7 @@ int getdoorlockdiff(int depth);
int getdoorsecretdiff(int depth);
flag_t *getmapcoords(map_t *m, int *x, int *y);
int getmapdifficulty(map_t *m);
map_t *getmapindir(map_t *src, int dir);
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);
@ -31,6 +32,7 @@ void calclight(map_t *map);
int calcroompos(map_t *map, int w, int h, int *bx, int *by, int force);
int countadjcellsoftype(cell_t *cell, int id);
int countadjcellswithflag(cell_t *cell, enum FLAG fid);
int countadjwalls(cell_t *cell);
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);

63
move.c
View File

@ -168,13 +168,24 @@ 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 (onlyifknown && !canseeob(lf, o)) continue;
if (hasflag(o->flags, F_TRAP)) {
if (error) {
*error = E_AVOIDOB;
rdata = o;
}
return B_TRUE;
}
f = hasflag(o->flags, F_PIT);
if (f && (f->val[0] == D_DOWN)) {
if (!isairborne(lf)) {
if (error) {
*error = E_AVOIDOB;
rdata = o;
}
return B_TRUE;
}
}
f = hasflag(o->flags, F_DEEPWATER);
if (f) {
// non swimming creature in water?
@ -340,6 +351,10 @@ int diropposite(int dir) {
return DC_E;
case DC_NW:
return DC_SE;
case D_UP:
return D_DOWN;
case D_DOWN:
return D_UP;
}
// should never happen!
return dir;
@ -582,6 +597,39 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in
return bestdir;
}
int getwalkoffdir(lifeform_t *lf, int dir) {
switch (dir) {
case DC_NE:
if (lf->cell->y == 0) {
return DC_N;
} else if ( lf->cell->x == (lf->cell->map->w-1)) {
return DC_E;
}
break;
case DC_SE:
if (lf->cell->y == (lf->cell->map->h-1)) {
return DC_S;
} else if ( lf->cell->x == (lf->cell->map->w-1)) {
return DC_E;
}
break;
case DC_SW:
if (lf->cell->y == (lf->cell->map->h-1)) {
return DC_S;
} else if ( lf->cell->x == 0) {
return DC_W;
}
break;
case DC_NW:
if (lf->cell->y == 0) {
return DC_N;
} else if ( lf->cell->x == 0) {
return DC_W;
}
break;
}
return D_NONE;
}
// use 'n/a' for zero chance of falling. 0 means 'calculate based on distance'
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff) {
@ -2018,16 +2066,23 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
if (isswimming(lf)) {
practice(lf, SK_SWIMMING, 1);
}
} else {
} else { // ie !moveok
object_t *inway = NULL;
int door, dooropen;
reason = errcode;
switch (errcode) {
case E_OFFMAP:
if ((lf->cell->map->region == RG_WORLDMAP) && (isorthogonal(dir))) {
if (lf->cell->map->region->rtype->id == RG_WORLDMAP) {
// cope with nonorthogonal!
// ie. ne counts as n if we are at the top.
if (!isorthogonal(dir)) {
dir = getwalkoffdir(lf, dir);
}
if (dir != D_NONE) {
// we are allowed to walk off the edge
return walkoffmap(lf, dir, B_TRUE);
}
}
// otherwise fall through...
case E_WALLINWAY:
if (isplayer(lf)) {
@ -2264,7 +2319,7 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
if (onpurpose) {
// get list of adjacent allies
if (isplayer(lf)) {
getadjallies(lf, adjally, &nadjallies);
getadjallies(lf, NULL, adjally, &nadjallies);
}
}

1
move.h
View File

@ -10,6 +10,7 @@ int diropposite(int dir);
int dorandommove(lifeform_t *lf, int badmovesok, int restonfail);
int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int getwalkoffdir(lifeform_t *lf, int dir);
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff);
int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype);
int moveclear(lifeform_t *lf, int dir, enum ERROR *error);

View File

@ -192,7 +192,7 @@ int main(int argc, char **argv) {
// create first dungeon
dregion = findregionbytype(RG_FIRSTDUNGEON);
dmap = addmap();
createmap(dmap, 1, dregion, NULL, D_NONE);
createmap(dmap, 1, dregion, firstmap, D_DOWN);
}
// find staircase

105
objects.c
View File

@ -390,7 +390,7 @@ void addocnoun(objectclass_t *oc, char *text) {
// create a new object, stacking ok
object_t *addob(obpile_t *where, char *name) {
return addobject(where, name, B_TRUE);
return addobject(where, name, B_TRUE, B_TRUE);
}
// create a new object
@ -399,7 +399,7 @@ object_t *addob(obpile_t *where, char *name) {
// object with o->amt set, instead of
// creating new obejct entries.
// NOTE: This function MUST return number of obs created via global "nretobs"
object_t *addobject(obpile_t *where, char *name, int canstack) {
object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes) {
objecttype_t *ot;
object_t *o = NULL;
char *p,*nsp,*p2;
@ -981,52 +981,25 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
addflag(o->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, selhn->text);
}
// link holes to adjacent maps
if (o && hasflag(o->flags,F_PIT)) {
dblog("added pit");
}
// create linked holes in adjacent maps
if (wantlinkholes && o && hasflag(o->flags, F_PIT)) {
cell_t *c;
map_t *adjmap = NULL;
f = hasflag(o->flags, F_PIT);
c = getoblocation(o);
if ((c->map->region->rtype->id == RG_WORLDMAP) && (f->val[0] == D_DOWN)) {
// ie. going down from the surface. MUST be down because holes
// going up make no sense!
adjmap = getmapindir(c->map, f->val[0]);
if ((c->map->region->rtype->id == RG_WORLDMAP) && !adjmap) {
// ie. going down from the surface, and no dungeon below.
// ( MUST be down because holes going up make no sense! )
createregionlink(c->map, c, o, NULL, RG_PIT, c->map->region);
} else {
// create linked holes on any existing adjacent maps
if (f->val[0] == D_DOWN) {
adjmap = findregionmap(c->map->region->id, c->map->depth+1);
} else if (f->val[0] == D_UP) {
if ((c->map->region->rtype->id != RG_WORLDMAP) &&
(c->map->depth == 1) &&
(c->map->region->rtype->deeperdir == D_DOWN)) {
cell_t *newcell;
object_t *newob;
char buf[BUFLEN];
// ie. digging up to the surface
adjmap = findsurfaceexitmap(c->map);
// make a hole here. don't use linkholes since it can't
// cross regions.
newcell = getcellat(adjmap, c->x, c->y);
if (newcell->type->solid) {
newcell = real_getrandomadjcell(newcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, &(o->type->id));
}
newob = addob(newcell->obpile, "hole in the ground");
sprintf(buf, "%ld", o->id);
addflag(newob->flags, F_MAPLINK, c->map->id, NA, NA, buf);
sprintf(buf, "%ld", newob->id);
addflag(o->flags, F_MAPLINK, adjmap->id, NA, NA, buf);
// don't call linkholes
adjmap = NULL;
} else {
adjmap = findregionmap(c->map->region->id, c->map->depth-1);
}
}
// create linked holes on the map at the other end of this one.
if (adjmap) {
linkholes(adjmap);
}
@ -5043,6 +5016,8 @@ void initobjects(void) {
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_FASTMOVE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_SLOTH, "of sloth", BP_FEET);
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_SLOWMOVE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_STEALTH, "of stealth", BP_FEET);
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_SILENTMOVE, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1);
// hands
addbrand(BR_POWER, "of power", BP_HANDS);
@ -6131,7 +6106,7 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l2
addot(OT_S_FREEZEOB, "freezing touch", "Permenantly changes the next object touched into solid ice.", MT_NOTHING, 0, OC_SPELL);
addot(OT_S_FREEZEOB, "freezing touch", "Changes the next thing touched into solid ice. The effect is permenant for inanimate objects, but will wear off on living creatures.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
@ -6709,7 +6684,7 @@ void initobjects(void) {
addot(OT_WAND_DIGGING, "wand of digging", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_DIG, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL);
//addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL);
addot(OT_WAND_COLD, "wand of cold", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_COLDRAY, NA, NA, NULL);
@ -6846,6 +6821,11 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addot(OT_ROPE, "rope", "A long length of strong rope.", MT_CLOTH, 5, OC_TOOLS);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 75, NA, NULL);
addflag(lastot->flags, F_HELPSCLIMB, 3, NA, NA, NULL);
addot(OT_TORCH, "torch", "A metre-long wooden rod with a flammable end.", MT_WOOD, 2, OC_TOOLS);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
@ -6973,7 +6953,28 @@ void initobjects(void) {
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
// tech - l3
addot(OT_INFOVISOR, "infovisor", "Sleek looking metal visor which displays info directly into the retina.", MT_METAL, 0.2, OC_TECH);
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_EXTRAINFO, B_TRUE, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ENHANCESEARCH, 10, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_ADEPT, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_LOCKHACKER, "lock hacker", "A sophisticated machine to manipulate physical locks.", MT_METAL, 3, OC_TECH);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_ADEPT, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_PORTLADDER, "portable ladder", "A lightweight two metre ladder which automatically folds down to pocket size.", MT_METAL, 2, OC_TECH);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_ADEPT, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
// tech - l4
addot(OT_JETPACK, "jet pack", "A portable ion-thruster which allows the wearer to fly.", MT_METAL, 10, OC_TECH);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
@ -6982,21 +6983,6 @@ void initobjects(void) {
addflag(lastot->flags, F_REFILLWITH, OT_POT_OIL, NA, NA, NULL);
addflag(lastot->flags, F_ACTIVATECONFER, F_FLYING, B_TRUE, NA, NULL);
addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 1, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_ADEPT, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
// tech - l4
addot(OT_INFOVISOR, "infovisor", "Sleek looking metal visor which displays info directly into the retina.", MT_METAL, 0.2, OC_TECH);
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_EXTRAINFO, B_TRUE, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ENHANCESEARCH, 10, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_SKILLED, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_LOCKHACKER, "lock hacker", "A sophisticated machine to manipulate physical locks.", MT_METAL, 3, OC_TECH);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_SKILLED, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
@ -9888,14 +9874,10 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
sprintf(buf, "Where will you aim %s?",obname);
where = askcoords(buf, subprompt, ttype, lf, UNLIMITED, LOF_NEED, B_TRUE);
if (!haslos(lf, where)) {
// exception - wand of digging doesn't need los
if (isknown(o) && (o->type->id == OT_WAND_DIGGING)) {
} else {
msg("You can't see there!");
return B_TRUE;
}
}
}
} else {
char lfname[BUFLEN];
getlfname(lf, lfname);
@ -10001,7 +9983,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
msg("%s zaps %s.",lfname,obname);
}
f = hasflag(o->flags, F_LINKSPELL);
if (f) {
enum OBTYPE spelltocast;
@ -11997,7 +11978,7 @@ object_t *splitob(object_t *o) {
// doesn't matter if it goes down to zero, as we will put it back up soon.
o->amt--;
// give new object
newob = addobject(o->pile, o->type->name, B_NOSTACK);
newob = addobject(o->pile, o->type->name, B_NOSTACK, B_FALSE);
// restore count
o->amt++;
if (newob) {

View File

@ -10,7 +10,7 @@ material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour);
void addocnoun(objectclass_t *oc, char *text);
object_t *addob(obpile_t *where, char *name);
object_t *addobject(obpile_t *where, char *name, int canstack);
object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes);
int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf, enum LOFTYPE needlof);
obmod_t *addobmod(enum OBMOD id, char *prefix);
obpile_t *addobpile(lifeform_t *owner, cell_t *where);

2
save.c
View File

@ -498,7 +498,7 @@ int loadob(FILE *f, obpile_t *op, long *id) {
return B_TRUE;
}
// create the object
o = addobject(op, ot->name, B_NOSTACK); // no stacking!
o = addobject(op, ot->name, B_NOSTACK, B_FALSE); // no stacking!
// overwrite ob parameters
o->id = obid;

49
spell.c
View File

@ -2584,29 +2584,49 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_DIG) {
int numseen = 0;
cell_t *retcell[MAXRETCELLS];
int nretcell,i;
cell_t *c;
int ndigs;
char ch;
int dir;
if (targcell) {
dir = getdirtowards(caster->cell, targcell, NULL, B_FALSE, DT_COMPASS);
} else {
// don't need line of fire OR sight!
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE;
//if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE;
ch = askchar("Dig in which direction (- to cancel)", "yuhjklbn.-<>","-", B_FALSE);
if ((ch == '.') || (ch == '-')) {
fizzle(caster);
return B_TRUE;
} else if (ch == '<') {
return digup(caster, NULL);
} else if (ch == '>') {
return digdown(caster, NULL);
} else {
dir = chartodir(ch);
}
}
// calculate a line from caster to the target cell
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y,
targcell->x, targcell->y, retcell, &nretcell);
if (dir == DT_NONE) {
fizzle(caster);
return B_TRUE;
}
ndigs = 0;
// get rid of rock in the cells...
for (i = 0; i < nretcell && (ndigs <= power) ; i++) {
c = getcellindir(caster->cell, dir);
while (c && (ndigs <= power)) {
int seenthiscell = B_FALSE;
if (haslos(player, retcell[i])) seenthiscell = B_TRUE;
if (retcell[i]->type->solid) {
if (haslos(player, c)) seenthiscell = B_TRUE;
if (c->type->solid) {
// can dig through stone, but nothing else.
if (retcell[i]->type->material->id == MT_STONE) {
setcelltype(retcell[i], retcell[i]->map->habitat->emptycelltype);
if (seenthiscell) {
if (c->type->material->id == MT_STONE) {
setcelltype(c, c->map->habitat->emptycelltype);
ndigs++;
if (seenthiscell) {
numseen++;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
@ -2616,7 +2636,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else {
object_t *o;
for (o = retcell[i]->obpile->first ; o ; o = o->next) {
for (o = c->obpile->first ; o ; o = o->next) {
if (hasflag(o->flags, F_IMPASSABLE)) {
char obname[BUFLEN];
// destroy this object then stop.
@ -2632,6 +2652,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
}
}
ndigs++;
}
// announce destruction of any walls seen
@ -3429,7 +3450,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else {
// next thing touched
addflag(caster->flags, F_FREEZINGTOUCH, 1, NA, NA, NULL);
addflag(caster->flags, F_FREEZINGTOUCH, 1, NA, 10+power, NULL);
if (isplayer(caster)) {
msg("Your hands begin to glow blue!");
if (seenbyplayer) *seenbyplayer = B_TRUE;