VAULTS
* [+] vaiultlegend_t * [+] vaultdef_t - [+] implement addlegend() - [+] implement addvault() - [+] function to read in a vault from a data file - [+] vs_noid - [+] vs_loadingmap - [+] vs_loadinglegend - [+] vs_loadingflags - [+] vs_loading - [+] load all vaultdefs in at start - [+] change createroom to calculate the posistion - [+] for each room, give a %chance of haivng a vault. (based on habitat?) * [+] createvault(map_t, roomid?, char *vaultid) - [+] mapdata with letters * [+] MSG up vault errors on load. - [+] Select job _before_ generating first map. * [+] make addob() handle door flags: * [+] addob() improvements * [+] wish bug: first object goes in pack, rest on ground. - [+] genericise getroomedge() - [+] finish 'autodoors' (at the end, add doors if none already done) - [+] at(x,y):type:what:pct -> f_vaultob / vaultlf / vaultcell, v0=x, v1=y, v2=pct text=what * [+] "what" can be: * [+] scatter:y1:x2:y2:what:chance%:howmany * [+] some way to make the @map bit just say 'random room at least 2x4' - [+] make "scatter" able to take range instead of count. - [+] make "scatter"able to take x% instead of count. - [+] upsidedown chars no longer working with winch() - [+] ensure no DUPE ids - [+] make legend take percentages (optional) - [+] make "at" take negative values... OPTIONS - [+] autodoors - put doors on edges like with normal dungeon rooms. * [+] autopop - fill with obs/monsters like normal rooms VAULT FILES - [+] flooded room - [+] labyrinth - [+] vault (lots of money, locked secret doors) - [+] monster zoos (money and monsters) - [+] diningroom - lots of tables and chairs - [+] circleroom - [+] pillared room - [+] glass pillared room - [+] cockatrice lair (statues) - [+] traproom - need "random trap". need OC_TRAP. - [+] BUG: piranhas walking out of water sometimes....... - [+] add startatt x-y rather than just a bracket. use text field. - [+] make teleport auto move away form lfs - [+] add minotaur
This commit is contained in:
parent
af0d8f244d
commit
11c03d71cf
4
Makefile
4
Makefile
|
@ -1,2 +1,2 @@
|
|||
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h
|
||||
gcc -Wall -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c -lncurses
|
||||
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h vault.c vault.h
|
||||
gcc -Wall -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c vault.c vault.h -lncurses
|
||||
|
|
104
defs.h
104
defs.h
|
@ -1,6 +1,8 @@
|
|||
#ifndef __DEFS_H
|
||||
#define __DEFS_H
|
||||
|
||||
|
||||
|
||||
// MACROS
|
||||
#define MAXOF(a,b) (a > b ? a : b)
|
||||
|
||||
|
@ -102,6 +104,7 @@ enum SKILLLEVEL {
|
|||
// save/load
|
||||
#define MAPDIR "data/maps"
|
||||
#define SAVEDIR "data/save"
|
||||
#define VAULTDIR "vaults"
|
||||
#define DUMMYCELLTYPE 0xabcd
|
||||
|
||||
// SPECIAL NUMBERS/CONSTANTS
|
||||
|
@ -110,10 +113,10 @@ enum SKILLLEVEL {
|
|||
#define NA (-9874)
|
||||
#define NOBODY (-1)
|
||||
#define ALLCONFERRED (-9873)
|
||||
#define PCT (65432) // must be POSITIVE
|
||||
|
||||
#define AUTO (-7654)
|
||||
|
||||
|
||||
enum GAMEMODE {
|
||||
GM_FIRST,
|
||||
GM_INIT,
|
||||
|
@ -407,8 +410,11 @@ enum LOFTYPE {
|
|||
|
||||
// Cell types
|
||||
enum CELLTYPE {
|
||||
CT_NONE = 0,
|
||||
// walls
|
||||
CT_WALL,
|
||||
CT_WALLGLASS,
|
||||
CT_WALLMETAL,
|
||||
CT_ROOMWALL,
|
||||
// empty
|
||||
CT_CORRIDOR,
|
||||
|
@ -419,12 +425,6 @@ enum CELLTYPE {
|
|||
CT_ROOM,
|
||||
};
|
||||
|
||||
enum SPECIALROOMTYPE {
|
||||
RT_NONE = 0,
|
||||
RT_FLOODED,
|
||||
};
|
||||
|
||||
|
||||
enum SPELLSCHOOL {
|
||||
SS_NONE,
|
||||
SS_DIVINE,
|
||||
|
@ -573,17 +573,24 @@ enum HABITAT {
|
|||
#define RARITYVARIANCELF (5)
|
||||
#define RARITYVARIANCEOB (10)
|
||||
|
||||
/*
|
||||
enum RARITY {
|
||||
RR_UNIQUE = 7,
|
||||
RR_NEVER = 6,
|
||||
RR_VERYRARE = 5,
|
||||
RR_RARE = 4,
|
||||
RR_UNCOMMON = 3,
|
||||
RR_COMMON = 2,
|
||||
RR_FREQUENT = 1,
|
||||
RR_UNIQUE = 6,
|
||||
RR_NEVER = 5,
|
||||
RR_VERYRARE = 4,
|
||||
RR_RARE = 3,
|
||||
RR_UNCOMMON = 2,
|
||||
RR_COMMON = 1,
|
||||
RR_NONE = 0,
|
||||
};
|
||||
|
||||
// for genericising weapons, etc
|
||||
enum GOODNESS {
|
||||
G_NA = 0,
|
||||
G_AVERAGE,
|
||||
G_GOOD,
|
||||
G_GREAT,
|
||||
G_EXCELLENT,
|
||||
};
|
||||
*/
|
||||
|
||||
enum RACECLASS {
|
||||
RC_ANY, // not actually ever defined
|
||||
|
@ -627,6 +634,7 @@ enum RACE {
|
|||
R_KOBOLD,
|
||||
R_LIZARDMAN,
|
||||
R_LURKINGHORROR,
|
||||
R_MINOTAUR,
|
||||
R_OGRE,
|
||||
R_OGRESAVAGE,
|
||||
R_OGREWARHULK,
|
||||
|
@ -1735,7 +1743,7 @@ enum FLAG {
|
|||
F_HASHIDDENNAME, // whether this object class has a hidden name
|
||||
F_IDENTIFIED, // whether this object is fully identified
|
||||
// bad flags
|
||||
F_DEEPWATER, // v0 = depth.oooooooooooo
|
||||
F_DEEPWATER, // v0 = depth.
|
||||
F_WALKDAM, // val0 = damtype, text = dam per sec
|
||||
F_WALKDAMBP, // v0 = bodypart, v1 = damtype, text = dam per sec
|
||||
// if v2 == FALLTHRU, damage falls through to lf if
|
||||
|
@ -1805,6 +1813,10 @@ enum FLAG {
|
|||
// calculation
|
||||
F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid
|
||||
F_STARTATT, // val0 = A_xxx, val0 = start bracket (ie. IQ_GENIUS)
|
||||
// if text is set, it overrides val0.
|
||||
// text can be:
|
||||
// x (single number)
|
||||
// x-y (range)
|
||||
F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will
|
||||
// start off hidden
|
||||
F_CORPSETYPE, // text field specifies what corpse obtype to leave
|
||||
|
@ -2088,7 +2100,20 @@ enum FLAG {
|
|||
F_LEVFLAG, // at level v0, this job gains flagid v1, flagval0=v2,
|
||||
// flagtext = text
|
||||
|
||||
//
|
||||
// vault flags
|
||||
F_AUTODOORS, // automatically create at least one door
|
||||
F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms
|
||||
F_VAULTATOB, // v0/1=x/y, v1=pctchance, text=obname
|
||||
F_VAULTATLF, // v0/1=x/y, v1=pctchance, text=lfname
|
||||
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_VAULTSCATTER, // v0=thingtype, v1=pctchance
|
||||
// text=x1,y1,x2,y2,mincount-maxcount,thingname
|
||||
// if maxcount is PCT, mincount is a percentage
|
||||
// of the total space.
|
||||
F_VAULTRANDOMMAP, // v0=minwidth, v1=minheight. this vault's map is
|
||||
// v0/1 can be NA.
|
||||
// just a normal random room
|
||||
F_NULL = -1
|
||||
};
|
||||
|
||||
|
@ -2325,6 +2350,46 @@ typedef struct map_s {
|
|||
struct map_s *next, *prev;
|
||||
} map_t; //////////////// remember to modify save/load for new props!!
|
||||
|
||||
#define MAXVAULTARGS 10
|
||||
|
||||
enum VAULTSTATE {
|
||||
VS_ALLOCATED,
|
||||
VS_NOID,
|
||||
VS_LOADING,
|
||||
VS_LOADINGMAP,
|
||||
VS_LOADINGLEGEND,
|
||||
VS_LOADINGFLAGS,
|
||||
};
|
||||
|
||||
enum VAULTTHING {
|
||||
VT_NONE,
|
||||
VT_OB,
|
||||
VT_LF,
|
||||
VT_CELL,
|
||||
};
|
||||
|
||||
typedef struct vlegend_s {
|
||||
char ch;
|
||||
enum VAULTTHING tt;
|
||||
char *what;
|
||||
int pct;
|
||||
struct vault_s *vault;
|
||||
struct vlegend_s *next, *prev;
|
||||
} vlegend_t;
|
||||
|
||||
typedef struct vault_s {
|
||||
char *filename;
|
||||
char *id;
|
||||
int valid;
|
||||
int state;
|
||||
char map[MAX_MAPW*MAX_MAPH];
|
||||
int mlen;
|
||||
int w,h;
|
||||
struct vlegend_s *legend, *lastlegend;
|
||||
struct vault_s *next, *prev;
|
||||
struct flagpile_s *flags;
|
||||
} vault_t;
|
||||
|
||||
typedef struct glyph_s {
|
||||
int ch;
|
||||
int colour;
|
||||
|
@ -2513,10 +2578,13 @@ typedef struct job_s {
|
|||
struct job_s *next, *prev;
|
||||
} job_t;
|
||||
|
||||
#define MAXOCNOUNS 5
|
||||
typedef struct objectclass_s {
|
||||
enum OBCLASS id;
|
||||
char *name;
|
||||
char *desc;
|
||||
char *noun[MAXOCNOUNS];
|
||||
int nnouns;
|
||||
glyph_t glyph;
|
||||
struct flagpile_s *flags;
|
||||
struct objectclass_s *next, *prev;
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
General format:
|
||||
@id:textual_name
|
||||
@map
|
||||
EITHER
|
||||
map definition
|
||||
OR
|
||||
random(minw,minh)
|
||||
@end
|
||||
@legend
|
||||
k:mon:kobold
|
||||
s:ob:50:short sword
|
||||
#:cell:stone wall
|
||||
@end
|
||||
@flags
|
||||
...
|
||||
@end
|
||||
|
||||
Legend is:
|
||||
c:type:what[:pct]
|
||||
|
||||
c = any letter
|
||||
type = ob, mon or cell
|
||||
pct = optional pct chance of appearing
|
||||
what = text of what this letter represents
|
||||
|
||||
Flags can be:
|
||||
at(x,y) type:what[:pct] // put what at position x,y
|
||||
'type' can be: ob, mon, cell
|
||||
coords can be negative ("count back from right/bottom")
|
||||
|
||||
box(x,y,x2,y2) type:what[:pct] // outline box with what
|
||||
fill(x,y,x2,y2) type:what[:pct] // filled box with what
|
||||
coords can be negative ("count back from right/bottom")
|
||||
|
||||
scatter(x,y,x2,y2) type:what:howmany[:pct] // scatter what within region
|
||||
howmany can be:
|
||||
- a number (x)
|
||||
- a range (x-y)
|
||||
- a pct of the total region cells (x%)
|
||||
coords can be negative ("count back from right/bottom")
|
||||
|
||||
|
||||
autodoors // automatically add at least one door to the edges of
|
||||
// this room.
|
||||
|
||||
autopop // automatically add obs/mons/pillars to this room
|
||||
|
||||
NOTES:
|
||||
when adding lfs/objects, "random" creates a random one.
|
||||
|
||||
|
||||
|
||||
|
6
io.c
6
io.c
|
@ -5038,8 +5038,12 @@ void drawglyph(glyph_t *g, int x, int y) {
|
|||
col = g->colour;
|
||||
}
|
||||
setcol(gamewin, col);
|
||||
//mvwprintw(gamewin, y, x, "%lc", g->ch);
|
||||
if (g->ch > 255) {
|
||||
// note: much slower
|
||||
mvwprintw(gamewin, y, x, "%lc", g->ch);
|
||||
} else {
|
||||
mvwaddch(gamewin, y, x, g->ch);
|
||||
}
|
||||
unsetcol(gamewin, col);
|
||||
}
|
||||
|
||||
|
|
55
lf.c
55
lf.c
|
@ -6875,7 +6875,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings");
|
||||
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
|
||||
|
||||
addrace(R_GIANTHILL, "hill giant", 160, 'H', C_BROWN, MT_FLESH, RC_HUMANOID);
|
||||
addrace(R_GIANTHILL, "hill giant", 160, 'H', C_GREY, MT_FLESH, RC_HUMANOID);
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 55, NA, NULL);
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL);
|
||||
|
@ -7348,6 +7348,34 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
|
||||
|
||||
|
||||
addrace(R_MINOTAUR, "minotaur", 130, 'H', C_BROWN, MT_FLESH, RC_HUMANOID);
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 62, NA, NULL);
|
||||
addflag(lastrace->flags, F_ENHANCESMELL, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HATESRACE, R_GNOLL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 6, 3, NA, NULL);
|
||||
addflag(lastrace->flags, F_ARMOURRATING, 12, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "5-7");
|
||||
addflag(lastrace->flags, F_STARTATT, A_DEX, DX_DEXTROUS, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, ST_TITANIC, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_BUTT, NA, NA, "2d4");
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_BUTT, NA, NA, "2d4");
|
||||
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "+2 heavy flail");
|
||||
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "greataxe");
|
||||
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASSKILL, SK_TRACKING, PR_EXPERT, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;");
|
||||
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "roars^a roar");
|
||||
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MORALE, 20, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
|
||||
|
||||
|
||||
addrace(R_OGRE, "ogre", 160, 'O', C_BROWN, MT_FLESH, RC_HUMANOID);
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
|
||||
|
@ -11391,7 +11419,27 @@ int rollstat(lifeform_t *lf, enum ATTRIB attr) {
|
|||
|
||||
f = hasflagval(lf->flags, F_STARTATT, attr, NA, NA, NULL);
|
||||
if (f) {
|
||||
if (strlen(f->text)) {
|
||||
int val;
|
||||
if (strchr(f->text, '-')) {
|
||||
int min,max;
|
||||
char *p;
|
||||
char buf[BUFLENSMALL];
|
||||
// text is a range
|
||||
p = readuntil(buf, f->text, '-');
|
||||
min = atoi(buf);
|
||||
p = readuntil(buf, p, '-');
|
||||
max = atoi(buf);
|
||||
val = rnd(min,max);
|
||||
} else {
|
||||
val = atoi(f->text);
|
||||
}
|
||||
lf->att[attr] = val;
|
||||
return B_FALSE;
|
||||
} else {
|
||||
bracket = f->val[1];
|
||||
}
|
||||
|
||||
} else {
|
||||
switch (attr) {
|
||||
case A_STR:
|
||||
|
@ -13686,6 +13734,11 @@ int validateraces(void) {
|
|||
printf("ERROR in race '%s' - F_HITCONFER, but no HITCONFERVALS defined.\n", r->name);
|
||||
goterror = B_TRUE;
|
||||
}
|
||||
} else if (f->id == F_STARTATT) {
|
||||
if (strlen(f->text) && (f->val[1] != NA)) {
|
||||
printf("ERROR in race '%s' - F_STARTATT has both text range and val1.", r->name);
|
||||
goterror = B_TRUE;
|
||||
}
|
||||
} else if (f->id == F_NOISETEXT) {
|
||||
if (f->val[0] == N_FLY) {
|
||||
if (!hasflag(r->flags, F_FLYING) && !hasflag(r->flags, F_LEVITATING)) {
|
||||
|
|
615
map.c
615
map.c
|
@ -12,6 +12,7 @@
|
|||
#include "map.h"
|
||||
#include "objects.h"
|
||||
#include "text.h"
|
||||
#include "vault.h"
|
||||
|
||||
extern map_t *firstmap,*lastmap;
|
||||
extern celltype_t *firstcelltype, *lastcelltype;
|
||||
|
@ -169,12 +170,6 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
|
||||
if (autogen) {
|
||||
// sometimes start off asleep in new maps
|
||||
if (!lfhasflag(lf, F_DEAF) && cansleep(lf)) {
|
||||
// TODO: base this on the time, and whether monster is nocturnal
|
||||
if (rnd(1,2) == 1) {
|
||||
addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
f = lfhasflag(lf, F_STARTHIDDENPCT);
|
||||
if (f) {
|
||||
if (rnd(1,100) <= f->val[0]) {
|
||||
|
@ -184,6 +179,12 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
|
|||
addflag(lf->flags, F_HIDING, 0, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
if (!lfhasflag(lf, F_HIDING) && !lfhasflag(lf, F_DEAF) && cansleep(lf)) {
|
||||
// TODO: base this on the time, and whether monster is nocturnal
|
||||
if (rnd(1,2) == 1) {
|
||||
addflag(lf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// appears in groups?
|
||||
|
@ -358,6 +359,134 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
// whichside should be D_ORTH
|
||||
// for now, this function will NOT include room corners
|
||||
void getroomedge(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells) {
|
||||
int x,y;
|
||||
*ncells = 0;
|
||||
if (whichside == D_N) {
|
||||
y = miny;
|
||||
for (x = minx+1; x <= maxx-1; x++) {
|
||||
retcell[*ncells] = getcellat(map, x, y);
|
||||
(*ncells)++;
|
||||
}
|
||||
} else if (whichside == D_S) {
|
||||
y = maxy;
|
||||
for (x = minx+1; x <= maxx-1; x++) {
|
||||
retcell[*ncells] = getcellat(map, x, y);
|
||||
(*ncells)++;
|
||||
}
|
||||
} else if (whichside == D_W) {
|
||||
x = minx;
|
||||
for (y = miny+1; y <= maxy-1; y++) {
|
||||
retcell[*ncells] = getcellat(map, x, y);
|
||||
(*ncells)++;
|
||||
}
|
||||
} else if (whichside == D_E) {
|
||||
x = maxx;
|
||||
for (y = miny+1; y <= maxy-1; y++) {
|
||||
retcell[*ncells] = getcellat(map, x, y);
|
||||
(*ncells)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy) {
|
||||
int i,d;
|
||||
cell_t *poss[MAXCANDIDATES], *cell[MAXCANDIDATES]; // TODO: should this be maxroomw * maxroomh ?
|
||||
int ncells = 0, npossible = 0;
|
||||
int doorsadded = 0;
|
||||
|
||||
// for each side, make list of all possible door locations
|
||||
// then pick one randomly.
|
||||
// BUT if the nearby corridor only has one exit, always
|
||||
// place a door.
|
||||
for (d = D_N; d <= D_W; d++) {
|
||||
npossible = 0;
|
||||
getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells);
|
||||
for (i = 0; i < ncells; i++) {
|
||||
cell_t *newcell;
|
||||
// is there empty space on the other side of this wall segment?
|
||||
newcell = getcellindir(cell[i], d);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
// if so, make sure there are no other adjacent doors
|
||||
doorcount = countadjcellswithflag(cell[i], F_DOOR);
|
||||
if (doorcount == 0) {
|
||||
// if there is only one way out of the adjacent empty cell, and
|
||||
// walls to either side of the potential door location, then
|
||||
// always add a door
|
||||
if ((countcellexits(newcell) == 1) && wallstoleftright(newcell, d)) {
|
||||
if (onein(2)) {
|
||||
makedoor(cell[i]);
|
||||
} else {
|
||||
setcelltype(cell[i], getemptycelltype(map->habitat));
|
||||
}
|
||||
} else {
|
||||
// otherwise mark this as a _potential_ door location.
|
||||
poss[npossible] = cell[i];
|
||||
npossible++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have potential door locations, add one somewhere along this wall.
|
||||
if (npossible > 0) {
|
||||
int sel;
|
||||
sel = rnd(0,npossible-1);
|
||||
makedoor(poss[sel]);
|
||||
doorsadded++;
|
||||
}
|
||||
} // end foreach direction
|
||||
|
||||
|
||||
if (doorsadded == 0) {
|
||||
int i,d,used[MAXDIR_ORTH],poss[MAXDIR_ORTH];
|
||||
int dodoor[MAXDIR_ORTH];
|
||||
int ndodoors = 0;
|
||||
int ndoors,nposs = 0;
|
||||
|
||||
int sel;
|
||||
//
|
||||
for (d = D_N; d <= D_W; d++) {
|
||||
used[d] = B_FALSE;
|
||||
}
|
||||
// no possible door locations - add a random number
|
||||
ndoors = rnd(1,4);
|
||||
|
||||
for (i = 0; i < ndoors; i++) {
|
||||
// find a dir we haven't already used
|
||||
nposs = 0;
|
||||
for (d = D_N; d <= D_W; d++) {
|
||||
if (!used[d]) poss[nposs++] = d;
|
||||
}
|
||||
if (nposs <= 0) {
|
||||
break;
|
||||
}
|
||||
sel = rnd(0,nposs-1);
|
||||
used[poss[sel]] = B_TRUE;
|
||||
dodoor[ndodoors++] = poss[sel];
|
||||
}
|
||||
|
||||
// actually make the doors
|
||||
for (i = 0; i < ndodoors; i++) {
|
||||
int sel;
|
||||
d = dodoor[i];
|
||||
getroomedge(map, roomid, minx, miny, maxx, maxy, d, cell, &ncells);
|
||||
sel = rnd(0,ncells-1);
|
||||
|
||||
if (onein(2)) {
|
||||
makedoor(cell[sel]);
|
||||
} else {
|
||||
setcelltype(cell[sel], getemptycelltype(map->habitat));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int cellhaslos(cell_t *c1, cell_t *dest) {
|
||||
int deltax, deltay;
|
||||
int numpixels;
|
||||
|
@ -579,6 +708,13 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
|
|||
}
|
||||
}
|
||||
|
||||
int getdoorlockdiff(int depth) {
|
||||
return 19 + depth;
|
||||
}
|
||||
int getdoorsecretdiff(int depth) {
|
||||
return 20 + (depth / 2);
|
||||
}
|
||||
|
||||
enum CELLTYPE getemptycelltype(enum HABITAT hab) {
|
||||
switch (hab) {
|
||||
case H_DUNGEON:
|
||||
|
@ -870,13 +1006,10 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
int lastdir;
|
||||
int numrooms = 0;
|
||||
int roomw[MAXROOMS],roomh[MAXROOMS];
|
||||
vault_t *roomvault[MAXROOMS];
|
||||
//int roomspecial[MAX_MAPROOMS];
|
||||
int minroomw = MIN_ROOMW;
|
||||
int minroomh = MIN_ROOMH;
|
||||
int maxroomw = MAX_ROOMW;
|
||||
int maxroomh = MAX_ROOMH;
|
||||
int bestx,besty;
|
||||
int w,h;
|
||||
//int bestx,besty;
|
||||
//int w,h;
|
||||
//int startdir,forcex,forcey,ntries;
|
||||
cell_t *cell, *c;
|
||||
object_t *o;
|
||||
|
@ -1075,40 +1208,24 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
//printf("using %d rooms\n",numrooms);
|
||||
//dblog("Adding %d rooms...\n",numrooms);
|
||||
for (i = 0; i < numrooms; i++) {
|
||||
// select random width/height
|
||||
w = rnd(minroomw, maxroomw);
|
||||
h = rnd(minroomh, maxroomh);
|
||||
|
||||
roomw[i] = w;
|
||||
roomh[i] = h;
|
||||
|
||||
if (calcroompos(map, w, h, &bestx, &besty)) {
|
||||
//printf("** couldn't make room!\n");
|
||||
} else {
|
||||
// we now have the room position - fill it in
|
||||
createroom(map, bestx,besty, w,h, i);
|
||||
|
||||
/*
|
||||
if (getrand(1,100) <= CH_SPECIALROOM) {
|
||||
int curpos;
|
||||
int roomid;
|
||||
roomid = getrandomspecialroom(wreck->mazelev[curz].type);
|
||||
for (y = besty; y <= (besty + (h-1)); y++) {
|
||||
for (x = bestx; x <= (bestx + (w-1)); x++) {
|
||||
curpos = y*MAZEW+x;
|
||||
wreck->mazelev[curz].maze[curpos].floorver = roomid;
|
||||
// maybe make it a special room
|
||||
roomvault[i] = NULL;
|
||||
if (rnd(1,100) <= getvaultchance(map)) {
|
||||
vault_t *v;
|
||||
v = getvaulttype(map);
|
||||
if (!createvault(map, i, v, &roomw[i],&roomh[i])) {
|
||||
// success
|
||||
roomvault[i] = v;
|
||||
}
|
||||
}
|
||||
roomspecial[i] = roomid;
|
||||
} else {
|
||||
roomspecial[i] = B_FALSE;
|
||||
}
|
||||
*/
|
||||
if (!roomvault[i]) {
|
||||
// just do a normal room
|
||||
createroom(map, i, NA, NA, NULL, NULL, &roomw[i],&roomh[i]);
|
||||
roomvault[i] = B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add staircases - dungeons always have an up and down stairs
|
||||
for (i = 0; i < 3; i++) {
|
||||
// add up stairs
|
||||
|
@ -1150,6 +1267,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
// add pillars & objects & monsters to rooms
|
||||
if (wantrooms && (numrooms > 0)) {
|
||||
for (i = 0; i < numrooms; i++) {
|
||||
if (!roomvault[i] || hasflag(roomvault[i]->flags, F_AUTOPOPULATE)) {
|
||||
int numobsmin,numobsmax,numobs,n;
|
||||
int maxpillars;
|
||||
|
||||
|
@ -1172,19 +1290,10 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (roomspecial[i]) {
|
||||
// chance is increased
|
||||
numobsmin = (roomw[i]*roomh[i]) / 4 ;
|
||||
numobsmax = (roomw[i]*roomh[i]) / 2 ;
|
||||
} else {
|
||||
*/
|
||||
numobsmin = 0;
|
||||
//numobsmax = MAXOF(roomw[i],roomh[i]) / 2;
|
||||
numobsmax = MAXOF(roomw[i],roomh[i]);
|
||||
|
||||
//}
|
||||
|
||||
// then objects/monsters
|
||||
if (numobsmax <= numobsmin) {
|
||||
numobs = numobsmin;
|
||||
|
@ -1225,9 +1334,9 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // end if !vault
|
||||
} // end foreach room
|
||||
} // end if wantrooms & nrooms>0
|
||||
|
||||
if (db) dblog("Finished adding objects.");
|
||||
}
|
||||
|
@ -1541,12 +1650,194 @@ void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap,
|
|||
map->beingcreated = B_FALSE;
|
||||
}
|
||||
|
||||
void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
||||
int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
|
||||
int w,h,x,y;
|
||||
int minx,miny,maxx,maxy;
|
||||
flag_t *f;
|
||||
if (!v) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
f = hasflag(v->flags, F_VAULTRANDOMMAP);
|
||||
if (f) {
|
||||
// just make a normal room to start with.
|
||||
if (createroom(map, roomid, f->val[0], f->val[1], &minx, &miny, &w, &h)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
maxx = minx + w - 1;
|
||||
maxy = miny + h - 1;
|
||||
} else {
|
||||
// get width/height from vault
|
||||
w = v->w;
|
||||
h = v->h;
|
||||
if (retw) *retw = w;
|
||||
if (reth) *reth = h;
|
||||
// find vault position
|
||||
if (calcroompos(map, w, h, &minx, &miny)) {
|
||||
dblog("** couldn't make vault room!\n");
|
||||
return B_TRUE;
|
||||
}
|
||||
maxx = minx + (w-1);
|
||||
maxy = miny + (h-1);
|
||||
|
||||
// now make it
|
||||
for (y = miny; y <= maxy; y++) {
|
||||
for (x = minx; x <= maxx; x++) {
|
||||
cell_t *cell;
|
||||
celltype_t *ct;
|
||||
cell = getcellat(map, x, y);
|
||||
|
||||
// set cell type
|
||||
ct = getvaultcelltype(v, x-minx,y-miny);
|
||||
setcelltype(cell, ct ? ct->id : getemptycelltype(cell->map->habitat));
|
||||
// set roomid
|
||||
cell->roomid = roomid;
|
||||
// add objects
|
||||
addvaultcellcontents(cell, v, x-minx,y-miny);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add other stuff to the vault
|
||||
addvaultcontents(map, v, minx, miny, maxx, maxy);
|
||||
|
||||
// auto add doors if required
|
||||
if (hasflag(v->flags, F_AUTODOORS)) {
|
||||
autodoors(map, roomid, minx, miny, maxx, maxy);
|
||||
}
|
||||
|
||||
linkdoors(map, roomid, minx, miny, maxx,maxy);
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// make sure doors in a given room link up to the rest of the map.
|
||||
void linkdoors(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
|
||||
int x,y,i;
|
||||
cell_t *poss[MAXCANDIDATES],*c;
|
||||
int nposs = 0;
|
||||
int db = B_FALSE;
|
||||
|
||||
if (db) dblog("linkdoors for roomid %d", roomid);
|
||||
|
||||
// find all doors // TODO: ...or "exits"
|
||||
for (y = miny; y <= maxy; y++) {
|
||||
for (x = minx; x <= maxx; x++) {
|
||||
c = getcellat(m, x, y);
|
||||
if (!c) continue;
|
||||
|
||||
if (hasobwithflag(c->obpile, F_DOOR)) {
|
||||
if (db) dblog("found door at %d,%d",x,y);
|
||||
poss[nposs++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (db) dblog("%d doors found.",nposs);
|
||||
|
||||
// for each door, make sure it links to at least one cell which isn't
|
||||
// part of this room
|
||||
for (i = 0; i < nposs; i++) {
|
||||
int d;
|
||||
int ncorridors = 0;
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
c = getcellindir(poss[i], d);
|
||||
if (c && cellwalkable(NULL, c, NULL) && (c->roomid != roomid)) {
|
||||
ncorridors++;
|
||||
}
|
||||
}
|
||||
if (db) dblog("Door #%d leads to %d corridors. ",i, ncorridors);
|
||||
|
||||
// no corridors?
|
||||
if (ncorridors == 0) {
|
||||
int poss2[MAXCANDIDATES],nposs2;
|
||||
int dist[MAXDIR_ORTH];
|
||||
int bestdist = 999;
|
||||
if (db) dblog(" Need to link.");
|
||||
// link it. starting from the door, count the number of cells in
|
||||
// each direction until we hit an empty (walkable) cell not of this room.
|
||||
// if we hit a cell of this roomid, mark this dir as invalid.
|
||||
for (d = D_N; d <= D_W; d++) {
|
||||
dist[d] = 0;
|
||||
c = getcellindir(poss[i], d);
|
||||
while (c) {
|
||||
dist[d]++;
|
||||
if (c->roomid == roomid) {
|
||||
// mark dir as invalid
|
||||
dist[d] = 999;
|
||||
break;
|
||||
} else if (cellwalkable(NULL, c, NULL)) {
|
||||
// walkable and not in this vault. finished.
|
||||
break;
|
||||
}
|
||||
// check next cell
|
||||
c = getcellindir(c, d); // getting the same cell!
|
||||
}
|
||||
if (dist[d] < bestdist) bestdist = dist[d];
|
||||
}
|
||||
|
||||
if (bestdist != 999) {
|
||||
int whichway,sel;
|
||||
// now pick the shortest one
|
||||
// get list of all the maximums and randomly tie-break
|
||||
nposs2 = 0;
|
||||
for (d = D_N; d <= D_W; d++) {
|
||||
if (dist[d] == bestdist) {
|
||||
poss2[nposs2++] = d;
|
||||
}
|
||||
}
|
||||
sel = rnd(0,nposs2-1);
|
||||
whichway = poss2[sel];
|
||||
|
||||
// now create a path
|
||||
if (db) dblog(" Linking %s (distance %d).", getdirname(whichway), bestdist);
|
||||
c = getcellindir(poss[i], whichway);
|
||||
while (c && !cellwalkable(NULL, c, NULL)) {
|
||||
setcelltype(c, getemptycelltype(c->map->habitat));
|
||||
c = getcellindir(poss[i], whichway);
|
||||
}
|
||||
}
|
||||
} // end if ncorridors = 0
|
||||
} // end for each door
|
||||
if (db) dblog("linkdoors complete.");
|
||||
}
|
||||
|
||||
// room w/h are returned in *w and *h if given.
|
||||
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth) {
|
||||
int x,y;
|
||||
int poss[MAXOF(MAX_MAPW,MAX_MAPH)];
|
||||
int npossible;
|
||||
cell_t *cell, *newcell;
|
||||
cell_t *cell;
|
||||
int minx,miny;
|
||||
int maxx,maxy;
|
||||
int w,h;
|
||||
int minroomw = MIN_ROOMW;
|
||||
int minroomh = MIN_ROOMH;
|
||||
int maxroomw = MAX_ROOMW;
|
||||
int maxroomh = MAX_ROOMH;
|
||||
|
||||
if (overrideminw != NA) {
|
||||
minroomw = overrideminw;
|
||||
}
|
||||
if (overrideminh != NA) {
|
||||
minroomh = overrideminh;
|
||||
}
|
||||
|
||||
// select random width/height
|
||||
w = rnd(minroomw, maxroomw);
|
||||
h = rnd(minroomh, maxroomh);
|
||||
|
||||
if (retw) *retw = w;
|
||||
if (reth) *reth = h;
|
||||
|
||||
// find room position
|
||||
if (calcroompos(map, w, h, &minx, &miny)) {
|
||||
dblog("** couldn't make room!\n");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (retx) *retx = minx;
|
||||
if (rety) *rety = miny;
|
||||
|
||||
// we now have the room position - fill it in
|
||||
|
||||
//printf("trying to create room at (%d,%d) w=%d,h=%d\n", minx, miny, w, h);
|
||||
|
||||
|
@ -1556,7 +1847,6 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
for (y = miny; y <= maxy; y++) {
|
||||
for (x = minx; x <= maxx; x++) {
|
||||
cell = getcellat(map, x, y);
|
||||
|
||||
// make it a border or room
|
||||
if ((y == miny) || (y == maxy) ||
|
||||
(x == minx) || (x == maxx)) {
|
||||
|
@ -1570,171 +1860,12 @@ void createroom(map_t *map, int minx, int miny, int w, int h, int roomid) {
|
|||
}
|
||||
}
|
||||
|
||||
// add doors
|
||||
autodoors(map, roomid, minx, miny, maxx, maxy);
|
||||
|
||||
// for each side, make list of all possible door locations
|
||||
// then pick one randomly.
|
||||
// BUT if the nearby corridor only has one exit, always
|
||||
// place a door.
|
||||
|
||||
// N
|
||||
npossible = 0;
|
||||
y = miny;
|
||||
for (x = minx+1; x <= maxx-1; x++) {
|
||||
cell = getcellat(map, x, y);
|
||||
newcell = getcellindir(cell, D_N);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
|
||||
doorcount = countadjcellswithflag(cell, F_DOOR);
|
||||
|
||||
if (doorcount == 0) {
|
||||
if ((countcellexits(newcell) == 1) &&
|
||||
(iswallindir(newcell,D_E)) &&
|
||||
(iswallindir(newcell,D_W))) { // always add door
|
||||
makedoor(cell);
|
||||
} else {
|
||||
poss[npossible] = x;
|
||||
npossible++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
if (npossible > 0) {
|
||||
int sel = rand() % npossible;
|
||||
//printf("adding N door at %d\n",poss[sel]);
|
||||
cell = getcellat(map, poss[sel], y);
|
||||
makedoor(cell);
|
||||
}
|
||||
|
||||
|
||||
// S
|
||||
npossible = 0;
|
||||
y = maxy;
|
||||
for (x = minx+1; x <= maxx-1; x++) {
|
||||
cell = getcellat(map, x, y);
|
||||
newcell = getcellindir(cell, D_S);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
|
||||
doorcount = countadjcellswithflag(cell, F_DOOR);
|
||||
|
||||
if (doorcount == 0) {
|
||||
if ((countcellexits(newcell) == 1) &&
|
||||
(iswallindir(newcell,D_E)) &&
|
||||
(iswallindir(newcell,D_W))) { // always add door
|
||||
makedoor(cell);
|
||||
} else {
|
||||
poss[npossible] = x;
|
||||
npossible++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (npossible > 0) {
|
||||
int sel = rand() % npossible;
|
||||
//printf("adding S door at %d\n",poss[sel]);
|
||||
cell = getcellat(map, poss[sel], y);
|
||||
makedoor(cell);
|
||||
}
|
||||
|
||||
|
||||
// W
|
||||
npossible = 0;
|
||||
x = minx;
|
||||
for (y = miny+1; y <= maxy-1; y++) {
|
||||
cell = getcellat(map, x, y);
|
||||
newcell = getcellindir(cell, D_W);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
doorcount = countadjcellswithflag(cell, F_DOOR);
|
||||
if (doorcount == 0) {
|
||||
if ((countcellexits(newcell) == 1) &&
|
||||
(iswallindir(newcell,D_N)) &&
|
||||
(iswallindir(newcell,D_S))) { // always add door
|
||||
makedoor(cell);
|
||||
} else {
|
||||
poss[npossible] = y;
|
||||
npossible++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (npossible > 0) {
|
||||
int sel = rand() % npossible;
|
||||
//printf("adding W door at %d\n",poss[sel]);
|
||||
cell = getcellat(map, x, poss[sel]);
|
||||
makedoor(cell);
|
||||
}
|
||||
|
||||
|
||||
// E
|
||||
npossible = 0;
|
||||
x = maxx;
|
||||
for (y = miny+1; y <= maxy-1; y++) {
|
||||
cell = getcellat(map, x, y);
|
||||
newcell = getcellindir(cell, D_E);
|
||||
if (newcell && !newcell->type->solid) {
|
||||
int doorcount;
|
||||
doorcount = countadjcellswithflag(cell, F_DOOR);
|
||||
if (doorcount == 0) {
|
||||
if ((countcellexits(newcell) == 1) &&
|
||||
(iswallindir(newcell,D_N)) &&
|
||||
(iswallindir(newcell,D_S))) { // always add door
|
||||
makedoor(cell);
|
||||
} else {
|
||||
poss[npossible] = y;
|
||||
npossible++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (npossible > 0) {
|
||||
int sel = rand() % npossible;
|
||||
//printf("adding E door at %d\n",poss[sel]);
|
||||
cell = getcellat(map, x, poss[sel]);
|
||||
makedoor(cell);
|
||||
}
|
||||
|
||||
// maybe make it a special room
|
||||
if (rnd(1,100) <= getspecialroomchance(map)) {
|
||||
enum SPECIALROOMTYPE rt;
|
||||
rt = getspecialroomtype(map);
|
||||
if (rt == RT_FLOODED) {
|
||||
int sx,sy,ex,ey;
|
||||
char wtype[BUFLEN];
|
||||
switch (rnd(1,2)) {
|
||||
case 1: strcpy(wtype, "deep water"); break;
|
||||
case 2: strcpy(wtype, "shallow water"); break;
|
||||
}
|
||||
switch (rnd(1,2)) {
|
||||
case 1: // entire room flooded
|
||||
sx = minx+1;
|
||||
sy = miny+1;
|
||||
ex = maxx-1;
|
||||
ey = maxy-1;
|
||||
break;
|
||||
case 2: // small walkway around the edge
|
||||
sx = minx+2;
|
||||
sy = miny+2;
|
||||
ex = maxx-2;
|
||||
ey = maxy-2;
|
||||
if (sx > ex) sx = ex;
|
||||
if (sy > ey) sy = ey;
|
||||
break;
|
||||
}
|
||||
for (y = sy; y <= ey; y++) {
|
||||
for (x = sx; x <= ex; x++) {
|
||||
cell = getcellat(map, x, y);
|
||||
addob(cell->obpile, wtype);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int dirtox(int dt, int dir) {
|
||||
if (dt == DT_ORTH) {
|
||||
|
@ -1897,6 +2028,14 @@ celltype_t *findcelltype(enum CELLTYPE cid) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
celltype_t *findcelltypebyname(char *name) {
|
||||
celltype_t *ct;
|
||||
for (ct = firstcelltype ; ct ; ct = ct->next) {
|
||||
if (!strcmp(ct->name, name)) return ct;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
map_t *findmap(int mid) {
|
||||
map_t *m;
|
||||
for (m = firstmap ; m ; m = m->next) {
|
||||
|
@ -2199,10 +2338,10 @@ int getobchance(int habitat) {
|
|||
return 0;
|
||||
}
|
||||
// chance that a room is a 'special' one
|
||||
int getspecialroomchance(map_t *m) {
|
||||
int getvaultchance(map_t *m) {
|
||||
switch (m->habitat) {
|
||||
case H_DUNGEON:
|
||||
return 5;
|
||||
return 10;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -2210,17 +2349,6 @@ int getspecialroomchance(map_t *m) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
enum SPECIALROOMTYPE getspecialroomtype(map_t *m) {
|
||||
if (m->habitat == H_DUNGEON) {
|
||||
/*
|
||||
switch (rnd(1,1)) {
|
||||
|
||||
}
|
||||
*/
|
||||
return RT_FLOODED;
|
||||
}
|
||||
return RT_NONE;
|
||||
}
|
||||
|
||||
|
||||
// chance of each empty cell in a map has of getting an object/monster
|
||||
|
@ -2844,7 +2972,7 @@ void makedoor(cell_t *cell) {
|
|||
chance = rolldie(1,6) - (m->depth / 10);
|
||||
|
||||
if (chance <= 1) {
|
||||
addflag(o->flags, F_LOCKED, B_TRUE, 19 + (m->depth), NA, NULL);
|
||||
addflag(o->flags, F_LOCKED, B_TRUE, getdoorlockdiff(m->depth), NA, NULL);
|
||||
}
|
||||
|
||||
// make it secret?
|
||||
|
@ -2855,7 +2983,7 @@ void makedoor(cell_t *cell) {
|
|||
// l10 = 25
|
||||
// l20 = 30
|
||||
if (chance <= 1) {
|
||||
addflag(o->flags, F_SECRET, 20 + (m->depth / 2), NA, NA, NULL);
|
||||
addflag(o->flags, F_SECRET, getdoorsecretdiff(m->depth), NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2960,6 +3088,9 @@ void setcelltype(cell_t *cell, int id) {
|
|||
cell->type = findcelltype(id);
|
||||
assert(cell->type);
|
||||
cell->roomid = 0;
|
||||
if ((gamemode == GM_GAMESTARTED) && haslos(player, cell)) {
|
||||
needredraw = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2989,3 +3120,19 @@ void updateknowncells(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
int wallstoleftright(cell_t *c, int dir) {
|
||||
int d1,d2;
|
||||
switch (dir) {
|
||||
case D_N:
|
||||
case D_S:
|
||||
d1 = D_E; d2 = D_W; break;
|
||||
case D_E:
|
||||
case D_W:
|
||||
d1 = D_N; d2 = D_S; break;
|
||||
}
|
||||
if (iswallindir(c,d1) && iswallindir(c,d2)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
|
14
map.h
14
map.h
|
@ -6,15 +6,19 @@ map_t *addmap(void);
|
|||
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded);
|
||||
object_t *addrandomob(cell_t *c);
|
||||
int addrandomthing(cell_t *c, int obchance, int *nadded);
|
||||
void autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy);
|
||||
int cellhaslos(cell_t *c1, cell_t *dest);
|
||||
cell_t *getcellat(map_t *map, int x, int y);
|
||||
int getcelldist(cell_t *src, cell_t *dst);
|
||||
int getcelldistorth(cell_t *src, cell_t *dst);
|
||||
void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer);
|
||||
int getdoorlockdiff(int depth);
|
||||
int getdoorsecretdiff(int depth);
|
||||
enum CELLTYPE getemptycelltype(enum HABITAT hab);
|
||||
enum CELLTYPE getwallcelltype(enum HABITAT hab);
|
||||
flag_t *getmapcoords(map_t *m, int *x, int *y);
|
||||
int getmapdifficulty(map_t *m);
|
||||
void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells);
|
||||
object_t *gettopobject(cell_t *where);
|
||||
void calclight(map_t *map);
|
||||
int calcroompos(map_t *map, int w, int h, int *bx, int *by);
|
||||
|
@ -24,13 +28,15 @@ int countcellexits(cell_t *cell);
|
|||
void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir);
|
||||
void createforest(map_t *map, int depth, map_t *parentmap, int exitdir);
|
||||
void createmap(map_t *map, int depth, int region, int habitat, map_t *parentmap, int exitdir);
|
||||
void createroom(map_t *map, int minx, int miny, int w, int h, int roomid);
|
||||
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, 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 dirtoy(int dt, int dir);
|
||||
void dumpmap(map_t *map);
|
||||
void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre);
|
||||
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 *findcelltypebyname(char *name);
|
||||
map_t *findmap(int mid);
|
||||
map_t *findmapofdepth(int depth);
|
||||
cell_t *findmapentrypoint(map_t *m, int side, lifeform_t *lf);
|
||||
|
@ -41,8 +47,8 @@ void forgetcells(map_t *map, int amt);
|
|||
cell_t *getcellindir(cell_t *cell, int dir);
|
||||
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
|
||||
int getobchance(int habitat);
|
||||
int getspecialroomchance(map_t *m);
|
||||
enum SPECIALROOMTYPE getspecialroomtype(map_t *m);
|
||||
int getvaultchance(map_t *m);
|
||||
char getvaultchar(vault_t *v, int x, int y);
|
||||
int getthingchance(int habitat);
|
||||
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
|
||||
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob);
|
||||
|
@ -70,6 +76,7 @@ int isnewcellok(cell_t *cell, char *err);
|
|||
int isonmap(map_t *map, int x, int y);
|
||||
int isoutdoors(map_t *m);
|
||||
int iswallindir(cell_t *cell, int dir);
|
||||
void linkdoors(map_t *m, int roomid, int minx, int miny, int maxx, int maxy);
|
||||
int linkstairs(object_t *o);
|
||||
void makedoor(cell_t *cell);
|
||||
void makelit(cell_t *c, enum LIGHTLEV how, int howlong);
|
||||
|
@ -77,3 +84,4 @@ void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);
|
|||
void setcellknown(cell_t *cell, int forcelev);
|
||||
void setcelltype(cell_t *cell, int id);
|
||||
void updateknowncells(void);
|
||||
int wallstoleftright(cell_t *c, int dir);
|
||||
|
|
58
move.c
58
move.c
|
@ -143,6 +143,16 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
|
|||
|
||||
// obvious things that you can see
|
||||
if (!onlyifknown || (haslos(lf, cell) && !lfhasflag(lf, F_UNDEAD))) {
|
||||
// water needing creature out of water?
|
||||
if (lfhasflag(lf, F_NEEDSWATER)) {
|
||||
if (!hasobwithflag(cell->obpile, F_DEEPWATER)) {
|
||||
if (error) {
|
||||
*error = E_DANGEROUS;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
for (o = cell->obpile->first ; o ; o = o->next) {
|
||||
f = hasflag(o->flags, F_DEEPWATER);
|
||||
if (f) {
|
||||
|
@ -156,14 +166,6 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
|
|||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// water needing creature out of water?
|
||||
if (lfhasflag(lf, F_NEEDSWATER)) {
|
||||
if (error) {
|
||||
*error = E_DANGEROUS;
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
f = hasflag(o->flags, F_WALKDAM);
|
||||
if (f) {
|
||||
|
@ -566,7 +568,6 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
|
|||
char newlfname[BUFLEN];
|
||||
int seen;
|
||||
int mightfall = B_TRUE;
|
||||
cell_t *newcell;
|
||||
lifeform_t *newlf;
|
||||
|
||||
// calculate chance of falling
|
||||
|
@ -600,6 +601,9 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
|
|||
trymove(lf, dir, B_FALSE);
|
||||
}
|
||||
if (reason != E_OK) {
|
||||
char buf[BUFLEN];
|
||||
cell_t *newcell;
|
||||
newcell = getcellindir(lf->cell, dir);
|
||||
// failed to move
|
||||
switch (reason) {
|
||||
case E_OFFMAP:
|
||||
|
@ -611,8 +615,10 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
|
|||
}
|
||||
// fall through
|
||||
case E_WALLINWAY:
|
||||
if (seen) msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s");
|
||||
losehp(lf, rnd(1,6), DT_BASH, pusher, "slamming into a wall");
|
||||
if (seen) msg("%s slam%s into a %s!",lfname,isplayer(lf) ? "" : "s",
|
||||
newcell ? newcell->type->name : "wall");
|
||||
sprintf(buf, "slamming into a %s", newcell ? newcell->type->name : "wall");
|
||||
losehp(lf, rnd(1,6), DT_BASH, pusher, buf);
|
||||
// stop moving
|
||||
i = howfar;
|
||||
// don't fall
|
||||
|
@ -1313,7 +1319,11 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
if (amt < 0) amt = 0;
|
||||
|
||||
if (lf && isplayer(lf)) {
|
||||
msg("You yank on the door but it holds fast.");
|
||||
if (amt > 0) {
|
||||
msg("The door moves slightly but seems jammed.");
|
||||
} else {
|
||||
msg("The door is jammed.");
|
||||
}
|
||||
}
|
||||
// loosen a bit
|
||||
if (amt) {
|
||||
|
@ -1758,11 +1768,15 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
|
|||
|
||||
// can't teleport on top of something else
|
||||
if (c->lf) {
|
||||
// go somewhere nearby
|
||||
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
if (!c) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You feel a wrenching sensation.");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isplayer(lf) && cansee(player, lf)) {
|
||||
getlfname(lf, buf);
|
||||
|
@ -1953,25 +1967,31 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
// otherwise fall through...
|
||||
case E_WALLINWAY:
|
||||
if (isplayer(lf)) {
|
||||
msg("Ouch! You %s into a wall.", getmoveverb(lf));
|
||||
msg("Ouch! You %s into a %s.", getmoveverb(lf),
|
||||
cell ? cell->type->name : "wall");
|
||||
} else if (cansee(player, lf)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s %ss into a wall.", buf, getmoveverb(lf));
|
||||
msg("%s %ss into a %s.", buf, getmoveverb(lf),
|
||||
cell ? cell->type->name : "wall");
|
||||
}
|
||||
//if (isblind(lf) || !haslos(lf, cell)) {
|
||||
if (!haslos(lf, cell)) {
|
||||
if (!cell || !haslos(lf, cell)) {
|
||||
if (isplayer(lf)) {
|
||||
// only take damage if we didn't know about this
|
||||
if (!cell->known || isdrunk(lf)) {
|
||||
sprintf(buf, "%sing into a wall", getmoveverb(lf));
|
||||
if ((cell && !cell->known) || isdrunk(lf)) {
|
||||
sprintf(buf, "%sing into a %s", getmoveverb(lf),
|
||||
cell ? cell->type->name : "wall");
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
if (cell) {
|
||||
// we now know there is a wall there.
|
||||
setcellknown(cell, B_FALSE);
|
||||
}
|
||||
|
||||
if (onpurpose) taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
} else {
|
||||
sprintf(buf, "%sing into a wall", getmoveverb(lf));
|
||||
sprintf(buf, "%sing into a %s", getmoveverb(lf),
|
||||
cell ? cell->type->name : "wall");
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
if (onpurpose) taketime(lf, getmovespeed(lf));
|
||||
}
|
||||
|
@ -1997,7 +2017,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
|
|||
} else {
|
||||
if (cansee(player, lf)) {
|
||||
getlfname(lf, buf);
|
||||
msg("%s %ss into a wall.", buf, getmoveverb(lf));
|
||||
msg("%s %ss into a door.", buf, getmoveverb(lf));
|
||||
}
|
||||
sprintf(buf, "%sing into a door", getmoveverb(lf));
|
||||
losehp(lf, 1, DT_BASH, NULL, buf);
|
||||
|
|
26
nexus.c
26
nexus.c
|
@ -17,6 +17,7 @@
|
|||
#include "objects.h"
|
||||
#include "save.h"
|
||||
#include "text.h"
|
||||
#include "vault.h"
|
||||
|
||||
material_t *material = NULL,*lastmaterial = NULL;
|
||||
objectclass_t *objectclass = NULL,*lastobjectclass = NULL;
|
||||
|
@ -33,6 +34,8 @@ map_t *firstmap = NULL,*lastmap = NULL;
|
|||
knowledge_t *knowledge = NULL, *lastknowledge = NULL;
|
||||
hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
|
||||
|
||||
extern vault_t *firstvault;
|
||||
|
||||
glyph_t playerglyph,tempglyph;
|
||||
|
||||
double startticks,lastticks;
|
||||
|
@ -86,6 +89,7 @@ int main(int argc, char **argv) {
|
|||
FILE *playerfile = NULL;
|
||||
int x,y;
|
||||
cell_t *c;
|
||||
vault_t *v;
|
||||
|
||||
atexit(cleanup);
|
||||
|
||||
|
@ -117,11 +121,11 @@ int main(int argc, char **argv) {
|
|||
// init graphics
|
||||
initgfx();
|
||||
|
||||
// if no maps, make the initial level
|
||||
if (!firstmap) {
|
||||
newworld = B_TRUE;
|
||||
addmap();
|
||||
createmap(firstmap, 1, RG_FIRSTDUNGEON, H_DUNGEON, NULL, D_NONE);
|
||||
// warn about vault problems.
|
||||
for (v = firstvault ; v ; v = v->next) {
|
||||
if (!v->valid) {
|
||||
msg("warning: invalid vaultfile '%s'",v->filename); more();
|
||||
}
|
||||
}
|
||||
|
||||
if (!knowledge) {
|
||||
|
@ -169,6 +173,13 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
// if no maps (ie. ALWAYS now that maps aren't persistent),
|
||||
// make the initial level
|
||||
if (!firstmap) {
|
||||
newworld = B_TRUE;
|
||||
addmap();
|
||||
createmap(firstmap, 1, RG_FIRSTDUNGEON, H_DUNGEON, NULL, D_NONE);
|
||||
}
|
||||
|
||||
// find staircase
|
||||
where = findobinmap(firstmap, OT_STAIRSUP);
|
||||
|
@ -740,6 +751,8 @@ int init(void) {
|
|||
|
||||
// cell types
|
||||
addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE);
|
||||
addcelltype(CT_WALLGLASS, "glass wall", '#', C_CYAN, B_SOLID, B_TRANS, MT_GLASS);
|
||||
addcelltype(CT_WALLMETAL, "metal wall", '#', C_WHITE, B_SOLID, B_OPAQUE, MT_METAL);
|
||||
addcelltype(CT_ROOMWALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE);
|
||||
addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
|
||||
addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE);
|
||||
|
@ -759,6 +772,9 @@ int init(void) {
|
|||
logfile = fopen("log.txt","wt");
|
||||
fprintf(logfile, "\n\n\n====== NEW LOGFILE ====\n");
|
||||
|
||||
// load in vaults
|
||||
loadvaults();
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
|
483
objects.c
483
objects.c
|
@ -73,6 +73,7 @@ enum OBCLASS sortorder[] = {
|
|||
OC_ROCK,
|
||||
OC_FLORA,
|
||||
OC_DFEATURE,
|
||||
OC_TRAP,
|
||||
OC_MISC,
|
||||
// omitting OC_SPELL and OC_JUMP because it shouldn't ever be displayed
|
||||
OC_NULL
|
||||
|
@ -370,6 +371,7 @@ objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int gl
|
|||
// props
|
||||
a->id = id;
|
||||
a->name = strdup(name);
|
||||
a->nnouns = 0;
|
||||
a->desc = strdup(desc);
|
||||
a->glyph.ch = glyph;
|
||||
a->glyph.colour = glyphcolour;
|
||||
|
@ -378,6 +380,12 @@ objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int gl
|
|||
return a;
|
||||
}
|
||||
|
||||
void addocnoun(objectclass_t *oc, char *text) {
|
||||
assert (oc->nnouns < MAXOCNOUNS);
|
||||
oc->noun[oc->nnouns] = strdup(text);
|
||||
oc->nnouns++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// create a new object, stacking ok
|
||||
|
@ -402,17 +410,27 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
char *localname;
|
||||
int wantblessed = B_UNCURSED;
|
||||
race_t *corpserace = NULL;
|
||||
int dorandombrand = B_FALSE;
|
||||
brand_t *wantbrand = NULL;
|
||||
brand_t *br;
|
||||
obmod_t *om;
|
||||
obmod_t *wantom[MAXOBMODS];
|
||||
int nom = 0;
|
||||
int n;
|
||||
int bookcontents = -1;
|
||||
int wantrarity = RR_NONE;
|
||||
int wantgoodness = G_NA;
|
||||
int donesomething;
|
||||
object_t *addedob[MAXPILEOBS];
|
||||
int nadded = 0;
|
||||
// for doors
|
||||
enum FLAG doorflag[5];
|
||||
int ndoorflags = 0;
|
||||
|
||||
addedob[0] = NULL; // just in case we don't add any
|
||||
|
||||
localname = strdup(name);
|
||||
|
||||
|
||||
// check for premods. eg. "flaming xxx" "frozen xxx" etc
|
||||
for (om = firstobmod ; om ; om = om->next) {
|
||||
if (db) dblog("DB: checking for '%s' in '%s'",om->prefix, localname);
|
||||
|
@ -431,6 +449,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
|
||||
if (where->owner && hasflag(where->owner->flags, F_NOPACK)) {
|
||||
if (db) dblog("error giving ob '%s' - owner isn't allowed to carry objects!", name);
|
||||
nretobs = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -485,23 +504,94 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
howmany = 1;
|
||||
}
|
||||
|
||||
// new objects after the game starts have unknown
|
||||
// blessed/cursed status, so we can never stack them
|
||||
// if (gamestarted && !hasflag(player->flags, F_DETECTAURAS)) {
|
||||
if (strstr(p, "blessed") || strstr(p, "holy water")) {
|
||||
|
||||
// handle prefixes. strip them off as we go.
|
||||
donesomething = B_TRUE;
|
||||
while (donesomething) {
|
||||
donesomething = B_FALSE;
|
||||
if (strstarts(p, "blessed ")) {
|
||||
if (db) dblog("DB: ob is blessed (%s)",p);
|
||||
wantblessed = B_BLESSED;
|
||||
//canstack = B_FALSE;
|
||||
} else if (strstr(p, "uncursed")) {
|
||||
p += strlen("blessed ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "uncursed ")) {
|
||||
if (db) dblog("DB: ob is uncursed (%s)",p);
|
||||
wantblessed = B_UNCURSED;
|
||||
} else if (strstr(p, "cursed") || strstr(p, "incompetence")) {
|
||||
p += strlen("uncursed ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "cursed ")) {
|
||||
if (db) dblog("DB: ob is cursed (%s)",p);
|
||||
wantblessed = B_CURSED;
|
||||
//canstack = B_FALSE;
|
||||
p += strlen("cursed ");
|
||||
donesomething = B_TRUE;
|
||||
// door flags
|
||||
} else if (strstarts(p, "locked ")) {
|
||||
doorflag[ndoorflags++] = F_LOCKED;
|
||||
p += strlen("locked ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "jammed ")) {
|
||||
doorflag[ndoorflags++] = F_JAMMED;
|
||||
p += strlen("jammed ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "secret ")) {
|
||||
doorflag[ndoorflags++] = F_SECRET;
|
||||
p += strlen("secret ");
|
||||
donesomething = B_TRUE;
|
||||
// rarity
|
||||
} else if (strstarts(p, "common ")) {
|
||||
wantrarity = RR_COMMON;
|
||||
p += strlen("common ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "uncommon ")) {
|
||||
wantrarity = RR_UNCOMMON;
|
||||
p += strlen("uncommon ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "rare ")) {
|
||||
wantrarity = RR_RARE;
|
||||
p += strlen("rare ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "very rare ")) {
|
||||
wantrarity = RR_VERYRARE;
|
||||
p += strlen("very rare ");
|
||||
donesomething = B_TRUE;
|
||||
// weapon "goodness"
|
||||
} else if (strstarts(p, "average ")) {
|
||||
wantgoodness = G_AVERAGE;
|
||||
p += strlen("average ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "good ")) {
|
||||
wantgoodness = G_GOOD;
|
||||
if (onein(4)) wantblessed = B_BLESSED;
|
||||
p += strlen("good ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "great ")) {
|
||||
wantgoodness = G_GREAT;
|
||||
if (onein(3)) wantblessed = B_BLESSED;
|
||||
if (onein(10)) dorandombrand = B_TRUE;
|
||||
p += strlen("great ");
|
||||
donesomething = B_TRUE;
|
||||
} else if (strstarts(p, "excellent ")) {
|
||||
wantgoodness = G_EXCELLENT;
|
||||
if (onein(2)) wantblessed = B_BLESSED;
|
||||
if (onein(4)) dorandombrand = B_TRUE;
|
||||
p += strlen("excellent ");
|
||||
donesomething = B_TRUE;
|
||||
// brands
|
||||
} else if (strstarts(p, "branded ")) {
|
||||
dorandombrand = B_TRUE;
|
||||
p += strlen("branded ");
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
if (strstr(p, "holy water") || strstr(p, "incompetence")) {
|
||||
if (db) dblog("DB: ob is blessed (%s)",p);
|
||||
wantblessed = B_BLESSED;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// handle special object names
|
||||
////////////////////////////////////
|
||||
if (strstr(p, "corpse")) {
|
||||
int len;
|
||||
char racename[BUFLEN];
|
||||
|
@ -556,8 +646,41 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
}
|
||||
}
|
||||
ot = findot(OT_MANUAL);
|
||||
////////////////////////////////////
|
||||
// also handle generic names
|
||||
////////////////////////////////////
|
||||
} else {
|
||||
// make sure we can find the requested object type
|
||||
objectclass_t *oc;
|
||||
char tempname[BUFLEN];
|
||||
int found = B_FALSE;
|
||||
|
||||
// check for things like "weapon" or "random ring"
|
||||
for (oc = objectclass; oc ; oc = oc->next) {
|
||||
int i;
|
||||
int matched = B_FALSE;
|
||||
for (i = 0; i < oc->nnouns; i++) {
|
||||
sprintf(tempname, "random %s", oc->noun[i]);
|
||||
if (strstarts(p, tempname) || streq(p, oc->noun[i])) {
|
||||
matched = B_TRUE;
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
int minrarity,maxrarity;
|
||||
// want a specific rarity?
|
||||
rrtorarity(wantrarity, &minrarity, &maxrarity);
|
||||
|
||||
ot = getrandomobofclass(oc->id, minrarity, maxrarity);
|
||||
if (ot) {
|
||||
found = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// look up the object name
|
||||
if (db) dblog("DB: Looking for object name '%s'", p );
|
||||
ot = findotn(p);
|
||||
if (!ot) {
|
||||
|
@ -566,8 +689,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (db) dblog("DB: FOUND: ot->name = '%s'", ot->name );
|
||||
|
||||
// we now have the objecttype.
|
||||
|
||||
// override blessed status from flags...
|
||||
f = hasflag(ot->flags, F_STARTBLESSED);
|
||||
if (f) {
|
||||
|
@ -576,11 +702,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
|
||||
// don't give nopickup objects to lifeforms
|
||||
if (hasflag(ot->flags, F_NOPICKUP) && where->owner) {
|
||||
nretobs = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ot->obclass->id == OC_SPELL) {
|
||||
if (db) dblog("DB: Cannot give a spell object! object name '%s'", p );
|
||||
nretobs = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -595,6 +723,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
// does this unique ob already exist?
|
||||
if (obexists(ot->id)) {
|
||||
if (db) dblog("DB: Unique ob %s already exists!", p );
|
||||
nretobs = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -615,10 +744,22 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
// does the pile already contain one?
|
||||
existob = canstacknewot(where, ot);
|
||||
if (existob) {
|
||||
int n,found = B_FALSE;
|
||||
if (db) dblog("DB: STACK FOUND (%d x %s). Adding %d obs to existing stack.",existob->amt, existob->type->name, howmany);
|
||||
existob->amt++;
|
||||
added = B_TRUE;
|
||||
o = existob;
|
||||
|
||||
// if this isn't already in our list of added obs, add it
|
||||
for (n = 0; n < nadded; n++) {
|
||||
if (addedob[n] == o) {
|
||||
found = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
addedob[nadded++] = o;
|
||||
}
|
||||
} else {
|
||||
if (db) dblog("DB: No stacks found.");
|
||||
}
|
||||
|
@ -715,6 +856,9 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
setblessed(o, wantblessed);
|
||||
}
|
||||
o->blessknown = B_FALSE;
|
||||
|
||||
addedob[nadded++] = o;
|
||||
|
||||
if (canstack) {
|
||||
// stop looping through
|
||||
break;
|
||||
|
@ -722,6 +866,43 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
need to do the below for _all_ objects added!
|
||||
*/
|
||||
|
||||
for (i = 0; i < nadded; i++) {
|
||||
o = addedob[i];
|
||||
|
||||
// fill in door flags
|
||||
if (ndoorflags && isdoor(o, NULL)) {
|
||||
int n;
|
||||
for (n = 0; n < ndoorflags; n++) {
|
||||
cell_t *c;
|
||||
int val[3];
|
||||
c = getoblocation(o);
|
||||
// fill in flag vals
|
||||
switch (doorflag[n]) {
|
||||
case F_LOCKED:
|
||||
val[0] = B_TRUE;
|
||||
val[1] = getdoorlockdiff(c->map->depth);
|
||||
val[2] = NA;
|
||||
break;
|
||||
case F_JAMMED:
|
||||
val[0] = rnd(1,c->map->depth+3);
|
||||
val[1] = NA;
|
||||
val[2] = NA;
|
||||
break;
|
||||
case F_SECRET:
|
||||
val[0] = getdoorsecretdiff(c->map->depth);
|
||||
val[1] = NA;
|
||||
val[2] = NA;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
addflag(o->flags, doorflag[n], val[0], val[1], val[2], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// fill in book types
|
||||
if (o && (o->type->obclass->id == OC_BOOK)) {
|
||||
hiddenname_t *hn,*selhn = NULL;
|
||||
|
@ -916,6 +1097,20 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
|
||||
}
|
||||
|
||||
// chance of masterwork based on wantgoodness
|
||||
switch (wantgoodness) {
|
||||
case G_GREAT:
|
||||
if (onein(6)) {
|
||||
wantom[nom++] = findobmod(OM_MASTERWORK);
|
||||
}
|
||||
break;
|
||||
case G_EXCELLENT:
|
||||
if (onein(3)) {
|
||||
wantom[nom++] = findobmod(OM_MASTERWORK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (n = 0; n < nom; n++) {
|
||||
// add flags from obmod
|
||||
applyobmod(o, wantom[n]);
|
||||
|
@ -1033,6 +1228,30 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
bonus -= atoi(numbuf);
|
||||
}
|
||||
|
||||
// if no bonus yet, get one based on 'wantgoodness'
|
||||
if (!bonus) {
|
||||
switch (wantgoodness) {
|
||||
case G_GOOD: // 1 - 2
|
||||
bonus = 1;
|
||||
if (onein(2)) bonus++;
|
||||
break;
|
||||
case G_GREAT: // 1 - 3
|
||||
bonus = 1;
|
||||
while (onein(2) && (bonus < 3)) {
|
||||
bonus++;
|
||||
}
|
||||
break;
|
||||
case G_EXCELLENT: // 1 - 4
|
||||
bonus = 1;
|
||||
while (onein(2) && (bonus < 4)) {
|
||||
bonus++;
|
||||
}
|
||||
break;
|
||||
default: // no bonus
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bonus) {
|
||||
if (hasflag(o->flags, F_ENCHANTABLE)) {
|
||||
// for swords, armour etc
|
||||
|
@ -1076,24 +1295,31 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
if (o->blessed == B_CURSED) f->val[2] *= -1;
|
||||
}
|
||||
|
||||
// check for postmods. eg. "xxx of pyromania"
|
||||
// now apply a random brand if we wanted one
|
||||
if (dorandombrand) {
|
||||
wantbrand = getrandombrandfor(ot);
|
||||
}
|
||||
|
||||
// check for specific brands. eg. "xxx of pyromania"
|
||||
// NOTE: this will override any random brands from "branded"
|
||||
for (br = firstbrand ; br ; br = br->next) {
|
||||
if (strstr(name, br->suffix)) {
|
||||
// does this brand apply to this objecttype?
|
||||
if (brandappliesto(br, o->type)) {
|
||||
copyflags(o->flags, br->flags, FROMBRAND);
|
||||
addflag(o->flags, F_HASBRAND, br->id, NA, NA, NULL);
|
||||
} else {
|
||||
// doesn't exist!
|
||||
return NULL;
|
||||
wantbrand = br;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wantbrand) {
|
||||
if (brandappliesto(wantbrand, o->type)) {
|
||||
copyflags(o->flags, wantbrand->flags, FROMBRAND);
|
||||
addflag(o->flags, F_HASBRAND, wantbrand->id, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(localname);
|
||||
}
|
||||
|
||||
if (where->owner) {
|
||||
// new owner gains "hold confer" flags conferred by this object
|
||||
|
@ -1135,9 +1361,22 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|||
needredraw = B_TRUE;
|
||||
}
|
||||
}
|
||||
} // end foreach added object
|
||||
|
||||
// return the last object given
|
||||
return o;
|
||||
// don't need the name anymore.
|
||||
free(localname);
|
||||
|
||||
// populate retobs
|
||||
for (i = 0; i < nadded; i++) {
|
||||
if (addedob[i]) {
|
||||
retobs[i] = addedob[i];
|
||||
retobscount[i] = addedob[i]->amt;
|
||||
}
|
||||
}
|
||||
nretobs = nadded;
|
||||
|
||||
// return the first object given
|
||||
return addedob[0];
|
||||
}
|
||||
|
||||
|
||||
|
@ -1225,7 +1464,6 @@ obpile_t *addobpile(lifeform_t *owner, cell_t *where) {
|
|||
return op;
|
||||
}
|
||||
|
||||
|
||||
void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int allowdupes) {
|
||||
int x,y;
|
||||
objecttype_t *ot;
|
||||
|
@ -2082,6 +2320,29 @@ void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype) {
|
|||
}
|
||||
}
|
||||
|
||||
void dumpobrarity(void) {
|
||||
enum RARITY rr;
|
||||
objecttype_t *ot;
|
||||
flag_t *f;
|
||||
int min,max;
|
||||
|
||||
for (rr = RR_COMMON; rr <= RR_VERYRARE; rr++) {
|
||||
rrtorarity(rr, &min, &max);
|
||||
dblog("Obs with rarity %s:", getrarityname(rr));
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (ot->obclass->id == OC_ARMOUR) {
|
||||
int thisrar;
|
||||
f = hasflag(ot->flags, F_RARITY);
|
||||
if (!f) continue;
|
||||
thisrar = f->val[1];
|
||||
|
||||
if ((thisrar >= min) && (thisrar <= max)) {
|
||||
dblog("\t%s", ot->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void explodeob(object_t *o, flag_t *f, int bigness) {
|
||||
cell_t *c;
|
||||
|
@ -2672,15 +2933,15 @@ int getobvalue(object_t *o) {
|
|||
}
|
||||
// one-off magical effects (linkspell) - use spell price
|
||||
if (f->id == F_LINKSPELL) {
|
||||
// spelllevel^2 * 20
|
||||
price += (pow(getspelllevel(f->val[0]), 2) * 20);
|
||||
// ...and spellbooks then cost triple
|
||||
if (o->type->obclass->id == OC_BOOK) {
|
||||
price *= 3;
|
||||
price += (pow(getspelllevel(f->val[0]), 2) * 30);
|
||||
} else if (o->type->obclass->id == OC_SCROLL) {
|
||||
// do nothing
|
||||
price += (pow(getspelllevel(f->val[0]), 2) * 2);
|
||||
} else if (o->type->obclass->id == OC_POTION) {
|
||||
price += (pow(getspelllevel(f->val[0]), 2) * 15);
|
||||
} else if (o->type->obclass->id == OC_WAND) {
|
||||
price *= 2.25;
|
||||
price += (pow(getspelllevel(f->val[0]), 2) * 22);
|
||||
}
|
||||
} else if (f->id == F_MANUALOF) {
|
||||
price *= 124;
|
||||
|
@ -2756,6 +3017,8 @@ int getobvalue(object_t *o) {
|
|||
|
||||
// minimum
|
||||
if (price < 1) price = 1;
|
||||
|
||||
price = ((int)price * o->amt);
|
||||
return (int) price;
|
||||
}
|
||||
|
||||
|
@ -2828,6 +3091,72 @@ object_t *getrandomammo(lifeform_t *lf) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
brand_t *getrandombrandfor(objecttype_t *ot) {
|
||||
brand_t *br, **poss;
|
||||
brand_t *result = NULL;
|
||||
int numbr;
|
||||
int nposs = 0;
|
||||
|
||||
// count number of brands
|
||||
numbr = 0;
|
||||
for (br = firstbrand ; br ; br = br->next) {
|
||||
numbr++;
|
||||
}
|
||||
poss = malloc(numbr * sizeof(brand_t *));
|
||||
|
||||
for (br = firstbrand ; br ; br = br->next) {
|
||||
if (brandappliesto(br, ot)) {
|
||||
poss[nposs] = br;
|
||||
nposs++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nposs > 0) {
|
||||
result = poss[rnd(0,nposs-1)];
|
||||
}
|
||||
free(poss);
|
||||
return result;
|
||||
}
|
||||
|
||||
objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity) {
|
||||
objecttype_t *ot;
|
||||
int count = 0,sel,n;
|
||||
flag_t *f;
|
||||
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if ((ot->obclass->id == ocid) && !hasflag(ot->flags, F_UNIQUE)) {
|
||||
f = hasflag(ot->flags, F_RARITY);
|
||||
if (f) {
|
||||
if ( ((minrarity == NA) || (f->val[1] >= minrarity)) &&
|
||||
((maxrarity == NA) || (f->val[1] <= maxrarity)) ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
sel = rnd(1,count);
|
||||
n = 0;
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if ((ot->obclass->id == ocid) && !hasflag(ot->flags, F_UNIQUE)) {
|
||||
f = hasflag(ot->flags, F_RARITY);
|
||||
if (f) {
|
||||
if ( ((minrarity == NA) || (f->val[1] >= minrarity)) &&
|
||||
((maxrarity == NA) || (f->val[1] <= maxrarity)) ) {
|
||||
n++;
|
||||
if (n == sel) {
|
||||
return ot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *getdamname(enum DAMTYPE damtype) {
|
||||
switch (damtype) {
|
||||
case DT_ALL: return "all damage";
|
||||
|
@ -4041,29 +4370,9 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
|
|||
// if so...
|
||||
strcpy(brandname, "");
|
||||
if (rnd(1,100) <= depth) {
|
||||
brand_t *om, **poss;
|
||||
int numom;
|
||||
int nposs = 0;
|
||||
|
||||
// count number of brands
|
||||
numom = 0;
|
||||
for (om = firstbrand ; om ; om = om->next) {
|
||||
numom++;
|
||||
}
|
||||
poss = malloc(numom * sizeof(brand_t *));
|
||||
|
||||
for (om = firstbrand ; om ; om = om->next) {
|
||||
if (brandappliesto(om, ot)) {
|
||||
poss[nposs] = om;
|
||||
nposs++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nposs > 0) {
|
||||
om = poss[rnd(0,nposs-1)];
|
||||
strcpy(brandname, om->suffix);
|
||||
}
|
||||
free(poss);
|
||||
brand_t *br;
|
||||
br = getrandombrandfor(ot);
|
||||
if (br) strcpy(brandname, br->suffix);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4101,13 +4410,13 @@ int getobrarity(object_t *o) {
|
|||
if (m) {
|
||||
f = hasflagval(o->flags, F_RARITY,m->habitat, NA, NA, NULL);
|
||||
if (f) {
|
||||
return f->val[0];
|
||||
return f->val[1];
|
||||
}
|
||||
}
|
||||
// any rarity value at all?
|
||||
f = hasflag(o->flags, F_RARITY);
|
||||
if (f) {
|
||||
return f->val[0];
|
||||
return f->val[1];
|
||||
}
|
||||
// ie. doesn't randomly appear
|
||||
return 0;
|
||||
|
@ -4696,8 +5005,11 @@ void initobjects(void) {
|
|||
// object classes
|
||||
addoc(OC_DFEATURE, "Dungeon Features", "Doors, etc.", '\\', C_GREY);
|
||||
addoc(OC_TERRAIN, "Terrain", "Water, etc.", '\\', C_GREY);
|
||||
addoc(OC_TRAP, "Trap", "Fiendish traps.", '^', C_GREY);
|
||||
addocnoun(lastobjectclass, "trap");
|
||||
addoc(OC_MONEY, "Money", "The standard currency of Nexus.", '$', C_GREY);
|
||||
addoc(OC_SCROLL, "Scrolls", "An arcane roll of parchment, inscribed with many magical glyphs.", '?', C_GREY);
|
||||
addocnoun(lastobjectclass, "scroll");
|
||||
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
|
@ -4707,6 +5019,7 @@ void initobjects(void) {
|
|||
//addflag(lastobjectclass->flags, F_MATCONVERTTEXTPL, MT_WATER, NA, NA, "go soggy");
|
||||
|
||||
addoc(OC_WAND, "Wands", "A limited-use magical wand which casts the imbued spell.", '/', C_GREY);
|
||||
addocnoun(lastobjectclass, "wand");
|
||||
addflag(lastobjectclass->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
|
@ -4714,34 +5027,45 @@ void initobjects(void) {
|
|||
addflag(lastobjectclass->flags, F_RNDCHARGES, 1, 8, NA, NULL);
|
||||
|
||||
addoc(OC_POTION, "Potions", "A strange concoction contained within a small flask.", '!', C_GREY);
|
||||
addocnoun(lastobjectclass, "potion");
|
||||
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_POURABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
|
||||
addoc(OC_RING, "Rings", "A circular band, worn on the finger.", '=', C_GREY);
|
||||
addocnoun(lastobjectclass, "ring");
|
||||
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_GOESON, BP_RIGHTHAND, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_GOESON, BP_LEFTHAND, NA, NA, NULL);
|
||||
addoc(OC_WEAPON, "Weapons", "An instrument used for the purpose of causing harm or death.", ')', C_GREY);
|
||||
addocnoun(lastobjectclass, "weapon");
|
||||
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_MASTERWORK, 17, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_SHODDY, 34, NA, NULL);
|
||||
addoc(OC_ARMOUR, "Armour/Clothing", "Protective gear.", ']', C_GREY);
|
||||
addocnoun(lastobjectclass, "armour");
|
||||
addocnoun(lastobjectclass, "clothing");
|
||||
addocnoun(lastobjectclass, "clothes");
|
||||
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_MASTERWORK, 17, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_SHODDY, 34, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_BLOODSTAINED, 17, NA, NULL);
|
||||
addoc(OC_MISSILE, "Missiles/Ammunition", "An instrument used for the purpose of causing harm or death.", ';', C_GREY);
|
||||
addocnoun(lastobjectclass, "missile");
|
||||
addocnoun(lastobjectclass, "ammo");
|
||||
addocnoun(lastobjectclass, "ammunition");
|
||||
addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addoc(OC_FLORA, "Plants", "All kinds of plants and foliage", ',', C_GREEN);
|
||||
addocnoun(lastobjectclass, "plant");
|
||||
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addoc(OC_ROCK, "Rocks/Gems", "Boring (or not so boring) rocks or plants.", '*', C_GREY);
|
||||
addoc(OC_FOOD, "Food", "Yum!", '%', C_GREY);
|
||||
addocnoun(lastobjectclass, "food");
|
||||
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
||||
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addoc(OC_CORPSE, "Corpses", "Dead flesh which was once living.", '%', C_GREY);
|
||||
|
@ -4751,9 +5075,12 @@ void initobjects(void) {
|
|||
addflag(lastobjectclass->flags, F_OBHP, 50, 50, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_OBHPDRAIN, 1, DT_DECAY, NA, NULL); // ie. corpses last for 50 turns
|
||||
addoc(OC_TECH, "Technology", "A strange piece of futuristic technology.", '~', C_GREY);
|
||||
addocnoun(lastobjectclass, "technology");
|
||||
addocnoun(lastobjectclass, "tech");
|
||||
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addoc(OC_TOOLS, "Tools", "Useful items, from the common to the obscure.", '[', C_GREY);
|
||||
addocnoun(lastobjectclass, "tool");
|
||||
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addoc(OC_MISC, "Miscellaneous", "This could be anything.", '\\', C_GREY);
|
||||
|
@ -4761,6 +5088,9 @@ void initobjects(void) {
|
|||
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
||||
addoc(OC_BOOK, "Books", "Spellbooks, tomes or manuals.", '+', C_GREY);
|
||||
addocnoun(lastobjectclass, "spellbook");
|
||||
addocnoun(lastobjectclass, "book");
|
||||
addocnoun(lastobjectclass, "tome");
|
||||
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addoc(OC_SPELL, "Spells", "A magical spell", '&', C_GREY); // this is a "virtual" object class
|
||||
|
@ -4900,7 +5230,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_REDUCEMOVEMENT, 4, NA, NA, NULL);
|
||||
|
||||
// traps
|
||||
addot(OT_TRAPTRIP, "tripwire", "A thin wire at ankle height.", MT_NOTHING, 0, OC_MISC);
|
||||
addot(OT_TRAPTRIP, "tripwire", "A thin wire at ankle height.", MT_NOTHING, 0, OC_TRAP);
|
||||
addflag(lastot->flags, F_TRAP, 10, B_FALSE, 20, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
|
||||
|
@ -4908,7 +5238,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
|
||||
addflag(lastot->flags, F_SECRET, 25, NA, NA, NULL);
|
||||
addot(OT_TRAPROCK, "falling rock trap", "A pressure plate which causes heavy rocks to drop from the ceiling.", MT_NOTHING, 0, OC_MISC);
|
||||
addot(OT_TRAPROCK, "falling rock trap", "A pressure plate which causes heavy rocks to drop from the ceiling.", MT_NOTHING, 0, OC_TRAP);
|
||||
addflag(lastot->flags, F_TRAP, 20, B_TRUE, 22, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
||||
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
|
||||
|
@ -4916,7 +5246,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
|
||||
addflag(lastot->flags, F_SECRET, 25, NA, NA, NULL);
|
||||
addot(OT_TRAPARROW, "arrow trap", "A pressure plate which causes arrows to shoot at you.", MT_NOTHING, 0, OC_MISC);
|
||||
addot(OT_TRAPARROW, "arrow trap", "A pressure plate which causes arrows to shoot at you.", MT_NOTHING, 0, OC_TRAP);
|
||||
addflag(lastot->flags, F_TRAP, 25, B_TRUE, NA, NULL);
|
||||
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 76, NA, NULL);
|
||||
|
@ -4925,7 +5255,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
|
||||
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
|
||||
addot(OT_TRAPARROWP, "poison arrow trap", "A pressure plate which causes poisoned arrows to shoot at you.", MT_NOTHING, 0, OC_MISC);
|
||||
addot(OT_TRAPARROWP, "poison arrow trap", "A pressure plate which causes poisoned arrows to shoot at you.", MT_NOTHING, 0, OC_TRAP);
|
||||
addflag(lastot->flags, F_TRAP, 25, B_TRUE, NA, NULL);
|
||||
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, NA, NULL);
|
||||
|
@ -4934,7 +5264,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
|
||||
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
|
||||
addot(OT_TRAPGAS, "gas trap", "A pressure plate which releases poisonous gas.", MT_NOTHING, 0, OC_MISC);
|
||||
addot(OT_TRAPGAS, "gas trap", "A pressure plate which releases poisonous gas.", MT_NOTHING, 0, OC_TRAP);
|
||||
addflag(lastot->flags, F_TRAP, 27, B_TRUE, NA, NULL);
|
||||
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, NA, NULL);
|
||||
|
@ -4943,7 +5273,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
|
||||
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
|
||||
addot(OT_TRAPFIRE, "fire trap", "A pressure plate which fires a pillar of flame.", MT_NOTHING, 0, OC_MISC);
|
||||
addot(OT_TRAPFIRE, "fire trap", "A pressure plate which fires a pillar of flame.", MT_NOTHING, 0, OC_TRAP);
|
||||
addflag(lastot->flags, F_TRAP, 30, B_TRUE, NA, NULL);
|
||||
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 59, NA, NULL);
|
||||
|
@ -4952,7 +5282,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
|
||||
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
|
||||
addot(OT_TRAPMINE, "landmine trap", "A buried, pressure-sensitive explosive device.", MT_NOTHING, 0, OC_MISC);
|
||||
addot(OT_TRAPMINE, "landmine trap", "A buried, pressure-sensitive explosive device.", MT_NOTHING, 0, OC_TRAP);
|
||||
addflag(lastot->flags, F_TRAP, 30, B_TRUE, NA, NULL);
|
||||
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
||||
|
@ -8761,11 +9091,15 @@ void killobpile(obpile_t *op) {
|
|||
|
||||
void killoc(objectclass_t *oc) {
|
||||
objectclass_t *nextone, *lastone;
|
||||
int i;
|
||||
|
||||
// free mem
|
||||
free(oc->name);
|
||||
free(oc->desc);
|
||||
if (oc->flags) killflagpile(oc->flags);
|
||||
for (i = 0; i < oc->nnouns; i++) {
|
||||
free(oc->noun[i]);
|
||||
}
|
||||
|
||||
// remove from list
|
||||
nextone = oc->next;
|
||||
|
@ -11313,6 +11647,37 @@ int removeob(object_t *o,int howmany) {
|
|||
return o->amt;
|
||||
}
|
||||
|
||||
void rrtorarity(enum RARITY r, int *minr, int *maxr) {
|
||||
switch (r) {
|
||||
case RR_UNIQUE:
|
||||
case RR_NEVER:
|
||||
if (minr) *minr = 0;
|
||||
if (maxr) *maxr = 0;
|
||||
break;
|
||||
case RR_VERYRARE:
|
||||
if (minr) *minr = 0;
|
||||
if (maxr) *maxr = 49;
|
||||
break;
|
||||
case RR_RARE:
|
||||
if (minr) *minr = 50;
|
||||
if (maxr) *maxr = 64;
|
||||
break;
|
||||
case RR_UNCOMMON:
|
||||
if (minr) *minr = 65;
|
||||
if (maxr) *maxr = 79;
|
||||
break;
|
||||
case RR_COMMON:
|
||||
if (minr) *minr = 80;
|
||||
if (maxr) *maxr = 100;
|
||||
break;
|
||||
default:
|
||||
if (minr) *minr = 0;
|
||||
if (maxr) *maxr = 100; // ie. rarity can be anything
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void setblessed(object_t *o, enum BLESSTYPE wantbless) {
|
||||
o->blessed = wantbless;
|
||||
if (wantbless != B_BLESSED) {
|
||||
|
|
|
@ -8,6 +8,7 @@ hiddenname_t *addhiddenname(enum OBCLASS obclass, char *text);
|
|||
knowledge_t *addknowledge(enum OBCLASS id, char *hiddenname, int known);
|
||||
material_t *addmaterial(enum MATERIAL id, char *name, float weightrating);
|
||||
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph, int glyphcolour);
|
||||
void addocnoun(objectclass_t *oc, char *text);
|
||||
object_t *addob(obpile_t *where, char *name);
|
||||
object_t *addobject(obpile_t *where, char *name, int canstack);
|
||||
int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fromlf, enum LOFTYPE needlof);
|
||||
|
@ -38,6 +39,7 @@ int countnoncosmeticobs(obpile_t *op, int onlyifknown);
|
|||
int curseob(object_t *o);
|
||||
void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype);
|
||||
void dumprandomobs(int amt);
|
||||
void dumpobrarity(void);
|
||||
void explodeob(object_t *o, flag_t *f, int bigness);
|
||||
void extinguish(object_t *o);
|
||||
material_t *findmaterial(int id);
|
||||
|
@ -64,6 +66,8 @@ int getobvalue(object_t *o);
|
|||
char *getaccuracyname(int accpct);
|
||||
object_t *getammo(lifeform_t *lf);
|
||||
object_t *getrandomammo(lifeform_t *lf);
|
||||
brand_t *getrandombrandfor(objecttype_t *ot);
|
||||
objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity);
|
||||
char *getdamname(enum DAMTYPE damtype);
|
||||
char *getdamnamenoun(enum DAMTYPE damtype);
|
||||
char *getfillingname(int nutrition);
|
||||
|
@ -193,6 +197,7 @@ int readsomething(lifeform_t *lf, object_t *o);
|
|||
void removedeadobs(obpile_t *op);
|
||||
int removeob(object_t *o, int howmany);
|
||||
object_t *relinkob(object_t *src, obpile_t *dst);
|
||||
void rrtorarity(enum RARITY r, int *minr, int *maxr);
|
||||
void setblessed(object_t *o, enum BLESSTYPE wantbless);
|
||||
void setinscription(object_t *o, char *text);
|
||||
void setobcreatedby(object_t *o, lifeform_t *lf);
|
||||
|
|
39
spell.c
39
spell.c
|
@ -31,6 +31,10 @@ extern objecttype_t *objecttype;
|
|||
|
||||
extern map_t *firstmap;
|
||||
|
||||
extern object_t *retobs[MAXPILEOBS+1];
|
||||
extern int retobscount[MAXPILEOBS+1];
|
||||
extern int nretobs;
|
||||
|
||||
extern enum ERROR reason;
|
||||
|
||||
extern int needredraw, statdirty;
|
||||
|
@ -2238,12 +2242,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
int seenthiscell = B_FALSE;
|
||||
if (haslos(player, retcell[i])) seenthiscell = B_TRUE;
|
||||
if (retcell[i]->type->solid) {
|
||||
// can dig through stone, but nothing else.
|
||||
if (retcell[i]->type->material->id == MT_STONE) {
|
||||
setcelltype(retcell[i], getemptycelltype(retcell[i]->map->habitat));
|
||||
if (seenthiscell) {
|
||||
ndigs++;
|
||||
numseen++;
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
// stop.
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
object_t *o;
|
||||
for (o = retcell[i]->obpile->first ; o ; o = o->next) {
|
||||
|
@ -5436,7 +5446,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// confirm
|
||||
ch = askchar("Are you sure to want to teleport into the unknown?", "yn", "n", B_TRUE);
|
||||
if (ch != 'y') c = NULL;
|
||||
} else if (!cellwalkable(caster, c, NULL)) {
|
||||
} else if (c->type->solid) {
|
||||
// confirm
|
||||
ch = askchar("Are you sure to want to teleport into solid rock?", "yn", "n", B_TRUE);
|
||||
if (ch != 'y') c = NULL;
|
||||
|
@ -5544,10 +5554,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
targcell = c;
|
||||
|
||||
if (!cellwalkable(caster, c, NULL)) {
|
||||
if (c->type->solid) {
|
||||
// ok, but you'll die!
|
||||
} else if (!cellwalkable(caster, c, NULL)) {
|
||||
// go somewhere nearby...
|
||||
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
if (!c) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// we can take up to 'power-1' allies with us.
|
||||
if (caster == target) {
|
||||
|
@ -6104,6 +6120,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (isplayer(caster)) {
|
||||
char lfname[BUFLEN];
|
||||
char question[BUFLEN];
|
||||
int i;
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
// ask for target
|
||||
if (spellid == OT_S_GIFT) {
|
||||
|
@ -6121,11 +6138,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
sprintf(question, "For what do you wish");
|
||||
}
|
||||
askstring(question, '?', buf, BUFLEN, NULL);
|
||||
o = addob(target->cell->obpile, buf);
|
||||
if (o) {
|
||||
addob(target->cell->obpile, buf);
|
||||
if (nretobs) {
|
||||
for (i = 0; i < nretobs; i++) {
|
||||
char obname[BUFLEN];
|
||||
o = retobs[i];
|
||||
getobname(o, obname, o->amt);
|
||||
if (!hasflag(o->flags, F_IMPASSABLE) && canpickup(target, o, ALL)) {
|
||||
// you gain it.
|
||||
relinkob(o, target->pack); // move to pack
|
||||
if (isplayer(target)) {
|
||||
msgnocap("%c - %s.", o->letter, obname);
|
||||
|
@ -6133,12 +6153,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
msg("%s is gifted with %s.", lfname, obname);
|
||||
}
|
||||
} else {
|
||||
// couldn't pick it up - try to place on ground!
|
||||
// impassable?
|
||||
// can't pick this up...
|
||||
|
||||
// impassable? goes in a nearby cell instead of at your feet.
|
||||
if (hasflag(o->flags, F_IMPASSABLE)) {
|
||||
cell_t *newloc;
|
||||
// if so, don't put it where the player is!
|
||||
newloc = getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
newloc = real_getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL);
|
||||
o = relinkob(o, newloc->obpile);
|
||||
}
|
||||
if (o) {
|
||||
|
@ -6147,8 +6168,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : "");
|
||||
}
|
||||
} else {
|
||||
// couldn't make it appear
|
||||
// ob exists but couldn't make it appear
|
||||
msg("The air in front of %s seems to ripple for a moment.", lfname);
|
||||
break; // don't process any more.
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
42
text.c
42
text.c
|
@ -208,6 +208,20 @@ char *getdrunktext(flag_t *drunkflag) {
|
|||
return "??drunk??";
|
||||
}
|
||||
|
||||
char *getrarityname(enum RARITY rr) {
|
||||
switch (rr) {
|
||||
case RR_UNIQUE: return "Unique";
|
||||
case RR_NEVER: return "Never";
|
||||
case RR_VERYRARE: return "Very Rare";
|
||||
case RR_RARE: return "Rare";
|
||||
case RR_UNCOMMON: return "Uncommon";
|
||||
case RR_COMMON: return "Common";
|
||||
case RR_NONE: return "None";
|
||||
}
|
||||
|
||||
return "?unknownrarity?";
|
||||
}
|
||||
|
||||
char *getsizetext(enum LFSIZE sz) {
|
||||
switch (sz) {
|
||||
case SZ_ENORMOUS:
|
||||
|
@ -458,6 +472,19 @@ char *numtotext(int num, char *buf) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
// returns posiiton AFTER end of copied text, or NULL on failure.
|
||||
char *readuntil(char *retbuf, char *src, char delim) {
|
||||
char *bp,*p;
|
||||
bp = retbuf;
|
||||
for (p=src; *p && (*p != delim); p++) {
|
||||
*bp = *p;
|
||||
bp++;
|
||||
}
|
||||
p++; // go past delimiter
|
||||
*bp = '\0'; // nul-terminate buffer
|
||||
return p;
|
||||
}
|
||||
|
||||
// convert number to roman numerals
|
||||
// only copes with 1-10
|
||||
char *roman(int num) {
|
||||
|
@ -546,6 +573,21 @@ char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv) {
|
|||
return *out;
|
||||
}
|
||||
|
||||
int streq(char *a, char *b) {
|
||||
if (!a || !b) return B_FALSE;
|
||||
return !strcmp(a,b);
|
||||
}
|
||||
|
||||
char *strstarts(char *a, char *prefix) {
|
||||
if (!a || !prefix) return NULL;
|
||||
|
||||
if (strstr(a, prefix) == a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int strpixmatch(char *haystack, char *needle) {
|
||||
int matched = B_FALSE;
|
||||
char *hword, *nword, *hcont,*ncont;
|
||||
|
|
4
text.h
4
text.h
|
@ -10,6 +10,7 @@ char *getattrname(enum ATTRIB att);
|
|||
int gethitconferlifetime(char *text, int *min, int *max);
|
||||
char *getpossessive(char *text);
|
||||
char *getdrunktext(flag_t *drunkflag);
|
||||
char *getrarityname(enum RARITY rr);
|
||||
char *getsizetext(enum LFSIZE sz);
|
||||
char *gettimetext(char *retbuf);
|
||||
char *gettimetextfuzzy(char *retbuf, int wantpm);
|
||||
|
@ -21,11 +22,14 @@ char *makeuppercase(char *text);
|
|||
int needses(char *text);
|
||||
char *noprefix(char *obname);
|
||||
char *numtotext(int num, char *buf);
|
||||
char *readuntil(char *retbuf, char *src, char delim);
|
||||
char *roman(int num);
|
||||
int speedtokph(int speed);
|
||||
void splittime(int *hours, int *mins, int *secs);
|
||||
char *strrep(char *text, char *oldtok, char *newtok, int *rv);
|
||||
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv);
|
||||
int streq(char *a, char *b);
|
||||
char *strstarts(char *a, char *prefix);
|
||||
int strpixmatch(char *haystack, char *needle);
|
||||
int texttodice(char *text, int *ndice, int *nsides, int *bonus);
|
||||
void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range);
|
||||
|
|
Loading…
Reference in New Issue