* [+] 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) { if (isunarmed) {
f = lfhasflag(lf, F_FREEZINGTOUCH); f = lfhasflag(lf, F_FREEZINGTOUCH);
if (f) { if (f) {
// victim turns to ice for a while! int diff;
freezelf(victim, lf, rnd(5,10)); 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); killflag(f);
} }
} }
@ -1074,6 +1082,24 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
return B_FALSE; 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... // returns the amount of damage the armour blocked...
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) { int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) {
int reduceamt = 0; 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 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); int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag);
void confereffects(flagpile_t *fp, lifeform_t *victim); 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); 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); 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); //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_BACKSTAB,
SK_CARTOGRAPHY, SK_CARTOGRAPHY,
SK_CHANNELING, SK_CHANNELING,
SK_CLIMBING,
SK_COOKING, SK_COOKING,
SK_FIRSTAID, SK_FIRSTAID,
SK_LISTEN, SK_LISTEN,
@ -90,7 +91,7 @@ enum SKILL {
SK_SS_TRANSLOCATION, SK_SS_TRANSLOCATION,
SK_SS_WILD, SK_SS_WILD,
}; };
#define MAXSKILLS 49 #define MAXSKILLS 50
// proficiency levels // proficiency levels
enum SKILLLEVEL { enum SKILLLEVEL {
@ -145,6 +146,7 @@ enum CHECKTYPE {
SC_IQ, SC_IQ,
SC_CON, SC_CON,
////////// //////////
SC_CLIMB,
SC_DISARM, SC_DISARM,
SC_DODGE, SC_DODGE,
SC_SHIELDBLOCK, SC_SHIELDBLOCK,
@ -1089,6 +1091,7 @@ enum OBTYPE {
OT_LOCKPICK, OT_LOCKPICK,
OT_PANPIPES, OT_PANPIPES,
OT_PICKAXE, OT_PICKAXE,
OT_ROPE,
OT_TORCH, OT_TORCH,
OT_TOWEL, OT_TOWEL,
// tech // tech
@ -1106,6 +1109,7 @@ enum OBTYPE {
OT_MOTIONSCANNER, OT_MOTIONSCANNER,
OT_NVGOGGLES, OT_NVGOGGLES,
OT_PAPERCLIP, OT_PAPERCLIP,
OT_PORTLADDER,
OT_SLEEPINGBAG, OT_SLEEPINGBAG,
OT_TELEPAD, OT_TELEPAD,
OT_TENT, OT_TENT,
@ -1518,6 +1522,7 @@ enum FLAG {
F_LIGHTSOURCE, // a light source like a torch, lantern etc F_LIGHTSOURCE, // a light source like a torch, lantern etc
F_CHARGELOWMSG, // text = msg when charges are nearly out F_CHARGELOWMSG, // text = msg when charges are nearly out
F_CHARGEOUTMSG, // text = msg when charges are gone F_CHARGEOUTMSG, // text = msg when charges are gone
F_HELPSCLIMB, // object gives v0 bonus to sc_climb checks.
// technology flags // technology flags
F_TECHLEVEL, // v0 is a PR_xxx enum for tech usage skill F_TECHLEVEL, // v0 is a PR_xxx enum for tech usage skill
// what can you do with this object? // what can you do with this object?
@ -1751,6 +1756,7 @@ enum FLAG {
// v0 is spell id // v0 is spell id
F_AVOIDCURSEDOB, // for AI animals - they will avoid walking on obid 'text' F_AVOIDCURSEDOB, // for AI animals - they will avoid walking on obid 'text'
// (text is a long) // (text is a long)
F_FALLDISTANCE, // how many floors this lf has fallen through.
// ABILITY/SPELL FLAGS / ability flags / spell flags // ABILITY/SPELL FLAGS / ability flags / spell flags
F_FAILEDINSPECT, // lf has failed an inspect check for item id v0 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 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. // this lf's spell casting at all.
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
F_BEHEADED, // use special corpse drop code F_BEHEADED, // use special corpse drop code
F_SILENTMOVE, // lf makes no noise when walking/flying
F_MOVESPEED, // override default move speed F_MOVESPEED, // override default move speed
F_ACTIONSPEED, // override default action speed F_ACTIONSPEED, // override default action speed
F_SPELLSPEED, // override default spellcast speed (ie. movespeed) F_SPELLSPEED, // override default spellcast speed (ie. movespeed)
@ -1925,6 +1930,7 @@ enum FLAG {
// v1 = power // v1 = power
// text = what from.eg'a bad egg' // text = what from.eg'a bad egg'
F_FREEZINGTOUCH,// next thing touched turns to ice! F_FREEZINGTOUCH,// next thing touched turns to ice!
// v2 is save difficulty
F_GRABBEDBY,// you've been grabbed by lf id v0 F_GRABBEDBY,// you've been grabbed by lf id v0
F_GRABBING, // you are grabbing lf id v0 F_GRABBING, // you are grabbing lf id v0
F_HEAVYBLOW, // next attack is a heavy blow F_HEAVYBLOW, // next attack is a heavy blow
@ -1958,11 +1964,12 @@ enum FLAG {
// text must have at least TWO words // text must have at least TWO words
F_RISEASGHOST, // become a ghost when you die. F_RISEASGHOST, // become a ghost when you die.
F_SEEINDARK, // nightvis range is val0 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_SEEINVIS, // can see invisible things
F_SILENTMOVE, // lf makes no noise when walking/flying
F_STABILITY, // doesn't slip over F_STABILITY, // doesn't slip over
F_STENCH, // creatures within v0 gain f_nauseated = v1 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. F_PRODUCESLIGHT, // produces light of val0 radius.
// (but not for obs in pack) // (but not for obs in pack)
// if val2 is true, will only make light if ob // if val2 is true, will only make light if ob
@ -2670,6 +2677,7 @@ enum BRAND {
BR_SHADOWS, BR_SHADOWS,
BR_SLOTH, BR_SLOTH,
BR_SPEED, BR_SPEED,
BR_STEALTH,
BR_POWER, BR_POWER,
BR_SWIFTNESS, BR_SWIFTNESS,
BR_TELEKINESIS, BR_TELEKINESIS,

107
io.c
View File

@ -1417,6 +1417,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; 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: case F_SLOWACT:
msg("%s %s",lfname, isplayer(lf) ? "feel sluggish." : "looks sluggish."); msg("%s %s",lfname, isplayer(lf) ? "feel sluggish." : "looks sluggish.");
donesomething = B_TRUE; donesomething = B_TRUE;
@ -1902,6 +1908,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; 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: case F_SLOWACT:
msg("%s %s",lfname, isplayer(lf) ? "no longer feel sluggish." : "no longer looks sluggish."); msg("%s %s",lfname, isplayer(lf) ? "no longer feel sluggish." : "no longer looks sluggish.");
donesomething = B_TRUE; donesomething = B_TRUE;
@ -2849,47 +2861,49 @@ void describeob(object_t *o) {
// weight // weight
y = 4; y = 4;
if (o->material->id == MT_FOOD) { if (o->material->id != MT_NOTHING) {
sprintf(buf, "%s food product%s, ",(o->amt == 1) ? "It is a" : "They are", if (o->material->id == MT_FOOD) {
(o->amt == 1) ? "" : "s"); sprintf(buf, "%s food product%s, ",(o->amt == 1) ? "It is a" : "They are",
} else { (o->amt == 1) ? "" : "s");
sprintf(buf, "%s made from %s, ",(o->amt == 1) ? "It is" : "They are", o->material->name);
}
if (o->amt == 1) {
char wbuf[BUFLEN];
getweighttext(getobweight(o), wbuf);
sprintf(buf2, "and weighs %s.",wbuf);
strcat(buf, buf2);
} else {
char wbuf[BUFLEN];
char wbuf2[BUFLEN];
getweighttext(getobweight(o), wbuf);
getweighttext(getobunitweight(o), wbuf2);
sprintf(buf2, "and weigh %s (%s each).",wbuf, wbuf2);
strcat(buf, buf2);
}
mvwprintw(mainwin, y, 0, "%s",buf);
y++;
throwrange = getmaxthrowrange(player, o);
if (throwrange >= 1) {
mvwprintw(mainwin, y, 0, " You could throw %s %d metres.",(o->amt == 1) ? "it" : "one", throwrange);
} else {
mvwprintw(mainwin, y, 0, " It is too heavy for you to throw.");
}
y++;
f = hasflag(o->flags, F_THROWMISSILE);
if (f) {
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
int dam;
dam = getthrowdam(o);
mvwprintw(mainwin, y, 0, " %s good for throwing [base damage %d].",(o->amt == 1) ? "It is" : "They are", dam);
} else { } else {
mvwprintw(mainwin, y, 0, " %s good for throwing.", (o->amt == 1) ? "It is" : "They are"); sprintf(buf, "%s made from %s, ",(o->amt == 1) ? "It is" : "They are", o->material->name);
}
if (o->amt == 1) {
char wbuf[BUFLEN];
getweighttext(getobweight(o), wbuf);
sprintf(buf2, "and weighs %s.",wbuf);
strcat(buf, buf2);
} else {
char wbuf[BUFLEN];
char wbuf2[BUFLEN];
getweighttext(getobweight(o), wbuf);
getweighttext(getobunitweight(o), wbuf2);
sprintf(buf2, "and weigh %s (%s each).",wbuf, wbuf2);
strcat(buf, buf2);
}
mvwprintw(mainwin, y, 0, "%s",buf);
y++;
throwrange = getmaxthrowrange(player, o);
if (throwrange >= 1) {
mvwprintw(mainwin, y, 0, " You could throw %s %d metres.",(o->amt == 1) ? "it" : "one", throwrange);
} else {
mvwprintw(mainwin, y, 0, " It is too heavy for you to throw.");
} }
y++; y++;
f = hasflag(o->flags, F_THROWMISSILE);
if (f) {
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
int dam;
dam = getthrowdam(o);
mvwprintw(mainwin, y, 0, " %s good for throwing [base damage %d].",(o->amt == 1) ? "It is" : "They are", dam);
} else {
mvwprintw(mainwin, y, 0, " %s good for throwing.", (o->amt == 1) ? "It is" : "They are");
}
y++;
}
} }
if (isedible(o)) { if (isedible(o)) {
@ -3049,6 +3063,13 @@ void describeob(object_t *o) {
y++; y++;
} }
f = hasflag(o->flags, F_HELPSCLIMB);
if (f) {
mvwprintw(mainwin, y, 0, "It can be used to assist in climbing.");
y++;
}
// skip line // skip line
y++; y++;
@ -3364,6 +3385,9 @@ void describeob(object_t *o) {
case F_SEEINDARK: case F_SEEINDARK:
mvwprintw(mainwin, y, 0, "%s allows you to see in the dark.", buf); y++; mvwprintw(mainwin, y, 0, "%s allows you to see in the dark.", buf); y++;
break; break;
case F_SILENTMOVE:
mvwprintw(mainwin, y, 0, "%s allows you to move silently.", buf); y++;
break;
case F_SLOWACT: case F_SLOWACT:
mvwprintw(mainwin, y, 0, "%s will slow down your actions.", buf); y++; mvwprintw(mainwin, y, 0, "%s will slow down your actions.", buf); y++;
break; break;
@ -3952,7 +3976,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) {
ch = f->val[0]; ch = f->val[0];
if (strlen(f->text)) { 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 // remember letter
o->letter = ch; o->letter = ch;
// make object fully known // make object fully known
@ -8325,6 +8349,11 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; 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); f = lfhasflag(lf, F_STABILITY);
if (f && (f->known)) { if (f && (f->known)) {

272
lf.c
View File

@ -49,11 +49,13 @@ extern int obdb;
extern enum ERROR reason; extern enum ERROR reason;
// for xplist // for xplist
race_t **raceposs; race_t **raceposs;
int *xpposs; int *xpposs;
int xplistlen; int xplistlen;
int notime = B_FALSE; // prevent taketime from doing anything
void autoweild(lifeform_t *lf) { void autoweild(lifeform_t *lf) {
object_t *bestwep,*bestfirearm; object_t *bestwep,*bestfirearm;
@ -1923,6 +1925,15 @@ int digdown(lifeform_t *lf, object_t *o) {
// TODO: check if the floor is solid? // 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)) { if (isplayer(lf)) {
msg("You dig a hole in the floor."); msg("You dig a hole in the floor.");
} else if (cansee(player, lf)) { } 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"); addob(lf->cell->obpile, "hole in the ground");
// takes a lot of time // takes a lot of time
taketime(lf, getactspeed(lf) * 9); if (o) {
taketime(lf, getactspeed(lf) * 9);
}
return B_FALSE; return B_FALSE;
} }
@ -1948,13 +1961,14 @@ int digup(lifeform_t *lf, object_t *o) {
return B_TRUE; 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 (!isairborne(lf)) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You can't reach the roof!"); msg("You can't reach the roof!");
}
return B_TRUE;
} }
return B_TRUE;
} }
if (isplayer(lf)) { if (isplayer(lf)) {
@ -1969,7 +1983,9 @@ int digup(lifeform_t *lf, object_t *o) {
addob(lf->cell->obpile, "hole in the roof"); addob(lf->cell->obpile, "hole in the roof");
// takes a LOT of time since gravity is against us // takes a LOT of time since gravity is against us
taketime(lf, getactspeed(lf) * 18); if (o) {
taketime(lf, getactspeed(lf) * 18);
}
return B_FALSE; return B_FALSE;
} }
@ -3170,8 +3186,8 @@ int getactspeed(lifeform_t *lf) {
return speed; return speed;
} }
// only include allies which will follow you up/down stairs etc // include allies or enemies which will follow you up/down stairs etc
void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies) { void getadjallies(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *nadjallies) {
int d; int d;
for (d = DC_N; d <= DC_NW; d++) { for (d = DC_N; d <= DC_NW; d++) {
cell_t *c; cell_t *c;
@ -3179,6 +3195,13 @@ void getadjallies(lifeform_t *lf, lifeform_t **adjally, int *nadjallies) {
if (c && c->lf) { if (c && c->lf) {
if (areallies(lf, c->lf) || areenemies(lf, c->lf)) { if (areallies(lf, c->lf) || areenemies(lf, c->lf)) {
if (!isimmobile(c->lf) && cansee(c->lf, 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; adjally[*nadjallies] = c->lf;
(*nadjallies)++; (*nadjallies)++;
} }
@ -6565,6 +6588,11 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
if (!islit(dest)) { if (!islit(dest)) {
return B_FALSE; 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); addflag(lastjob->flags, F_STARTSKILL, SK_LOCKPICKING, PR_NOVICE, NA, NULL);
mayusespellschool(lastjob->flags, SS_ALLOMANCY, F_CANCAST); mayusespellschool(lastjob->flags, SS_ALLOMANCY, F_CANCAST);
addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, NA, NULL); 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_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STEALTH, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STEALTH, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, 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_LORE_NATURE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TRACKING, 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_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_COOKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LOCKPICKING, 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_STARTSKILL, SK_LORE_HUMANOID, PR_SKILLED, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, NA, 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_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_COOKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, 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_CANWILL, OT_A_JUMP, 3, 3, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_NOVICE, NA, 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_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_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_METALWORK, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_METALWORK, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, 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"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "5 potions of rum");
// skills // skills
addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_SKILLED, NA, NULL); 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_LONGBLADES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, 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_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_STARTOB, 100, NA, NA, "5 lockpicks");
addflag(lastjob->flags, F_MPDICE, 1, NA, NA, NULL); 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_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_STEALTH, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LISTEN, 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); addflag(lastjob->flags, F_STARTSKILL, SK_BACKSTAB, PR_BEGINNER, NA, NULL);
@ -10622,16 +10656,8 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
} }
// occasionally drop blood // occasionally drop blood
switch (damtype) { if (damtypecausesbleed(damtype) && onein(3)) {
case DT_POISON: bleed(lf);
case DT_POISONGAS:
case DT_WATER:
break;
default:
if (onein(3)) {
bleed(lf);
}
break;
} }
if (hasflag(lf->flags, F_DEBUG)) { if (hasflag(lf->flags, F_DEBUG)) {
@ -12339,6 +12365,7 @@ void initskills(void) {
addskill(SK_BACKSTAB, "Backstab", "Lets you inflict massive damage with stabs when unseen.", 50); 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_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_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_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_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); 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); attrib += (getattr(lf, A_DEX)/4);
} }
break; break;
case SC_CLIMB:
attrib = (getskill(lf, SK_CLIMBING)*2);
break;
case SC_DODGE: case SC_DODGE:
// getevasion returns 0-100 (ie. pct chance) // getevasion returns 0-100 (ie. pct chance)
// convert this to 0-20 // 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); levmod = (lf->level / 3);
// other modifiers // 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)) { if (getequippedob(lf->pack, BP_FEET)) {
othermod += 5; othermod += 5;
} }
@ -13001,8 +13039,7 @@ void taketime(lifeform_t *lf, long howlong) {
int db = B_FALSE; int db = B_FALSE;
map_t *map; map_t *map;
if (notime || lfhasflag(lf, F_NOTIME)) {
if (lfhasflag(lf, F_NOTIME)) {
return; return;
} }
@ -13061,6 +13098,10 @@ int throwat(lifeform_t *thrower, object_t *o, cell_t *where) {
void timeeffectslf(lifeform_t *lf) { void timeeffectslf(lifeform_t *lf) {
object_t *o, *nexto; object_t *o, *nexto;
flag_t *f,*nextf; flag_t *f,*nextf;
int dir;
// make SURE we don't take any time!
notime = B_TRUE;
// decrement flags // decrement flags
timeeffectsflags(lf->flags); timeeffectsflags(lf->flags);
@ -13082,6 +13123,7 @@ void timeeffectslf(lifeform_t *lf) {
} }
if (isdead(lf)) { if (isdead(lf)) {
killflagsofid(lf->flags, F_NOTIME);
return; return;
} }
@ -13121,19 +13163,78 @@ void timeeffectslf(lifeform_t *lf) {
} }
// holes in the floor/roof // holes in the floor/roof
o = hasobwithflagval(lf->cell->obpile, F_PIT, D_DOWN, NA, NA, NULL); for (dir = D_UP; dir <= D_DOWN; dir++) {
if (o) { int donesomething = B_TRUE;
if (!isairborne(lf)) { o = hasobwithflagval(lf->cell->obpile, F_PIT, dir, NA, NA, NULL);
usestairs(lf, o, B_FALSE); while (o && donesomething) {
} int willfall = B_FALSE;
} donesomething = B_FALSE;
o = hasobwithflagval(lf->cell->obpile, F_PIT, D_UP, NA, NA, NULL); if ((dir == D_DOWN) && !isairborne(lf)) {
if (o) { willfall = B_TRUE;
if (lfhasflag(lf, F_LEVITATING)) { } else if ((dir == D_UP) && lfhasflag(lf, F_LEVITATING)) {
usestairs(lf, o, B_FALSE); willfall = B_TRUE;
}
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; flag_t *f;
map_t *curmap; map_t *curmap;
map_t *newmap; map_t *newmap;
cell_t *obcell;
cell_t *newcell; cell_t *newcell;
int dir; int dir;
int newdepth; int newdepth;
@ -13985,20 +14087,21 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
getlfname(lf, lfname); getlfname(lf, lfname);
getobname(o, obname, 1); getobname(o, obname, 1);
obcell = getoblocation(o);
if (initiatemove(lf, NULL, NULL)) { if (initiatemove(lf, NULL, NULL)) {
// failed? // failed?
return B_FALSE; return B_FALSE;
} }
curmap = lf->cell->map; curmap = obcell->map;
f = hasflag(o->flags, F_CLIMBABLE); f = hasflag(o->flags, F_CLIMBABLE);
assert(f); assert(f);
dir = f->val[0]; dir = f->val[0];
if (f->val[1] == NA) { if (f->val[1] == NA) {
// use same region // use same region
newregion = lf->cell->map->region; newregion = obcell->map->region;
} else { } else {
newregion = findregion(f->val[1]); newregion = findregion(f->val[1]);
} }
@ -14032,11 +14135,13 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
// can only go up if you have a rope or are flying/levitating // can only go up if you have a rope or are flying/levitating
if (lfhasflag(lf, F_LEVITATING) || lfhasflag(lf, F_FLYING)) { if (lfhasflag(lf, F_LEVITATING) || lfhasflag(lf, F_FLYING)) {
// ok. // ok.
} else { // TODO: if has rope??? } else {
if (isplayer(lf)) { char buf[BUFLEN];
msg("You can't reach the roof!"); sprintf(buf, "the %s", noprefix(obname));
if (tryclimb(lf, obcell, buf)) {
// failed
return B_TRUE;
} }
return B_TRUE;
} }
} }
} }
@ -14070,9 +14175,9 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
} }
// find adjacent allies or enemies which will follow you // find adjacent allies or enemies which will follow you
// (but not into/out of pits) // (getadjallies will handle following through pits)
if (isplayer(lf) || !hasflag(o->flags, F_PIT)) { if (isplayer(lf)) {
getadjallies(lf, adjally, &nadjallies); getadjallies(lf, o, adjally, &nadjallies);
} }
// do stairs go somewhere? // 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. // previous/next levels in the same region.
// if not, we need to call linkstairs() on the staircase first. // if not, we need to call linkstairs() on the staircase first.
/*
if (newmap->region->id != curmap->region->id) { if (newmap->region->id != curmap->region->id) {
linkstairs(o); linkstairs(o);
} }
*/
// at this point, stairs should have a destination // at this point, stairs should have a destination
newcell = getstairdestination(o); newcell = getstairdestination(o);
} }
@ -14112,10 +14219,29 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
curs_set(0); curs_set(0);
if (newcell) { if (newcell) {
int n; 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 // check noone is in the way
if (newcell->lf) { if (newcell->lf) {
cell_t *c; cell_t *c;
// if they are, move them // if they are, find somewhere to move them.
c = getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND); c = getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) { if (c) {
// move them there // move them there
@ -14168,24 +14294,56 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
if (falling) { if (falling) {
if (dir == D_DOWN) { if (dir == D_DOWN) {
if (isplayer(lf)) { if (hasobwithflagval(lf->cell->obpile, F_PIT, D_DOWN, NA, NA, NULL)) {
msg("You slam into the ground!"); flag_t *ff;
} else if (cansee(player, lf)){ // inc fall distance
msg("%s slams into the ground!", lfname); 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);
}
// 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);
} }
// take fall damage
losehp(lf, roll("2d6"), DT_FALL, NULL, "falling");
// fall over
fall(lf, NULL, B_FALSE);
} else { } else {
// TODO: if you are outside, DIE! // TODO: if you are outside, DIE!
if (isplayer(lf)) { if (hasobwithflagval(lf->cell->obpile, F_PIT, D_UP, NA, NA, NULL)) {
msg("You slam into the roof!"); flag_t *ff;
} else if (cansee(player, lf)){ // inc fall distance
msg("%s slams into the roof!", lfname); 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);
}
// 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);
} }
// take hitting roof damage
losehp(lf, roll("1d4"), DT_FALL, NULL, "slamming into the roof");
} }
} }

3
lf.h
View File

@ -79,7 +79,7 @@ void gainmp(lifeform_t *lf, int amt);
void gainxp(lifeform_t *lf, long amt); void gainxp(lifeform_t *lf, long amt);
void genxplist(void); void genxplist(void);
int getactspeed(lifeform_t *lf); 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); enum ALLEGIENCE getallegiance(lifeform_t *lf);
int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs); int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs);
object_t *getarmour(lifeform_t *lf, enum BODYPART bp); 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); void taketime(lifeform_t *lf, long howlong);
int throwat(lifeform_t *thrower, object_t *o, cell_t *where); int throwat(lifeform_t *thrower, object_t *o, cell_t *where);
void timeeffectslf(lifeform_t *lf); void timeeffectslf(lifeform_t *lf);
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat);
void turneffectslf(lifeform_t *lf); void turneffectslf(lifeform_t *lf);
int touch(lifeform_t *lf, object_t *o); int touch(lifeform_t *lf, object_t *o);
void unpoison(lifeform_t *lf); void unpoison(lifeform_t *lf);

169
map.c
View File

@ -389,6 +389,20 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) {
return rv; 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 // 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) { 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 (*distfunc)(cell_t *, cell_t *);
@ -1276,6 +1290,20 @@ int countadjcellsoftype(cell_t *cell, int id) {
return count; 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 countcellexits(cell_t *cell) {
int d; int d;
int exits = 0; 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; map_t *m;
char buf[BUFLEN]; char buf[BUFLEN];
int i,x,y; int i,x,y;
int firstworldmap = B_FALSE;
enum HABITAT habitat; enum HABITAT habitat;
regionthing_t *thing[MAXOUTLINETHINGS]; regionthing_t *thing[MAXOUTLINETHINGS];
int nthings = 0; 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 // note: we might override this later based on our region outline
habitat = region->rtype->defaulthabitat; habitat = region->rtype->defaulthabitat;
/*
if ((region->rtype->id == RG_WORLDMAP) && (depth == 1)) { if ((region->rtype->id == RG_WORLDMAP) && (depth == 1)) {
firstworldmap = B_TRUE; firstworldmap = B_TRUE;
} }
*/
map->beingcreated = B_TRUE; map->beingcreated = B_TRUE;
map->depth = depth; 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. // link to other maps if required.
// default to no links // default to no links
for (i = D_N; i <= D_W; i++) {
map->nextmap[i] = -1;
}
for (i = D_UP; i <= D_DOWN; i++) { for (i = D_UP; i <= D_DOWN; i++) {
map->nextmap[i] = -1; 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? // did we come from a previous map?
if (parentmap) { if (parentmap) {
parentmap->nextmap[exitdir] = map->id; parentmap->nextmap[exitdir] = map->id;
for (i = 0; i < MAXDIR_ORTH; i++) { map->nextmap[diropposite(exitdir)] = parentmap->id;
if (parentmap && (i == diropposite(exitdir)) ) { }
/*
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; map->nextmap[i] = parentmap->id;
} else { } else {
map->nextmap[i] = -1; map->nextmap[i] = -1;
} }
} }
} }
*/
map->w = MAX_MAPW; map->w = MAX_MAPW;
map->h = MAX_MAPH; 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); srand(map->seed);
// set map coords // set map coords
if (firstworldmap) { // first world map??
if (map == firstmap) {
addflag(map->flags, F_MAPCOORDS, 0, 0, NA, NULL); addflag(map->flags, F_MAPCOORDS, 0, 0, NA, NULL);
} else { } else {
// set mapcoords if not already done. // 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); linkholes(map);
// add random objects and monsters // add random objects and monsters
@ -2175,8 +2218,8 @@ void createpit(map_t *map, int depth, map_t *parentmap, int exitdir) {
c = getrandomcell(map); c = getrandomcell(map);
// clear it // clear it
setcelltype(c, CT_CORRIDOR); setcelltype(c, CT_CORRIDOR);
// put an exit here // put an exit here - don't link it yet - this will happen back in createmap().
o = addob(c->obpile, "hole in the roof"); o = addobject(c->obpile, "hole in the roof", B_FALSE, B_FALSE);
assert(o); assert(o);
} }
@ -2622,10 +2665,10 @@ map_t *findsurfaceexitmap(map_t *m) {
if (c) { if (c) {
for (o = c->obpile->first ; o ; o = o->next) { for (o = c->obpile->first ; o ; o = o->next) {
if (hasflagval(o->flags, F_CLIMBABLE, D_UP, NA, NA, NULL)) { if (hasflagval(o->flags, F_CLIMBABLE, D_UP, NA, NA, NULL)) {
cell_t *c; cell_t *newc;
c = getstairdestination(o); newc = getstairdestination(o);
if (c) { if (newc) {
return c->map; return newc->map;
} }
} }
} }
@ -3449,34 +3492,42 @@ int iswallindir(cell_t *cell, int dir) {
return B_FALSE; return B_FALSE;
} }
// search for unlinked pits/holes in roof in adjacent maps // 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. // if we find any, add a matching end as close as we can in THIS map.
void linkholes(map_t *map) { void linkholes(map_t *map) {
map_t *adjmap; map_t *adjmap;
cell_t *c; cell_t *c;
object_t *o, *newob; object_t *o, *newob;
int x,y; int x,y;
// check previous map for pits. int dir;
adjmap = findregionmap(map->region->id, map->depth-1);
if (adjmap) { for (dir = D_UP ; dir <= D_DOWN; dir++) {
for (y = 0; y < adjmap->h; y++) { adjmap = getmapindir(map, dir);
for (x = 0; x < adjmap->w; x++) { if (adjmap) {
c = getcellat(adjmap, x, y); for (y = 0; y < adjmap->h; y++) {
if (c) { for (x = 0; x < adjmap->w; x++) {
for (o = c->obpile->first ; o ; o = o->next) { c = getcellat(adjmap, x, y);
if (hasflagval(o->flags, F_PIT, D_DOWN, NA, NA, NULL) && if (c) {
!hasflag(o->flags, F_MAPLINK)) { // does the adjacent map have an unlinked pit going to us?
cell_t *c2; for (o = c->obpile->first ; o ; o = o->next) {
objecttype_t *ot; if (hasflagval(o->flags, F_PIT, diropposite(dir), NA, NA, NULL) &&
ot = getoppositestairs(o->type); !hasflag(o->flags, F_MAPLINK)) {
// make a link to it in this map, as close as possible to same pos cell_t *c2;
c2 = getcellat(map, x, y); objecttype_t *ot;
if (c2->type->solid) { ot = getoppositestairs(o->type);
c2 = real_getrandomadjcell(c2, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, &ot->id); // make a link to it in this map, as close as possible to same pos
c2 = getcellat(map, x, y);
if (c2->type->solid) {
// 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);
}
// note we specifically say DONT link the new hole!
newob = addobject(c2->obpile, ot->name, B_FALSE, B_FALSE);
// link them!
linkstairs(newob);
} }
newob = addob(c2->obpile, ot->name);
// link them!
linkstairs(newob);
} }
} }
} }
@ -3489,7 +3540,6 @@ void linkholes(map_t *map) {
// returns TRUE if it failed because othermap doesn't exist. // returns TRUE if it failed because othermap doesn't exist.
int linkstairs(object_t *o) { int linkstairs(object_t *o) {
map_t *othermap; map_t *othermap;
int othermapid;
object_t *o2; object_t *o2;
map_t *stairmap; map_t *stairmap;
cell_t *staircell; cell_t *staircell;
@ -3522,13 +3572,7 @@ int linkstairs(object_t *o) {
// if so, find the first map in that region (ie depth 1) // if so, find the first map in that region (ie depth 1)
othermap = findregionmap(f->val[1], 1); othermap = findregionmap(f->val[1], 1);
} else { } else {
othermapid = stairmap->nextmap[f->val[0]]; othermap = getmapindir(stairmap, f->val[0]);
othermap = findmap(othermapid);
if (!othermap) {
// find next map based on depth...
othermap = findregionmap(stairmap->region->id, stairmap->depth+dir);
}
} }
if (othermap) { if (othermap) {
// find an empty staircase in other map // find an empty staircase in other map
@ -3536,33 +3580,19 @@ int linkstairs(object_t *o) {
c2 = othermap->cell[n]; c2 = othermap->cell[n];
o2 = hasob(c2->obpile, otherstairtype->id); o2 = hasob(c2->obpile, otherstairtype->id);
if (o2) { if (o2) {
int ok = B_FALSE;
// does it go nowhere? // does it go nowhere?
if (!hasflag(o2->flags, F_MAPLINK)) { if (!hasflag(o2->flags, F_MAPLINK)) {
if (othermap->region->id == stairmap->region->id) { char obid[BUFLEN];
ok = B_TRUE; // link it to here!
} else { sprintf(obid, "%ld", o->id);
/* addflag(o2->flags, F_MAPLINK, stairmap->id, NA, NA, obid);
// handle cross-region stairs! // link me to there
f = hasflag(o2->flags, F_CLIMBABLE); sprintf(obid, "%ld", o2->id);
if (f->val[1] == stairmap->region->id) { addflag(o->flags, F_MAPLINK, othermap->id, NA, NA, obid);
ok = B_TRUE; found = B_TRUE;
} // now mark that we are not a new staircase to a new region anymore
*/ f->val[1] = NA;
ok = B_TRUE; break;
}
if (ok) {
char obid[BUFLEN];
// link it to here!
sprintf(obid, "%ld", o->id);
addflag(o2->flags, F_MAPLINK, stairmap->id, NA, NA, obid);
// link me to there
sprintf(obid, "%ld", o2->id);
addflag(o->flags, F_MAPLINK, othermap->id, NA, NA, obid);
found = B_TRUE;
break;
}
} }
} }
} }
@ -3883,3 +3913,8 @@ int wallstoleftright(cell_t *c, int dir) {
} }
return B_FALSE; return B_FALSE;
} }

2
map.h
View File

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

67
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) { 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) { if (error) {
*error = E_AVOIDOB; *error = E_AVOIDOB;
rdata = o; rdata = o;
} }
return B_TRUE; 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); f = hasflag(o->flags, F_DEEPWATER);
if (f) { if (f) {
// non swimming creature in water? // non swimming creature in water?
@ -340,6 +351,10 @@ int diropposite(int dir) {
return DC_E; return DC_E;
case DC_NW: case DC_NW:
return DC_SE; return DC_SE;
case D_UP:
return D_DOWN;
case D_DOWN:
return D_UP;
} }
// should never happen! // should never happen!
return dir; return dir;
@ -582,6 +597,39 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in
return bestdir; 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' // 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) { int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff) {
@ -2018,15 +2066,22 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
if (isswimming(lf)) { if (isswimming(lf)) {
practice(lf, SK_SWIMMING, 1); practice(lf, SK_SWIMMING, 1);
} }
} else { } else { // ie !moveok
object_t *inway = NULL; object_t *inway = NULL;
int door, dooropen; int door, dooropen;
reason = errcode; reason = errcode;
switch (errcode) { switch (errcode) {
case E_OFFMAP: case E_OFFMAP:
if ((lf->cell->map->region == RG_WORLDMAP) && (isorthogonal(dir))) { if (lf->cell->map->region->rtype->id == RG_WORLDMAP) {
// we are allowed to walk off the edge // cope with nonorthogonal!
return walkoffmap(lf, dir, B_TRUE); // 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... // otherwise fall through...
case E_WALLINWAY: case E_WALLINWAY:
@ -2264,7 +2319,7 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
if (onpurpose) { if (onpurpose) {
// get list of adjacent allies // get list of adjacent allies
if (isplayer(lf)) { 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 dorandommove(lifeform_t *lf, int badmovesok, int restonfail);
int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); 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 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 knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff);
int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype); int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype);
int moveclear(lifeform_t *lf, int dir, enum ERROR *error); 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 // create first dungeon
dregion = findregionbytype(RG_FIRSTDUNGEON); dregion = findregionbytype(RG_FIRSTDUNGEON);
dmap = addmap(); dmap = addmap();
createmap(dmap, 1, dregion, NULL, D_NONE); createmap(dmap, 1, dregion, firstmap, D_DOWN);
} }
// find staircase // find staircase

109
objects.c
View File

@ -390,7 +390,7 @@ void addocnoun(objectclass_t *oc, char *text) {
// create a new object, stacking ok // create a new object, stacking ok
object_t *addob(obpile_t *where, char *name) { 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 // create a new object
@ -399,7 +399,7 @@ object_t *addob(obpile_t *where, char *name) {
// object with o->amt set, instead of // object with o->amt set, instead of
// creating new obejct entries. // creating new obejct entries.
// NOTE: This function MUST return number of obs created via global "nretobs" // 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; objecttype_t *ot;
object_t *o = NULL; object_t *o = NULL;
char *p,*nsp,*p2; 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); addflag(o->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, selhn->text);
} }
if (o && hasflag(o->flags,F_PIT)) {
dblog("added pit");
}
// link holes to adjacent maps // create linked holes in adjacent maps
if (o && hasflag(o->flags, F_PIT)) { if (wantlinkholes && o && hasflag(o->flags, F_PIT)) {
cell_t *c; cell_t *c;
map_t *adjmap = NULL; map_t *adjmap = NULL;
f = hasflag(o->flags, F_PIT); f = hasflag(o->flags, F_PIT);
c = getoblocation(o); c = getoblocation(o);
if ((c->map->region->rtype->id == RG_WORLDMAP) && (f->val[0] == D_DOWN)) { adjmap = getmapindir(c->map, f->val[0]);
// ie. going down from the surface. MUST be down because holes if ((c->map->region->rtype->id == RG_WORLDMAP) && !adjmap) {
// going up make no sense! // 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); createregionlink(c->map, c, o, NULL, RG_PIT, c->map->region);
} else { } else {
// create linked holes on any existing adjacent maps // create linked holes on the map at the other end of this one.
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);
}
}
if (adjmap) { if (adjmap) {
linkholes(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); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_FASTMOVE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_SLOTH, "of sloth", BP_FEET); addbrand(BR_SLOTH, "of sloth", BP_FEET);
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_SLOWMOVE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1); 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 // hands
addbrand(BR_POWER, "of power", BP_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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l2 // 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_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, 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); 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_RARITY, H_DUNGEON, 80, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_DIG, NA, NA, 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); 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_RARITY, H_DUNGEON, 73, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_COLDRAY, NA, NA, 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_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, 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); 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_RARITY, H_DUNGEON, 85, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, 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_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
// tech - l3 // 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); 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_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, 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_REFILLWITH, OT_POT_OIL, NA, NA, NULL);
addflag(lastot->flags, F_ACTIVATECONFER, F_FLYING, B_TRUE, 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_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_TECHLEVEL, PR_SKILLED, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
@ -9888,12 +9874,8 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
sprintf(buf, "Where will you aim %s?",obname); sprintf(buf, "Where will you aim %s?",obname);
where = askcoords(buf, subprompt, ttype, lf, UNLIMITED, LOF_NEED, B_TRUE); where = askcoords(buf, subprompt, ttype, lf, UNLIMITED, LOF_NEED, B_TRUE);
if (!haslos(lf, where)) { if (!haslos(lf, where)) {
// exception - wand of digging doesn't need los msg("You can't see there!");
if (isknown(o) && (o->type->id == OT_WAND_DIGGING)) { return B_TRUE;
} else {
msg("You can't see there!");
return B_TRUE;
}
} }
} }
} else { } else {
@ -10001,7 +9983,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
msg("%s zaps %s.",lfname,obname); msg("%s zaps %s.",lfname,obname);
} }
f = hasflag(o->flags, F_LINKSPELL); f = hasflag(o->flags, F_LINKSPELL);
if (f) { if (f) {
enum OBTYPE spelltocast; 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. // doesn't matter if it goes down to zero, as we will put it back up soon.
o->amt--; o->amt--;
// give new object // 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 // restore count
o->amt++; o->amt++;
if (newob) { 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); objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour);
void addocnoun(objectclass_t *oc, char *text); void addocnoun(objectclass_t *oc, char *text);
object_t *addob(obpile_t *where, char *name); 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); 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); obmod_t *addobmod(enum OBMOD id, char *prefix);
obpile_t *addobpile(lifeform_t *owner, cell_t *where); 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; return B_TRUE;
} }
// create the object // 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 // overwrite ob parameters
o->id = obid; o->id = obid;

51
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) { } else if (spellid == OT_S_DIG) {
int numseen = 0; int numseen = 0;
cell_t *retcell[MAXRETCELLS]; cell_t *c;
int nretcell,i;
int ndigs; int ndigs;
char ch;
int dir;
// don't need line of fire OR sight! if (targcell) {
if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE; 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;
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 if (dir == DT_NONE) {
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, fizzle(caster);
targcell->x, targcell->y, retcell, &nretcell); return B_TRUE;
}
ndigs = 0; ndigs = 0;
// get rid of rock in the cells... // 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; 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. // can dig through stone, but nothing else.
if (retcell[i]->type->material->id == MT_STONE) { if (c->type->material->id == MT_STONE) {
setcelltype(retcell[i], retcell[i]->map->habitat->emptycelltype); setcelltype(c, c->map->habitat->emptycelltype);
ndigs++;
if (seenthiscell) { if (seenthiscell) {
ndigs++;
numseen++; numseen++;
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
@ -2616,7 +2636,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else { } else {
object_t *o; 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)) { if (hasflag(o->flags, F_IMPASSABLE)) {
char obname[BUFLEN]; char obname[BUFLEN];
// destroy this object then stop. // 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 // announce destruction of any walls seen
@ -3429,7 +3450,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else { } else {
// next thing touched // 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)) { if (isplayer(caster)) {
msg("Your hands begin to glow blue!"); msg("Your hands begin to glow blue!");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;