- [+] monster: triclops. perception. vuln to light.

- [+] flying creatures shoudl fall to the ground when unconscious
    - [+] (this might kill them)

- [+] animate statue - bring statue to life
- [+] excavate - radial, obliterate walls + obs, doesn't affect lfs
- [+] test unicode wall glyph! 0x2588
- [+] use unicode for gas
    - [+] change f_glyph so that v1 = symbol, instead of text = symbol
        - [+] change code
        - [+] change definitions (macro)
    - [+] test
    - [+] implement puff  = UNI_SHADELIGHT
    - [+] implement cloud = bolded
    - [+] if good, extend to staem etc
- [+] blue background for lfs in the water
- [+] prone in water means effective lower height
- [+] glass/ice cells not shattering properly
- [+] make magic barriers be solid too
- [+] combine lockpick code in io.c and objects.c into the lockpick()
      function.
    - [+] first ask what to use (if required)
    - [+] then ask what dir (if required)
    - [+] then ask what to unlock (if reuiqred)
    - [+] then do it
- [+] locked containers
    - [+] picklocks prompts to try them.
    - [+] in addob, use non-inheritable f_lockedchance for both doors
          and chests?
        - [+] v0 = chance v1 = mod per depth
        - [+] doors:
            - [+] base 20% chance locked
            - [+] every 5 levels, add 10% chance
    - [+] add this to chests / safeboxes
    - [+] operate doesn't let you open them
- [+] bugs in linkexits and linkexit
    - [+] linkexits: wasn't checking the correct exit cell!!!
    - [+] lnkexit: wasn't blanking the startcell
GRATINGS:
- [+] flags:
    - [+]         addflag(lastot->flags, F_OPPOSITESTAIRS,
          OT_HOLEINROOF, NA, NA, NULL);
    - [+] climbable d_down NA
- [+] BUT you can't climb it if it's locked.
- [+] usestairs() - if you climb a grating and it has no maplink:
    - [+] use createregionlink(map, cell, grating_object, NULL,
          RG_SEWER, map->region)
- [+] make stench affect enhancedsmell creatures more.
- [+] excavate should only affect SOLID matter.
- [+] going down a drain:
    - [+] "You walk down a staircase" should be "climb down a drain"
- [+] deep slime in sewers sohuldn't spread
- [+] deep slime should spread to a slime puddle if it does....
- [+] fix background glyph colour for slime
- [+] killed by drowning should really be "drowned in %s"
SEWER HABITAT
- [+] permenant stench
    - [+] if you're in a sewer cell and are not nauseated, add it.
    - [+] nauseated doesn't expire in sewers.
- [+] add RG_SEWER
- [+] new regiontype - RG_SEWER
- [+] map:
    - [+] pick size 2 - 5
    - [+] start at x=2,y=2
    - [+] add square 3x3 rooms in gridlike layout (but need space for 5)
    - [+] connect rooms to orthogonally adjacent ones with passages
        - [+] use addexits().  no exits on outer walls.
    - [+] fill all empty cells with low floor and water (but NOt the
          one with the exit!)
    - [+] any solid with orthogonally adjacent water changes to a
          walkway
    - [+] cope with different x/y room counts
    - [+] cope with differnet vert/horz corridor sizes.
        - [+] horz = 2
        - [+] vert = 1
    - [+] random room size
- [+] allow objectclasses to have f_rarity
    - [+] modify getrandomobcalss
    - [+] but DONT make objects inherit it!!!
    - [+] this is used to override selection hased on habitat - modify
          getrandomobcalss appropriately
- [+] random objects/treasure:
    - [+] add these only in non-water cells??
        - [+] move all obs from water clls to random land cells
    - [+] frequent
        - [+] vomit
        - [+] soggy paper
        - [+] rotted food (add f_tainted to it)
    - [+] common
        - [+] wep/arm
        - [+] all wep/arm are shoddy in sewers
    - [+] uncommon
        - [+] rings (higher than normal chance - they were lost down
              sinks)
        - [+] occasional tech
- [+] bug: playerstart3 vault filled with walls when made randomly!
- [+] death speech text for intelligent monsters
    - [+] 'aaargh!'
    - [+] 'this isn't over!'
- [+] BUG: linkexits() - gettings exits in the wrong place.  maybe not
      taking rotation into account???
    - [+] for example in playerstart_5 vault, found an 'exit' at the x:
    - [+] this comes from the map flag f_roomexit, x, y
    - [+] the flag may have bene added from autodoors()
    - [+] have changed code so that f_roomexti uses text field to say
          who added it
This commit is contained in:
Rob Pearce 2011-11-29 02:25:04 +00:00
parent c522cac6c0
commit 6c26901e75
18 changed files with 996 additions and 474 deletions

View File

@ -1112,17 +1112,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// if victim was flying and took >= 40% of its hit points, it drops to the ground. // if victim was flying and took >= 40% of its hit points, it drops to the ground.
if (isphysicaldam(damtype[i]) && (dam[i] >= pctof(40, lf->maxhp))) { if (isphysicaldam(damtype[i]) && (dam[i] >= pctof(40, lf->maxhp))) {
int willfall = B_FALSE,willinjure = B_FALSE,n; fall_from_air(lf);
getflags(victim->flags, retflag, &nretflags, F_FLYING, F_LEVITATING, F_NONE);
for (n = 0; n < nretflags; n++) {
if (!istransitoryflag(retflag[n]) || (retflag[n]->lifetime == FROMRACE)) {
if (retflag[n]->id == F_FLYING) willinjure = B_TRUE;
willfall = B_TRUE;
killflag(retflag[n]);
}
}
if (willfall) fall(victim, NULL, B_TRUE);
if (willinjure) injure(victim, getrandomcorebp(victim), DT_BASH);
} }
// if victim can still move... // if victim can still move...
if (hasfreeaction(victim)) { if (hasfreeaction(victim)) {

376
data.c

File diff suppressed because it is too large Load Diff

Binary file not shown.

35
defs.h
View File

@ -12,7 +12,7 @@
#define PCTCH_PILLAR 5 #define PCTCH_PILLAR 5
// Text // Text
#define TEXT_WARN_ATTACK_NOXP "You cannot gain experience until you train. Really attack?" #define TEXT_WARN_ATTACK_NOXP "You will not gain experience until you train. Really attack?"
// Defaults // Defaults
#define DEF_AIFOLLOWTIME (50) // if target lf is out of view #define DEF_AIFOLLOWTIME (50) // if target lf is out of view
@ -38,6 +38,13 @@
// lifeform defaults // lifeform defaults
#define DEF_HITDICE "1d4" #define DEF_HITDICE "1d4"
// unicode chars
#define UNI_SOLID 0x2588
#define UNI_SHADELIGHT 0x2591
#define UNI_SHADEMED 0x2592
#define UNI_SHADEDARK 0x2593
//#define UNI_SOLID '#'
// getrandomemptycell() params // getrandomemptycell() params
#define WE_WALKABLE 1 #define WE_WALKABLE 1
#define WE_EMPTY 2 #define WE_EMPTY 2
@ -138,6 +145,9 @@
#define MINCLEARINGRADIUS 2 #define MINCLEARINGRADIUS 2
#define MAXCLEARINGRADIUS 5 #define MAXCLEARINGRADIUS 5
#define MAXMAPROOMS 80
#define MINROOMS 5 #define MINROOMS 5
#define MAXROOMS 10 #define MAXROOMS 10
#define MIN_ROOMH 4 #define MIN_ROOMH 4
@ -373,6 +383,7 @@ enum COLOUR {
C_DARKGREY = 15, C_DARKGREY = 15,
}; };
#define BLUEBG 50 #define BLUEBG 50
#define GREENBG 100
enum CASTTYPE { enum CASTTYPE {
CT_NORMAL = 0, CT_NORMAL = 0,
@ -423,12 +434,12 @@ enum QUADRANT {
enum SAYPHRASE { enum SAYPHRASE {
SP_ALLY_ATTACK, SP_ALLY_ATTACK,
SP_ALLY_ATTACKUNSEEN, SP_ALLY_ATTACKUNSEEN,
SP_ALLY_DIE,
SP_ALLY_INPAIN, SP_ALLY_INPAIN,
SP_ALLY_TARGETKILL, SP_ALLY_TARGETKILL,
SP_BEG, SP_BEG,
SP_BEGATTACK, SP_BEGATTACK,
SP_BEGTHANKS, SP_BEGTHANKS,
SP_DIE,
SP_DRUNK, SP_DRUNK,
SP_PAYWARN, SP_PAYWARN,
SP_PAYTHREAT, SP_PAYTHREAT,
@ -650,6 +661,7 @@ enum CELLTYPE {
CT_GRASS, CT_GRASS,
CT_LOOPCORRIDOR, CT_LOOPCORRIDOR,
CT_LOWFLOOR, CT_LOWFLOOR,
CT_VLOWFLOOR,
// rooms // rooms
CT_ROOM, CT_ROOM,
}; };
@ -866,6 +878,7 @@ enum RACE {
R_SHADOWCAT, R_SHADOWCAT,
R_SPRITEFIRE, R_SPRITEFIRE,
R_SPRITEICE, R_SPRITEICE,
R_TRICLOPS,
R_TROGLODYTE, R_TROGLODYTE,
R_TROLL, R_TROLL,
R_VAMPIRE, R_VAMPIRE,
@ -1016,6 +1029,8 @@ enum OBTYPE {
OT_NONE, OT_NONE,
// dungeon features // dungeon features
OT_BOULDER, OT_BOULDER,
OT_GRATINGFLOOR,
OT_GRATINGROOF,
OT_ICICLE, OT_ICICLE,
OT_STATUE, OT_STATUE,
OT_DOORWOOD, OT_DOORWOOD,
@ -1293,7 +1308,7 @@ enum OBTYPE {
OT_S_STUNMASS, OT_S_STUNMASS,
OT_S_TELEKINESIS, OT_S_TELEKINESIS,
// -- modification // -- modification
OT_S_ANIMATESTONE, OT_S_ANIMATESTATUE,
OT_S_DARKNESS, OT_S_DARKNESS,
OT_S_ENCHANT, OT_S_ENCHANT,
OT_S_GASEOUSFORM, OT_S_GASEOUSFORM,
@ -1320,6 +1335,7 @@ enum OBTYPE {
OT_S_DIG, OT_S_DIG,
OT_S_EARTHQUAKE, OT_S_EARTHQUAKE,
OT_S_EVAPORATE, OT_S_EVAPORATE,
OT_S_EXCAVATE,
OT_S_WEB, OT_S_WEB,
OT_S_ENDUREELEMENTS, OT_S_ENDUREELEMENTS,
OT_S_ENTANGLE, OT_S_ENTANGLE,
@ -1519,6 +1535,7 @@ enum OBTYPE {
OT_ACIDSPLASH, OT_ACIDSPLASH,
OT_ACIDPUDDLE, OT_ACIDPUDDLE,
OT_ACIDPOOL, OT_ACIDPOOL,
OT_SLIMEPUDDLE,
OT_SLIMEPOOL, OT_SLIMEPOOL,
OT_VOMITPOOL, OT_VOMITPOOL,
OT_BLOODSTAIN, OT_BLOODSTAIN,
@ -2040,6 +2057,9 @@ enum FLAG {
// v0 = base pct chance // v0 = base pct chance
// v1 = extra pct chance every 5 levels // v1 = extra pct chance every 5 levels
// v2 = max trap chance // v2 = max trap chance
F_CANBELOCKED, // this object might start off locked
// v0 = base pct chance
// v1 = extra pct chance every 5 levels
F_TRAPPED, // this object HAS a trap. F_TRAPPED, // this object HAS a trap.
// v0 is the trap object type // v0 is the trap object type
// v1 - 'curtime' when this trap was last triggered // v1 - 'curtime' when this trap was last triggered
@ -2077,7 +2097,8 @@ 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. // OPTIONAL v1 = id of regiontype to link to.
// (ie. RG_xxx)
F_PIT, // this is a pit which we can fall down. F_PIT, // this is a pit which we can fall down.
// v0 = up/down // v0 = up/down
//F_STAIRDIR//, // val0 = direcion //F_STAIRDIR//, // val0 = direcion
@ -3058,6 +3079,7 @@ enum REGIONTYPE {
RG_FIRSTDUNGEON, RG_FIRSTDUNGEON,
RG_HEAVEN, RG_HEAVEN,
RG_PIT, RG_PIT,
RG_SEWER,
}; };
enum HABITAT { enum HABITAT {
@ -3066,7 +3088,8 @@ enum HABITAT {
H_HEAVEN = 3, H_HEAVEN = 3,
H_PIT = 4, H_PIT = 4,
H_VILLAGE = 5, H_VILLAGE = 5,
H_SWAMP = 6, H_SEWER = 6,
H_SWAMP = 7,
H_ALL = 999 H_ALL = 999
}; };
@ -3140,7 +3163,7 @@ typedef struct map_s {
region_t *region; region_t *region;
int depth; int depth;
int lit; int lit;
struct room_s room[MAXROOMS]; struct room_s room[MAXMAPROOMS];
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
habitat_t *habitat; habitat_t *habitat;

View File

@ -1,6 +1,7 @@
@ = human @ = human
: = timid animal : = timid animal
{ = water { = fountain
UNI_SOLID = deep water
} = gas } = gas
^ = trap / dangerous thing ^ = trap / dangerous thing
) = weapon ) = weapon
@ -52,7 +53,9 @@ hybrid human animal?
~ = deep liquid (water / lava) ~ = deep liquid (water / lava)
] = tool ] = tool
[ = armour [ = armour
} = gas } = fire / effect
UNI_SHADEMED = dense gas
UNI_SHADELIGHT = light gas
, = small puddle , = small puddle
{ = large puddle/pool { = large puddle/pool
( = barrel/container ( = barrel/container

5
flag.c
View File

@ -1019,6 +1019,11 @@ void timeeffectsflag(flag_t *f, int howlong) {
return; return;
} }
// always nauseated in the sewer
if ((f->id == F_NAUSEATED) && f->pile->owner && f->pile->owner->cell && (f->pile->owner->cell->habitat->id == H_SEWER)) {
return;
}
if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) { if ((f->lifetime != PERMENANT) && (f->lifetime > 0)) {
// special case - fast metabolism speeds up poison too. // special case - fast metabolism speeds up poison too.
if (f->id == F_POISONED) { if (f->id == F_POISONED) {

76
io.c
View File

@ -3316,7 +3316,8 @@ void drawscreen(void) {
if (statdirty) { if (statdirty) {
drawstatus(); drawstatus();
wrefresh(statwin); //wrefresh(statwin);
wnoutrefresh(statwin);
statdirty = B_FALSE; statdirty = B_FALSE;
didstatus = B_TRUE; didstatus = B_TRUE;
} }
@ -3329,6 +3330,7 @@ void drawscreen(void) {
} }
if (didstatus && !didredraw) { if (didstatus && !didredraw) {
doupdate();
drawcursor(); drawcursor();
} }
} }
@ -6594,54 +6596,6 @@ void doquaff(obpile_t *op) {
} }
} }
void dolockpick(obpile_t *op) {
object_t *o;
char ch;
int dir;
if (!hasobwithflag(player->pack, F_PICKLOCKS)) {
msg("You have nothing to use for lockpicking!");
return;
}
// ask direction
ch = askchar("Lockpick in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE, B_TRUE);
dir = chartodir(ch);
if (dir == D_NONE) {
clearmsg();
return;
} else {
cell_t *c;
c = getcellindir(player->cell, dir);
if (c) {
object_t *targ;
// something to lockpick there?
targ = hasobwithflag(c->obpile, F_LOCKED);
if (targ) {
// ask which object to use
o = askobjectwithflag(op, "Lockpick using what", NULL, 'p', AO_NONE, F_PICKLOCKS);
if (o) {
if (hasflag(o->flags, F_PICKLOCKS)) {
lockpick(player, targ, o);
} else {
msg("That can't be used to pick locks!");
}
} else {
msg("Cancelled.");
return;
}
} else {
// fail
msg("There is nothing locked there!");
}
} else {
clearmsg();
return;
}
}
}
void donextguntarget(void) { void donextguntarget(void) {
object_t *gun; object_t *gun;
char gunname[BUFLEN]; char gunname[BUFLEN];
@ -7028,9 +6982,11 @@ void drawglyph(glyph_t *g, int x, int y) {
void drawcursor(void) { void drawcursor(void) {
// move cursor to player position // move cursor to player position
wmove(gamewin, player->cell->y - viewy, player->cell->x - viewx); wmove(gamewin, player->cell->y - viewy, player->cell->x - viewx);
wrefresh(gamewin); //wrefresh(gamewin);
// turn on cursor // turn on cursor
curs_set(1); curs_set(1);
wnoutrefresh(gamewin);
doupdate();
} }
void drawlevelfor(lifeform_t *lf) { void drawlevelfor(lifeform_t *lf) {
@ -7185,6 +7141,22 @@ void initgfx(void) {
init_pair(BLUEBG+C_BOLDGREEN, COLOR_GREEN, COLOR_BLUE); init_pair(BLUEBG+C_BOLDGREEN, COLOR_GREEN, COLOR_BLUE);
init_pair(BLUEBG+C_ORANGE, COLOR_RED, COLOR_BLUE); init_pair(BLUEBG+C_ORANGE, COLOR_RED, COLOR_BLUE);
init_pair(GREENBG+C_BLACK, COLOR_BLACK, COLOR_GREEN);
init_pair(GREENBG+C_RED, COLOR_RED, COLOR_GREEN);
init_pair(GREENBG+C_GREEN, COLOR_GREEN, COLOR_GREEN);
init_pair(GREENBG+C_BROWN, COLOR_YELLOW, COLOR_GREEN);
init_pair(GREENBG+C_YELLOW, COLOR_YELLOW, COLOR_GREEN);
init_pair(GREENBG+C_BLUE, COLOR_BLUE, COLOR_GREEN);
init_pair(GREENBG+C_MAGENTA, COLOR_MAGENTA, COLOR_GREEN);
init_pair(GREENBG+C_CYAN, COLOR_CYAN, COLOR_GREEN);
init_pair(GREENBG+C_GREY, COLOR_WHITE, COLOR_GREEN);
init_pair(GREENBG+C_YELLOW, COLOR_YELLOW, COLOR_GREEN);
init_pair(GREENBG+C_WHITE, COLOR_WHITE, COLOR_GREEN);
init_pair(GREENBG+C_BOLDCYAN, COLOR_CYAN, COLOR_GREEN);
init_pair(GREENBG+C_BOLDBLUE, COLOR_BLUE, COLOR_GREEN);
init_pair(GREENBG+C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_GREEN);
init_pair(GREENBG+C_BOLDGREEN, COLOR_GREEN, COLOR_GREEN);
init_pair(GREENBG+C_ORANGE, COLOR_RED, COLOR_GREEN);
noecho(); noecho();
// TODO: change back to raw mode, or make this a switch // TODO: change back to raw mode, or make this a switch
@ -7692,7 +7664,7 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
ch = getch(); ch = getch();
} }
if ((ch >= '0') && (ch <= '9')) { // shortcut if (useshortcuts && ((ch >= '0') && (ch <= '9'))) { // shortcut
flag_t *f; flag_t *f;
// autofill from the shortcut // autofill from the shortcut
f = lfhasflagval(player, F_SHORTCUT, ch - '0', NA, NA, NULL); f = lfhasflagval(player, F_SHORTCUT, ch - '0', NA, NA, NULL);
@ -8225,7 +8197,7 @@ void handleinput(void) {
break; break;
case 'p': // pick lock case 'p': // pick lock
addflag(player->flags, F_LASTCMD, NA, NA, NA, temp); addflag(player->flags, F_LASTCMD, NA, NA, NA, temp);
dolockpick(player->pack); lockpick(player, NULL, NULL, NULL);
break; break;
case 'P': // Pour case 'P': // Pour
dopour(player->pack); dopour(player->pack);

1
io.h
View File

@ -60,7 +60,6 @@ void domsghist(void);
void dooffer(void); void dooffer(void);
void dooperate(obpile_t *op); void dooperate(obpile_t *op);
int dopickup(obpile_t *op, int forceask); int dopickup(obpile_t *op, int forceask);
void dolockpick(obpile_t *op);
void donextguntarget(void); void donextguntarget(void);
void dopour(obpile_t *op); void dopour(obpile_t *op);
void doquit(void); void doquit(void);

226
lf.c
View File

@ -1874,6 +1874,7 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
limit(&damamt, 1, NA); limit(&damamt, 1, NA);
if (damamt >= lf->hp) { if (damamt >= lf->hp) {
char obname[BUFLEN];
if (isplayer(lf)) { if (isplayer(lf)) {
msg("^BYou drown."); msg("^BYou drown.");
didsomething = B_TRUE; didsomething = B_TRUE;
@ -1885,8 +1886,11 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
} }
addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
lf->hp = 0; lf->hp = 0;
setlastdam(lf, "drowning"); real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE);
setlastdam(lf, obname);
setkillverb(lf, "Drowned");
} else { } else {
char obname[BUFLEN];
if (isplayer(lf)) { if (isplayer(lf)) {
msg("^BYou are drowning!"); msg("^BYou are drowning!");
didsomething = B_TRUE; didsomething = B_TRUE;
@ -1896,7 +1900,10 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
msg("^%c%s is drowning!", getlfcol(lf, CC_VBAD), lfname); msg("^%c%s is drowning!", getlfcol(lf, CC_VBAD), lfname);
didsomething = B_TRUE; didsomething = B_TRUE;
} }
losehp(lf, damamt, DT_DIRECT, NULL, "drowning"); real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE);
losehp(lf, damamt, DT_DIRECT, NULL, obname);
setlastdam(lf, obname);
setkillverb(lf, "Drowned");
} }
} }
} }
@ -2270,6 +2277,21 @@ void die(lifeform_t *lf) {
} }
} }
} else { } else {
// intelligent monsters will say something
if (ispetof(lf, player)) {
if (cantalk(lf) && canhear(player, lf->cell, 4)) {
sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL);
} else if (cantalk(lf)) {
warn("You feel a profound sense of loss.");
more();
//} else {
// makenoise(lf, N_DIE);
}
} else if (cantalk(lf)) {
sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL);
}
if (!hasflag(lf->flags, F_NODEATHANNOUNCE)) { if (!hasflag(lf->flags, F_NODEATHANNOUNCE)) {
if (cansee(player, lf)) { if (cansee(player, lf)) {
getlfname(lf, buf); getlfname(lf, buf);
@ -2309,20 +2331,6 @@ void die(lifeform_t *lf) {
} }
} }
// announce pet death
if (ispetof(lf, player)) {
if (cantalk(lf) && canhear(player, lf->cell, 4)) {
sayphrase(lf, SP_ALLY_DIE, SV_SHOUT, NA, NULL);
} else if (cantalk(lf)) {
warn("You feel a profound sense of loss.");
//} else {
// makenoise(lf, N_DIE);
}
}
if (ispetof(lf, player)) {
more();
}
// drop/kill all objects // drop/kill all objects
if (willbecomeghost || !isplayer(lf)) { if (willbecomeghost || !isplayer(lf)) {
while (lf->pack->first) { while (lf->pack->first) {
@ -3794,7 +3802,9 @@ int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong) {
loseconcentration(lf); loseconcentration(lf);
interrupt(lf); interrupt(lf);
killtransitoryflags(lf->flags, F_FLYING); // falling asleep while flying = fall!
fall_from_air(lf);
killflagsofid(lf->flags, F_RAGE); killflagsofid(lf->flags, F_RAGE);
killflagsofid(lf->flags, F_TRAINING); killflagsofid(lf->flags, F_TRAINING);
@ -3802,6 +3812,27 @@ int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong) {
return B_FALSE; return B_FALSE;
} }
// returns true if you fell
int fall_from_air(lifeform_t *lf) {
int willfall = B_FALSE,willinjure = B_FALSE, n;
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0;
getflags(lf->flags, retflag, &nretflags, F_FLYING, F_LEVITATING, F_NONE);
for (n = 0; n < nretflags; n++) {
if (!istransitoryflag(retflag[n]) || (retflag[n]->lifetime == FROMRACE)) {
if (retflag[n]->id == F_FLYING) willinjure = B_TRUE;
willfall = B_TRUE;
killflag(retflag[n]);
}
}
if (willfall) fall(lf, NULL, B_TRUE);
if (willinjure) injure(lf, getrandomcorebp(lf), DT_BASH);
if (willfall || willinjure) {
return B_TRUE;
}
return B_FALSE;
}
// make 'lf' respond to damage // make 'lf' respond to damage
void fightback(lifeform_t *lf, lifeform_t *attacker) { void fightback(lifeform_t *lf, lifeform_t *attacker) {
interrupt(lf); interrupt(lf);
@ -6263,21 +6294,29 @@ char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer) {
glyph_t *getlfglyph(lifeform_t *lf) { glyph_t *getlfglyph(lifeform_t *lf) {
flag_t *f; flag_t *f;
if (lfhasflag(lf, F_FEIGNINGDEATH)) { if (lfhasflag(lf, F_FEIGNINGDEATH)) {
// look like a corpse // look like a corpse
tempglyph.ch = '%'; tempglyph.ch = '%';
tempglyph.colour = lf->race->glyph.colour; tempglyph.colour = lf->race->glyph.colour;
} else if ((f = lfhasflag(lf, F_GLYPH)) != NULL) {
return &tempglyph; tempglyph.ch = f->val[1];
} else {
tempglyph = lf->race->glyph;
} }
f = lfhasflag(lf, F_GLYPH); if (lf->cell && (getcellwaterdepth(lf->cell, player) >= DP_WAIST)) {
if (f) { object_t *o;
tempglyph.ch = f->text[0]; o = hasobwithflag(lf->cell->obpile, F_DEEPWATER);
return &tempglyph; switch (o->type->material->id) {
case MT_WATER: tempglyph.colour += BLUEBG; break;
case MT_SLIME: tempglyph.colour += GREENBG; break;
default: break;
}
} }
return &lf->race->glyph; //return &lf->race->glyph;
return &tempglyph;
} }
enum MATERIAL getlfmaterial(lifeform_t *lf) { enum MATERIAL getlfmaterial(lifeform_t *lf) {
@ -7112,7 +7151,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
race_t *poss[MAXRANDOMLFCANDIDATES]; race_t *poss[MAXRANDOMLFCANDIDATES];
int nposs = 0; int nposs = 0;
int selidx; int selidx;
int db = B_TRUE; int db = B_FALSE;
int depth; int depth;
int hdmin,hdmax; int hdmin,hdmax;
enum RARITY wantrr = RR_FREQUENT; enum RARITY wantrr = RR_FREQUENT;
@ -9152,15 +9191,93 @@ int lfproduceslight(lifeform_t *lf) {
return radius; return radius;
} }
// if you pass in 'target', then you don't need 'targcell'
// return true on failure // return true on failure
int lockpick(lifeform_t *lf, object_t *target, object_t *device) { int lockpick(lifeform_t *lf, cell_t *targcell, object_t *target, object_t *device) {
flag_t *f,*lockflag; flag_t *f,*lockflag;
char lfname[BUFLEN]; char lfname[BUFLEN];
char obname[BUFLEN]; char obname[BUFLEN];
int faileffect; int faileffect;
int difficulty = 20; // default, never used though int difficulty = 20; // default, never used though
int bonus = 0; int bonus = 0;
char ch;
// TODO: for now, only players can lockpick
if (!isplayer(lf)) {
return B_TRUE;
}
// what will we use?
if (!device) {
if (!hasobwithflag(lf->pack, F_PICKLOCKS)) {
msg("You have nothing to use for lockpicking!");
return B_TRUE;
}
// ask which object to use
device = askobjectwithflag(lf->pack, "Lockpick using what", NULL, 'p', AO_NONE, F_PICKLOCKS);
if (!device) {
msg("Cancelled.");
return B_TRUE;
} else if (!hasflag(device->flags, F_PICKLOCKS)) {
msg("That can't be used to pick locks!");
return B_TRUE;
}
}
if (!target) {
object_t *poss[MAXCANDIDATES],*o;
int nposs = 0,i;
if (!targcell) {
int dir;
ch = askchar("Lockpick in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE, B_TRUE);
if ((ch == '-') || (ch == '\0')) {
msg("Cancelled.");
return B_TRUE;
}
dir = chartodir(ch);
if (dir == D_NONE) {
targcell = lf->cell;
} else {
targcell = getcellindir(lf->cell, dir);
}
if (!targcell) {
return B_TRUE;
}
}
// get a list of lockpickable obejcts there
for (o = targcell->obpile->first ; o ; o = o->next) {
if (hasflag(o->flags, F_LOCKED)) {
poss[nposs++] = o;
}
}
if (!nposs) {
msg("There is nothing here to lockpick!");
return B_TRUE;
} else if (nposs == 1) {
target = poss[0];
} else {
// ask which one
initprompt(&prompt, "What will you try to unlock?");
ch = 'a';
for (i = 0 ; i < nposs; i++) {
char obname[BUFLEN];
getobname(poss[i], obname, 1);
addchoice(&prompt, ch++, obname, NULL, poss[i], NULL);
}
prompt.maycancel = B_TRUE;
ch = getchoice(&prompt);
if (ch != '\0') target = (object_t *)prompt.result;
if (!target) {
msg("Cancelled.");
return B_TRUE;
}
}
}
// we should now have both 'device' and 'target' filled in.
lockflag = hasflag(target->flags, F_LOCKED); lockflag = hasflag(target->flags, F_LOCKED);
if (lockflag) { if (lockflag) {
difficulty = lockflag->val[1]; difficulty = lockflag->val[1];
@ -10619,7 +10736,7 @@ lifeform_t *makezombie(object_t *o) {
lf = addlf(where, r->id, 1); lf = addlf(where, r->id, 1);
addflag(lf->flags, F_LFSUFFIX, B_TRUE, NA, NA, "zombie"); addflag(lf->flags, F_LFSUFFIX, B_TRUE, NA, NA, "zombie");
addflag(lf->flags, F_GLYPH, C_GREY, NA, NA, "Z"); addflag(lf->flags, F_GLYPH, C_GREY, 'Z', NA, NULL);
addflag(lf->flags, F_UNDEAD, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_UNDEAD, B_TRUE, NA, NA, NULL);
addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lf->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); addflag(lf->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
@ -11570,7 +11687,6 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
default: break; default: break;
} }
// special case // special case
if (lf->race->id == R_DREAMFUNGUS) { if (lf->race->id == R_DREAMFUNGUS) {
if (cansee(player, lf)) { if (cansee(player, lf)) {
@ -11707,8 +11823,10 @@ int makenauseated(lifeform_t *lf, int amt, int howlong) {
flag_t *f; flag_t *f;
if (isundead(lf)) return B_TRUE; if (isundead(lf)) return B_TRUE;
if (!hasbp(lf, BP_HEAD)) return B_TRUE; // can't smell with no head if (!hasbp(lf, BP_HEAD)) return B_TRUE; // can't smell with no head
if (lfhasflag(lf, F_STENCH)) return B_TRUE; // your own smell makes you used to it
if (lfhasflag(lf, F_ENHANCESMELL)) amt += 2;
//if (!lfhasflag(lf, F_HUMANOID)) return B_TRUE; //if (!lfhasflag(lf, F_HUMANOID)) return B_TRUE;
@ -13357,17 +13475,6 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
free(p); free(p);
rv = say(lf, buf, volume); rv = say(lf, buf, volume);
break; break;
case SP_ALLY_DIE:
switch (rnd(1,3)) {
case 1:
getplayername(buf2);
snprintf(buf, BUFLEN, "Avenge me, %s!", buf2);
break;
case 2: snprintf(buf, BUFLEN, "Argh!"); break;
case 3: snprintf(buf, BUFLEN, "Nooooo!"); break;
}
rv = say(lf, buf, volume);
break;
case SP_ALLY_INPAIN: case SP_ALLY_INPAIN:
switch (rnd(1,3)) { switch (rnd(1,3)) {
case 1: snprintf(buf, BUFLEN, "I'm hurting here!"); break; case 1: snprintf(buf, BUFLEN, "I'm hurting here!"); break;
@ -13411,6 +13518,22 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
} }
rv = say(lf, buf, volume); rv = say(lf, buf, volume);
break; break;
case SP_DIE:
switch (rnd(1,4)) {
case 1:
if (ispetof(lf, player)) {
getplayername(buf2);
snprintf(buf, BUFLEN, "Avenge me, %s!", buf2);
} else {
snprintf(buf, BUFLEN, "My death will be avenged!");
}
break;
case 2: snprintf(buf, BUFLEN, "Argh!"); break;
case 3: snprintf(buf, BUFLEN, "Nooooo!"); break;
case 4: snprintf(buf, BUFLEN, "This isn't over!"); break;
}
rv = say(lf, buf, volume);
break;
case SP_DRUNK: case SP_DRUNK:
// random blurred speech // random blurred speech
strcpy(buf, ""); strcpy(buf, "");
@ -14658,6 +14781,12 @@ void startlfturn(lifeform_t *lf) {
} }
} }
// get nauseated if in the sewer
if (lf->cell && (lf->cell->habitat->id == H_SEWER)) {
makenauseated(lf, 2, 2);
}
// get more hungry // get more hungry
modhunger(lf, 1); modhunger(lf, 1);
@ -16304,8 +16433,19 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
return B_FALSE; return B_FALSE;
} }
// locked?
if (hasflag(o->flags, F_LOCKED)) {
if (isplayer(lf)) msg("The %s seems to be locked.", noprefix(obname));
if (onpurpose) taketime(lf, getmovespeed(lf));
return B_FALSE;
}
curmap = obcell->map; curmap = obcell->map;
if ((o->type->id == OT_GRATINGFLOOR) && !hasflag(o->flags, F_MAPLINK)) {
createregionlink(curmap, obcell, o, NULL, RG_SEWER, curmap->region);
}
f = hasflag(o->flags, F_CLIMBABLE); f = hasflag(o->flags, F_CLIMBABLE);
assert(f); assert(f);
dir = f->val[0]; dir = f->val[0];
@ -16341,7 +16481,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
return B_TRUE; return B_TRUE;
} }
} else if (dir == D_UP) { } else if (dir == D_UP) {
if (hasflagval(o->flags, F_PIT, D_UP, NA, NA, NULL)) { if (hasflagval(o->flags, F_PIT, D_UP, NA, NA, NULL) || (o->type->id == OT_GRATINGROOF)) {
// can only go up if you have a rope or are flying/levitating // can only go up if you have a rope or are flying/levitating
if (lfhasflag(lf, F_LEVITATING) || lfhasflag(lf, F_FLYING)) { if (lfhasflag(lf, F_LEVITATING) || lfhasflag(lf, F_FLYING)) {
// ok. // ok.
@ -16369,8 +16509,8 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
} 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)) { } else if (hasflag(o->flags, F_PIT) || (o->type->id == OT_GRATINGFLOOR) || (o->type->id == OT_GRATINGROOF)) {
f = hasflag(o->flags, F_PIT); //f = hasflag(o->flags, F_PIT);
if (isplayer(lf) || cansee(player, lf)) { if (isplayer(lf) || cansee(player, lf)) {
msg("%s %s %s the %s...", lfname, getpitverb(lf, dir,onpurpose, climb), getdirname(dir), noprefix(obname)); msg("%s %s %s the %s...", lfname, getpitverb(lf, dir,onpurpose, climb), getdirname(dir), noprefix(obname));

3
lf.h
View File

@ -88,6 +88,7 @@ void extinguishlf(lifeform_t *lf);
object_t *eyesshaded(lifeform_t *lf); object_t *eyesshaded(lifeform_t *lf);
int fall(lifeform_t *lf, lifeform_t *fromlf, int announce); int fall(lifeform_t *lf, lifeform_t *fromlf, int announce);
int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong); int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong);
int fall_from_air(lifeform_t *lf);
void fightback(lifeform_t *lf, lifeform_t *attacker); void fightback(lifeform_t *lf, lifeform_t *attacker);
job_t *findjob(enum JOB jobid); job_t *findjob(enum JOB jobid);
job_t *findjobbyname(char *name); job_t *findjobbyname(char *name);
@ -257,7 +258,7 @@ flag_t *lfhasflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2
flag_t *lfhasknownflag(lifeform_t *lf, enum FLAG fid); flag_t *lfhasknownflag(lifeform_t *lf, enum FLAG fid);
flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, /*@null@*/ char *text); flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, /*@null@*/ char *text);
int lfproduceslight(lifeform_t *lf); int lfproduceslight(lifeform_t *lf);
int lockpick(lifeform_t *lf, object_t *target, object_t *device); int lockpick(lifeform_t *lf, cell_t *targcell, object_t *target, object_t *device);
void loseobflags(lifeform_t *lf, object_t *o, int kind); void loseobflags(lifeform_t *lf, object_t *o, int kind);
int hasbp(lifeform_t *lf, enum BODYPART bp); int hasbp(lifeform_t *lf, enum BODYPART bp);
flag_t *hasactivespell(lifeform_t *lf, enum OBTYPE sid); flag_t *hasactivespell(lifeform_t *lf, enum OBTYPE sid);

404
map.c
View File

@ -792,7 +792,7 @@ void adjustcellglyphforlight(cell_t *c, glyph_t *g) {
case L_TEMP: // lit by a light source case L_TEMP: // lit by a light source
if (g->colour < 8) { if (g->colour < 8) {
g->colour = g->colour + 8; // ie. make bold g->colour = g->colour + 8; // ie. make bold
if (g->colour >= C_DARKGREY) g->colour = C_WHITE; if (g->colour >= C_GREY) g->colour = C_WHITE;
} }
break; break;
case L_PERMLIGHT: case L_PERMLIGHT:
@ -1108,7 +1108,6 @@ int doelementspread(cell_t *c) {
thisdepth = getcellwaterdepth(c, NULL); thisdepth = getcellwaterdepth(c, NULL);
if (thisdepth) { if (thisdepth) {
// count surrounding cells of lower depth // count surrounding cells of lower depth
for (i = DC_N; i <= DC_NW; i++) { for (i = DC_N; i <= DC_NW; i++) {
cell_t *newc; cell_t *newc;
@ -1399,7 +1398,7 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
g->ch = ' '; g->ch = ' ';
} }
// out of LOS - show as dark // out of LOS - show as dark
// TODO: if terminal supports it, use C_DARKGREY instead. // TODO: if terminal supports it, use C_GREY instead.
g->colour = C_BLUE; g->colour = C_BLUE;
} }
break; break;
@ -2070,7 +2069,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
} }
} }
// just do a normal room // just do a normal room
createroom(map, map->nrooms, NA, NA, DEF_VAULTMARGIN, DEF_VAULTMARGIN, NULL, NULL, NULL, NULL, 50, B_FALSE); calcposandmakeroom(map, map->nrooms, NA, NA, DEF_VAULTMARGIN, DEF_VAULTMARGIN, NULL, NULL, NULL, NULL, 50, B_FALSE);
//roomvault[i] = B_FALSE; //roomvault[i] = B_FALSE;
} }
} }
@ -2374,9 +2373,13 @@ void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir, object_
case H_PIT: case H_PIT:
createpit(map, depth, parentmap, exitdir, entryob); createpit(map, depth, parentmap, exitdir, entryob);
break; break;
default: case H_SEWER:
createsewer(map, depth, parentmap, exitdir, entryob);
break;
case H_ALL:
dblog("ERROR - createhabitat with invalid habitat!"); dblog("ERROR - createhabitat with invalid habitat!");
msg("ERROR - createhabitat with invalid habitat!"); msg("ERROR - createhabitat with invalid habitat!");
break;
} }
} }
@ -2857,7 +2860,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
object_t *o; object_t *o;
c = getcellat(map, x, y); c = getcellat(map, x, y);
o = hasobwithflag(c->obpile, F_CLIMBABLE); o = hasobwithflag(c->obpile, F_CLIMBABLE);
if (o && !getstairdestination(o, NULL)) { if (o && (o->type->id != OT_PORTAL) && !getstairdestination(o, NULL)) {
// this will join these stairs to existing ones on // this will join these stairs to existing ones on
// existing adjacent maps // existing adjacent maps
if (!linkstairs(o, NULL)) { if (!linkstairs(o, NULL)) {
@ -2939,6 +2942,228 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
if (db) dblog(" Map creation finished."); if (db) dblog(" Map creation finished.");
} }
void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) {
object_t *o,*nexto;
cell_t *c;
flag_t *f;
int i;
int startx,starty,x,y,rx,ry;
int maxroomsx,maxroomsy;
int roomcountx,roomcounty;
//int corridorsizex = 3;
//int corridorsizey = 2;
int corridorsize; // length of corridors between rooms
int roomfullsize; // room size including walls
int roomsize; // room size without walls
int sectionsize; // a section is a room+corridor
int *roomon,*rowfirst,*rowlast,*colfirst,*collast;
int numon = 0;
char buf[BUFLEN];
// select room size
//roomsize = 5;
sectionsize = rnd(5,9);
// must be an odd number
if ((sectionsize % 2) == 0) sectionsize++;
// subtract corridor size
corridorsize = rnd(2,3);
roomfullsize = sectionsize - corridorsize;
roomsize = roomsize - 2; // ie. don't include outer walls
// select how many very/horz rooms
maxroomsx = (map->w - 1) / (sectionsize);
maxroomsy = (map->h - 1) / (sectionsize);
roomcountx = maxroomsx;
roomcounty = maxroomsy;
// fill entire maze with walls
for (y = 0; y < map->h; y++) {
for (x = 0; x < map->w; x++) {
addcell(map, x, y);
}
}
roomon = malloc((roomcountx * roomcounty) * sizeof(int));
rowfirst = malloc(roomcounty * sizeof(int));
rowlast = malloc(roomcounty * sizeof(int));
colfirst = malloc(roomcountx * sizeof(int));
collast = malloc(roomcountx * sizeof(int));
numon = 0;
while (numon == 0) {
for (ry = 0; ry < roomcounty; ry++) {
for (rx = 0; rx < roomcountx; rx++) {
i = rx * ry;
if (pctchance(66)) {
roomon[i] = B_TRUE;
numon++;
} else {
roomon[i] = B_FALSE;
}
}
}
}
// now figure first/last rooms in each row
for (ry = 0; ry < roomcounty; ry++) {
rowfirst[ry] = -1;
for (rx = 0; rx < roomcountx; rx++) {
i = rx * ry;
if (roomon[i]) {
if (rowfirst[ry] == -1) {
rowfirst[ry] = rx;
}
rowlast[ry] = rx;
}
}
}
// now figure first/last rooms in each column
for (rx = 0; rx < roomcountx; rx++) {
colfirst[rx] = -1;
for (ry = 0; ry < roomcounty; ry++) {
i = rx * ry;
if (roomon[i]) {
if (colfirst[rx] == -1) {
colfirst[rx] = ry;
}
collast[rx] = ry;
}
}
}
dblog("SEWER debug:");
for (ry = 0; ry < roomcounty; ry++) {
char buf2[BUFLEN];
strcpy(buf, "");
for (rx = 0; rx < roomcountx; rx++) {
if (roomon[rx*ry]) {
strcat(buf, "#");
} else {
strcat(buf, "-");
}
}
sprintf(buf2, " (rowfirst is %d, rowlast is %d)", rowfirst[ry], rowlast[ry]);
dblog("%s%s", buf, buf2);
}
// start at top left corner of top left room
startx = 1;
starty = 1;
x = startx;
y = starty;
// add square rooms in a gridlike layout
for (ry = 0; ry < roomcounty; ry++) {
for (rx = 0; rx < roomcountx; rx++) {
if (roomon[rx*ry]) {
int thisid;
int x2,y2;
thisid = map->nrooms;
// add a room here
x2 = x+roomfullsize-1;
y2 = y+roomfullsize-1;
createroom(map, thisid, x, y, x2, y2, B_TRUE);
// define exit locations
if (ry != colfirst[rx]) addflag(map->flags, F_ROOMEXIT, thisid, x+(roomfullsize/2), y, NULL); // N
if (ry != collast[rx]) addflag(map->flags, F_ROOMEXIT, thisid, x+(roomfullsize/2), y2, NULL); // S
if (rx != rowfirst[ry]) addflag(map->flags, F_ROOMEXIT, thisid, x, y+(roomfullsize/2), NULL); // W
if (rx != rowlast[ry]) addflag(map->flags, F_ROOMEXIT, thisid, x2, y+(roomfullsize/2), NULL); // E
}
// move on to next room position
x += sectionsize;
assert(x < map->w);
}
x = startx;
y += sectionsize;
assert(y < map->h);
}
free(roomon);
free(rowfirst);
free(rowlast);
free(colfirst);
free(collast);
dblog("END SEWER debug");
// link rooms with corridors
for (i = 0; i < map->nrooms; i++) {
linkexits(map, map->room[i].id);
}
// replace all empty cells with slime (except the exit one)
for (i = 0; i < (map->w*map->h); i++){
c = map->cell[i];
if (!c->type->solid) {
setcelltype(c, CT_LOWFLOOR);
addob(c->obpile, "waist-deep slime");
}
}
// any solid cell with orthogonally-adjacent water (except the exit one)
// now turns into a walkway
for (i = 0; i < (map->w*map->h); i++){
cell_t *c2;
c = map->cell[i];
if (c->type->solid) {
int dir,makewalkway = B_FALSE;
for (dir = D_N; dir <= D_W; dir++) {
c2 = getcellindir(c, dir);
if (c2 && (c2->type->id == CT_LOWFLOOR)) {
makewalkway = B_TRUE;
break;
}
}
if (makewalkway) setcelltype(c, c->habitat->emptycelltype);
} else if (c->type->id == CT_LOWFLOOR) {
int dir,surrounded = B_TRUE;
for (dir = D_N; dir <= D_W; dir++) {
c2 = getcellindir(c, dir);
if (c2 && (c2->type->id != CT_LOWFLOOR)) {
surrounded = B_FALSE;
break;
}
}
if (surrounded) {
setcelltype(c, CT_VLOWFLOOR);
setwaterdepth(c, DP_MAX);
}
}
}
// any water cell orthogonally surrounded by water becomes very deep
// now move all objects out of the water
for (i = 0; i < (map->w*map->h); i++){
c = map->cell[i];
if (c->type->id == CT_LOWFLOOR) {
for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (o->type->id != OT_SLIMEPOOL) {
cell_t *c2;
c2 = getrandomcelloftype(map, c->habitat->emptycelltype);
moveob(o, c2->obpile, ALL);
}
}
}
}
// add the exit. make sure it's next to a wall so it's possible to climb to.
c = NULL;
while (!c || (countadjwalls(c) == 0)) {
c = getrandomroomcell(map, ANYROOM);
assert(c);
}
o = addobfast(c->obpile, OT_GRATINGROOF);
// have to force these stairs to go back to a different region.
f = hasflag(o->flags, F_CLIMBABLE);
f->val[1] = map->region->parentregion->id;
linkstairs(o, NULL);
}
void createswamp(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) { void createswamp(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) {
int x,y; int x,y;
cell_t *c; cell_t *c;
@ -3000,7 +3225,7 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r
// - we don't do autodoors (will handle this further down) ------------- // - we don't do autodoors (will handle this further down) -------------
minw = f->val[0]; minw = f->val[0];
minh = f->val[1]; minh = f->val[1];
if (createroom(map, roomid, minw, minh, xmargin, ymargin, &minx, &miny, &w, &h, B_NODOORS, B_TRUE)) { if (calcposandmakeroom(map, roomid, minw, minh, xmargin, ymargin, &minx, &miny, &w, &h, B_NODOORS, B_TRUE)) {
return B_TRUE; return B_TRUE;
} }
if (db) dblog("made random vault %s at pos %d,%d on map %s", v->id, minx, miny, map->name); if (db) dblog("made random vault %s at pos %d,%d on map %s", v->id, minx, miny, map->name);
@ -3462,6 +3687,13 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
c = getcellindir(c, whichway); c = getcellindir(c, whichway);
} }
} }
// now make sure the START cell is empty too!
if (startcell->type->solid) {
setcelltype(startcell, startcell->habitat->emptycelltype);
}
return B_FALSE; return B_FALSE;
} }
@ -3521,15 +3753,16 @@ int linkexits(map_t *m, int roomid) {
} }
} }
if (db) dblog("%d doors/exits found.",nposs); if (db) dblog("%d exit positions found.",nposs);
// for each door, make sure it links to at least one cell which isn't // for each exit position, make sure it links to at least one cell which isn't
// part of this room // part of this room
for (i = 0; i < nposs; i++) { for (i = 0; i < nposs; i++) {
int ncorridors = 0,d; int ncorridors = 0,d;
if (db) dblog("exit at %d,%d:",poss[i]->x, poss[i]->y);
// if exit is solid and COMPLETELY surrounded by solid, ignore it. // if exit is solid and COMPLETELY surrounded by solid, ignore it.
if (c->type->solid && (countcellexits(c, DT_ORTH) == 0)){ if (poss[i]->type->solid && (countcellexits(poss[i], DT_ORTH) == 0)){
if (db) dblog("cell is solid and surrounded by solids. ignoring."); if (db) dblog("cell is solid and surrounded by solids. ignoring.");
continue; continue;
} }
@ -3584,7 +3817,7 @@ void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIO
region_t *r; region_t *r;
// create a new region // create a new region
r = addregion(newregiontype, m->region, -1); r = addregion(newregiontype, m->region, -1);
// add stairs to new region // add stairs going to the new region, if required
if (!c) { if (!c) {
c = NULL; c = NULL;
while (!c || !cellwalkable(NULL, c, NULL)) { while (!c || !cellwalkable(NULL, c, NULL)) {
@ -3666,10 +3899,46 @@ void createriver(map_t *m) {
} }
} }
// room w/h are returned in *w and *h if given. void createroom(map_t *map, int roomid, int x1, int y1, int x2, int y2, int forcewalls) {
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int xmargin, int ymargin, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls) {
int x,y; int x,y;
room_t *thisroom = NULL;
cell_t *cell; cell_t *cell;
map->room[map->nrooms].id = roomid;
map->room[map->nrooms].x1 = x1;
map->room[map->nrooms].y1 = y1;
map->room[map->nrooms].x2 = x2;
map->room[map->nrooms].y2 = y2;
map->room[map->nrooms].vault = NULL;
map->room[map->nrooms].exitslinked = B_FALSE;
thisroom = &(map->room[map->nrooms]);
map->nrooms++;
for (y = y1; y <= y2; y++) {
for (x = x1; x <= x2; x++) {
cell = getcellat(map, x, y);
if (cell) {
// kill contents, EXCEPT for staircases!
clearcell_exceptflags(cell, F_CLIMBABLE, F_NONE);
// make it a border or room
if ((y == y1) || (y == y2) ||
(x == x1) || (x == x2)) {
// ie. if you haven't forced walls then if this room overlaps
// with another one, no walls will be created.
if (forcewalls || (!forcewalls && cell->type->solid)) {
setcelltype(cell, CT_ROOMWALL);
}
//}
} else {
setcelltype(cell, CT_ROOM);
}
cell->room = thisroom;
}
}
}
}
// room w/h are returned in *w and *h if given.
int calcposandmakeroom(map_t *map, int roomid, int overrideminw, int overrideminh, int xmargin, int ymargin, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls) {
int minx,miny; int minx,miny;
int maxx,maxy; int maxx,maxy;
int w,h; int w,h;
@ -3677,7 +3946,6 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int x
int minroomh = MIN_ROOMH; int minroomh = MIN_ROOMH;
int maxroomw = MAX_ROOMW; int maxroomw = MAX_ROOMW;
int maxroomh = MAX_ROOMH; int maxroomh = MAX_ROOMH;
room_t *thisroom = NULL;
if (overrideminw != NA) { if (overrideminw != NA) {
minroomw = overrideminw; minroomw = overrideminw;
@ -3709,38 +3977,8 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int x
maxx = minx + (w-1); maxx = minx + (w-1);
maxy = miny + (h-1); maxy = miny + (h-1);
map->room[map->nrooms].id = roomid; // actually make the room now.
map->room[map->nrooms].x1 = minx; createroom(map, roomid, minx,miny,maxx,maxy, forcewalls);
map->room[map->nrooms].y1 = miny;
map->room[map->nrooms].x2 = maxx;
map->room[map->nrooms].y2 = maxy;
map->room[map->nrooms].vault = NULL;
map->room[map->nrooms].exitslinked = B_FALSE;
thisroom = &(map->room[map->nrooms]);
map->nrooms++;
for (y = miny; y <= maxy; y++) {
for (x = minx; x <= maxx; x++) {
cell = getcellat(map, x, y);
if (cell) {
// kill contents, EXCEPT for staircases!
clearcell_exceptflags(cell, F_CLIMBABLE, F_NONE);
// make it a border or room
if ((y == miny) || (y == maxy) ||
(x == minx) || (x == maxx)) {
// ie. if you haven't forced walls then if this room overlaps
// with another one, no walls will be created.
if (forcewalls || (!forcewalls && cell->type->solid)) {
setcelltype(cell, CT_ROOMWALL);
}
//}
} else {
setcelltype(cell, CT_ROOM);
}
cell->room = thisroom;
}
}
}
// add doors // add doors
if (doorpct) { if (doorpct) {
@ -4417,8 +4655,8 @@ char *getregionname(char *buf, map_t *m, int withlevel) {
case RG_PIT: case RG_PIT:
snprintf(buf, BUFLEN, "a pit L%d", m->depth); snprintf(buf, BUFLEN, "a pit L%d", m->depth);
break; break;
default: case RG_SEWER:
strcpy(buf, "?unknownregiontype??"); snprintf(buf, BUFLEN, "a sewer L%d", m->depth);
break; break;
} }
} else { } else {
@ -4435,8 +4673,8 @@ char *getregionname(char *buf, map_t *m, int withlevel) {
case RG_PIT: case RG_PIT:
snprintf(buf, BUFLEN, "a pit"); snprintf(buf, BUFLEN, "a pit");
break; break;
default: case RG_SEWER:
strcpy(buf, "?unknownregiontype??"); snprintf(buf, BUFLEN, "a sewer");
break; break;
} }
} }
@ -4814,15 +5052,17 @@ void initmap(void) {
addhabitat(H_HEAVEN, "heaven", CT_CORRIDOR, CT_WALL, 0, 0, 0, MAXVISRANGE); addhabitat(H_HEAVEN, "heaven", CT_CORRIDOR, CT_WALL, 0, 0, 0, MAXVISRANGE);
addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0, 5); addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0, 5);
addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 3, 70, 0, MAXVISRANGE); addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 3, 70, 0, MAXVISRANGE);
addhabitat(H_SEWER, "sewer", CT_CORRIDOR, CT_WALL, 5, 50, 0, MAXVISRANGE);
addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE); addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE);
// cell types // cell types - solid
addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0);
addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0);
addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0);
addcelltype(CT_ROOMWALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
// cell types - non-solid
addcelltype(CT_FAKE, "fake cell", '.', C_GREEN, B_EMPTY, B_TRANS, MT_STONE, 0); addcelltype(CT_FAKE, "fake cell", '.', C_GREEN, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
addcelltype(CT_WALLWOOD, "wooden wall", '#', C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 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_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_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_FLOORWOOD, "wood floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0); addcelltype(CT_FLOORWOOD, "wood floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0);
@ -4831,12 +5071,14 @@ void initmap(void) {
addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT, 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_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); addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -1);
addcelltype(CT_VLOWFLOOR, "very low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -2);
// region types // region types
addregiontype(RG_WORLDMAP, "World map", H_FOREST, 10, 0, D_NONE, B_TRUE); addregiontype(RG_WORLDMAP, "World map", H_FOREST, 10, 0, D_NONE, B_TRUE);
addregiontype(RG_FIRSTDUNGEON, "First Dungeon", H_DUNGEON, 10, 3, D_DOWN, B_TRUE); addregiontype(RG_FIRSTDUNGEON, "First Dungeon", H_DUNGEON, 10, 3, D_DOWN, B_TRUE);
addregiontype(RG_HEAVEN, "Realm of Gods", H_HEAVEN, 1, 0, D_NONE, B_FALSE); addregiontype(RG_HEAVEN, "Realm of Gods", H_HEAVEN, 1, 0, D_NONE, B_FALSE);
addregiontype(RG_PIT, "Pit", H_PIT, 1, 1, D_DOWN, B_FALSE); addregiontype(RG_PIT, "Pit", H_PIT, 1, 1, D_DOWN, B_FALSE);
addregiontype(RG_SEWER, "Sewer", H_SEWER, 1, 0, D_NONE, B_FALSE);
// MAPMAPMAPMAP // MAPMAPMAPMAP
// region definitions (outlines) // region definitions (outlines)
@ -5381,38 +5623,30 @@ void makedoor(cell_t *cell, int openchance) {
strcpy(doorbuf, "wooden door"); strcpy(doorbuf, "wooden door");
} }
// addob will determine whether the door is locked. if so,
// don't open it!
o = addob(cell->obpile, doorbuf); o = addob(cell->obpile, doorbuf);
if (o && (rnd(1,100) <= openchance)) { if (o) {
opendoor(NULL, o); if (!hasflag(o->flags, F_LOCKED) && (rnd(1,100) <= openchance)) {
} else { opendoor(NULL, o);
int chance; } else {
// door is closed - lock it? int chance;
// door might be secret?
chance = rolldie(1,6) - (m->depth / 10);
// ie. at dungeon lev 10, chance is 2 in 6 // difficulty:
// at dungeon lev 20, chance is 3 in 6 // l1 = 20
// ... // l10 = 25
// at dungeon lev 50, chance is 5 in 6 // l20 = 30
chance = rolldie(1,6) - (m->depth / 10); if (chance <= 1) {
addflag(o->flags, F_SECRET, getdoorsecretdiff(m->depth), NA, NA, NULL);
}
if (chance <= 1) {
addflag(o->flags, F_LOCKED, B_TRUE, getdoorlockdiff(m->depth), NA, NULL);
}
// make it secret?
chance = rolldie(1,6) - (m->depth / 10);
// difficulty:
// l1 = 20
// l10 = 25
// l20 = 30
if (chance <= 1) {
addflag(o->flags, F_SECRET, getdoorsecretdiff(m->depth), NA, NA, NULL);
} }
} }
} }
void makelit(cell_t *c, enum LIGHTLEV how, int howlong) { void makelit(cell_t *c, enum LIGHTLEV how, int howlong) {
// don't override permenant light with temp light! // don't override permenant light with temp light!
//if ((c->lit == L_PERMLIGHT) && (how == L_TEMP)) { //if ((c->lit == L_PERMLIGHT) && (how == L_TEMP)) {
@ -5697,6 +5931,7 @@ int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring) {
} }
// shatter solid glass cells // shatter solid glass cells
if (c->type->solid && willshatter(c->type->material->id)) { if (c->type->solid && willshatter(c->type->material->id)) {
enum MATERIAL origmat;
rv = B_TRUE; rv = B_TRUE;
// announce // announce
if (haslos(player, c)) { if (haslos(player, c)) {
@ -5714,16 +5949,19 @@ int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring) {
losehp(target, rnd(1,100), DT_SLASH, fromlf, damstring); // BIG damage losehp(target, rnd(1,100), DT_SLASH, fromlf, damstring); // BIG damage
} }
// remember original material
origmat = c->type->material->id;
// change cell type // change cell type
setcelltype(c, c->habitat->emptycelltype); setcelltype(c, c->habitat->emptycelltype);
// place shards // place shards
if (c->type->material->id == MT_GLASS) { if (origmat == MT_GLASS) {
int numshards; int numshards;
numshards = rnd(50,100); numshards = rnd(50,100);
snprintf(buf, BUFLEN, "%d pieces of broken glass",numshards); snprintf(buf, BUFLEN, "%d pieces of broken glass",numshards);
addob(c->obpile, buf); addob(c->obpile, buf);
} else if (c->type->material->id == MT_ICE) { } else if (origmat == MT_ICE) {
int numshards; int numshards;
numshards = rnd(50,100); numshards = rnd(50,100);
snprintf(buf, BUFLEN, "%d chunks of ice",numshards); snprintf(buf, BUFLEN, "%d chunks of ice",numshards);

4
map.h
View File

@ -56,7 +56,9 @@ void createpit(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *e
void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIONTYPE newregiontype, region_t *parent); void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIONTYPE newregiontype, region_t *parent);
void createregionthing(map_t *map, regionthing_t *rt); void createregionthing(map_t *map, regionthing_t *rt);
void createriver(map_t *m); void createriver(map_t *m);
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int xmargin, int ymargin, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls); void createroom(map_t *map, int roomid, int x1, int y1, int x2, int y2, int forcewalls);
int calcposandmakeroom(map_t *map, int roomid, int overrideminw, int overrideminh, int xmargin, int ymargin, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls);
void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob);
void createswamp(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); void createswamp(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob);
int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *retx, int *rety); int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *retx, int *rety);
int dirtox(int dt, int dir); int dirtox(int dt, int dir);

View File

@ -526,7 +526,7 @@ int main(int argc, char **argv) {
return B_FALSE; return B_FALSE;
} }
celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight) { celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight) {
celltype_t *a; celltype_t *a;
// add to the end of the list // add to the end of the list

View File

@ -1,6 +1,6 @@
#include "defs.h" #include "defs.h"
celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight); celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight);
warning_t *addwarning(char *text); warning_t *addwarning(char *text);
void checkdeath(void); void checkdeath(void);
void checkendgame(void); void checkendgame(void);

278
objects.c
View File

@ -445,6 +445,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
int wantlit = B_FALSE; int wantlit = B_FALSE;
int wantrarity = RR_NONE; int wantrarity = RR_NONE;
int wantgoodness = G_NA; int wantgoodness = G_NA;
int wantfoodtaint = B_FALSE;
enum LFSIZE wantarmsize = SZ_ANY; enum LFSIZE wantarmsize = SZ_ANY;
enum MATERIAL wantdiffmat = MT_NOTHING; enum MATERIAL wantdiffmat = MT_NOTHING;
map_t *targetmap = NULL; // for portals map_t *targetmap = NULL; // for portals
@ -457,6 +458,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
int ndoorflags = 0; int ndoorflags = 0;
char *signtext = NULL; char *signtext = NULL;
int trapchance = 0; int trapchance = 0;
int lockchance = 0;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags = 0; int nretflags = 0;
@ -622,7 +624,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
donesomething = B_TRUE; donesomething = B_TRUE;
// door flags // door flags
} else if (strstarts(p, "locked ")) { } else if (strstarts(p, "locked ")) {
doorflag[ndoorflags++] = F_LOCKED; doorflag[ndoorflags++] = F_LOCKED; // for doors
lockchance = 100; // for other objects like chests
p += strlen("locked "); p += strlen("locked ");
donesomething = B_TRUE; donesomething = B_TRUE;
} else if (strstarts(p, "jammed ")) { } else if (strstarts(p, "jammed ")) {
@ -695,6 +698,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
trapchance = 100; trapchance = 100;
p += strlen("trapped "); p += strlen("trapped ");
donesomething = B_TRUE; donesomething = B_TRUE;
// food
} else if (strstarts(p, "tainted ")) {
wantfoodtaint = B_TRUE;
p += strlen("tainted ");
donesomething = B_TRUE;
} }
} }
@ -882,19 +890,28 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
//////////////////////////////////// ////////////////////////////////////
if ((gamemode != GM_LOADING) && hasflag(ot->flags, F_ONEPERCELL)) { if (gamemode != GM_LOADING) {
if (hasob(where, ot->id)) { if (hasflag(ot->flags, F_ONEPERCELL)) {
if (db) dblog("DB: trying to add >1 ONEPERCELL object to a cell. (%s) bailing out.", ot->name); if (hasob(where, ot->id)) {
nretobs = 0; if (db) dblog("DB: trying to add >1 ONEPERCELL object to a cell. (%s) bailing out.", ot->name);
return NULL; nretobs = 0;
return NULL;
}
} }
}
// water ob onto dirt -> mud // water ob onto dirt -> mud
if (where->where) { if (where->where) {
if ((ot->material->id == MT_WATER) || (ot->id == OT_SPLASHWATER)) { if ((ot->material->id == MT_WATER) || (ot->id == OT_SPLASHWATER)) {
if (where->where->type->id == CT_DIRT) { if (where->where->type->id == CT_DIRT) {
ot = findot(OT_MUDPOOL); ot = findot(OT_MUDPOOL);
}
}
}
if (ot->obclass->id == OC_SPELL) {
if (where->owner || where->where) {
if (db) dblog("DB: Cannot give a spell object to a player, or a cell! object name '%s'", ot->name );
nretobs = 0;
return NULL;
} }
} }
} }
@ -911,13 +928,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
return NULL; return NULL;
} }
if (ot->obclass->id == OC_SPELL) {
if (where->owner || where->where) {
if (db) dblog("DB: Cannot give a spell object to a player, or a cell! object name '%s'", ot->name );
nretobs = 0;
return NULL;
}
}
// override canstack if required // override canstack if required
if (!hasflag(ot->flags, F_STACKABLE)) { if (!hasflag(ot->flags, F_STACKABLE)) {
@ -1197,6 +1207,10 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
// food flags
if ((ot->obclass->id == OC_FOOD) && wantfoodtaint) {
addflag(o->flags, F_TAINTED, B_TRUE, NA, NA, NULL);
}
// tool flags // tool flags
if (o && hasflag(o->flags, F_LIGHTSOURCE) && wantlit) { if (o && hasflag(o->flags, F_LIGHTSOURCE) && wantlit) {
turnon(NULL, o); turnon(NULL, o);
@ -1444,12 +1458,14 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
cf->val[1] = sizetonutrition(rf->val[0]); cf->val[1] = sizetonutrition(rf->val[0]);
} }
} }
} else if (o->type->id == OT_WATERDEEP) {
f = hasflag(o->flags, F_DEEPWATER);
if (f && (f->val[0] != wantdepth)) {
f->val[0] = wantdepth;
}
} }
// depth
f = hasflag(o->flags, F_DEEPWATER);
if (f && (f->val[0] != wantdepth)) {
f->val[0] = wantdepth;
}
// chance of masterwork based on wantgoodness // chance of masterwork based on wantgoodness
switch (wantgoodness) { switch (wantgoodness) {
case G_GREAT: case G_GREAT:
@ -1607,6 +1623,20 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
} }
// locked?
if (!lockchance) {
f = hasflag(o->flags, F_CANBELOCKED);
if (f) {
lockchance = f->val[0] + (f->val[1] * (obloc->map->depth/5));
limit(&lockchance, f->val[0], 100);
}
}
if (lockchance && pctchance(lockchance)) {
addflag(o->flags, F_LOCKED, B_TRUE, getdoorlockdiff(obloc->map->depth), NA, NULL);
}
// trapped? l1=10%, l5=20%, l10=30%, l15=40%, l20+=60% // trapped? l1=10%, l5=20%, l10=30%, l15=40%, l20+=60%
if (!trapchance) { if (!trapchance) {
f = hasflag(o->flags, F_CANBETRAPPED); f = hasflag(o->flags, F_CANBETRAPPED);
@ -1615,15 +1645,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
limit(&trapchance, f->val[0], f->val[2]); limit(&trapchance, f->val[0], f->val[2]);
} }
} }
if (trapchance && pctchance(trapchance)) {
if (trapchance) { enum OBTYPE traptype;
if (pctchance(trapchance)) { // get a random trap
enum OBTYPE traptype; //
// get a random trap traptype = getrandomtrapforob();
// addflag(o->flags, F_TRAPPED, traptype, NA, NA, NULL);
traptype = getrandomtrapforob();
addflag(o->flags, F_TRAPPED, traptype, NA, NA, NULL);
}
} }
} }
@ -1808,6 +1835,8 @@ objecttype_t *addot(enum OBTYPE id, char *name, char *description, int material,
a->flags = addflagpile(NULL, NULL); a->flags = addflagpile(NULL, NULL);
// inherit flags from object class // inherit flags from object class
copyflags(a->flags, a->obclass->flags, NA); copyflags(a->flags, a->obclass->flags, NA);
// ...but don'to inherit rarity
killflagsofid(a->flags, F_RARITY);
if (a->material) { if (a->material) {
// inherit flags from material // inherit flags from material
copyflags(a->flags, a->material->flags, FROMMAT); copyflags(a->flags, a->material->flags, FROMMAT);
@ -2534,16 +2563,11 @@ void colourmatchob(object_t *o, lifeform_t *lf) {
f = hasflag(o->flags, F_GLYPH); f = hasflag(o->flags, F_GLYPH);
if (f) { if (f) {
f->val[1] = lfglyph->colour;
f->val[0] = lfglyph->colour;
} else { } else {
glyph_t *obglyph; glyph_t *obglyph;
char buf[2];
obglyph = getglyph(o); obglyph = getglyph(o);
buf[0] = obglyph->ch; addflag(o->flags, F_GLYPH, lfglyph->colour, obglyph->ch, NA, NULL);
buf[1] = '\0';
addflag(o->flags, F_GLYPH, lfglyph->colour, NA, NA, buf);
} }
} }
@ -3095,7 +3119,7 @@ int getfirearmspeed(object_t *o) {
glyph_t *getglyph(object_t *o) { glyph_t *getglyph(object_t *o) {
flag_t *f; flag_t *f;
int isopen; int isopen;
char g = ' '; // default int g = ' '; // default
int col = C_GREY; int col = C_GREY;
cell_t *obloc; cell_t *obloc;
obloc = getoblocation(o); obloc = getoblocation(o);
@ -3115,7 +3139,7 @@ glyph_t *getglyph(object_t *o) {
f = hasflag(o->flags, F_GLYPH); f = hasflag(o->flags, F_GLYPH);
if (f) { if (f) {
g = f->text[0]; g = f->val[1];
if (f->val[0] != NA) { if (f->val[0] != NA) {
col = f->val[0]; col = f->val[0];
} }
@ -3127,21 +3151,24 @@ glyph_t *getglyph(object_t *o) {
} }
// special case // special case
if (o->type->id == OT_WATERDEEP) { if (hasflag(o->flags, F_DEEPWATER)) {
cell_t *loc; cell_t *loc;
loc = getoblocation(o);
// override colour // override colour
if (getobdepth(o, player) >= DP_HEAD) { //if (getobdepth(o, player) >= DP_HEAD) {
/*
if (getcellwaterdepth(loc, player) >= DP_HEAD) {
col = C_BOLDBLUE; col = C_BOLDBLUE;
} else { } else {
col = C_BLUE; col = C_BLUE;
} }
loc = getoblocation(o); */
if (getcellwaterdepth(loc, player) >= DP_WAIST) { if (getcellwaterdepth(loc, player) >= DP_WAIST) {
g = '{'; g = UNI_SOLID;
} else { } else {
g = '~'; g = '~';
} }
} }
tempglyph.ch = g; tempglyph.ch = g;
@ -4117,7 +4144,17 @@ enum DEPTH getobdepth(object_t *o, lifeform_t *lf) {
depth = f->val[0]; depth = f->val[0];
if (lf) { if (lf) {
int mod; int mod;
mod = (SZ_HUMAN - getlfsize(lf)) * DP_CALF; int lfsize;
lfsize = getlfsize(lf);
if (isprone(lf)) {
lfsize -= 2;
limit(&lfsize, SZ_MINI, NA);
}
mod = (SZ_HUMAN - lfsize);
limit(&mod, SZ_MINI, NA);
mod *= DP_CALF;
depth += mod; depth += mod;
limit(&depth, DP_NONE, DP_HEAD); limit(&depth, DP_NONE, DP_HEAD);
} }
@ -4184,8 +4221,8 @@ char *getobdesc(object_t *o, char *buf) {
} else { } else {
snprintf(buf, BUFLEN, "%s", o->type->desc); snprintf(buf, BUFLEN, "%s", o->type->desc);
} }
} else if (o->type->id == OT_WATERDEEP) { } else if (hasflag(o->flags, F_DEEPWATER)) {
snprintf(buf, BUFLEN, "%s water.", getwaterdepthname(getobdepth(o, player))); snprintf(buf, BUFLEN, "%s %s.", getwaterdepthname(getobdepth(o, player)), o->type->name);
capitalise(buf); capitalise(buf);
} else { } else {
snprintf(buf, BUFLEN, "%s", o->type->desc); snprintf(buf, BUFLEN, "%s", o->type->desc);
@ -4458,8 +4495,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} else { } else {
sprintf(basename, "abandoned temple"); sprintf(basename, "abandoned temple");
} }
} else if (o->type->id == OT_WATERDEEP) { } else if (hasflag(o->flags, F_DEEPWATER)) {
snprintf(basename, BUFLEN, "%s water", getwaterdepthname(getobdepth(o, player))); snprintf(basename, BUFLEN, "%s %s", getwaterdepthname(getobdepth(o, player)), o->type->name);
} else { } else {
strcpy(basename, ""); strcpy(basename, "");
@ -4969,7 +5006,11 @@ char *getobconditionname(object_t *o, char *buf) {
if (isrotting(o) && if (isrotting(o) &&
( (iqb >= AT_GTAVERAGE) || getskill(player, SK_COOKING)) ) { ( (iqb >= AT_GTAVERAGE) || getskill(player, SK_COOKING)) ) {
if (strlen(buf)) strcat(buf, " "); if (strlen(buf)) strcat(buf, " ");
strcat(buf, "rotting"); if (hasflag(o->flags, F_ISMEAT)) {
strcat(buf, "rotting");
} else {
strcat(buf, "mouldy");
}
} }
} else { } else {
@ -5054,7 +5095,7 @@ float getobunitweight(object_t *o) {
return 0; return 0;
} }
if (o->type->id == OT_WATERDEEP) { if (hasflag(o->flags, F_DEEPWATER)) {
weight = 75 * getobdepth(o, NULL); weight = 75 * getobdepth(o, NULL);
} else { } else {
weight = o->weight; weight = o->weight;
@ -5190,7 +5231,7 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat,
// no obclass given? pick one randomly. // no obclass given? pick one randomly.
if (!nwantclass) { if (!nwantclass) {
wantclass[0] = getrandomobclass(); wantclass[0] = getrandomobclass(hab->id);
nwantclass = 1; nwantclass = 1;
} }
@ -5421,16 +5462,28 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat,
} }
} }
} }
om = NULL;
if (noms) { if (noms) {
// pick a random one to maybe apply // pick a random one to maybe apply
f = omposs[rnd(0,noms-1)]; f = omposs[rnd(0,noms-1)];
if (rnd(1,100) <= f->val[1]) { if (rnd(1,100) <= f->val[1]) {
om = findobmod(f->val[0]); om = findobmod(f->val[0]);
if (om) {
strcat(cursestr, om->prefix);
}
} }
} }
if (!om) {
// in sewers, everythinng is shoddy
if ((map->habitat->id == H_SEWER) && hasflagval(ot->flags, F_CANHAVEOBMOD, OM_SHODDY, NA, NA, NULL)) {
om = findobmod(OM_SHODDY);
}
}
if (om) {
strcat(cursestr, om->prefix);
strcat(cursestr, " ");
}
if ((map->habitat->id == H_SEWER) && (ot->obclass->id == OC_FOOD)) {
strcat(cursestr, "tainted ");
}
// get random chance of having a brand (1% per depth)... // get random chance of having a brand (1% per depth)...
// if so... // if so...
@ -5468,14 +5521,26 @@ char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod
return real_getrandomob(map, buf, getmapdifficulty(map) + depthmod, NA, SZ_MAX, B_FALSE, cid, OC_NONE, DT_NONE); return real_getrandomob(map, buf, getmapdifficulty(map) + depthmod, NA, SZ_MAX, B_FALSE, cid, OC_NONE, DT_NONE);
} }
enum OBCLASS getrandomobclass(void) { enum OBCLASS getrandomobclass(enum HABITAT hab) {
enum RARITY wantrr; enum RARITY wantrr;
objectclass_t *oc,*poss[MAXCANDIDATES]; objectclass_t *oc,*poss[MAXCANDIDATES];
int nposs = 0; int nposs = 0;
wantrr = pickrr(TT_OBJECT); wantrr = pickrr(TT_OBJECT);
while (!nposs) { while (!nposs) {
for (oc = objectclass ; oc ; oc = oc->next) { for (oc = objectclass ; oc ; oc = oc->next) {
enum RARITY thisrarity = RR_NONE;
// if we were given a map, check the objectclass for specific
// rarity flag for the maps' habitat.
if (hab != H_ALL) {
flag_t *f;
f = hasflagval(oc->flags, F_RARITY, hab, NA, NA, NULL);
if (f) thisrarity = f->val[2];
}
// otherwise just use the default objectclass rarity
if (thisrarity == RR_NONE) thisrarity = oc->rarity;
if (oc->rarity == wantrr) { if (oc->rarity == wantrr) {
poss[nposs++] = oc; poss[nposs++] = oc;
} }
@ -5602,15 +5667,21 @@ void setwaterdepth(cell_t *c, int depth) {
} }
} else { } else {
int nkilled = 0; int nkilled = 0;
enum MATERIAL killedmat = MT_NOTHING;
// water depth is now zero. // water depth is now zero.
o = hasobwithflag(c->obpile, F_DEEPWATER); o = hasobwithflag(c->obpile, F_DEEPWATER);
while (o) { while (o) {
if (killedmat == MT_NOTHING) killedmat = o->material->id;
killob(o); killob(o);
nkilled++; nkilled++;
o = hasobwithflag(c->obpile, F_DEEPWATER); o = hasobwithflag(c->obpile, F_DEEPWATER);
} }
if (nkilled) { if (nkilled) {
addob(c->obpile, "large puddle of water"); if (killedmat == MT_WATER) {
addob(c->obpile, "large puddle of water");
} else if (killedmat == MT_SLIME) {
addob(c->obpile, "puddle of slime");
}
} }
} }
} }
@ -7735,6 +7806,10 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
if (hasflag(o->flags, F_CONTAINER) && !hasflag(o->flags, F_SHOP)) { // loot it if (hasflag(o->flags, F_CONTAINER) && !hasflag(o->flags, F_SHOP)) { // loot it
if (isplayer(lf)) { // only player can loot. if (isplayer(lf)) { // only player can loot.
char ch; char ch;
if (hasflag(o->flags, F_LOCKED)) {
msg("The %s seems to be locked.", noprefix(obname));
return B_TRUE;
}
snprintf(buf, BUFLEN, "Looting %s. Will you:",obname); snprintf(buf, BUFLEN, "Looting %s. Will you:",obname);
initprompt(&prompt, buf); initprompt(&prompt, buf);
if (countobs(lf->pack, B_FALSE)) { if (countobs(lf->pack, B_FALSE)) {
@ -8206,32 +8281,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
} else if ((o->type->id == OT_LOCKPICK) } else if ((o->type->id == OT_LOCKPICK)
|| (o->type->id == OT_PAPERCLIP) || (o->type->id == OT_PAPERCLIP)
|| (o->type->id == OT_CREDITCARD)) { || (o->type->id == OT_CREDITCARD)) {
char ch; lockpick(lf, NULL, NULL, o);
int dir;
// ask direction
ch = askchar("Lockpick in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE, B_TRUE);
dir = chartodir(ch);
if (dir == D_NONE) {
clearmsg();
return B_TRUE;
} else {
cell_t *c;
c = getcellindir(player->cell, dir);
if (c) {
object_t *targ;
// something to lockpick there?
targ = hasobwithflag(c->obpile, F_LOCKED);
if (targ) {
lockpick(player, targ, o);
} else {
// fail
msg("There is nothing locked there!");
}
} else {
clearmsg();
return B_TRUE;
}
}
} else if (o->type->id == OT_LOCKHACKER) { } else if (o->type->id == OT_LOCKHACKER) {
char ch; char ch;
int dir; int dir;
@ -8249,29 +8299,27 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
// lock/unlock everything there // lock/unlock everything there
for (oo = c->obpile->first ; oo ; oo = nextoo) { for (oo = c->obpile->first ; oo ; oo = nextoo) {
nextoo = oo->next; nextoo = oo->next;
if (hasflag(oo->flags, F_LOCKABLE)) { flag_t *f;
flag_t *f; f = hasflag(oo->flags, F_LOCKED);
f = hasflag(oo->flags, F_LOCKED); if (f) {
if (f) { killflag(f);
killflag(f); if (isplayer(lf)) {
if (isplayer(lf)) { msg("Your %s beeps.", noprefix(obname));
msg("Your %s beeps.", noprefix(obname)); } else if (cansee(player, lf)) {
} else if (cansee(player, lf)) { char lfname[BUFLEN];
char lfname[BUFLEN]; getlfname(lf, lfname);
getlfname(lf, lfname); msg("%s%s %s beeps.", lfname, getpossessive(lfname),
msg("%s%s %s beeps.", lfname, getpossessive(lfname), noprefix(obname));
noprefix(obname)); }
} } else {
} else { addflag(oo->flags, F_LOCKED, B_TRUE, 20, NA, NULL);
addflag(oo->flags, F_LOCKED, B_TRUE, 20, NA, NULL); if (isplayer(lf)) {
if (isplayer(lf)) { msg("Your %s buzzes.", noprefix(obname));
msg("Your %s buzzes.", noprefix(obname)); } else if (cansee(player, lf)) {
} else if (cansee(player, lf)) { char lfname[BUFLEN];
char lfname[BUFLEN]; getlfname(lf, lfname);
getlfname(lf, lfname); msg("%s%s %s buzzes.", lfname, getpossessive(lfname),
msg("%s%s %s buzzes.", lfname, getpossessive(lfname), noprefix(obname));
noprefix(obname));
}
} }
} }
} }
@ -10055,11 +10103,7 @@ int sethiddenname(objecttype_t *ot, char *text) {
if (gf) { if (gf) {
gf->val[0] = colour[n].col; gf->val[0] = colour[n].col;
} else { } else {
char buf[2]; addflag(ot->flags, F_GLYPH, colour[n].col, ot->obclass->glyph.ch, NA, NULL);
buf[0] = ot->obclass->glyph.ch;
buf[1] = '\0';
addflag(ot->flags, F_GLYPH, colour[n].col, NA, NA, buf);
gotcolour = B_TRUE; gotcolour = B_TRUE;
//dblog("assigning colour %s to %s (%s)",colour[n].name, text, ot->name); //dblog("assigning colour %s to %s (%s)",colour[n].name, text, ot->name);
break; break;
@ -10075,11 +10119,7 @@ int sethiddenname(objecttype_t *ot, char *text) {
if (gf) { if (gf) {
gf->val[0] = gemtype[n].col; gf->val[0] = gemtype[n].col;
} else { } else {
char buf[2]; addflag(ot->flags, F_GLYPH, gemtype[n].col, ot->obclass->glyph.ch, NA, NULL);
buf[0] = ot->obclass->glyph.ch;
buf[1] = '\0';
addflag(ot->flags, F_GLYPH, gemtype[n].col, NA, NA, buf);
break; break;
} }
} }

View File

@ -132,7 +132,7 @@ char *getrandomob(map_t *map, char *buf);
char *getrandomobofsize(map_t *map, char *buf, enum LFSIZE maxsize); char *getrandomobofsize(map_t *map, char *buf, enum LFSIZE maxsize);
char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf); char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf);
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod); char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod);
enum OBCLASS getrandomobclass(void); enum OBCLASS getrandomobclass(enum HABITAT hab);
int getobrarity(object_t *o, enum RARITY *rr); int getobrarity(object_t *o, enum RARITY *rr);
enum SPELLSCHOOL getschool(enum OBTYPE sid); enum SPELLSCHOOL getschool(enum OBTYPE sid);
char *getschoolname(enum SPELLSCHOOL sch); char *getschoolname(enum SPELLSCHOOL sch);

31
spell.c
View File

@ -3263,7 +3263,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else { } else {
fizzle(caster); fizzle(caster);
} }
} else if (spellid == OT_S_ANIMATESTONE) { } else if (spellid == OT_S_ANIMATESTATUE) {
object_t *o; object_t *o;
target = targcell->lf; target = targcell->lf;
if (target) { if (target) {
@ -4682,7 +4682,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int nseen = 0; int nseen = 0;
int nsteamseen = 0; int nsteamseen = 0;
// don't need line of fire! // don't need line of fire!
getradiuscells(targcell, power, DT_ORTH, B_FALSE, LOF_NEED, B_TRUE, cell, &ncells, B_FALSE); getradiuscells(targcell, power, DT_ORTH, B_FALSE, LOF_NEED, B_TRUE, cell, &ncells, B_FALSE);
for (i = 0; i < ncells; i++) { for (i = 0; i < ncells; i++) {
object_t *o,*nexto; object_t *o,*nexto;
@ -5400,6 +5399,34 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// is broken and vines will vanish. // is broken and vines will vanish.
setobcreatedby(o, caster); setobcreatedby(o, caster);
} else if (spellid == OT_S_EXCAVATE) {
cell_t *retcell[MAXRETCELLS],*c;
int nretcells,i,radius,seenwalls = 0, seenobs = 0;
radius = power;
limit(&radius, 3, NA);
getradiuscells(caster->cell, radius, DT_ORTH, B_FALSE, LOF_DONTNEED, B_FALSE, retcell, &nretcells, 0);
for (i = 0; i < nretcells; i++) {
object_t *o, *nexto;
c = retcell[i];
if (c->type->solid) {
if (haslos(player, c)) seenwalls++;
setcelltype(c, c->map->habitat->emptycelltype);
addob(c->obpile, "10-20 piles of ash");
}
// impassable objects here are destroyed
for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next;
if ((o->type->id != OT_ASH) && (getmaterialstate(o->material->id) == MS_SOLID)) {
killob(o);
addobfast(c->obpile, OT_ASH);
if (haslos(player, c)) seenobs++;
}
}
}
if (seenobs || seenwalls || cansee(player, caster)) {
msg("A shockwave of destructive force rips through the air!");
setlosdirty(player);
}
} else if (spellid == OT_S_FLIGHT) { } else if (spellid == OT_S_FLIGHT) {
flag_t *f; flag_t *f;
// always targetted at caster // always targetted at caster

4
text.c
View File

@ -1101,7 +1101,9 @@ char *makekillertext(char *retbuf, char *killverb, char *lastdam, int wantextra)
if (!strcmp(p, "you")) { if (!strcmp(p, "you")) {
strcpy(retbuf, "Committed suicide."); strcpy(retbuf, "Committed suicide.");
} else { } else {
snprintf(retbuf, BUFLEN, "%s by %s.",killverb, p); snprintf(retbuf, BUFLEN, "%s %s %s.",killverb,
streq(killverb, "Drowned") ? "in" : "by",
p);
} }
if (wantextra) { if (wantextra) {
p = strtok_r(NULL, "^", &dummy); p = strtok_r(NULL, "^", &dummy);