- [+] askchar - default isnt working.

* [+] implement regions
- [+] new vaultflag:  norandom (doesn't rnadomly appear)
* [+] jimbo's lair
* [+] implememnt skill training
* [+] still a bug with flooded rooms having no doors!
* [+] change f_impassable to be a size _range_ which can't pass it.
- [+] metal armour should add to walking volume!
- [+] sewing/metalwork skill to repair cloth/metal armour, instead of
      "armour" skill?
- [+] moveob() onto a pit - they fall through!
vault options:
- [+] dlevmin/max:xx appears at this depth/difficulty
- [+] goesin appears in habitat xx (if none of these, can be anywhere)
    - [+] habitat has to be a struct first, with a name.
- [+] norandom (don't randomly generate - only from outline)
- [+] pits
    - [+] only one can exist in a cell
- [+] replace getemptycelltype() with entries in habitat_t
- [+] make map->habitat a link.
* [+] update linkstairs to do pits
SPELLS:
- [+] shatter (grav/air, break glass, break potions. damage to anyone
      nearby)
This commit is contained in:
Rob Pearce 2011-06-22 06:01:48 +00:00
parent 1ab3bd3620
commit 6cd743b9f9
31 changed files with 1710 additions and 494 deletions

4
ai.c
View File

@ -35,7 +35,9 @@ void aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
// mindless? // mindless?
if (getiqname(getattr(lf, A_IQ), NULL) == IQ_MINDLESS) { if (getiqname(getattr(lf, A_IQ), NULL) == IQ_MINDLESS) {
return; if (!isundead(lf)) {
return;
}
} }
// already targetting this lf? // already targetting this lf?

View File

@ -742,6 +742,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// victim's armour loses hp // victim's armour loses hp
if (reduceamt) { if (reduceamt) {
applyarmourdamage(victim, wep, reduceamt, damtype[i]); applyarmourdamage(victim, wep, reduceamt, damtype[i]);
// train armour
practice(victim, SK_ARMOUR, 1);
}
if (backstab) {
practice(lf, SK_BACKSTAB, 1);
} }
} }
} // end foreach damtype } // end foreach damtype
@ -903,8 +908,13 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
// practice? // practice?
if (wepsk && !getskill(lf, wepsk->id)) { if (hit) {
practice(lf, wepsk->id, hit ? 2 : 1); if (wepsk) {
practice(lf, wepsk->id, 1);
}
if (isdualweilding(lf)) {
practice(lf, SK_TWOWEAPON, 1);
}
} }
// induction of fear? // induction of fear?

103
defs.h
View File

@ -6,7 +6,7 @@
// MACROS // MACROS
#define MAXOF(a,b) (a > b ? a : b) #define MAXOF(a,b) (a > b ? a : b)
#define PRACTICETIME 15 // #attempts it takes to learn new weapon skill // #define PRACTICETIME 15 // #attempts it takes to learn new weapon skill
#define WETTIME 10 // how long it takes for things to dry #define WETTIME 10 // how long it takes for things to dry
#define DRUNKTIME 10 // how long it takes for alcohol to wear off #define DRUNKTIME 10 // how long it takes for alcohol to wear off
@ -47,7 +47,9 @@ enum SKILL {
SK_FIRSTAID, SK_FIRSTAID,
SK_LISTEN, SK_LISTEN,
SK_LOCKPICKING, SK_LOCKPICKING,
SK_METALWORK,
SK_RANGED, SK_RANGED,
SK_SEWING,
SK_SHIELDS, SK_SHIELDS,
SK_SPELLCASTING, SK_SPELLCASTING,
SK_SPOTHIDDEN, SK_SPOTHIDDEN,
@ -88,7 +90,7 @@ enum SKILL {
SK_SS_TRANSLOCATION, SK_SS_TRANSLOCATION,
SK_SS_WILD, SK_SS_WILD,
}; };
#define MAXSKILLS 47 #define MAXSKILLS 49
// proficiency levels // proficiency levels
enum SKILLLEVEL { enum SKILLLEVEL {
@ -572,12 +574,6 @@ enum BLESSTYPE {
B_CURSED = -1 B_CURSED = -1
}; };
enum HABITAT {
H_DUNGEON = 1,
H_FOREST = 2,
H_ALL = 999
};
#define RARITYVARIANCELF (5) #define RARITYVARIANCELF (5)
#define RARITYVARIANCEOB (10) #define RARITYVARIANCEOB (10)
@ -780,11 +776,14 @@ enum OBTYPE {
OT_STATUE, OT_STATUE,
OT_DOORWOOD, OT_DOORWOOD,
OT_DOORIRON, OT_DOORIRON,
OT_IRONGATE,
OT_WOODENTABLE, OT_WOODENTABLE,
OT_WOODENBARREL, OT_WOODENBARREL,
OT_WOODENSTOOL, OT_WOODENSTOOL,
OT_HOLYCIRCLE, OT_HOLYCIRCLE,
OT_PENTAGRAM, OT_PENTAGRAM,
OT_HOLEINGROUND,
OT_HOLEINROOF,
OT_STAIRSDOWN, OT_STAIRSDOWN,
OT_STAIRSUP, OT_STAIRSUP,
OT_VENDINGMACHINE, OT_VENDINGMACHINE,
@ -896,6 +895,7 @@ enum OBTYPE {
OT_S_METALHEAL, OT_S_METALHEAL,
// -- death // -- death
OT_S_ANIMATEDEAD, OT_S_ANIMATEDEAD,
OT_S_COMMANDUNDEAD,
OT_S_DRAINLIFE, OT_S_DRAINLIFE,
OT_S_FEAR, OT_S_FEAR,
OT_S_PAIN, OT_S_PAIN,
@ -925,6 +925,7 @@ enum OBTYPE {
OT_S_CLOUDKILL, OT_S_CLOUDKILL,
OT_S_GUSTOFWIND, OT_S_GUSTOFWIND,
OT_S_MIST, OT_S_MIST,
OT_S_SHATTER,
OT_S_WINDSHIELD, OT_S_WINDSHIELD,
// -- elemental - fire // -- elemental - fire
OT_S_BLADEBURN, OT_S_BLADEBURN,
@ -1370,7 +1371,8 @@ enum NOISETYPE {
}; };
enum LFSIZE { enum LFSIZE {
SZ_ANY = -1, SZ_ANY = -2,
SZ_MIN = -1,
SZ_MINI = 0, // ie. fly SZ_MINI = 0, // ie. fly
SZ_TINY = 1, // ie. mouse SZ_TINY = 1, // ie. mouse
SZ_SMALL = 2, // ie. cat SZ_SMALL = 2, // ie. cat
@ -1415,6 +1417,7 @@ enum FLAG {
F_ONEPERCELL, // only one of these objects can exist per cell F_ONEPERCELL, // only one of these objects can exist per cell
F_CREATEDBY, // object was made by lf id v0, text=real lfname F_CREATEDBY, // object was made by lf id v0, text=real lfname
F_ENCHANTABLE, // object can get +1/-1 ect F_ENCHANTABLE, // object can get +1/-1 ect
F_NOSHATTER, // object will not shatter, even if it's material should.
F_STACKABLE, // can stack multiple objects togethr F_STACKABLE, // can stack multiple objects togethr
F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money) F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money)
F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold) F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold)
@ -1447,7 +1450,8 @@ enum FLAG {
F_NOGLYPH, // this object doesn't appear normally F_NOGLYPH, // this object doesn't appear normally
F_COSMETIC, // this object is mostly cosmetic, don't say 'you see xx' F_COSMETIC, // this object is mostly cosmetic, don't say 'you see xx'
F_NOPICKUP, // cannot pick this up F_NOPICKUP, // cannot pick this up
F_IMPASSABLE, // cannot walk past this if your size if v0 or smaller F_IMPASSABLE, // cannot walk past this if your size is between v0 and v1
// (inclusive)
F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it
F_CAUSESCOUGH, // being in this ob's cell will make you cough unless F_CAUSESCOUGH, // being in this ob's cell will make you cough unless
// immune to gas. // immune to gas.
@ -1537,6 +1541,7 @@ enum FLAG {
// v2 = sc_dodge difficulty // v2 = sc_dodge difficulty
// doors // doors
F_DOOR, // this object is a door - ie. can open it F_DOOR, // this object is a door - ie. can open it
// v0 and v1 are like F_IMPASSABLE
F_OPEN, // is this door open? F_OPEN, // is this door open?
F_LOCKED,// door is locked F_LOCKED,// door is locked
// v1 is difficulty to disarm // v1 is difficulty to disarm
@ -1547,6 +1552,9 @@ enum FLAG {
// stairs / teleporters / portals // stairs / teleporters / portals
F_CLIMBABLE, // this is a stiarcase, v0 = up/down/in F_CLIMBABLE, // this is a stiarcase, v0 = up/down/in
// also use this for portals // also use this for portals
// OPTIONAL v1 = id of region to link to.
F_PIT, // this is a pit which we can fall down.
// v0 = up/down
//F_STAIRDIR//, // val0 = direcion //F_STAIRDIR//, // val0 = direcion
F_OPPOSITESTAIRS, // val0 = opposite kind of stairs F_OPPOSITESTAIRS, // val0 = opposite kind of stairs
F_MAPLINK, // val0 = map to link to. F_MAPLINK, // val0 = map to link to.
@ -2022,11 +2030,17 @@ enum FLAG {
// v0 is pct chance of door (as opposed to empty // v0 is pct chance of door (as opposed to empty
// doorway with no door). // doorway with no door).
F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms
F_NORANDOM, // this vault does not randomly appear
F_VAULTATOB, // v0/1=x/y, v1=pctchance, text=obname F_VAULTATOB, // v0/1=x/y, v1=pctchance, text=obname
F_VAULTATLF, // v0/1=x/y, v1=pctchance, text=lfname F_VAULTATLF, // v0/1=x/y, v1=pctchance, text=lfname
F_VAULTATCELL, // v0/1=x/y, v1=pctchance, text=cellname F_VAULTATCELL, // v0/1=x/y, v1=pctchance, text=cellname
F_VAULTBOX, // v0=thingtype, v1=pctchance, v2=fill?, text=x1,y1,x2,y2,thingname F_VAULTBOX, // v0=thingtype, v1=pctchance, v2=fill?, text=x1,y1,x2,y2,thingname
F_VAULTDLEVMIN, // v0 = mininum map depth/difficulty for this vault
F_VAULTDLEVMAX, // v0 = maximum map depth/difficulty for this vault
F_VAULTEXIT, // v0/1=x,y for exit. F_VAULTEXIT, // v0/1=x,y for exit.
F_VAULTGOESIN, // this vault randomly appears in habitat type v0.
// can be repeated multiple times
// if a vault doesnt have this flag, it can go anywhere
F_VAULTSCATTER, // v0=thingtype, v1=pctchance F_VAULTSCATTER, // v0=thingtype, v1=pctchance
// text=x1,y1,x2,y2,mincount-maxcount,thingname // text=x1,y1,x2,y2,mincount-maxcount,thingname
// if maxcount is PCT, mincount is a percentage // if maxcount is PCT, mincount is a percentage
@ -2067,6 +2081,8 @@ enum HUNGER {
#define B_FALSE (0) #define B_FALSE (0)
#define B_TRUE (-1) #define B_TRUE (-1)
#define B_NODOORS (0)
#define B_DONTKILL (-1) #define B_DONTKILL (-1)
#define FALLTHRU (-8765) #define FALLTHRU (-8765)
@ -2248,16 +2264,74 @@ typedef struct command_s {
struct command_s *next, *prev; struct command_s *next, *prev;
} command_t; } command_t;
#define RG_WORLDMAP 0 enum REGIONTYPE {
#define RG_FIRSTDUNGEON 1 RG_WORLDMAP,
RG_FIRSTDUNGEON,
RG_PIT,
};
enum HABITAT {
H_DUNGEON = 1,
H_FOREST = 2,
H_PIT = 3,
H_ALL = 999
};
typedef struct regiontype_s {
enum REGIONTYPE id;
enum HABITAT defaulthabitat;
int maxdepth;
int stairsperlev;
int deeperdir;
struct regiontype_s *next, *prev;
} regiontype_t;
enum REGIONTHING {
RT_HABITAT, // val is habitat
RT_REGIONLINK, // val is enum regiontype to link to.
// what is stair object type
RT_VAULT, // what is vaultname
};
typedef struct regionthing_s {
int depth; // only need depth OR x,y
int x,y;
enum REGIONTHING whatkind;
int value;
char *what;
} regionthing_t;
#define MAXOUTLINETHINGS 20
typedef struct regionoutline_s {
regiontype_t *rtype;
regionthing_t thing[MAXOUTLINETHINGS];
int nthings;
struct regionoutline_s *next, *prev;
} regionoutline_t;
typedef struct region_s {
int id;
regiontype_t *rtype;
regionoutline_t *outline;
struct region_s *parentregion;
int nthings;
struct region_s *next, *prev;
} region_t;
typedef struct habitat_s {
enum HABITAT id;
char *name;
enum CELLTYPE emptycelltype,solidcelltype;
struct habitat_s *next, *prev;
} habitat_t;
typedef struct map_s { typedef struct map_s {
int id; int id;
int region; region_t *region;
int depth; int depth;
int nrooms; // how many rooms on this map int nrooms; // how many rooms on this map
char *name; // name of this map char *name; // name of this map
enum HABITAT habitat; // eg. dungeon, forest, etc habitat_t *habitat;
unsigned int seed; unsigned int seed;
int w,h; // width/height of this map int w,h; // width/height of this map
struct cell_s *cell[MAX_MAPW*MAX_MAPH]; // list of cells in this map struct cell_s *cell[MAX_MAPW*MAX_MAPH]; // list of cells in this map
@ -2476,6 +2550,7 @@ typedef struct skill_s {
enum SKILL id; enum SKILL id;
char *name; char *name;
char *desc; char *desc;
int traintime;
struct skill_s *next, *prev; struct skill_s *next, *prev;
} skill_t; } skill_t;

View File

@ -2,4 +2,7 @@ defs.h:
add H_xx enum add H_xx enum
map.c: map.c:
update getemptycelltype() initmap: define via addhabitat()
make a new function to create this kind of habitat

10
doc/add_regiontype.txt Normal file
View File

@ -0,0 +1,10 @@
defs.h:
add new RG_xxx entry to enum REGIONTYPE
map.c:
initmap(): define via new "addregiontype()" call
OPTIONAL: initmap(): define at least one regionoutline
create new habitats if required.
update getregionname()

View File

@ -44,12 +44,24 @@ Flags can be:
- a pct of the total region cells (x%) - a pct of the total region cells (x%)
coords can be negative ("count back from right/bottom") coords can be negative ("count back from right/bottom")
autodoors:pct // automatically add at least one door to the edges of
autodoors // automatically add at least one door to the edges of
// this room. // this room.
// pct is chance of the exit being a door as opposed
// to jsut an opening.
autopop // automatically add obs/mons/pillars to this room autopop // automatically add obs/mons/pillars to this room
dlevmin:xxx // can only randomly appear at or below dungeon
// level xxx (or map difficulty xxx for world map)
dlevmax:xxx // can only randomly appear at or before dungeon
// levle xxx
goesin:xxx // can only randomly appear in habitat xxx
norandom // this vault doesn't appear randomly. it will only
// appear when specifically requested via a region's
// outline.
NOTES: NOTES:
when adding lfs/objects, "random" creates a random one. when adding lfs/objects, "random" creates a random one.

48
io.c
View File

@ -501,7 +501,7 @@ char askchar(char *prompt, char *validchars, char *def, int showchars) {
} }
curs_set(0); curs_set(0);
clearmsg(); clearmsg();
if ((ch == 13) && def) { if ((ch == 10) && def) {
return def[0]; return def[0];
} }
return ch; return ch;
@ -986,7 +986,7 @@ void announcearrival(lifeform_t *lf, map_t *newmap) {
} else { } else {
msg("You arrive at the surface."); msg("You arrive at the surface.");
} }
} else if (newmap->habitat == H_DUNGEON) { } else if (newmap->habitat->id == H_DUNGEON) {
msg("You arrive at dungeon level %d.", newmap->depth); msg("You arrive at dungeon level %d.", newmap->depth);
} }
} }
@ -3616,8 +3616,7 @@ void doclose(void) {
} }
} }
void docomms(void) { void docomms(lifeform_t *lf) {
lifeform_t *lf = NULL;
cell_t *where; cell_t *where;
char buf[BUFLEN]; char buf[BUFLEN];
char lfname[BUFLEN]; char lfname[BUFLEN];
@ -3626,9 +3625,11 @@ void docomms(void) {
flag_t *f; flag_t *f;
where = askcoords("Talk to who?", "Talk->", TT_MONSTER, player, UNLIMITED, LOF_DONTNEED, B_FALSE); if (!lf) {
if (where && where->lf && cansee(player, where->lf)) { where = askcoords("Talk to who?", "Talk->", TT_MONSTER, player, UNLIMITED, LOF_DONTNEED, B_FALSE);
lf = where->lf; if (where && where->lf && cansee(player, where->lf)) {
lf = where->lf;
}
} }
if (!lf) { if (!lf) {
msg("Cancelled."); msg("Cancelled.");
@ -3644,7 +3645,7 @@ void docomms(void) {
// are they friendly? // are they friendly?
if (ispetof(lf, player)) { if (ispetof(lf, player)) {
if (iqb >= IQ_ANIMAL) { if ((iqb >= IQ_ANIMAL) || isundead(lf)) {
addchoice(&prompt, 'a', "Attack something", NULL, NULL); addchoice(&prompt, 'a', "Attack something", NULL, NULL);
} }
@ -3694,6 +3695,8 @@ void docomms(void) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("%s looks confused at your command.", lfname); msg("%s looks confused at your command.", lfname);
} else { } else {
// stop attacking all current targets first...
killflagsofid(lf->flags, F_TARGETLF);
aiattack(lf, lf2, AI_FOLLOWTIME); aiattack(lf, lf2, AI_FOLLOWTIME);
} }
break; break;
@ -3709,11 +3712,13 @@ void docomms(void) {
sprintf(buf, "Tell %s to go where?",lfname); sprintf(buf, "Tell %s to go where?",lfname);
sprintf(buf2, "%s->Goto->",lfname); sprintf(buf2, "%s->Goto->",lfname);
c = askcoords(buf, buf2, TT_NONE, lf, UNLIMITED, LOF_DONTNEED, B_FALSE); c = askcoords(buf, buf2, TT_NONE, lf, UNLIMITED, LOF_DONTNEED, B_FALSE);
if (c && cellwalkable(lf, c, NULL) && cansee(lf, c->lf)) { if (c && cellwalkable(lf, c, NULL) ) {
} else { } else {
msg("Cancelled."); msg("Cancelled.");
return; return;
} }
// stop attacking all current targets first...
killflagsofid(lf->flags, F_TARGETLF);
msg("You say \"Go over there!\" to %s.", lfname); msg("You say \"Go over there!\" to %s.", lfname);
aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME); aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME);
break; break;
@ -4627,7 +4632,7 @@ void doenter(lifeform_t *lf) {
} }
enterob = hasob(lf->cell->obpile, OT_PORTAL); enterob = hasob(lf->cell->obpile, OT_PORTAL);
if (enterob) { if (enterob) {
usestairs(lf, enterob); usestairs(lf, enterob, B_TRUE);
return; return;
} }
@ -5014,7 +5019,7 @@ void dostairs(int dir) {
object_t *o; object_t *o;
o = hasobwithflagval(player->cell->obpile, F_CLIMBABLE, dir, NA, NA, NULL); o = hasobwithflagval(player->cell->obpile, F_CLIMBABLE, dir, NA, NA, NULL);
if (o) { if (o) {
usestairs(player, o); usestairs(player, o, B_TRUE);
} else { } else {
msg("There are no stairs going %s here!", getdirname(dir)); msg("There are no stairs going %s here!", getdirname(dir));
} }
@ -6107,7 +6112,7 @@ void handleinput(void) {
doclose(); doclose();
break; break;
case 'C': // communicate case 'C': // communicate
docomms(); docomms(NULL);
break; break;
case 'e': // eat case 'e': // eat
doeat(player->pack); doeat(player->pack);
@ -6653,7 +6658,12 @@ void drawstatus(void) {
} }
} }
wprintw(statwin, "DLev:%d", player->cell->map->depth); //wprintw(statwin, "DLev:%d", player->cell->map->depth);
setcol(statwin, C_BROWN);
getregionname(buf, player->cell->map, B_TRUE);
capitalise(buf);
wprintw(statwin, "%s", buf);
unsetcol(statwin, C_BROWN);
} }
void drawmsg(void) { void drawmsg(void) {
@ -8245,7 +8255,7 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
f = lfhasflag(lf, F_RAGE); f = lfhasflag(lf, F_RAGE);
if (f && (f->known)) { if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s enraged.", you(lf), is(lf)); mvwprintw(mainwin, y, 0, "%s %s enraged, gaining temporary strength and hit points.", you(lf), is(lf));
y++; y++;
} }
f = lfhasknownflag(lf, F_REGENERATES); f = lfhasknownflag(lf, F_REGENERATES);
@ -8419,6 +8429,7 @@ void showlfstats(lifeform_t *lf, int showall) {
void tombstone(lifeform_t *lf) { void tombstone(lifeform_t *lf) {
char pname[BUFLEN]; char pname[BUFLEN];
char buf[BUFLEN];
int y; int y;
char *p, *dummy; char *p, *dummy;
@ -8431,10 +8442,13 @@ void tombstone(lifeform_t *lf) {
centre(mainwin, y, "R.I.P."); y++; centre(mainwin, y, "R.I.P."); y++;
//printf("%s\n",lf->name); //printf("%s\n",lf->name);
centre(mainwin, y, "%s (%ld points)",pname, calcscore(lf)); y++; centre(mainwin, y, "%s (%ld points)",pname, calcscore(lf)); y++;
if (lf->cell->map->region == RG_WORLDMAP) {
centre(mainwin, y, "Died in the forest."); if (player->cell->map->region->rtype->id == RG_WORLDMAP) {
getregionname(buf, player->cell->map, B_TRUE);
centre(mainwin, y, "Died on %s.", buf); y++;
} else { } else {
centre(mainwin, y, "Died on level %d of the dungeon.", lf->cell->map->depth); y++; getregionname(buf, player->cell->map, B_FALSE);
centre(mainwin, y, "Died on level %d of %s.", player->cell->map->depth, buf); y++;
} }
p = strtok_r(lf->lastdam,"^", &dummy); p = strtok_r(lf->lastdam,"^", &dummy);

2
io.h
View File

@ -37,7 +37,7 @@ void describeob(object_t *o);
void describespell(objecttype_t *ot); void describespell(objecttype_t *ot);
void doattackcell(char dirch); void doattackcell(char dirch);
void doclose(void); void doclose(void);
void docomms(void); void docomms(lifeform_t *target);
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst); void dodrop(obpile_t *op, int wantmulti, obpile_t *dst);
void doeat(obpile_t *op); void doeat(obpile_t *op);
void doenter(lifeform_t *lf); void doenter(lifeform_t *lf);

528
lf.c
View File

@ -1161,6 +1161,11 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
// stop hiding // stop hiding
killflagsofid(lf->flags, F_HIDING); killflagsofid(lf->flags, F_HIDING);
// successful cast?
if (!rv) {
practice(lf, SK_SPELLCASTING, 1);
}
return rv; return rv;
} }
@ -1815,6 +1820,159 @@ void dumpxp(void) {
} }
} }
int digcell(lifeform_t *lf, cell_t *c, object_t *o) {
char obname[BUFLEN];
getobname(o, obname, 1);
if (!c) {
return B_TRUE;
}
if (c->type->solid) {
if (isdiggable(c)) {
// replace wall
setcelltype(c, c->map->habitat->id);
if (isplayer(lf)) {
msg("You dig through the wall.");
needredraw = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s digs through a wall.",lfname);
needredraw = B_TRUE;
}
//drawscreen();
// takes extra time
taketime(lf, getactspeed(lf)*9);
} else {
// fail
if (isplayer(lf)) {
msg("This wall is too hard to dig.");
}
}
} else { // not solid
int failed = B_FALSE;
object_t *door;
door = hasobwithflag(c->obpile, F_DOOR);
if (door) {
int dooropen;
// only closed doors!
isdoor(door, &dooropen);
if (dooropen) {
door = NULL;
}
}
if (door) {
// TODO: metal doors are immune to CHOP damage
if (!isimmuneto(door->flags, DT_CHOP)) {
taketime(lf, getactspeed(lf));
removeob(door, door->amt);
if (isplayer(lf)) {
msg("You smash open a door!");
needredraw = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s smashes open a door.",lfname);
needredraw = B_TRUE;
}
drawscreen();
failed = B_FALSE;
}
} else if (hasob(c->obpile, OT_STATUE)) {
int dam;
object_t *so;
char statname[BUFLEN];
flag_t *f;
so = hasob(c->obpile, OT_STATUE);
getobname(so, statname, so->amt);
taketime(lf, getactspeed(lf));
// statue takes 1/2 damage
f = hasflag(so->flags, F_OBHP);
if (f) {
dam = (f->val[1] / 2); // ie. half max hp
} else {
dam = 1;
}
// statue ?
if (isplayer(lf)) {
msg("You hit %s with your %s.", statname, noprefix(obname));
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s hits %s with %s.", lfname, statname, obname);
}
takedamage(so, dam, DT_CHOP);
} else {
if (isplayer(lf)) {
msg("You swing your %s through the air.",noprefix(obname));
}
taketime(lf, getactspeed(lf));
}
}
return B_FALSE;
}
int digdown(lifeform_t *lf, object_t *o) {
char lfname[BUFLEN];
getlfname(lf, lfname);
// TODO: check if the floor is solid?
if (isplayer(lf)) {
msg("You dig a hole in the floor.");
} else if (cansee(player, lf)) {
msg("%s digs a hole in the floor.");
}
addob(lf->cell->obpile, "hole in the ground");
// takes a lot of time
taketime(lf, getactspeed(lf) * 9);
return B_FALSE;
}
int digup(lifeform_t *lf, object_t *o) {
char lfname[BUFLEN];
getlfname(lf, lfname);
// no roof?
if (lf->cell->map->region->rtype->id == RG_WORLDMAP) {
if (isplayer(lf)) {
msg("There is no roof above you to dig into!");
}
return B_TRUE;
}
// TODO: check if the roof is solid?
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.");
} else if (cansee(player, lf)) {
msg("%s digs a hole in the roof.");
}
// add some stones here
addob(lf->cell->obpile, "20-50 stones");
addob(lf->cell->obpile, "hole in the roof");
// takes a LOT of time since gravity is against us
taketime(lf, getactspeed(lf) * 18);
return B_FALSE;
}
// dump which level random things will appear at // dump which level random things will appear at
void dumplev(void) { void dumplev(void) {
int i; int i;
@ -2728,7 +2886,7 @@ int flee(lifeform_t *lf) {
// can we flee via stairs? // can we flee via stairs?
stairs = hasobwithflag(lf->cell->obpile, F_CLIMBABLE); stairs = hasobwithflag(lf->cell->obpile, F_CLIMBABLE);
if (stairs) { if (stairs) {
if (!usestairs(lf, stairs)) { if (!usestairs(lf, stairs, B_TRUE)) {
return B_TRUE; return B_TRUE;
} }
} }
@ -3082,6 +3240,24 @@ object_t *getarmour(lifeform_t *lf, enum BODYPART bp) {
return NULL; return NULL;
} }
int getarmournoise(lifeform_t *lf) {
object_t *o;
int volmod = 0;
for (o = lf->pack->first ; o ; o = o->next) {
if (isarmour(o) && isequipped(o)) {
// heavy metal armour makes noise
if (ismetal(o->material->id) && (getobweight(o) >= 4)) {
volmod++;
}
}
}
volmod -= getskill(lf, SK_ARMOUR);
limit(&volmod, 0, NA);
return volmod;
}
int getarmourrating(lifeform_t *lf) { int getarmourrating(lifeform_t *lf) {
object_t *o; object_t *o;
flag_t *f; flag_t *f;
@ -3288,25 +3464,28 @@ int getavgdam(lifeform_t *lf, int forxp) {
o = addob(op2, f->text); o = addob(op2, f->text);
getdamrange(hasflag(o->flags, F_DAM), &min,&max); if (o) {
thisavg = ((float)min + (float)max) / 2.0; getdamrange(hasflag(o->flags, F_DAM), &min,&max);
thisavg = ((float)min + (float)max) / 2.0;
// confers anything? // confers anything?
for (of = o->flags->first ; of ; of = of->next) { for (of = o->flags->first ; of ; of = of->next) {
if (of->id == F_HITCONFER) { if (of->id == F_HITCONFER) {
thisavg += 10; thisavg += 10;
}
} }
}
// modify for accuracy // modify for accuracy
acc = getlfaccuracy(lf, o); acc = getlfaccuracy(lf, o);
thisavg = pctof(acc, thisavg); thisavg = pctof(acc, thisavg);
avgdam += thisavg; avgdam += thisavg;
if (db) { if (db) {
char obname[BUFLEN]; char obname[BUFLEN];
getobname(o,obname,1); getobname(o,obname,1);
if (db) dblog("getavgdam: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg); if (db) dblog("getavgdam: %s: == %d-%d dam, avg is %0.1f",obname, min, max, thisavg);
}
} }
killobpile(op2); killobpile(op2);
@ -4345,6 +4524,30 @@ lifeform_t *getnearbypeaceful(lifeform_t *lf) {
return NULL; return NULL;
} }
char *getpitverb(lifeform_t *lf, int dir, int onpurpose) {
if (lfhasflag(lf, F_FLYING)) {
if (isplayer(lf)) return "fly";
else return "flies";
} else if (onpurpose) { // TODO: check if we are using a rope
if (dir == D_DOWN) {
if (isplayer(lf)) return "jump";
else return "jumps";
} else {
if (isplayer(lf)) return "climb";
else return "climbs";
}
} else {
if (dir == D_DOWN) {
if (isplayer(lf)) return "fall";
else return "falls";
} else {
if (isplayer(lf)) return "rise";
else return "rises";
}
}
return "?unkonwnmoveverb?";
}
char *getlfname(lifeform_t *lf, char *buf) { char *getlfname(lifeform_t *lf, char *buf) {
return real_getlfname(lf, buf, B_TRUE); return real_getlfname(lf, buf, B_TRUE);
} }
@ -4622,7 +4825,7 @@ int getracerarity(map_t *map, enum RACE rid) {
f = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL); f = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!f) { if (!f) {
if (map) { if (map) {
f = hasflagval(r->flags, F_RARITY, map->habitat, NA, NA, NULL); f = hasflagval(r->flags, F_RARITY, map->habitat->id, NA, NA, NULL);
} else { } else {
f = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL); f = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL);
} }
@ -4744,7 +4947,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
rarflag = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL); rarflag = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!rarflag) { if (!rarflag) {
if (c) { if (c) {
rarflag = hasflagval(r->flags, F_RARITY, c->map->habitat, NA, NA, NULL); rarflag = hasflagval(r->flags, F_RARITY, c->map->habitat->id, NA, NA, NULL);
} else { } else {
rarflag = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL); rarflag = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL);
} }
@ -5464,6 +5667,18 @@ int giveskill(lifeform_t *lf, enum SKILL id) {
} else if (id == SK_LORE_ARCANA) { } else if (id == SK_LORE_ARCANA) {
newf = addflag(lf->flags, F_CANWILL, OT_A_INSPECT, NA, NA, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_INSPECT, NA, NA, NULL);
newf->lifetime = FROMJOB; newf->lifetime = FROMJOB;
} else if (id == SK_METALWORK) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL);
if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL);
newf->lifetime = FROMJOB;
}
} else if (id == SK_SEWING) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL);
if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL);
newf->lifetime = FROMJOB;
}
} else if (id == SK_THIEVERY) { } else if (id == SK_THIEVERY) {
newf = addflag(lf->flags, F_CANWILL, OT_A_STEAL, NA, NA, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_STEAL, NA, NA, NULL);
newf->lifetime = FROMJOB; newf->lifetime = FROMJOB;
@ -5482,11 +5697,6 @@ int giveskill(lifeform_t *lf, enum SKILL id) {
newf = addflag(lf->flags, F_CANWILL, OT_A_JUMP, 3, 3, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_JUMP, 3, 3, NULL);
newf->lifetime = FROMJOB; newf->lifetime = FROMJOB;
} }
} else if (id == SK_ARMOUR) {
if (f->val[1] == PR_SKILLED) {
newf = addflag(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL);
newf->lifetime = FROMJOB;
}
} else if (id == SK_CARTOGRAPHY) { } else if (id == SK_CARTOGRAPHY) {
if ((gamemode == GM_GAMESTARTED) && isplayer(lf)) { if ((gamemode == GM_GAMESTARTED) && isplayer(lf)) {
if (f->val[1] == PR_NOVICE) { if (f->val[1] == PR_NOVICE) {
@ -6109,6 +6319,8 @@ int lockpick(lifeform_t *lf, object_t *target, object_t *device) {
gainxp(lf, difficulty/3); gainxp(lf, difficulty/3);
} }
} }
// training
practice(lf, SK_LOCKPICKING, 1);
} else { } else {
// failed! // failed!
if (faileffect == B_DIEONFAIL) { if (faileffect == B_DIEONFAIL) {
@ -6553,6 +6765,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_CLUBS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CLUBS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LONGBLADES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LONGBLADES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL);
@ -6591,6 +6804,7 @@ void initjobs(void) {
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);
addflag(lastjob->flags, F_CANLEARN, SK_METALWORK, 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_SHORTBLADES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL);
@ -6636,6 +6850,7 @@ void initjobs(void) {
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_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_TECHUSAGE, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SPELLCASTING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SPELLCASTING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_FIRE, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SS_FIRE, NA, NA, NULL);
@ -6659,7 +6874,9 @@ void initjobs(void) {
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_CARTOGRAPHY, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, 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_CHANNELING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_ARCANA, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LORE_ARCANA, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_POLEARMS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TRACKING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_TRACKING, NA, NA, NULL);
@ -6698,6 +6915,7 @@ void initjobs(void) {
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_CHANNELING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_ARCANA, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LORE_ARCANA, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SEWING, 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_THIEVERY, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_THIEVERY, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TRACKING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_TRACKING, NA, NA, NULL);
@ -8243,6 +8461,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "roars^a roars"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "roars^a roars");
addrace(R_DOGBLINK, "blink dog", 35, 'd', C_YELLOW, MT_FLESH, RC_ANIMAL); addrace(R_DOGBLINK, "blink dog", 35, 'd', C_YELLOW, MT_FLESH, RC_ANIMAL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 2, 8, NA, ""); addflag(lastrace->flags, F_NUMAPPEAR, 2, 8, NA, "");
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ENLIGHTENED, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ENLIGHTENED, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
@ -8250,7 +8469,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 77, NA, ""); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 77, NA, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, 77, NA, ""); addflag(lastrace->flags, F_RARITY, H_FOREST, 77, NA, "");
addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, 0, NA, ""); addflag(lastrace->flags, F_HITDICE, 2, 3, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d6"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d6");
addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL); addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL);
@ -9710,7 +9929,7 @@ raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum
return a; return a;
} }
skill_t *addskill(enum SKILL id, char *name, char *desc) { skill_t *addskill(enum SKILL id, char *name, char *desc, int traintime) {
skill_t *a; skill_t *a;
assert(!findskill(id)); assert(!findskill(id));
@ -9735,6 +9954,7 @@ skill_t *addskill(enum SKILL id, char *name, char *desc) {
a->id = id; a->id = id;
a->name = strdup(name); a->name = strdup(name);
a->desc = strdup(desc); a->desc = strdup(desc);
a->traintime = traintime;
return a; return a;
} }
@ -10606,6 +10826,9 @@ void makenoise(lifeform_t *lf, enum NOISETYPE nid) {
} }
sprintf(noisetext, "%s.",noun); sprintf(noisetext, "%s.",noun);
if (nid == N_WALK) {
volume += getarmournoise(lf);
}
noise(lf->cell, lf, volume, noisetext, verb); noise(lf->cell, lf, volume, noisetext, verb);
} else { } else {
// some defaults // some defaults
@ -10647,6 +10870,7 @@ void makenoise(lifeform_t *lf, enum NOISETYPE nid) {
default: default:
break; break;
} }
volume += getarmournoise(lf);
if (strlen(movetext)) { if (strlen(movetext)) {
noise(lf->cell, lf, volume, movetext, NULL); noise(lf->cell, lf, volume, movetext, NULL);
} }
@ -11011,6 +11235,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, int volume, char *text, char *seete
} }
// only hear one thing per turn. // only hear one thing per turn.
addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL); addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL);
practice(l, SK_LISTEN, 1);
} }
} }
// wake up a little // wake up a little
@ -11279,24 +11504,39 @@ int poisonthreatenslife(lifeform_t *lf, flag_t *f) {
return B_FALSE; return B_FALSE;
} }
// maybe practice a skill
void practice(lifeform_t *lf, enum SKILL skid, int amt) { void practice(lifeform_t *lf, enum SKILL skid, int amt) {
flag_t *f; flag_t *f;
skill_t *sk;
enum SKILLLEVEL slev;
int timeneeded;
// already got the skill? sk = findskill(skid);
if (getskill(lf, skid)) { if (!sk) return;
return;
} slev = getskill(lf, skid);
// practice a little bit...
f = lfhasflagval(lf, F_PRACTICINGSKILL, skid, NA, NA, NULL); timeneeded = sk->traintime * (getskill(lf, skid)+1);
if (f) { if (!timeneeded) return;
f->val[1] += amt;
if (f->val[1] >= PRACTICETIME) { // can only practice skills which you're capable of learning
// learnt it! if (!canlearn(lf, skid)) return;
if (!slev || onein(slev)) {
// practice a little bit...
f = lfhasflagval(lf, F_PRACTICINGSKILL, skid, NA, NA, NULL);
if (f) {
f->val[1] += amt;
} else {
f = addflag(lf->flags, F_PRACTICINGSKILL, skid, amt, NA, NULL);
}
if (f->val[1] >= timeneeded) {
// learnt the next rank
giveskill(lf, skid); giveskill(lf, skid);
killflag(f); killflag(f);
} }
} else {
addflag(lf->flags, F_PRACTICINGSKILL, skid, amt, NA, NULL);
} }
} }
@ -12098,55 +12338,57 @@ void setlastdam(lifeform_t *lf, char *buf) {
} }
void initskills(void) { void initskills(void) {
addskill(SK_ARMOUR, "Armour", "Lets you repair armour, and reduces evasion penalties from armour."); addskill(SK_ARMOUR, "Armour", "Reduces evasion and stealth penalties from wearing armour.", 100);
addskill(SK_ATHLETICS, "Athletics", "Assists with sprinting and exhaustion recovery."); addskill(SK_ATHLETICS, "Athletics", "Assists with sprinting and exhaustion recovery.", 50);
addskill(SK_BACKSTAB, "Backstab", "Lets you inflict massive damage with stabs when unseen."); 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."); addskill(SK_CARTOGRAPHY, "Cartography", "Your ability to create and interpret maps.", 0); // untrainable
addskill(SK_COOKING, "Cooking", "Your ability to combine foods into nutritious meals."); addskill(SK_CHANNELING, "Channeling", "Lets you make better use of magical items.", 0); // untrainable
addskill(SK_FIRSTAID, "First Aid", "Increases your healing rate and reduces duration of poison."); addskill(SK_COOKING, "Cooking", "Your ability to combine foods into nutritious meals.", 50);
addskill(SK_LISTEN, "Listen", "How good you are at hearing and interpreting sounds."); addskill(SK_FIRSTAID, "First Aid", "Increases your healing rate and reduces duration of poison.", 0); // untrainable
addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks."); addskill(SK_LISTEN, "Listen", "How good you are at hearing and interpreting sounds.", 100);
addskill(SK_CHANNELING, "Channeling", "Lets you make better use of magical items."); addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks.", 50);
addskill(SK_RANGED, "Ranged Weapons", "Your ability to aim a ranged weapon like a bow or gun."); addskill(SK_METALWORK, "Metalwork", "Lets you repair metal objects.", 100);
addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block projectiles."); addskill(SK_RANGED, "Ranged Weapons", "Your ability to aim a ranged weapon like a bow or gun.", 50);
addskill(SK_SPELLCASTING, "Sorcery", "Determines your ability to cast spells from all schools."); addskill(SK_SEWING, "Sewing", "Lets you repair cloth or leather objects.", 100);
addskill(SK_SPOTHIDDEN, "Searching", "Helps you to spot hidden traps or creatures."); addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block projectiles.", 50);
addskill(SK_STEALTH, "Stealth", "Affects your ability to move silently."); addskill(SK_SPELLCASTING, "Sorcery", "Determines your ability to cast spells from all schools.", 50);
addskill(SK_SWIMMING, "Swimming", "Allows you to safely swim through deep water."); addskill(SK_SPOTHIDDEN, "Searching", "Helps you to spot hidden traps or creatures.", 50);
addskill(SK_TECHUSAGE, "Technology", "Determines your comprehension of modern technological items."); addskill(SK_STEALTH, "Stealth", "Affects your ability to move silently.", 0); // untrainable?
addskill(SK_THIEVERY, "Thievery", "Your ability to pick pockets and steal items."); addskill(SK_SWIMMING, "Swimming", "Allows you to safely swim through deep water.", 50);
addskill(SK_TRACKING, "Tracking", "Allows you to track enemies by their footprints."); addskill(SK_TECHUSAGE, "Technology", "Determines your comprehension of modern technological items.", 0); // untrain
addskill(SK_TRAPS, "Traps", "Affects your ability to locate and disarm traps."); addskill(SK_THIEVERY, "Thievery", "Your ability to pick pockets and steal items.", 50);
addskill(SK_TWOWEAPON, "Dual Weilding", "Allows you to weild two melee weapons at once."); addskill(SK_TRACKING, "Tracking", "Allows you to track enemies by their footprints.", 0); // untrain
addskill(SK_TRAPS, "Traps", "Affects your ability to locate and disarm traps.", 25);
addskill(SK_TWOWEAPON, "Dual Weilding", "Allows you to weild two melee weapons at once.", 50);
// knowledge // knowledge
addskill(SK_LORE_ARCANA, "Lore:Arcana", "Allows you a chance of recognising magical objects and creatures."); addskill(SK_LORE_ARCANA, "Lore:Arcana", "Allows you a chance of recognising magical objects and creatures.", 0);
addskill(SK_LORE_DEMONS, "Lore:Demonology", "Determines your knowledge about demons."); addskill(SK_LORE_DEMONS, "Lore:Demonology", "Determines your knowledge about demons.", 0);
addskill(SK_LORE_HUMANOID, "Lore:Humanoid", "Determines your knowledge about humanoid (bipedal) creatures."); addskill(SK_LORE_HUMANOID, "Lore:Humanoid", "Determines your knowledge about humanoid (bipedal) creatures.", 0);
addskill(SK_LORE_NATURE, "Lore:Nature", "Determines your knowledge of plants, animals and insects."); addskill(SK_LORE_NATURE, "Lore:Nature", "Determines your knowledge of plants, animals and insects.", 0);
addskill(SK_LORE_UNDEAD, "Lore:Undead", "Determines your knowledge of the undead."); addskill(SK_LORE_UNDEAD, "Lore:Undead", "Determines your knowledge of the undead.", 0);
// weaponry // weaponry
addskill(SK_AXES, "Axes", "Helps you use chopping weapons like axes."); addskill(SK_AXES, "Axes", "Helps you use chopping weapons like axes.", 50);
addskill(SK_CLUBS, "Clubs", "Helps you use bashing weapons like maces or clubs."); addskill(SK_CLUBS, "Clubs", "Helps you use bashing weapons like maces or clubs.", 50);
addskill(SK_LONGBLADES, "Long Blades", "Helps you use long swords, scimitars, etc."); addskill(SK_LONGBLADES, "Long Blades", "Helps you use long swords, scimitars, etc.", 50);
addskill(SK_POLEARMS, "Polearms", "Helps you use long bladed weapons like halberds."); addskill(SK_POLEARMS, "Polearms", "Helps you use long bladed weapons like halberds.", 50);
addskill(SK_SHORTBLADES, "Short Blades", "Helps you use daggers, short swords, etc."); addskill(SK_SHORTBLADES, "Short Blades", "Helps you use daggers, short swords, etc.", 50);
addskill(SK_STAVES, "Staves", "Helps you use quarterstaffs, staffs, etc."); addskill(SK_STAVES, "Staves", "Helps you use quarterstaffs, staffs, etc.", 50);
addskill(SK_UNARMED, "Unarmed Combat", "Helps you fight using your bare hands."); addskill(SK_UNARMED, "Unarmed Combat", "Helps you fight using your bare hands.", 50);
// spell schools // spell schools
addskill(SK_SS_ALLOMANCY, "Allomancy", "Boosts casting of spells from this school."); addskill(SK_SS_ALLOMANCY, "Allomancy", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_AIR, "Air Magic", "Boosts casting of spells from this school."); addskill(SK_SS_AIR, "Air Magic", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_DEATH, "Necromancy", "Boosts casting of spells from this school."); addskill(SK_SS_DEATH, "Necromancy", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_DIVINATION, "Divination", "Boosts casting of spells from this school."); addskill(SK_SS_DIVINATION, "Divination", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_FIRE, "Fire Magic", "Boosts casting of spells from this school."); addskill(SK_SS_FIRE, "Fire Magic", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_COLD, "Cold Magic", "Boosts casting of spells from this school."); addskill(SK_SS_COLD, "Cold Magic", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_GRAVITY, "Gravitation Magic", "Boosts casting of spells from this school."); addskill(SK_SS_GRAVITY, "Gravitation Magic", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_LIFE, "Life Magic", "Boosts casting of spells from this school."); addskill(SK_SS_LIFE, "Life Magic", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_MODIFICATION, "Modification", "Boosts casting of spells from this school."); addskill(SK_SS_MODIFICATION, "Modification", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_MENTAL, "Psionics", "Boosts casting of spells from this school."); addskill(SK_SS_MENTAL, "Psionics", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_NATURE, "Nature Magic", "Boosts casting of spells from this school."); addskill(SK_SS_NATURE, "Nature Magic", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_SUMMONING, "Summoning", "Boosts casting of spells from this school."); addskill(SK_SS_SUMMONING, "Summoning", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_TRANSLOCATION, "Translocation", "Boosts casting of spells from this school."); addskill(SK_SS_TRANSLOCATION, "Translocation", "Boosts casting of spells from this school.", 50);
addskill(SK_SS_WILD, "Wild Magic", "Boosts casting of spells from this school."); addskill(SK_SS_WILD, "Wild Magic", "Boosts casting of spells from this school.", 50);
} }
void interrupt(lifeform_t *lf) { void interrupt(lifeform_t *lf) {
@ -12882,6 +13124,20 @@ void timeeffectslf(lifeform_t *lf) {
timeeffectsob(o); timeeffectsob(o);
} }
// 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);
}
}
o = hasobwithflagval(lf->cell->obpile, F_PIT, D_UP, NA, NA, NULL);
if (o) {
if (lfhasflag(lf, F_LEVITATING)) {
usestairs(lf, o, B_FALSE);
}
}
} }
////////////////////////////////// //////////////////////////////////
@ -13132,6 +13388,7 @@ void turneffectslf(lifeform_t *lf) {
getlfname(lf, lfname); getlfname(lf, lfname);
msg("You think %s has spotted you!", lfname); msg("You think %s has spotted you!", lfname);
} }
practice(lf, SK_SPOTHIDDEN, 1);
} }
} }
} }
@ -13162,6 +13419,11 @@ void turneffectslf(lifeform_t *lf) {
killflag(f); killflag(f);
needredraw = B_TRUE; needredraw = B_TRUE;
drawscreen(); drawscreen();
// train skills
practice(lf, SK_SPOTHIDDEN, 1);
if (hasflag(o->flags, F_TRAP)) {
practice(lf, SK_TRAPS, 1);
}
} }
} }
} }
@ -13703,7 +13965,7 @@ int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where)
} }
int usestairs(lifeform_t *lf, object_t *o) { 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;
@ -13715,6 +13977,8 @@ int usestairs(lifeform_t *lf, object_t *o) {
int isportal = B_FALSE; int isportal = B_FALSE;
lifeform_t *adjally[8]; lifeform_t *adjally[8];
int nadjallies = 0; int nadjallies = 0;
int falling = B_FALSE;
region_t *newregion = NULL;
// need up update 'dlev:' // need up update 'dlev:'
if (isplayer(lf)) { if (isplayer(lf)) {
@ -13734,6 +13998,12 @@ int usestairs(lifeform_t *lf, object_t *o) {
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) {
// use same region
newregion = lf->cell->map->region;
} else {
newregion = findregion(f->val[1]);
}
// depth of new level? // depth of new level?
if (dir == D_UP) { if (dir == D_UP) {
@ -13747,6 +14017,10 @@ int usestairs(lifeform_t *lf, object_t *o) {
isportal = B_TRUE; isportal = B_TRUE;
} }
if (!onpurpose) {
falling = B_TRUE;
}
// check... // check...
if (dir == D_DOWN) { if (dir == D_DOWN) {
if (lfhasflag(lf, F_LEVITATING)) { if (lfhasflag(lf, F_LEVITATING)) {
@ -13755,6 +14029,18 @@ int usestairs(lifeform_t *lf, object_t *o) {
} }
return B_TRUE; return B_TRUE;
} }
} else if (dir == D_UP) {
if (hasflagval(o->flags, F_PIT, D_UP, NA, NA, NULL)) {
// 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!");
}
return B_TRUE;
}
}
} }
// announce // announce
@ -13767,18 +14053,27 @@ int usestairs(lifeform_t *lf, object_t *o) {
} else if (cansee(player, lf)) { } else if (cansee(player, lf)) {
msg("%s enters %s...", lfname, obname); msg("%s enters %s...", lfname, obname);
} }
} else if (hasflag(o->flags, F_PIT)) {
f = hasflag(o->flags, F_PIT);
if (isplayer(lf) || cansee(player, lf)) {
msg("%s %s %s the %s...", lfname, getpitverb(lf, dir,onpurpose), getdirname(dir), noprefix(obname));
// move cursor to msgwindow while we create the new level...
if (isplayer(lf)) wrefresh(msgwin);
}
} else { } else {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You %s %s the staircase...", getmoveverb(lf), getdirname(dir)); msg("You %s %s the staircase...", getmoveverb(lf), getdirname(dir));
// move cursor to msgwindow while we create the new level... // move cursor to msgwindow while we create the new level...
wrefresh(msgwin); wrefresh(msgwin);
} else if (cansee(player, lf)) { } else if (cansee(player, lf)) {
msg("%s %s %s the staircase...", lfname, getmoveverbother(lf), getdirname(dir)); msg("%s %s %s the staircase.", lfname, getmoveverbother(lf), getdirname(dir));
} }
} }
// find adjacent allies or enemies which will follow you // find adjacent allies or enemies which will follow you
if (isplayer(lf)) { // (but not into/out of pits)
if (isplayer(lf) || !hasflag(o->flags, F_PIT)) {
getadjallies(lf, adjally, &nadjallies); getadjallies(lf, adjally, &nadjallies);
} }
@ -13790,27 +14085,27 @@ int usestairs(lifeform_t *lf, object_t *o) {
if (isplayer(lf)) msg("This portal doesn't seem to go anywhere."); if (isplayer(lf)) msg("This portal doesn't seem to go anywhere.");
} else { } else {
// is there already a level of the correct depth? // is there already a level of the correct depth?
newmap = findregionmap(lf->cell->map->region, newdepth); newmap = findregionmap(newregion->id, newdepth);
if (newmap) { if (newmap) {
dblog("ERROR - unlinked stairs!\n"); dblog("ERROR - unlinked stairs!\n");
msg("ERROR - unlinked stairs!\n"); msg("ERROR - unlinked stairs!\n");
} else { } else {
enum HABITAT newhabitat;
int newregion;
// generate a new map! this will fill in the destination of our stairs // generate a new map! this will fill in the destination of our stairs
newmap = addmap(); newmap = addmap();
if (newdepth == 0) { // first map of a newly created region?
newregion = RG_WORLDMAP; if (newregion->id != curmap->region->id) {
newhabitat = AUTO; newdepth = 1;
} else {
newregion = lf->cell->map->region;
newhabitat = AUTO;
} }
createmap(newmap, newdepth, newregion, newhabitat, curmap, dir); createmap(newmap, newdepth, newregion, curmap, dir);
// link our stairs to the new map. // if we stayed within the same region, our stairs should
//linkstairs(o); // now have a destination, since createmap() will automatically check
// previous/next levels in the same region.
// NOW our stairs should have a destination // 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); newcell = getstairdestination(o);
} }
} }
@ -13841,12 +14136,14 @@ int usestairs(lifeform_t *lf, object_t *o) {
if (f) f->known = B_KNOWN; if (f) f->known = B_KNOWN;
} }
// move player to new map // move player to new map
moveto(lf, newcell, B_TRUE, B_TRUE); moveto(lf, newcell, onpurpose, B_TRUE);
// take time
if ((dir == D_UP) && !isairborne(lf)) { if ((dir == D_UP) && !isairborne(lf)) {
stopsprinting(lf); // you can sprint down stairs, but not up stopsprinting(lf); // you can sprint down stairs, but not up
taketime(lf, getmovespeed(lf)*2); // takes longer to climb if (onpurpose) taketime(lf, getmovespeed(lf)*2); // takes longer to climb
} else { } else {
taketime(lf, getmovespeed(lf)); if (onpurpose) taketime(lf, getmovespeed(lf));
} }
// move adjacent allies/monsters too // move adjacent allies/monsters too
@ -13858,9 +14155,9 @@ int usestairs(lifeform_t *lf, object_t *o) {
stopsprinting(adjally[n]); stopsprinting(adjally[n]);
movelf(adjally[n], c); movelf(adjally[n], c);
if ((dir == D_UP) && !isairborne(adjally[n])) { if ((dir == D_UP) && !isairborne(adjally[n])) {
taketime(adjally[n], getmovespeed(adjally[n])*2); // takes longer to climb if (onpurpose) taketime(adjally[n], getmovespeed(adjally[n])*2); // takes longer to climb
} else { } else {
taketime(adjally[n], getmovespeed(adjally[n])); if (onpurpose) taketime(adjally[n], getmovespeed(adjally[n]));
} }
} }
} }
@ -13871,6 +14168,29 @@ int usestairs(lifeform_t *lf, object_t *o) {
return B_TRUE; return B_TRUE;
} }
if (falling) {
if (dir == D_DOWN) {
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");
// fall over
fall(lf, NULL, B_FALSE);
} else {
// TODO: if you are outside, DIE!
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");
}
}
if (isplayer(lf)) { if (isplayer(lf)) {
statdirty = B_TRUE; statdirty = B_TRUE;
needredraw = B_TRUE; needredraw = B_TRUE;

9
lf.h
View File

@ -5,7 +5,7 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller);
job_t *addjob(enum JOB id, char *name); job_t *addjob(enum JOB id, char *name);
race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat, enum RACECLASS raceclass); race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat, enum RACECLASS raceclass);
raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill); raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill);
skill_t *addskill(enum SKILL id, char *name, char *desc); skill_t *addskill(enum SKILL id, char *name, char *desc, int traintime);
void addtrail(lifeform_t *lf, int dir); void addtrail(lifeform_t *lf, int dir);
void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype); void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype);
void adjustspeedforwater(lifeform_t *lf, int *speed); void adjustspeedforwater(lifeform_t *lf, int *speed);
@ -48,6 +48,9 @@ int countnearbyhurtallies(lifeform_t *lf);
void debug(lifeform_t *lf); void debug(lifeform_t *lf);
int demandbribe(lifeform_t *lf); int demandbribe(lifeform_t *lf);
void die(lifeform_t *lf); void die(lifeform_t *lf);
int digcell(lifeform_t *lf, cell_t *c, object_t *o);
int digdown(lifeform_t *lf, object_t *o);
int digup(lifeform_t *lf, object_t *o);
void dumplev(void); void dumplev(void);
void dumplf(void); void dumplf(void);
void dumpxp(void); void dumpxp(void);
@ -80,6 +83,7 @@ void getadjallies(lifeform_t *lf, 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);
int getarmournoise(lifeform_t *lf);
int getarmourrating(lifeform_t *lf); int getarmourrating(lifeform_t *lf);
int getattackspeed(lifeform_t *lf); int getattackspeed(lifeform_t *lf);
int getattpoints(lifeform_t *lf); int getattpoints(lifeform_t *lf);
@ -131,6 +135,7 @@ int getmovespeed(lifeform_t *lf);
char *getmoveverb(lifeform_t *lf); char *getmoveverb(lifeform_t *lf);
char *getmoveverbother(lifeform_t *lf); char *getmoveverbother(lifeform_t *lf);
lifeform_t *getnearbypeaceful(lifeform_t *lf); lifeform_t *getnearbypeaceful(lifeform_t *lf);
char *getpitverb(lifeform_t *lf, int dir, int onpurpose);
char *getlfname(lifeform_t *lf, char *buf); char *getlfname(lifeform_t *lf, char *buf);
char *real_getlfname(lifeform_t *lf, char *buf, int usevis); char *real_getlfname(lifeform_t *lf, char *buf, int usevis);
char *getlfnamea(lifeform_t *lf, char *buf); char *getlfnamea(lifeform_t *lf, char *buf);
@ -297,7 +302,7 @@ void unsummon(lifeform_t *lf, int vanishobs);
int unweild(lifeform_t *lf, object_t *o); int unweild(lifeform_t *lf, object_t *o);
int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where); int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where);
int useringofmiracles(lifeform_t *lf, int charges); int useringofmiracles(lifeform_t *lf, int charges);
int usestairs(lifeform_t *lf, object_t *o); int usestairs(lifeform_t *lf, object_t *o, int onpurpose);
int validateraces(void); int validateraces(void);
int wear(lifeform_t *lf, object_t *o); int wear(lifeform_t *lf, object_t *o);
int weild(lifeform_t *lf, object_t *o); int weild(lifeform_t *lf, object_t *o);

853
map.c

File diff suppressed because it is too large Load Diff

34
map.h
View File

@ -1,12 +1,17 @@
#include "defs.h" #include "defs.h"
cell_t *addcell(map_t *map, int x, int y); cell_t *addcell(map_t *map, int x, int y);
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell);
void addhomeobs(lifeform_t *lf); void addhomeobs(lifeform_t *lf);
map_t *addmap(void); map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded); lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded);
object_t *addrandomob(cell_t *c); object_t *addrandomob(cell_t *c);
int addrandomthing(cell_t *c, int obchance, int *nadded); int addrandomthing(cell_t *c, int obchance, int *nadded);
int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct); region_t *addregion(enum REGIONTYPE rtype, region_t *parent);
regionoutline_t *addregionoutline(enum REGIONTYPE rtype);
regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum REGIONTHING whatkind, int value, char *what);
regiontype_t *addregiontype(enum REGIONTYPE id, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir);
int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance);
int cellhaslos(cell_t *c1, cell_t *dest); int cellhaslos(cell_t *c1, cell_t *dest);
void clearcell(cell_t *c); void clearcell(cell_t *c);
int dowaterspread(cell_t *c); int dowaterspread(cell_t *c);
@ -17,21 +22,22 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer);
enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf); enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf);
int getdoorlockdiff(int depth); int getdoorlockdiff(int depth);
int getdoorsecretdiff(int depth); int getdoorsecretdiff(int depth);
enum CELLTYPE getemptycelltype(enum HABITAT hab);
enum CELLTYPE getwallcelltype(enum HABITAT hab);
flag_t *getmapcoords(map_t *m, int *x, int *y); flag_t *getmapcoords(map_t *m, int *x, int *y);
int getmapdifficulty(map_t *m); int getmapdifficulty(map_t *m);
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);
void calclight(map_t *map); void calclight(map_t *map);
int calcroompos(map_t *map, int w, int h, int *bx, int *by); 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 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);
void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap, int exitdir); void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir);
void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int exitdir);
void createpit(map_t *map, int depth, map_t *parentmap, int exitdir);
void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIONTYPE newregiontype, region_t *parent);
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls); int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls);
int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth); int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth);
int dirtox(int dt, int dir); int dirtox(int dt, int dir);
@ -41,16 +47,23 @@ void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *c
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce); void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce);
celltype_t *findcelltype(enum CELLTYPE cid); celltype_t *findcelltype(enum CELLTYPE cid);
celltype_t *findcelltypebyname(char *name); celltype_t *findcelltypebyname(char *name);
habitat_t *findhabitat(enum HABITAT id);
habitat_t *findhabitatbyname(char *name);
map_t *findmap(int mid); map_t *findmap(int mid);
map_t *findmapofdepth(int depth); map_t *findmapofdepth(int depth);
cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf); cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf);
object_t *findobidinmap(map_t *m, long id); object_t *findobidinmap(map_t *m, long id);
cell_t *findobinmap(map_t *m, enum OBCLASS oid); cell_t *findobinmap(map_t *m, enum OBCLASS oid);
map_t *findregionmap(int region, int depth); region_t *findregion(int regionid);
region_t *findregionbytype(enum REGIONTYPE rtid);
map_t *findregionmap(int regionid, int depth);
regiontype_t *findregiontype(enum REGIONTYPE rtype);
map_t *findsurfaceexitmap(map_t *m);
void forgetcells(map_t *map, int amt); void forgetcells(map_t *map, int amt);
cell_t *getcellindir(cell_t *cell, int dir); cell_t *getcellindir(cell_t *cell, int dir);
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved); int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
int getobchance(int habitat); int getobchance(int habitat);
char *getregionname(char *buf, map_t *m, int withlevel);
int getvaultchance(map_t *m); int getvaultchance(map_t *m);
char getvaultchar(vault_t *v, int x, int y); char getvaultchar(vault_t *v, int x, int y);
int getthingchance(int habitat); int getthingchance(int habitat);
@ -69,6 +82,7 @@ lifeform_t *haslf(cell_t *c);
int hasknownobject(cell_t *c); int hasknownobject(cell_t *c);
int hasobject(cell_t *c); int hasobject(cell_t *c);
object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tflag, lifeform_t *viewer); object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tflag, lifeform_t *viewer);
void initmap(void);
int isadjacent(cell_t *src, cell_t *dst); int isadjacent(cell_t *src, cell_t *dst);
int isdark(cell_t *c); int isdark(cell_t *c);
int isdiggable(cell_t *c); int isdiggable(cell_t *c);
@ -82,11 +96,15 @@ int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m); int isoutdoors(map_t *m);
int iswallindir(cell_t *cell, int dir); int iswallindir(cell_t *cell, int dir);
int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy); int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy);
void linkholes(map_t *map);
int linkstairs(object_t *o); int linkstairs(object_t *o);
void makedoor(cell_t *cell); void makedoor(cell_t *cell, int openchance);
void makelit(cell_t *c, enum LIGHTLEV how, int howlong); void makelit(cell_t *c, enum LIGHTLEV how, int howlong);
void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong); void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);
void setcellknown(cell_t *cell, int forcelev); void setcellknown(cell_t *cell, int forcelev);
void setcelltype(cell_t *cell, int id); void setcelltype(cell_t *cell, enum CELLTYPE id);
int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring);
void updateknowncells(void); void updateknowncells(void);
int validateregions(void);
int validateregionthing(regionthing_t *thing);
int wallstoleftright(cell_t *c, int dir); int wallstoleftright(cell_t *c, int dir);

21
move.c
View File

@ -1202,7 +1202,9 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
// just clear the message buffer // just clear the message buffer
if (!didmsg) clearmsg(); if (!didmsg) clearmsg();
} else { // tell player what is here } else { // tell player what is here
dolook(newcell, B_FALSE); if (onpurpose) {
dolook(newcell, B_FALSE);
}
} }
} }
} }
@ -1348,7 +1350,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
// locked? // locked?
if (hasflag(o->flags, F_LOCKED)) { if (hasflag(o->flags, F_LOCKED)) {
if (lf && isplayer(lf)) { if (lf && isplayer(lf)) {
msg("The door is locked."); msg("The %s is locked.", noprefix(obname));
} }
return B_TRUE; return B_TRUE;
} else { } else {
@ -1361,9 +1363,9 @@ int opendoor(lifeform_t *lf, object_t *o) {
if (lf && isplayer(lf)) { if (lf && isplayer(lf)) {
if (amt > 0) { if (amt > 0) {
msg("The door moves slightly but seems jammed."); msg("The %s moves slightly but seems jammed.", noprefix(obname));
} else { } else {
msg("The door is jammed."); msg("The %s is jammed.", noprefix(obname));
} }
} }
// loosen a bit // loosen a bit
@ -1491,7 +1493,9 @@ int closedoor(lifeform_t *lf, object_t *o) {
} else { } else {
// close it // close it
killflag(f); killflag(f);
addflag(o->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL); f = hasflag(o->flags, F_DOOR);
addflag(o->flags, F_IMPASSABLE, f->val[0], f->val[1], f->val[2], f->text);
addflag(o->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(o->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
if (lf) { if (lf) {
@ -2009,6 +2013,11 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} }
} }
} }
// train
if (isswimming(lf)) {
practice(lf, SK_SWIMMING, 1);
}
} else { } else {
object_t *inway = NULL; object_t *inway = NULL;
int door, dooropen; int door, dooropen;
@ -2236,7 +2245,7 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
if (!adjmap) { if (!adjmap) {
// make one // make one
adjmap = addmap(); adjmap = addmap();
createmap(adjmap, thismap->depth, thismap->region, AUTO, thismap, dir); createmap(adjmap, thismap->depth, thismap->region, thismap, dir);
} }
if (adjmap) { if (adjmap) {

36
nexus.c
View File

@ -30,7 +30,11 @@ race_t *firstrace = NULL,*lastrace = NULL;
raceclass_t *firstraceclass = NULL,*lastraceclass = NULL; raceclass_t *firstraceclass = NULL,*lastraceclass = NULL;
job_t *firstjob = NULL,*lastjob = NULL; job_t *firstjob = NULL,*lastjob = NULL;
skill_t *firstskill = NULL,*lastskill = NULL; skill_t *firstskill = NULL,*lastskill = NULL;
habitat_t *firsthabitat = NULL,*lasthabitat = NULL;
map_t *firstmap = NULL,*lastmap = NULL; map_t *firstmap = NULL,*lastmap = NULL;
region_t *firstregion = NULL,*lastregion = NULL;
regionoutline_t *firstregionoutline = NULL,*lastregionoutline = NULL;
regiontype_t *firstregiontype = NULL,*lastregiontype = NULL;
knowledge_t *knowledge = NULL, *lastknowledge = NULL; knowledge_t *knowledge = NULL, *lastknowledge = NULL;
hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL; hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
@ -145,6 +149,7 @@ int main(int argc, char **argv) {
cell_t *where; cell_t *where;
int dir; int dir;
flag_t *f; flag_t *f;
map_t *dmap;
// read from input file if required // read from input file if required
if (playerfile) { if (playerfile) {
@ -178,13 +183,21 @@ int main(int argc, char **argv) {
// if no maps (ie. ALWAYS now that maps aren't persistent), // if no maps (ie. ALWAYS now that maps aren't persistent),
// make the initial level // make the initial level
if (!firstmap) { if (!firstmap) {
region_t *wregion, *dregion;
newworld = B_TRUE; newworld = B_TRUE;
// create world map.
wregion = addregion(RG_WORLDMAP, NULL);
addmap(); addmap();
createmap(firstmap, 1, RG_FIRSTDUNGEON, H_DUNGEON, NULL, D_NONE); createmap(firstmap, 1, wregion, NULL, D_NONE);
//createmap(firstmap, 1, RG_FIRSTDUNGEON, H_DUNGEON, NULL, D_NONE);
// create first dungeon
dregion = findregionbytype(RG_FIRSTDUNGEON);
dmap = addmap();
createmap(dmap, 1, dregion, NULL, D_NONE);
} }
// find staircase // find staircase
where = findobinmap(firstmap, OT_STAIRSUP); where = findobinmap(dmap, OT_STAIRSUP);
assert(where); assert(where);
// make sure no lifeforms are there // make sure no lifeforms are there
if (where->lf) { if (where->lf) {
@ -752,17 +765,7 @@ int init(void) {
initjobs(); initjobs();
initrace(); initrace();
// cell types initmap();
addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
addcelltype(CT_WALLGLASS, "glass wall", '#', C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0);
addcelltype(CT_WALLMETAL, "metal wall", '#', C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0);
addcelltype(CT_ROOMWALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT, 0);
addcelltype(CT_DIRT, "dirt", '.', C_BROWN, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -1);
gamemode = GM_VALIDATION; gamemode = GM_VALIDATION;
if (validateobs()) { if (validateobs()) {
@ -779,6 +782,12 @@ int init(void) {
// load in vaults // load in vaults
loadvaults(); loadvaults();
// validate regions
if (validateregions()) {
printf("Errors found in map outlines - check log for details. Bailing out.");
exit(1);
}
return B_FALSE; return B_FALSE;
} }
@ -927,6 +936,7 @@ int limitf(float *what, float min, float max) {
} }
int onein(int howmany) { int onein(int howmany) {
if (howmany <= 0) return B_FALSE;
if (rnd(1,howmany) == 1) return B_TRUE; if (rnd(1,howmany) == 1) return B_TRUE;
return B_FALSE; return B_FALSE;
} }

362
objects.c
View File

@ -982,6 +982,57 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
} }
// link holes to adjacent maps
if (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!
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);
}
}
if (adjmap) {
linkholes(adjmap);
}
}
}
// other special changes we need to make based on what was // other special changes we need to make based on what was
// asked for // asked for
if ((gamemode != GM_LOADING) && o) { if ((gamemode != GM_LOADING) && o) {
@ -1064,7 +1115,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
if (f) { if (f) {
rf = hasflag(corpserace->flags, F_SIZE); rf = hasflag(corpserace->flags, F_SIZE);
if (rf) { if (rf) {
f->val[0] = rf->val[0]; f->val[0] = SZ_MIN;
f->val[1] = rf->val[0];
} else { } else {
killflag(f); killflag(f);
} }
@ -2666,7 +2718,7 @@ glyph_t *getglyph(object_t *o) {
if (isdoor(o, &isopen)) { if (isdoor(o, &isopen)) {
if (issecretdoor(o)) { if (issecretdoor(o)) {
return &(findcelltype(getwallcelltype(obloc->map->habitat))->glyph); return &(findcelltype(obloc->map->habitat->solidcelltype)->glyph);
} else { } else {
if (isopen) { if (isopen) {
g = '-'; g = '-';
@ -4017,13 +4069,24 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
// show portal/stair destination // show portal/stair destination
f = hasflag(o->flags, F_MAPLINK); f = hasflag(o->flags, F_MAPLINK);
if (f && f->known) { if (f && f->known && !hasflag(o->flags, F_PIT)) {
cell_t *thiscell;
map_t *thismap;
map_t *newmap; map_t *newmap;
thiscell = getoblocation(o);
thismap = thiscell->map;
newmap = findmap(f->val[0]); newmap = findmap(f->val[0]);
if (newmap) { if (newmap) {
char buf2[BUFLEN]; if (newmap->region == thismap->region) {
sprintf(buf2, " to level %d", newmap->depth); char buf2[BUFLEN];
strcat(localbuf, buf2); sprintf(buf2, " to level %d", newmap->depth);
strcat(localbuf, buf2);
} else {
char buf2[BUFLEN];
strcat(localbuf, " to ");
getregionname(buf2, newmap, B_FALSE);
strcat(localbuf, buf2);
}
} }
} }
@ -4300,7 +4363,7 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
rarflag = hasflagval(ot->flags, F_RARITY, H_ALL, NA, NA, NULL); rarflag = hasflagval(ot->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!rarflag) { if (!rarflag) {
if (map) { if (map) {
rarflag = hasflagval(ot->flags, F_RARITY, map->habitat, NA, NA, NULL); rarflag = hasflagval(ot->flags, F_RARITY, map->habitat->id, NA, NA, NULL);
} else { } else {
rarflag = hasflagval(ot->flags, F_RARITY, NA, NA, NA, NULL); rarflag = hasflagval(ot->flags, F_RARITY, NA, NA, NA, NULL);
} }
@ -4479,7 +4542,7 @@ int getobrarity(object_t *o, enum RARITY *rr) {
m = c->map; m = c->map;
} }
if (m) { if (m) {
f = hasflagval(o->flags, F_RARITY,m->habitat, NA, NA, NULL); f = hasflagval(o->flags, F_RARITY,m->habitat->id, NA, NA, NULL);
if (f) { if (f) {
if (rr) { if (rr) {
*rr = (f->val[2] == NA) ? RR_COMMON : f->val[2]; *rr = (f->val[2] == NA) ? RR_COMMON : f->val[2];
@ -5197,8 +5260,8 @@ void initobjects(void) {
// dungeon features // dungeon features
addot(OT_DOORWOOD, "wooden door", "A sturdy wooden door.", MT_WOOD, 150, OC_DFEATURE); addot(OT_DOORWOOD, "wooden door", "A sturdy wooden door.", MT_WOOD, 150, OC_DFEATURE);
// GLYPH here is a special case in getglyph // GLYPH here is a special case in getglyph
addflag(lastot->flags, F_DOOR, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DOOR, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -5210,8 +5273,8 @@ void initobjects(void) {
addot(OT_DOORIRON, "iron door", "A strong iron door.", MT_METAL, 300, OC_DFEATURE); addot(OT_DOORIRON, "iron door", "A strong iron door.", MT_METAL, 300, OC_DFEATURE);
// GLYPH here is a special case in getglyph // GLYPH here is a special case in getglyph
addflag(lastot->flags, F_DOOR, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DOOR, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -5222,11 +5285,25 @@ void initobjects(void) {
addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL); addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL); addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL);
// blocks movement, but you can see and fire through them.
addot(OT_IRONGATE, "iron gate", "A gate comprised of a series of vertical iron bars.", MT_METAL, 0, OC_DFEATURE);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "|");
addflag(lastot->flags, F_DOOR, SZ_MEDIUM, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MEDIUM, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 120, 120, NA, NULL);
addflag(lastot->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL);
addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_ROCK); addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_ROCK);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, "");
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'"); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'");
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL);
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
@ -5237,9 +5314,10 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL); addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "50-100 stones"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "50-100 stones");
addot(OT_ICICLE, "huge icicle", "A massive ice stalacmite.", MT_ICE, 200, OC_ROCK); addot(OT_ICICLE, "huge icicle", "A massive ice stalacmite.", MT_ICE, 200, OC_ROCK);
addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "'"); addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "'");
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL);
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -5249,7 +5327,7 @@ void initobjects(void) {
addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_ROCK); addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_ROCK);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, "");
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'"); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'");
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL); // will be overridden
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -5258,6 +5336,25 @@ void initobjects(void) {
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "20-50 stones"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "20-50 stones");
addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "a statue"); addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "a statue");
addot(OT_HOLEINGROUND, "hole in the ground", "A gaping hole in the ground.", MT_NOTHING, 0, OC_DFEATURE);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "^");
addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, NULL);
addflag(lastot->flags, F_PIT, D_DOWN, NA, NA, NULL);
addflag(lastot->flags, F_OPPOSITESTAIRS, OT_HOLEINROOF, NA, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL);
addot(OT_HOLEINROOF, "hole in the roof", "A gaping hole in the roof.", MT_NOTHING, 0, OC_DFEATURE);
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "<");
addflag(lastot->flags, F_CLIMBABLE, D_UP, NA, NA, NULL);
addflag(lastot->flags, F_PIT, D_UP, NA, NA, NULL);
addflag(lastot->flags, F_OPPOSITESTAIRS, OT_HOLEINGROUND, NA, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL);
addot(OT_STAIRSDOWN, "staircase going down", "A stone staircase winding downwards.", MT_STONE, 3000, OC_DFEATURE); addot(OT_STAIRSDOWN, "staircase going down", "A stone staircase winding downwards.", MT_STONE, 3000, OC_DFEATURE);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ">"); addflag(lastot->flags, F_GLYPH, NA, NA, NA, ">");
addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, NULL); addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, NULL);
@ -5472,7 +5569,7 @@ void initobjects(void) {
addot(OT_SHRUB, "shrub", "A small but dense shrub.", MT_PLANT, 40, OC_FLORA); addot(OT_SHRUB, "shrub", "A small but dense shrub.", MT_PLANT, 40, OC_FLORA);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, ""); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, "");
addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "%"); addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "%");
addflag(lastot->flags, F_IMPASSABLE, SZ_MEDIUM, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MEDIUM, NA, NULL);
addflag(lastot->flags, F_REDUCEMOVEMENT, 1, NA, NA, NULL); addflag(lastot->flags, F_REDUCEMOVEMENT, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -5482,7 +5579,7 @@ void initobjects(void) {
addot(OT_STUMP, "stump", "A large tree stump.", MT_WOOD, 150, OC_FLORA); addot(OT_STUMP, "stump", "A large tree stump.", MT_WOOD, 150, OC_FLORA);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, ""); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, "");
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "'"); addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "'");
addflag(lastot->flags, F_IMPASSABLE, SZ_HUMAN, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_HUMAN, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL);
@ -5491,7 +5588,7 @@ void initobjects(void) {
addot(OT_TREE, "tree", "A tree.", MT_WOOD, 200, OC_FLORA); addot(OT_TREE, "tree", "A tree.", MT_WOOD, 200, OC_FLORA);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, ""); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, "");
addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "#"); addflag(lastot->flags, F_GLYPH, C_GREEN, NA, NA, "#");
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL);
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
@ -5814,6 +5911,10 @@ void initobjects(void) {
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
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);
addot(OT_S_COMMANDUNDEAD, "command undead", "Compels an undead creature to follow a single simple command.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_FEAR, "cause fear", "Causes intense fear in the target.", MT_NOTHING, 0, OC_SPELL); addot(OT_S_FEAR, "cause fear", "Causes intense fear in the target.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
@ -5943,6 +6044,12 @@ 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_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
addot(OT_S_SHATTER, "shatter", "Instantly shatters all glass in the target location.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l3 // l3
addot(OT_S_AIRBLAST, "airblast", "Knocks enemies back with a powerful blast of air.", MT_NOTHING, 0, OC_SPELL); addot(OT_S_AIRBLAST, "airblast", "Knocks enemies back with a powerful blast of air.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
@ -6553,7 +6660,7 @@ void initobjects(void) {
addot(OT_A_RAGE, "rage", "Enter a state of berzerker rage, gaining attack and defence bonuses.", MT_NOTHING, 0, OC_ABILITY); addot(OT_A_RAGE, "rage", "Enter a state of berzerker rage, gaining attack and defence bonuses.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL);
addot(OT_A_REPAIR, "repair armour", "Repair damage done to your armour.", MT_NOTHING, 0, OC_ABILITY); addot(OT_A_REPAIR, "repair equipment", "Repair damage done to your equipment.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_SPRINT, "sprint", "You can run at high speed over short distances.", MT_NOTHING, 0, OC_ABILITY); addot(OT_A_SPRINT, "sprint", "You can run at high speed over short distances.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
@ -6931,6 +7038,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SHARP, 1, 2, NA, NULL); addflag(lastot->flags, F_SHARP, 1, 2, NA, NULL);
addflag(lastot->flags, F_CRUSHABLE, SZ_MEDIUM, NA, NA, NULL); addflag(lastot->flags, F_CRUSHABLE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastot->flags, F_NOSHATTER, B_TRUE, NA, NA, NULL);
addot(OT_CALTROP, "caltrop", "Connected metal spikes arranged such that one will always point upwards.", MT_METAL, 0.2, OC_MISC); addot(OT_CALTROP, "caltrop", "Connected metal spikes arranged such that one will always point upwards.", MT_METAL, 0.2, OC_MISC);
addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL); addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL);
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, NULL); addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, NULL);
@ -6963,6 +7071,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOSHATTER, B_TRUE, NA, NA, NULL);
addot(OT_MELTEDWAX, "lump of melted wax", "A useless lump of melted wax.", MT_WAX, 0.1, OC_MISC); addot(OT_MELTEDWAX, "lump of melted wax", "A useless lump of melted wax.", MT_WAX, 0.1, OC_MISC);
addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL); addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL);
@ -7167,7 +7276,7 @@ void initobjects(void) {
addot(OT_WOODENBARREL, "wooden barrel", "A solid wooden barrel.", MT_WOOD, 20, OC_MISC); addot(OT_WOODENBARREL, "wooden barrel", "A solid wooden barrel.", MT_WOOD, 20, OC_MISC);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "("); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "(");
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL);
addflag(lastot->flags, F_CRUSHABLE, SZ_HUGE, NA, NA, NULL); addflag(lastot->flags, F_CRUSHABLE, SZ_HUGE, NA, NA, NULL);
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -7178,7 +7287,7 @@ void initobjects(void) {
addot(OT_WOODENTABLE, "wooden table", "A waist-height wooden table.", MT_WOOD, 25, OC_MISC); addot(OT_WOODENTABLE, "wooden table", "A waist-height wooden table.", MT_WOOD, 25, OC_MISC);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "\\"); addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "\\");
addflag(lastot->flags, F_IMPASSABLE, SZ_HUMAN, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_HUMAN, NA, NULL);
addflag(lastot->flags, F_CRUSHABLE, SZ_LARGE, NA, NA, NULL); addflag(lastot->flags, F_CRUSHABLE, SZ_LARGE, NA, NA, NULL);
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
//addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); //addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -7376,14 +7485,15 @@ void initobjects(void) {
addot(OT_ICEWALL, "wall of ice", "A wall made of solid ice.", MT_ICE, 0, OC_EFFECT); addot(OT_ICEWALL, "wall of ice", "A wall made of solid ice.", MT_ICE, 0, OC_EFFECT);
addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "#"); addflag(lastot->flags, F_GLYPH, C_CYAN, NA, NA, "#");
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 100, 100, NA, NULL); addflag(lastot->flags, F_OBHP, 100, 100, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addot(OT_MAGICBARRIER, "magical barrier", "A glowing, impassable barrier of magical energy.", MT_MAGIC, 0, OC_EFFECT); addot(OT_MAGICBARRIER, "magical barrier", "A glowing, impassable barrier of magical energy.", MT_MAGIC, 0, OC_EFFECT);
addflag(lastot->flags, F_GLYPH, C_YELLOW, NA, NA, "#"); addflag(lastot->flags, F_GLYPH, C_YELLOW, NA, NA, "#");
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes"); addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes");
@ -7589,7 +7699,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL); addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
addot(OT_GASMASK, "gas mask", "A full face mask which protects the wearer from toxic gasses.", MT_METAL, 1, OC_ARMOUR); addot(OT_GASMASK, "gas mask", "A full face mask which protects the wearer from toxic gasses.", MT_METAL, 3.5, OC_ARMOUR);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
@ -8639,14 +8749,15 @@ int isimpassableob(object_t *o, lifeform_t *lf) {
f = hasflag(o->flags, F_IMPASSABLE); f = hasflag(o->flags, F_IMPASSABLE);
if (f) { if (f) {
enum LFSIZE lfsize; enum LFSIZE lfsize;
enum LFSIZE blocksize; enum LFSIZE blockmin, blockmax;
if (!lf) return B_TRUE; if (!lf) return B_TRUE;
lfsize = getlfsize(lf); lfsize = getlfsize(lf);
blocksize = f->val[0];
if (lfsize <= blocksize) { blockmin = f->val[0];
blockmax = f->val[1];
if ((lfsize >= blockmin) && (lfsize <= blockmax)) {
return B_TRUE; return B_TRUE;
} }
} }
@ -9274,6 +9385,18 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
reason = E_OK; reason = E_OK;
// adjust destination for pits
if (dst->where) {
object_t *pit;
pit = hasobwithflagval(dst->where->obpile, F_PIT, D_DOWN, NA, NA, NULL);
if (pit) {
cell_t *newcell;
newcell = getstairdestination(pit);
if (newcell) {
dst = newcell->obpile;
}
}
}
if (db) dblog("DB: moveob() - moving %d x %s",howmany, src->type->name); if (db) dblog("DB: moveob() - moving %d x %s",howmany, src->type->name);
if (stackok) { if (stackok) {
@ -9354,6 +9477,7 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
killflagsofid(o->flags, F_SECRET); killflagsofid(o->flags, F_SECRET);
if (!hasflag(o->flags, F_OPEN)) { if (!hasflag(o->flags, F_OPEN)) {
addflag(o->flags, F_OPEN, B_TRUE, NA, NA, NULL); addflag(o->flags, F_OPEN, B_TRUE, NA, NA, NULL);
killflagsofid(o->flags, F_IMPASSABLE);
} }
} }
} }
@ -10124,7 +10248,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
} else if (o->type->id == OT_ORBDUNGEONEXIT) { } else if (o->type->id == OT_ORBDUNGEONEXIT) {
map_t *m; map_t *m;
m = lf->cell->map; m = lf->cell->map;
if ((m->region == RG_FIRSTDUNGEON) && (m->depth == 1)) { if ((m->region->rtype->id == RG_FIRSTDUNGEON) && (m->depth == 1)) {
cell_t *cell[MAXCANDIDATES]; cell_t *cell[MAXCANDIDATES];
int ncells,i; int ncells,i;
getradiuscells(lf->cell, 1, DT_COMPASS, B_FALSE, B_TRUE, cell, &ncells); getradiuscells(lf->cell, 1, DT_COMPASS, B_FALSE, B_TRUE, cell, &ncells);
@ -10255,101 +10379,30 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
} else if (o->type->id == OT_PICKAXE) { } else if (o->type->id == OT_PICKAXE) {
int ch,dir; int ch,dir;
cell_t *c; cell_t *c;
ch = askchar("Dig in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE); ch = askchar("Dig in which direction (- to cancel)", "yuhjklbn><-","-", B_FALSE);
dir = chartodir(ch); if (ch == '-') {
c = getcellindir(player->cell, dir);
if (!c) {
// cancel // cancel
clearmsg(); clearmsg();
return B_TRUE; return B_TRUE;
} } else if (ch == '>') {
if (c->type->solid) { if (digdown(lf, o)) {
if (isdiggable(c)) { // failed
// replace wall return B_TRUE;
setcelltype(c, getemptycelltype(c->map->habitat));
if (isplayer(lf)) {
msg("You dig through the wall.");
needredraw = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s digs through a wall.",lfname);
needredraw = B_TRUE;
}
//drawscreen();
// takes extra time
taketime(lf, getactspeed(lf)*9);
} else {
// fail
if (isplayer(lf)) {
msg("This wall is too hard to dig.");
}
} }
} else { // not solid } else if (ch == '<') {
int failed = B_FALSE; if (digup(lf, o)) {
object_t *door; // failed
return B_TRUE;
door = hasobwithflag(c->obpile, F_DOOR);
if (door) {
int dooropen;
// only closed doors!
isdoor(door, &dooropen);
if (dooropen) {
door = NULL;
}
} }
} else {
if (door) { dir = chartodir(ch);
// TODO: metal doors are immune to CHOP damage c = getcellindir(lf->cell, dir);
if (!isimmuneto(door->flags, DT_CHOP)) {
taketime(lf, getactspeed(lf)); if (digcell(lf, c, o)) {
removeob(door, door->amt); // failed
if (isplayer(lf)) { return B_TRUE;
msg("You smash open a door!");
needredraw = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s smashes open a door.",lfname);
needredraw = B_TRUE;
}
drawscreen();
failed = B_FALSE;
}
} else if (hasob(c->obpile, OT_STATUE)) {
int dam;
object_t *so;
char statname[BUFLEN];
so = hasob(c->obpile, OT_STATUE);
getobname(so, statname, so->amt);
taketime(lf, getactspeed(lf));
// statue takes 1/2 damage
f = hasflag(so->flags, F_OBHP);
if (f) {
dam = (f->val[1] / 2); // ie. half max hp
} else {
dam = 1;
}
// statue ?
if (isplayer(lf)) {
msg("You hit %s with your %s.", statname, noprefix(obname));
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s hits %s with %s.", lfname, statname, obname);
}
takedamage(so, dam, DT_CHOP);
} else {
if (isplayer(lf)) {
msg("You swing your %s through the air.",noprefix(obname));
}
taketime(lf, getactspeed(lf));
} }
} } // end if ch is a direction
} else if (o->type->id == OT_SPANNER) { } else if (o->type->id == OT_SPANNER) {
int donesomething = B_FALSE; int donesomething = B_FALSE;
if (!where) { if (!where) {
@ -11671,7 +11724,8 @@ void setobcreatedby(object_t *o, lifeform_t *lf) {
} }
void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) { // returns TRUE if it did shatter
int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
int shatterdam; int shatterdam;
cell_t *where = NULL; cell_t *where = NULL;
lifeform_t *target = NULL; lifeform_t *target = NULL;
@ -11680,6 +11734,10 @@ void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
char targetname[BUFLEN]; char targetname[BUFLEN];
int seen = B_FALSE; int seen = B_FALSE;
if (hasflag(o->flags, F_NOSHATTER)) {
return B_FALSE;
}
getobname(o,obname,o->amt); getobname(o,obname,o->amt);
where = getoblocation(o); where = getoblocation(o);
@ -11695,13 +11753,20 @@ void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
// announce // announce
if (haslos(player, where)) { if (haslos(player, where)) {
char *obcaps; char prefix[BUFLEN];
obcaps = strdup(obname);
capitalise(obcaps); if (o->pile->owner) {
obcaps = strrep(obcaps, "An ", "The ", NULL); char lfname[BUFLEN];
obcaps = strrep(obcaps, "A ", "The ", NULL); getlfname(o->pile->owner, lfname);
msg("%s shatter%s!",obcaps, (o->amt == 1) ? "s" : ""); sprintf(prefix, "%s%s ", lfname, getpossessive(lfname));
free(obcaps); // ie. "the kobold's"
} else {
strcpy(prefix, "");
}
msg("%s%s shatter%s!",prefix, strlen(prefix) ? noprefix(obname) : obname,
(o->amt == 1) ? "s" : "");
seen = B_TRUE; seen = B_TRUE;
} else { } else {
@ -11873,6 +11938,8 @@ void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
// object is dead. // object is dead.
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL); addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
addflag(o->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); addflag(o->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
return B_TRUE;
} }
// randomizes hidden names // randomizes hidden names
@ -12101,14 +12168,14 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
// special cases.... // special cases....
if (damtype == DT_FIRE) { if (damtype == DT_FIRE) {
if (o->material->id == MT_FLESH) { // fire roasts flesh if ((o->material->id == MT_FLESH) && rnd(1,3)) { // fire sometimes roasts flesh
object_t *meat; object_t *meat;
meat = addob(o->pile, "chunk of roast meat"); meat = addob(o->pile, "chunk of roast meat");
// purposely don't use getweight! // purposely don't use getweight!
meat->weight = o->weight; meat->weight = o->weight;
} else { // fire turns other things to ash }
addob(o->pile, "pile of ash"); // fire turns things to ash
} addob(o->pile, "pile of ash");
} else if (damtype == DT_BASH) { } else if (damtype == DT_BASH) {
if (o->material->id == MT_GLASS) { // bashing damage breaks glass if (o->material->id == MT_GLASS) { // bashing damage breaks glass
int nshards; int nshards;
@ -12194,7 +12261,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
char throwverbpast[BUFLEN]; char throwverbpast[BUFLEN];
char throwverbpres[BUFLEN]; char throwverbpres[BUFLEN];
int acc; int acc;
int youhit; int youhit = B_FALSE;
object_t *newob; object_t *newob;
cell_t *newloc; cell_t *newloc;
int db = B_TRUE; int db = B_TRUE;
@ -12537,6 +12604,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
dam = (int)((float)throwdam * multiplier); dam = (int)((float)throwdam * multiplier);
takedamage(shield, dam, DT_PROJECTILE); takedamage(shield, dam, DT_PROJECTILE);
youhit = B_FALSE; youhit = B_FALSE;
practice(target, SK_SHIELDS, 1);
} }
} }
} }
@ -12640,6 +12708,10 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
} }
wepeffects(o->flags, target->cell, hasflag(o->flags, F_DAM), dam); wepeffects(o->flags, target->cell, hasflag(o->flags, F_DAM), dam);
if (firearm) {
practice(thrower, SK_RANGED, 1);
}
} }
} else { // ie. if !youhit } else { // ie. if !youhit
if (!announcedmiss) { if (!announcedmiss) {
@ -12672,8 +12744,11 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
sprintf(dambuf, "%s (%s by %s)",obname,throwverbpast, realthrowernamea); sprintf(dambuf, "%s (%s by %s)",obname,throwverbpast, realthrowernamea);
shatter(newob, youhit, dambuf, thrower); shatter(newob, youhit, dambuf, thrower);
} else { } else {
// don't announce damage to the thrown object // object only gets damaged if it hit someone
real_takedamage(newob, speed-1, DT_BASH, B_FALSE); if (youhit) {
// don't announce damage to the thrown object
real_takedamage(newob, speed-1, DT_BASH, B_FALSE);
}
} }
return B_FALSE; return B_FALSE;
@ -13154,7 +13229,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, lifeform_t *lf) {
} else if (oid == OT_TRAPTELEPORT) { } else if (oid == OT_TRAPTELEPORT) {
cell_t *newc; cell_t *newc;
// move somewhere else! // move somewhere else!
newc = getrandomcelloftype(lf->cell->map, getemptycelltype(lf->cell->map->habitat)); newc = getrandomcelloftype(lf->cell->map, lf->cell->map->habitat->id);
if (newc) { if (newc) {
teleportto(lf, newc, B_TRUE); teleportto(lf, newc, B_TRUE);
} }
@ -13486,6 +13561,25 @@ int validateobs(void) {
printf("ERROR in object '%s' - has f_thereishere but no ->text.\n", ot->name); printf("ERROR in object '%s' - has f_thereishere but no ->text.\n", ot->name);
goterror = B_TRUE; goterror = B_TRUE;
} }
f = hasflag(ot->flags, F_IMPASSABLE);
if (f && ((f->val[0] == NA) || (f->val[1] == NA)) ) {
printf("ERROR in object '%s' - f_impassable missing either min or max.\n", ot->name);
goterror = B_TRUE;
}
f = hasflag(ot->flags, F_DOOR);
if (f) {
flag_t *f2;
f2 = hasflag(ot->flags, F_IMPASSABLE);
if (f2) {
if ((f->val[0] != f2->val[0]) || (f->val[1] != f2->val[1])) {
printf("ERROR in object '%s' - f_door vals don't match f_impassable vals.\n", ot->name);
goterror = B_TRUE;
}
} else {
printf("ERROR in object '%s' - has f_door but not f_impassable.\n", ot->name);
goterror = B_TRUE;
}
}
} }
/* /*

View File

@ -204,7 +204,7 @@ void setblessed(object_t *o, enum BLESSTYPE wantbless);
int sethiddenname(objecttype_t *o, char *text); int sethiddenname(objecttype_t *o, char *text);
void setinscription(object_t *o, char *text); void setinscription(object_t *o, char *text);
void setobcreatedby(object_t *o, lifeform_t *lf); void setobcreatedby(object_t *o, lifeform_t *lf);
void shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf); int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf);
void shufflehiddennames(void); void shufflehiddennames(void);
object_t *splitob(object_t *o); object_t *splitob(object_t *o);
int takedamage(object_t *o, unsigned int howmuch, int damtype); int takedamage(object_t *o, unsigned int howmuch, int damtype);

6
save.c
View File

@ -256,6 +256,7 @@ map_t *loadmap(char *basefile) {
int i; int i;
int x,y; int x,y;
int db = B_TRUE; int db = B_TRUE;
enum HABITAT habitatid;
lifeform_t *l; lifeform_t *l;
object_t *o; object_t *o;
map_t *m; map_t *m;
@ -284,7 +285,8 @@ map_t *loadmap(char *basefile) {
fgets(buf, BUFLEN, f); // map name fgets(buf, BUFLEN, f); // map name
buf[strlen(buf)-1] = '\0'; // strip newline buf[strlen(buf)-1] = '\0'; // strip newline
m->name = strdup(buf + 5); // after 'name:' m->name = strdup(buf + 5); // after 'name:'
fscanf(f, "habitat:%d\n",(int *)&m->habitat); // habitat fscanf(f, "habitat:%d\n",(int *)habitatid); // habitat
m->habitat = findhabitat(habitatid);
fscanf(f, "seed:%d\n",&m->seed); // seed fscanf(f, "seed:%d\n",&m->seed); // seed
fscanf(f, "dims:%d,%d\n",&m->w, &m->h); // map dimensons fscanf(f, "dims:%d,%d\n",&m->w, &m->h); // map dimensons
fscanf(f, "nextmaps:\n"); fscanf(f, "nextmaps:\n");
@ -724,7 +726,7 @@ int savemap(map_t *m) {
fprintf(f, "id:%d\n",m->id); // map id fprintf(f, "id:%d\n",m->id); // map id
fprintf(f, "depth:%d\n",m->depth); // map depth fprintf(f, "depth:%d\n",m->depth); // map depth
fprintf(f, "name:%s\n",m->name); // map name fprintf(f, "name:%s\n",m->name); // map name
fprintf(f, "habitat:%d\n",m->habitat); // habitat fprintf(f, "habitat:%d\n",m->habitat->id); // habitat
fprintf(f, "seed:%d\n",m->seed); // seed fprintf(f, "seed:%d\n",m->seed); // seed
fprintf(f, "dims:%d,%d\n",m->w, m->h); // map dimensons fprintf(f, "dims:%d,%d\n",m->w, m->h); // map dimensons
fprintf(f, "nextmaps:\n"); fprintf(f, "nextmaps:\n");

138
spell.c
View File

@ -249,6 +249,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
getobname(o, buf, o->amt); getobname(o, buf, o->amt);
msgnocap("%c - %s", o->letter, buf); msgnocap("%c - %s", o->letter, buf);
practice(user, SK_COOKING, 1);
} else { } else {
msg("Your cooking attempt fails (maybe your pack was too full?)."); msg("Your cooking attempt fails (maybe your pack was too full?).");
} }
@ -371,6 +372,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user) && hasjob(user, J_ROGUE)) { if (isplayer(user) && hasjob(user, J_ROGUE)) {
gainxp(user, trapflag->val[0]); gainxp(user, trapflag->val[0]);
} }
practice(user, SK_TRAPS, 1);
} else { } else {
// failed. another check to see if it goes off // failed. another check to see if it goes off
if ((trapflag->val[1] == B_TRUE) && !skillcheck(user, SC_DISARM, trapflag->val[0], 0)) { if ((trapflag->val[1] == B_TRUE) && !skillcheck(user, SC_DISARM, trapflag->val[0], 0)) {
@ -693,29 +695,69 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else if (abilid == OT_A_REPAIR) { } else if (abilid == OT_A_REPAIR) {
enum SKILLLEVEL slev; enum SKILLLEVEL slev;
object_t *o; object_t *o;
int cutoffpct = 0; enum MATERIAL repairablemats[MAXCANDIDATES];
slev = getskill(user, SK_ARMOUR); int repaircutoff = 0;
switch (slev) { int cutoffpct[MAXCANDIDATES];
default: int nmats = 0;
if (isplayer(user)) { int i;
msg("You are too unskilled to repair your armour.");
} // get list of repairable materials
return B_TRUE; slev = getskill(user, SK_METALWORK);
case PR_SKILLED: cutoffpct = 50; break; if (slev) {
case PR_EXPERT: cutoffpct = 75; break; int cutoff;
case PR_MASTER: cutoffpct = 100; break; switch (slev) {
case PR_NOVICE: cutoff = 33; break;
case PR_BEGINNER: cutoff = 40; break;
case PR_ADEPT: cutoff = 50; break;
case PR_SKILLED: cutoff = 65; break;
case PR_EXPERT: cutoff = 80; break;
case PR_MASTER: cutoff = 100; break;
default: cutoff = 0; break;
}
repairablemats[nmats] = MT_METAL;
cutoffpct[nmats] = cutoff;
nmats++;
} }
slev = getskill(user, SK_SEWING);
if (slev) {
int cutoff;
switch (slev) {
case PR_NOVICE: cutoff = 33; break;
case PR_BEGINNER: cutoff = 40; break;
case PR_ADEPT: cutoff = 50; break;
case PR_SKILLED: cutoff = 65; break;
case PR_EXPERT: cutoff = 80; break;
case PR_MASTER: cutoff = 100; break;
default: cutoff = 0; break;
}
repairablemats[nmats] = MT_CLOTH;
cutoffpct[nmats] = cutoff;
nmats++;
repairablemats[nmats] = MT_LEATHER;
cutoffpct[nmats] = cutoff;
nmats++;
}
// 1.compile a list of repairable objects // 1.compile a list of repairable objects
// sk_armour lets you repair armour up to xx% (depends on skill) // sk_armour lets you repair armour up to xx% (depends on skill)
initprompt(&prompt, "Repair which object?"); initprompt(&prompt, "Repair which object?");
addchoice(&prompt, '-', "Cancel", buf, o); addchoice(&prompt, '-', "Cancel", "Cancel", o);
for (o = user->pack->first ; o ; o = o->next) { for (o = user->pack->first ; o ; o = o->next) {
if (isarmour(o) && isdamaged(o)) { int ok = B_FALSE;
int cutoff = 0;
for (i = 0; i < nmats; i++) {
if (o->material->id == repairablemats[i]) {
ok = B_TRUE;
cutoff = cutoffpct[i];
break;
}
}
if (ok && isdamaged(o)) {
float pct; float pct;
f = hasflag(o->flags, F_OBHP); f = hasflag(o->flags, F_OBHP);
pct = ((float)f->val[0] /(float) f->val[1]) * 100; pct = ((float)f->val[0] /(float) f->val[1]) * 100;
if (pct < cutoffpct) { if (pct < cutoff) {
char buf[BUFLEN]; char buf[BUFLEN];
getobname(o, buf, o->amt); getobname(o, buf, o->amt);
// we can repair this object // we can repair this object
@ -746,10 +788,20 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
taketime(user, getactspeed(user)); taketime(user, getactspeed(user));
return B_TRUE; return B_TRUE;
} }
// select cutoff hp
repaircutoff = 0;
for (i = 0; i < nmats; i++) {
if (o->material->id == repairablemats[i]) {
repaircutoff = cutoffpct[i];
break;
}
}
assert(repaircutoff != 0);
// repair it! // repair it!
f = hasflag(o->flags, F_OBHP); f = hasflag(o->flags, F_OBHP);
f->val[0] = pctof(cutoffpct, f->val[1]); f->val[0] = pctof(repaircutoff, f->val[1]);
if (isplayer(user)) { if (isplayer(user)) {
char buf[BUFLEN]; char buf[BUFLEN];
real_getobname(o, buf, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE); real_getobname(o, buf, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE);
@ -815,6 +867,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
addtempflag(user->flags, F_SPRINTING, B_TRUE, NA, NA, NULL, howlong); addtempflag(user->flags, F_SPRINTING, B_TRUE, NA, NA, NULL, howlong);
practice(user, SK_ATHLETICS, 1);
} else if (abilid == OT_A_STINGACID) { } else if (abilid == OT_A_STINGACID) {
validateabillf(user, abilid, &target); validateabillf(user, abilid, &target);
if (!target) return B_TRUE; if (!target) return B_TRUE;
@ -1259,6 +1312,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else if (cansee(player, user)) { } else if (cansee(player, user)) {
msg("%s tries to steal from %s, but fails.", username, targetname); msg("%s tries to steal from %s, but fails.", username, targetname);
} }
} else {
practice(user, SK_THIEVERY, 1);
} }
} else if (abilid == OT_A_WARCRY) { } else if (abilid == OT_A_WARCRY) {
// announce // announce
@ -2324,6 +2379,43 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
damageallobs(NULL, retcell[i]->obpile, 0, DT_COLD); damageallobs(NULL, retcell[i]->obpile, 0, DT_COLD);
} }
} }
} else if (spellid == OT_S_COMMANDUNDEAD) {
// mosnters won't cast this.
if (!isplayer(caster)) {
fizzle(caster);
return B_TRUE;
}
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target || !isundead(target)) {
fizzle(caster);
return B_TRUE;
}
// saving throw
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(caster) || cansee(player, target)) {
char tname[BUFLEN];
getlfname(target, tname);
msg("%s resists.",tname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
// they get angry!
if (!isplayer(target) && cansee(target, caster)) {
fightback(target, caster);
}
} else {
flag_t *f;
if (isplayer(caster) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
// it worked. temporarily make them a pet so that you
// can command them.
f = addflag(target->flags, F_PETOF, caster->id, NA, NA, NULL);
docomms(target);
killflag(f);
}
} else if (spellid == OT_S_CREATEMONSTER) { } else if (spellid == OT_S_CREATEMONSTER) {
lifeform_t *newlf; lifeform_t *newlf;
job_t *forcejob = NULL; job_t *forcejob = NULL;
@ -2512,7 +2604,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (retcell[i]->type->solid) { if (retcell[i]->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 (retcell[i]->type->material->id == MT_STONE) {
setcelltype(retcell[i], getemptycelltype(retcell[i]->map->habitat)); setcelltype(retcell[i], retcell[i]->map->habitat->emptycelltype);
if (seenthiscell) { if (seenthiscell) {
ndigs++; ndigs++;
numseen++; numseen++;
@ -2700,7 +2792,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
// destroy objects right away // destroy objects right away
removedeadobs(targcell->lf->pack); removedeadobs(targcell->obpile);
// explosion, based on size... // explosion, based on size...
if (totalmass > 0) { if (totalmass > 0) {
@ -4118,7 +4210,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else { } else {
int howlong = 7; int howlong = 7;
howlong = getspellduration(3,5,blessed) + (power/2); howlong = getspellduration(3,5,blessed) + (power/2);
addtempflag(target->flags, F_PAIN, DT_MAGIC, NA, NA, "2d4+2", howlong); addtempflag(target->flags, F_PAIN, DT_MAGIC, NA, NA, "1d3", howlong);
} }
} else { } else {
fizzle(caster); fizzle(caster);
@ -4467,7 +4559,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!newmap) { if (!newmap) {
// create new map // create new map
newmap = addmap(); newmap = addmap();
createmap(newmap, newdepth, caster->cell->map->region, AUTO, NULL, D_NONE); createmap(newmap, newdepth, caster->cell->map->region, NULL, D_NONE);
} }
@ -5461,6 +5553,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(caster->flags, F_SEEINVIS, B_TRUE, NA, NA, NULL, FROMSPELL); f = addtempflag(caster->flags, F_SEEINVIS, B_TRUE, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid; f->obfrom = spellid;
} else if (spellid == OT_S_SHATTER) {
char buf[BUFLEN];
if (!validatespellcell(caster, &targcell,TT_NONE, spellid, power, frompot)) return B_TRUE;
sprintf(buf, "%s%s shatter spell", castername, getpossessive(castername));
if (!shattercell(targcell, caster, buf)) {
fizzle(caster);
}
} else if (spellid == OT_S_SLEEP) { } else if (spellid == OT_S_SLEEP) {
int howlong; int howlong;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;

View File

@ -8,6 +8,7 @@ random(4,4)
@end @end
@flags @flags
goesin:dungeon
autodoors:25 autodoors:25
autopop autopop
scatter(1,1,-2,-2) ob:boulder:25% scatter(1,1,-2,-2) ob:boulder:25%

View File

@ -17,6 +17,7 @@
@end @end
@flags @flags
goesin:dungeon
autodoors:50 autodoors:50
autopop autopop
@end @end

View File

@ -8,6 +8,7 @@ random(4,4)
@end @end
@flags @flags
goesin:dungeon
autodoors:75 autodoors:75
autopop autopop
! tables & chairs ! tables & chairs

View File

@ -9,6 +9,7 @@ random(5,5)
@end @end
@flags @flags
goesin:dungeon
! 100% chance of doors - don't want the water escaping ! 100% chance of doors - don't want the water escaping
autodoors:100 autodoors:100
autopop autopop

View File

@ -8,6 +8,7 @@ random(5,5)
@end @end
@flags @flags
goesin:dungeon
autodoors:50 autodoors:50
autopop autopop
fill(2,2,-3,-3) cell:low rock floor:100 fill(2,2,-3,-3) cell:low rock floor:100

View File

@ -24,6 +24,7 @@ m:mon:minotaur
@end @end
@flags @flags
goesin:dungeon
! the reward ! the reward
at(7,7) ob:200-450 gold at(7,7) ob:200-450 gold
at(7,7) ob:good weapon at(7,7) ob:good weapon

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,6 +15,7 @@ $:ob:25-200 gold
@end @end
@flags @flags
goesin:dungeon
! no auto doors. ie this can be in the middle of nowhere. ! no auto doors. ie this can be in the middle of nowhere.
@end @end