- [+] BUG: trying to go down stairs from L7 (6?)
- [+] You walk down the staircase... ERROR - can't find opposite end of stairs/portal! - [+] You walk down the staircase... ERROR - unlinked stairs! - [+] This is related to the fact that all the staircases came from Jimbo's vault - [+] For some reason we're not linking them when they come for ma vault!!! - [+] "joining unliked stairs" section not working??? - [+] it calls getstairdestination, but this DOESNT call linkstairs! - [+] maby: call autolink everytime i add stairs ? or only do this during createvault ? - [+] automatically remove useless doors (ie. ones where all adjacent walkable cells are in the same room) - [+] in fix_reachability i'm drawing a corridor through vault/room walls. <- probably this one. - [+] don't allow auto reachability to enter rooms through the wrong side wall. - [+] TEST during regular playtests, see if maps look better. - [+] quality on doors. - [+] sturdy / plain / shoddy doors. this impacts the hp - [+] stone doors (solid / plain /crumbling) - [+] metal ( reinforced / plain / rusty) - [+] only show this if perception >= beginner - [+] dungeon shapes - [+] new cell attribute - locked. - [+] calcroompos can't make rooms on locked cells. - [+] normal - [+] cross - [+] circle - [+] turret - [+] - premask out blocked cells before generation! - [+] minion code - if leader dies, - [+] minions drop morale - [+] and might either immediately flee - [+] need lastdamlf - [+] if wisdom >= gtaverage, automatically turn off lamps when you go to sleep - [+] "scratch"/"gnaw" etc should be based on actual damage hp amount, not percentage. - [+] change getattackverb() - [+] 1-2 - [+] 3-6 - [+] 8-12 - [+] 12-18 - [+] 18+ - [+] shop objects should start with all flags known. - [+] allow usage of godstones without id'ing them first. this will id them. - [+] weapon/armour shop should resize armour for you for a cost. - [+] chanelling bonus - [+] novice - [+] tell you when wand is low on charges (0-3) - [+] beginner - [+] let you determine exact remaining charges in wands once it is == 1! - [+] adept - [+] let you determine exact remaining charges in wands once it is <= 3! - [+] skilled: - [+] let you determine exact remaining charges in wands once it is <= 6! - [+] master - [+] lets you always see full amount of want charges. - [+] lets you convert your mp into wand charges? "imbue item"
This commit is contained in:
parent
6d57f7ebe3
commit
e1b569f306
36
data.c
36
data.c
|
@ -1246,6 +1246,7 @@ void initobjects(void) {
|
|||
addflag(lastobjectclass->flags, F_UNIQUE, NA, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_OPERWITHOUTID, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addoc(OC_CORPSE, "Corpses", "Dead flesh which was once living.", '%', C_GREY, RR_NEVER);
|
||||
|
@ -1296,6 +1297,8 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
|
||||
addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_CANHAVEOBMOD, OM_MASTERWORK, 25, NA, NULL);
|
||||
addflag(lastot->flags, F_CANHAVEOBMOD, OM_SHODDY, 25, NA, NULL);
|
||||
|
||||
addot(OT_DOORIRON, "iron door", "A strong iron door.", MT_METAL, 300, OC_DFEATURE, SZ_LARGE);
|
||||
// GLYPH here is a special case in getglyph
|
||||
|
@ -1457,7 +1460,8 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something");
|
||||
addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, SM_DONATE, "d:donate something");
|
||||
addflag(lastot->flags, F_SHOPMENU, 2, MA_QUIT, NA, "q:leave");
|
||||
addflag(lastot->flags, F_SHOPMENU, 2, MA_GOTOMENU, SM_RESIZE, "r:resize equipment");
|
||||
addflag(lastot->flags, F_SHOPMENU, 3, MA_QUIT, NA, "q:leave");
|
||||
for (i = 0; i < 10; i++) {
|
||||
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_ARMOUR, RANDOM, NULL);
|
||||
}
|
||||
|
@ -1523,7 +1527,8 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something");
|
||||
addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, SM_DONATE, "d:donate something");
|
||||
addflag(lastot->flags, F_SHOPMENU, 2, MA_QUIT, NA, "q:leave");
|
||||
addflag(lastot->flags, F_SHOPMENU, 2, MA_GOTOMENU, SM_RESIZE, "r:resize equipment");
|
||||
addflag(lastot->flags, F_SHOPMENU, 3, MA_QUIT, NA, "q:leave");
|
||||
for (i = 0; i < 10; i++) {
|
||||
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_WEAPON, RANDOM, NULL);
|
||||
}
|
||||
|
@ -5831,9 +5836,9 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_USESSKILL, SK_UNARMED, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTACKVERB, NA, 5, NA, "scratch");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 6, 15, NA, "scrape");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 16, NA, NA, "rake");
|
||||
addflag(lastot->flags, F_ATTACKVERB, NA, 2, NA, "scratch");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 3, 6, NA, "scrape");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 7, NA, NA, "rake");
|
||||
|
||||
|
||||
addot(OT_TEETH, "teeth", "teeth object", MT_BONE, 0, OC_WEAPON, SZ_TINY);
|
||||
|
@ -5865,12 +5870,12 @@ void initobjects(void) {
|
|||
addot(OT_CLAWS, "claws", "claws object", MT_BONE, 0, OC_WEAPON, SZ_TINY);
|
||||
addflag(lastot->flags, F_DAM, DT_SLASH, 2, NA, NULL);
|
||||
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTACKVERB, NA, 5, NA, "scratch");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 6, 15, NA, "claw");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 16, 30, NA, "tear");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 31, 40, NA, "rake");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 41, 50, NA, "gouge");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 51, NA, NA, "shred");
|
||||
addflag(lastot->flags, F_ATTACKVERB, NA, 2, NA, "scratch");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 3, 6, NA, "claw");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 7, 12, NA, "tear");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 13, 18, NA, "rake");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 19, 24, NA, "gouge");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 25, NA, NA, "shred");
|
||||
addflag(lastot->flags, F_KILLVERB, 70, NA, NA, "disembowel");
|
||||
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
|
||||
|
@ -5880,7 +5885,8 @@ void initobjects(void) {
|
|||
addot(OT_HOOF, "hooves", "hoof object", MT_BONE, 0, OC_WEAPON, SZ_TINY);
|
||||
addflag(lastot->flags, F_DAM, DT_BASH, 2, NA, NULL);
|
||||
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "kick");
|
||||
addflag(lastot->flags, F_ATTACKVERB, NA, 11, NA, "kick");
|
||||
addflag(lastot->flags, F_ATTACKVERB, 12, NA, NA, "trample");
|
||||
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL);
|
||||
|
@ -11365,11 +11371,17 @@ void initskills(void) {
|
|||
addskilldesc(SK_CARTOGRAPHY, PR_MASTER, "^gEvery 50 turns, you can intuitively map a small area around you.^n", B_FALSE);
|
||||
addskill(SK_CHANNELING, "Channeling", "Lets you make better use of magical items.", 0); // untrainable
|
||||
addskilldesc(SK_CHANNELING, PR_NOVICE, "^gThe power level of wands and scrolls is increased by 1.^n", B_FALSE);
|
||||
addskilldesc(SK_CHANNELING, PR_NOVICE, "^gYou can now recognise when objects are low on charges.^n", B_TRUE);
|
||||
addskilldesc(SK_CHANNELING, PR_BEGINNER, "^gThe power level of wands and scrolls is increased by 2.^n", B_FALSE);
|
||||
addskilldesc(SK_CHANNELING, PR_BEGINNER, "^gYou now know when objects have a single charge remaining.^n", B_TRUE);
|
||||
addskilldesc(SK_CHANNELING, PR_ADEPT, "^gThe power level of wands and scrolls is increased by 4.^n", B_FALSE);
|
||||
addskilldesc(SK_CHANNELING, PR_ADEPT, "^gYou now know when objects have less than four charges left.^n", B_TRUE);
|
||||
addskilldesc(SK_CHANNELING, PR_SKILLED, "^gThe power level of wands and scrolls is increased by 6.^n", B_FALSE);
|
||||
addskilldesc(SK_CHANNELING, PR_SKILLED, "^gYou now know when objects have less than seven charges left.^n", B_TRUE);
|
||||
addskilldesc(SK_CHANNELING, PR_EXPERT, "^gThe power level of wands and scrolls is increased by 8.^n", B_FALSE);
|
||||
addskilldesc(SK_CHANNELING, PR_EXPERT, "^gUsing any object will now reveal its remaining charges.^n", B_TRUE);
|
||||
addskilldesc(SK_CHANNELING, PR_MASTER, "^gThe power level of wands and scrolls is increased by 10.^n", B_FALSE);
|
||||
addskilldesc(SK_CHANNELING, PR_MASTER, "^gYou now always know remaining charges for all objects.^n", B_TRUE);
|
||||
addskill(SK_CLIMBING, "Climbing", "Helps you to climb walls, mountains or other terrain.", 50);
|
||||
addskilldesc(SK_CLIMBING, PR_INEPT, "Increases your chances of successfully climbing by 10% per level.", B_FALSE);
|
||||
addskilldesc(SK_CLIMBING, PR_NOVICE, "You gain the 'climb walls' ability. Cannot attack while climbing.", B_FALSE);
|
||||
|
|
26
defs.h
26
defs.h
|
@ -5,6 +5,7 @@
|
|||
|
||||
// MACROS
|
||||
#define MAXOF(a,b) (a > b ? a : b)
|
||||
#define MINOF(a,b) (a < b ? a : b)
|
||||
#define OB1(o,one,many) (o->amt == 1) ? one : many
|
||||
#define OBS1(o) (o->amt == 1) ? "s" : ""
|
||||
#define OBNOS1(o) (o->amt == 1) ? "" : "s"
|
||||
|
@ -1986,6 +1987,7 @@ enum FLAG {
|
|||
F_NONE = 0, // dummy flag
|
||||
// map flags
|
||||
F_MAPCOORDS, // v0+v1 are x/y coords for this map area
|
||||
F_MAPSHAPE, // v0 = enum MAPSHAPE
|
||||
F_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2
|
||||
F_NEWWATERDEPTH, // temp flag for the spread of f_deepwater obs.
|
||||
// v0+1 are x/y, v2 is new depth.
|
||||
|
@ -2272,11 +2274,11 @@ enum FLAG {
|
|||
F_SHODDY, // weps do less damage, armour protects less.
|
||||
// weapon flags
|
||||
F_ATTACKVERB, // text=verb for attacking. ie. "hit" "slash" "sting" etc
|
||||
// if v0/v1 are set, only use this text if dam pct is
|
||||
// if v0/v1 are set, only use this text if dam AMOUNT (not pct) is
|
||||
// between v0 and v1.
|
||||
// should always be singular
|
||||
F_KILLVERB, // text=verb for a fatal attacking. ie. "kill" "behead"
|
||||
// if v0/v1 are set, only use this text if dam pct is
|
||||
// if v0/v1 are set, only use this text if dam PCT (not amount) is
|
||||
// between v0 and v1.
|
||||
// should always be singular
|
||||
F_OBATTACKDELAY, // how long weapon takes to attack
|
||||
|
@ -2753,6 +2755,7 @@ enum FLAG {
|
|||
// if v2 is set, means we are sleeping on
|
||||
// purpose and will wake up when at full hp/mp/etc.
|
||||
// ie. "resting"
|
||||
// text = obid of light source which you turned off.
|
||||
F_ATTACHEDTO, // you are attached to lf id v0, and will move with it
|
||||
F_AWARENESS, // you can see 360 degrees around yourself
|
||||
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
|
||||
|
@ -3438,6 +3441,19 @@ typedef struct hiddennamewithcol_s {
|
|||
enum COLOUR col;
|
||||
} hiddennamewithcol_t;
|
||||
|
||||
enum MAPSHAPE {
|
||||
MS_NORMAL,
|
||||
MS_CROSS,
|
||||
MS_CIRCLE,
|
||||
MS_TURRET,
|
||||
};
|
||||
#define MAXMAPSHAPES (4)
|
||||
|
||||
enum CORRIDORTYPE {
|
||||
CDT_NORMAL, // make corridors, remove deadends, add rooms, autolink
|
||||
CDT_SIMPLE, // add rooms, autolink
|
||||
};
|
||||
|
||||
typedef struct cell_s {
|
||||
map_t *map; // pointer back to map
|
||||
int x,y; // map coords
|
||||
|
@ -3455,12 +3471,15 @@ typedef struct cell_s {
|
|||
char *writing;
|
||||
int writinglifetime;
|
||||
|
||||
int locked; // cannot make rooms on top of this.
|
||||
|
||||
// lifeform pile
|
||||
struct lifeform_s *lf;
|
||||
// known to player?
|
||||
int known;
|
||||
struct glyph_s knownglyph;
|
||||
int knowntime;
|
||||
int isroomwall;
|
||||
|
||||
// FOR CONSTRUCTION
|
||||
int visited;
|
||||
|
@ -3527,6 +3546,7 @@ typedef struct lifeform_s {
|
|||
int mp,maxmp;
|
||||
float stamina;
|
||||
int alive;
|
||||
int lastdamlf; // id of lf who just hurt us
|
||||
char *lastdam;
|
||||
char *killverb;
|
||||
struct material_s *material;
|
||||
|
@ -3852,6 +3872,8 @@ enum SHOPMENU {
|
|||
SM_MIRACLE = -6,
|
||||
// motels
|
||||
SM_REST = -7,
|
||||
// weapon/armour shops
|
||||
SM_RESIZE = -8,
|
||||
};
|
||||
|
||||
enum SHOPRETURN {
|
||||
|
|
2
flag.c
2
flag.c
|
@ -240,6 +240,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
|
|||
case F_RUNNING:
|
||||
case F_TRAINING:
|
||||
case F_AUTOCMD:
|
||||
case F_PRODUCESLIGHT:
|
||||
break;
|
||||
case F_ASLEEP:
|
||||
if (f->val[2] == NA) { // ie. sleeping, not resting
|
||||
|
@ -972,6 +973,7 @@ void killflag(flag_t *f) {
|
|||
case F_RUNNING:
|
||||
case F_TRAINING:
|
||||
case F_AUTOCMD:
|
||||
case F_PRODUCESLIGHT:
|
||||
break;
|
||||
case F_ASLEEP:
|
||||
if (f->val[2] != NA) { // ie. resting
|
||||
|
|
73
io.c
73
io.c
|
@ -5357,42 +5357,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
|
|||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
|
||||
// charges remaining
|
||||
if ((o->type->obclass->id == OC_WAND) || (o->type->id == OT_BATTERY)) {
|
||||
if (isidentified(o)) {
|
||||
int charges;
|
||||
charges = getcharges(o);
|
||||
if (charges) {
|
||||
sprintf(buf, "It has %d charges left.\n",charges);
|
||||
} else {
|
||||
sprintf(buf, "It has no charges left.\n");
|
||||
}
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
} else if (o->type->obclass->id == OC_GODSTONE) {
|
||||
if (isidentified(o)) {
|
||||
int charges,max;
|
||||
getchargeinfo(o, &charges, &max);
|
||||
if (charges == max) {
|
||||
sprintf(buf, "It is fully charged.\n");
|
||||
} else {
|
||||
sprintf(buf, "It is depleted.\n");
|
||||
}
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
} else if (o->type->id == OT_CREDITCARD) {
|
||||
if (isidentified(o)) {
|
||||
int charges;
|
||||
charges = getcharges(o);
|
||||
if (charges) {
|
||||
sprintf(buf, "It has $%d remaining until its limit.\n",charges);
|
||||
} else {
|
||||
sprintf(buf, "It is maxed out.\n");
|
||||
}
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
}
|
||||
|
||||
f = hasflag(o->flags, F_PICKLOCKS);
|
||||
if (f) {
|
||||
sprintf(buf, "You can use it to pick locks.\n");
|
||||
|
@ -5506,6 +5470,43 @@ char *makedesc_ob(object_t *o, char *retbuf) {
|
|||
}
|
||||
} // end if isknown
|
||||
|
||||
// charges remaining
|
||||
if ((o->type->obclass->id == OC_WAND) || (o->type->id == OT_BATTERY)) {
|
||||
if (isidentified(o) || chargesknown(o)) {
|
||||
int charges;
|
||||
charges = getcharges(o);
|
||||
if (charges) {
|
||||
sprintf(buf, "It has %d charge%s left.\n",charges, (charges == 1) ? "" : "s");
|
||||
} else {
|
||||
sprintf(buf, "It has no charges left.\n");
|
||||
}
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
} else if (o->type->obclass->id == OC_GODSTONE) {
|
||||
if (isidentified(o)) {
|
||||
int charges,max;
|
||||
getchargeinfo(o, &charges, &max);
|
||||
if (charges == max) {
|
||||
sprintf(buf, "It is fully charged.\n");
|
||||
} else {
|
||||
sprintf(buf, "It is depleted.\n");
|
||||
}
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
} else if (o->type->id == OT_CREDITCARD) {
|
||||
if (isidentified(o)) {
|
||||
int charges;
|
||||
charges = getcharges(o);
|
||||
if (charges) {
|
||||
sprintf(buf, "It has $%d remaining until its limit.\n",charges);
|
||||
} else {
|
||||
sprintf(buf, "It is maxed out.\n");
|
||||
}
|
||||
strncat(retbuf, buf, HUGEBUFLEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// skip line
|
||||
strncat(retbuf, "\n", HUGEBUFLEN);
|
||||
|
||||
|
|
90
lf.c
90
lf.c
|
@ -2290,6 +2290,11 @@ void die(lifeform_t *lf) {
|
|||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags;
|
||||
cell_t *corpsecell;
|
||||
lifeform_t *killer = NULL;
|
||||
|
||||
if (lf->lastdamlf != -1) {
|
||||
killer = findlf(lf->cell->map, lf->lastdamlf);
|
||||
}
|
||||
|
||||
if (cansee(player, lf)) {
|
||||
needredraw = B_TRUE;
|
||||
|
@ -2416,6 +2421,8 @@ void die(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
lifeform_t *minion[MAXCANDIDATES];
|
||||
int nminions = 0;
|
||||
// intelligent monsters will say something
|
||||
if (!hasflag(lf->flags, F_NODEATHSPEECH)) {
|
||||
if (ispetof(lf, player)) {
|
||||
|
@ -2473,6 +2480,19 @@ void die(lifeform_t *lf) {
|
|||
// mercy god doesn't like killing
|
||||
//angergodmaybe(R_GODMERCY, 1, GA_MURDER);
|
||||
}
|
||||
|
||||
// minions drop morale, and might flee
|
||||
getminions(lf, minion, &nminions);
|
||||
for (i = 0; i < nminions; i++) {
|
||||
f = lfhasflag(minion[i], F_MORALE);
|
||||
if (f) {
|
||||
f->val[0] -= 10;
|
||||
// might flee?
|
||||
if (killer && (f->val[0] <= 0)) {
|
||||
scare(minion[i], killer, PERMENANT, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determine where to drop objects
|
||||
|
@ -4269,7 +4289,6 @@ int flee(lifeform_t *lf) {
|
|||
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
|
||||
|
||||
real_getlfname(lf, lfname, B_FALSE);
|
||||
|
||||
|
||||
// are we fleeing?
|
||||
getflags(lf->flags, retflag, &nretflags, F_FLEEFROM, F_NONE);
|
||||
|
@ -8723,8 +8742,10 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
|
|||
addflag(lf->flags, F_PHOTOMEM, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
if (f->val[1] == PR_MASTER) {
|
||||
newf = addflag(lf->flags, F_CANWILL, OT_S_MAPPING, 50, 50, "pw:1;");
|
||||
newf->lifetime = FROMSKILL;
|
||||
if (!hasflagval(lf->flags, F_CANWILL, OT_S_MAPPING, NA, NA, NULL)) {
|
||||
newf = addflag(lf->flags, F_CANWILL, OT_S_MAPPING, 50, 50, "pw:1;");
|
||||
newf->lifetime = FROMSKILL;
|
||||
}
|
||||
}
|
||||
} else if (id == SK_COOKING) {
|
||||
if (f->val[1] == PR_ADEPT) {
|
||||
|
@ -9053,8 +9074,6 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
|
|||
case RANDOM: depthmod = rnd(0,MAXDEPTH); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// if (getrandomobofsize(targmap, buf, maxobsize)) {
|
||||
if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE, B_TRUE, OC_NONE, DT_NONE)) {
|
||||
if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water");
|
||||
o = addob(op, buf);
|
||||
|
@ -9103,7 +9122,6 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
|
|||
} else {
|
||||
if (db) snprintf(buf2, BUFLEN, "finished startobwepsk, failed.");
|
||||
}
|
||||
//assert(strlen(buf) > 0);
|
||||
}
|
||||
} else if (id == F_STARTOBCLASS) {
|
||||
if (rnd(1,100) <= val[0]) {
|
||||
|
@ -9120,7 +9138,6 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
|
|||
}
|
||||
|
||||
//obdb = B_TRUE;
|
||||
//if (getrandomobwithclass(targmap, val[1], buf, val[2])) {
|
||||
if (real_getrandomob(targmap, buf, getmapdifficulty(targmap) + depthmod, NA, maxobsize, SK_NONE, B_TRUE,
|
||||
val[1], OC_NONE, DT_NONE)) {
|
||||
if (db) snprintf(buf2, BUFLEN, "finished startobclass, success.");
|
||||
|
@ -9130,9 +9147,8 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
|
|||
//obdb = B_FALSE;
|
||||
if (db) snprintf(buf2, BUFLEN, "finished startobclass. couldnt find an object.");
|
||||
}
|
||||
//if (strlen(buf) <= 0);
|
||||
}
|
||||
}
|
||||
} // end what is fid?
|
||||
|
||||
// TODO: maybe add object to temp cell, then MOVE it to the destination pile.
|
||||
// this will make sure the right checks happen.
|
||||
|
@ -9162,9 +9178,15 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
|
|||
// not worth any points
|
||||
addflag(o->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
} else if (isshop) {
|
||||
flag_t *f2;
|
||||
// all flags are known
|
||||
for (f2 = o->flags->first ; f2; f2 = f2->next) {
|
||||
f2->known = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end if o
|
||||
} // end foreach container flag
|
||||
|
||||
|
||||
// now remove startob flags so we don't get them again!
|
||||
|
@ -9216,14 +9238,36 @@ void givestartskills(lifeform_t *lf, flagpile_t *fp) {
|
|||
}
|
||||
|
||||
int gotosleep(lifeform_t *lf, int onpurpose) {
|
||||
char lightid[BUFLEN];
|
||||
strcpy(lightid, "");
|
||||
if (lfhasflag(lf, F_CAFFEINATED)) {
|
||||
if (isplayer(lf)) {
|
||||
msg("Your caffeine high prevents you from sleeping.");
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
if (onpurpose) taketime(lf, getactspeed(lf));
|
||||
addflag(lf->flags, F_ASLEEP, B_TRUE, lfhasflag(lf, F_MEDITATES) ? ST_MEDITATING : ST_ASLEEP, onpurpose ? B_TRUE : NA, NULL);
|
||||
if (onpurpose) {
|
||||
taketime(lf, getactspeed(lf));
|
||||
if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_GTAVERAGE) {
|
||||
object_t *o;
|
||||
// turn off light sources first
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_LIGHTSOURCE) && hasflag(o->flags, F_ACTIVATED)) {
|
||||
if (!strlen(lightid)) {
|
||||
// first one.
|
||||
if (isplayer(lf)) {
|
||||
char ch;
|
||||
ch = askchar("Turn off your light sources before resting?", "yn","y", B_TRUE, B_FALSE);
|
||||
if (ch != 'y') break;
|
||||
}
|
||||
sprintf(lightid, "%ld", o->id);
|
||||
}
|
||||
turnoff(lf, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addflag(lf->flags, F_ASLEEP, B_TRUE, lfhasflag(lf, F_MEDITATES) ? ST_MEDITATING : ST_ASLEEP, onpurpose ? B_TRUE : NA, lightid);
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -10908,6 +10952,7 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
|
|||
a->alive = B_TRUE;
|
||||
a->lastdam = strdup("nothing");
|
||||
a->lastdamtype = DT_NONE;
|
||||
a->lastdamlf = -1;
|
||||
a->damlastturn = 0;
|
||||
a->mplastturn = 0;
|
||||
a->stamlastturn = 0;
|
||||
|
@ -12305,6 +12350,12 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
|
|||
// fill in lastdam...
|
||||
lf->lastdamtype = damtype;
|
||||
|
||||
if (fromlf) {
|
||||
lf->lastdamlf = fromlf->id;
|
||||
} else {
|
||||
lf->lastdamlf = -1;
|
||||
}
|
||||
|
||||
// if they died
|
||||
if (lf->hp <= 0) {
|
||||
//if (!fromlf || (fromlf == player)) {
|
||||
|
@ -18167,7 +18218,18 @@ int rest(lifeform_t *lf, int onpurpose) {
|
|||
|
||||
killflagsofid(lf->flags, F_TRAINING);
|
||||
rf = isresting(lf);
|
||||
if (rf) killflag(rf);
|
||||
if (rf) {
|
||||
// since you've woken up normally, turn your light source back on.
|
||||
if (strlen(rf->text)) {
|
||||
object_t *light;
|
||||
light = hasobid(lf->pack, atol(rf->text));
|
||||
if (light) {
|
||||
turnon(lf, light);
|
||||
}
|
||||
}
|
||||
// kill sleeping flag
|
||||
killflag(rf);
|
||||
}
|
||||
wantclearmsg = B_FALSE;
|
||||
}
|
||||
}
|
||||
|
|
575
map.c
575
map.c
|
@ -69,6 +69,7 @@ cell_t *addcell(map_t *m, int x, int y) {
|
|||
setcelltype(cell, cell->habitat->solidcelltype);
|
||||
cell->lf = NULL;
|
||||
cell->room = NULL;
|
||||
cell->locked = B_FALSE;
|
||||
cell->lit = L_NOTLIT;
|
||||
cell->origlit = L_NOTLIT;
|
||||
cell->littimer = 0;
|
||||
|
@ -81,6 +82,7 @@ cell_t *addcell(map_t *m, int x, int y) {
|
|||
cell->knownglyph.colour = C_GREY;
|
||||
cell->visited = B_FALSE;
|
||||
cell->filled = B_FALSE;
|
||||
cell->isroomwall = D_NONE;
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
@ -1536,7 +1538,8 @@ object_t *gettopobject(cell_t *where, int forglyph) {
|
|||
for (o = where->obpile->first ; o ; o = o->next) {
|
||||
flag_t *f;
|
||||
// ignore hidden traps, but not secret doors
|
||||
if (hasflag(o->flags, F_SECRET) && !isdoor(o, NULL)) {
|
||||
if (isdeadob(o)) {
|
||||
} else if (hasflag(o->flags, F_SECRET) && !isdoor(o, NULL)) {
|
||||
} else if (hasflag(o->flags, F_INVISOB)) {
|
||||
} else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) {
|
||||
} else if (forglyph && hasflag(o->flags, F_NOGLYPH)) {
|
||||
|
@ -1560,7 +1563,8 @@ object_t *gettopobject(cell_t *where, int forglyph) {
|
|||
// appear first.
|
||||
for (o = where->obpile->last ; o ; o = o->prev) {
|
||||
if (o->type->obclass->id == sortorder[c]) {
|
||||
if (hasflag(o->flags, F_SECRET)) {
|
||||
if (isdeadob(o)) {
|
||||
} else if (hasflag(o->flags, F_SECRET)) {
|
||||
} else if (hasflag(o->flags, F_INVISOB)) {
|
||||
} else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) {
|
||||
} else if (forglyph && hasflag(o->flags, F_NOGLYPH)) {
|
||||
|
@ -1719,6 +1723,11 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int
|
|||
if (cell->room) {
|
||||
valid = B_FALSE;
|
||||
}
|
||||
// - overlap a 'locked' cell
|
||||
if (cell->locked) {
|
||||
valid = B_FALSE;
|
||||
}
|
||||
|
||||
|
||||
// is this cell adjacent to an empty cell and not a
|
||||
// corner (ie. a valid door location)
|
||||
|
@ -2074,13 +2083,14 @@ void createcave(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *
|
|||
void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) {
|
||||
int wantrooms = B_TRUE;
|
||||
int d;
|
||||
int x,y;
|
||||
int x,y,w,h;
|
||||
enum MAPSHAPE shape = MS_NORMAL;
|
||||
int i;
|
||||
int done,unused;
|
||||
int dir;
|
||||
int lastdir;
|
||||
int numrooms = 0;
|
||||
cell_t *cell, *c;
|
||||
cell_t *c,*centre;
|
||||
//object_t *o;
|
||||
int db = B_TRUE;
|
||||
int digdb = B_FALSE;
|
||||
|
@ -2091,10 +2101,12 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
int looppct = DEF_LOOPPCT;
|
||||
int minrooms = MINROOMS;
|
||||
int maxrooms = MAXROOMS;
|
||||
enum CORRIDORTYPE corridortype = CDT_NORMAL;
|
||||
|
||||
int moved = 0;
|
||||
|
||||
enum CELLTYPE emptycell,solidcell;
|
||||
char buf[BUFLEN];
|
||||
|
||||
// fill entire maze with walls
|
||||
for (y = 0; y < map->h; y++) {
|
||||
|
@ -2103,6 +2115,110 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
}
|
||||
}
|
||||
|
||||
// select dungeon shape.
|
||||
if (onein(3)) {
|
||||
shape = rnd(0,MAXMAPSHAPES-1);
|
||||
} else {
|
||||
shape = MS_NORMAL;
|
||||
}
|
||||
switch (shape) {
|
||||
case MS_NORMAL:// normal
|
||||
break;
|
||||
case MS_CROSS: // cross
|
||||
// ## ##
|
||||
// ## ##
|
||||
//
|
||||
// ## ##
|
||||
// ## ##
|
||||
for (y = 0; y < map->h/3; y++) {
|
||||
for (x = 0; x < map->w/3; x++) {
|
||||
c = getcellat(map, x, y); c->locked = B_TRUE;
|
||||
}
|
||||
for (x = map->w - (map->w/3); x < map->w; x++) {
|
||||
c = getcellat(map, x, y); c->locked = B_TRUE;
|
||||
}
|
||||
}
|
||||
for (y = map->h-(map->h/3); y < map->h; y++) {
|
||||
for (x = 0; x < map->w/3; x++) {
|
||||
c = getcellat(map, x, y); c->locked = B_TRUE;
|
||||
}
|
||||
for (x = map->w - (map->w/3); x < map->w; x++) {
|
||||
c = getcellat(map, x, y); c->locked = B_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MS_TURRET: // kind of a reverse cross
|
||||
// ##########
|
||||
// # #
|
||||
// # ## #
|
||||
// # ###### #
|
||||
// # ###### #
|
||||
// # ###### #
|
||||
// # ## #
|
||||
// # #
|
||||
// ##########
|
||||
for (y = (map->h/4); y < map->h/3; y++) {
|
||||
for (x = map->w/3; x < map->w - (map->w/3); x++) {
|
||||
c = getcellat(map, x, y); c->locked = B_TRUE;
|
||||
}
|
||||
}
|
||||
for (y = map->h/3; y < map->h - (map->h/3); y++) {
|
||||
for (x = map->w/4; x < map->w - (map->w/4); x++) {
|
||||
c = getcellat(map, x, y); c->locked = B_TRUE;
|
||||
}
|
||||
}
|
||||
for (y = map->h-(map->h/3); y < map->h - (map->h/4); y++) {
|
||||
for (x = map->w/3; x < map->w - (map->w/3); x++) {
|
||||
c = getcellat(map, x, y); c->locked = B_TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MS_CIRCLE: // circle / ellipse
|
||||
centre = getcellat(map, map->w/2, map->h/2);
|
||||
w = map->w - 5;
|
||||
h = map->h - 4;
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
float val;
|
||||
val = (pow(x - centre->x, 2) / pow(w/2, 2)) +
|
||||
(pow(y - centre->y, 2) / pow(h/2, 2));
|
||||
if (val > 1) {
|
||||
c = getcellat(map, x, y);
|
||||
c->locked = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
addflag(map->flags, F_MAPSHAPE, shape, NA, NA, NULL);
|
||||
|
||||
for (y = 0; y < map->h; y++) {
|
||||
strcpy(buf, "");
|
||||
for (x = 0; x < map->w; x++) {
|
||||
c = getcellat(map, x, y);
|
||||
if (c->locked) {
|
||||
c->visited = B_TRUE;
|
||||
}
|
||||
if (c->locked) {
|
||||
strcat(buf, "X");
|
||||
} else {
|
||||
strcat(buf, " ");
|
||||
}
|
||||
}
|
||||
dblog("%s",buf);
|
||||
}
|
||||
|
||||
// randomise dungeon parameters
|
||||
turnpct += (rnd(0,40)-20); // (-20 to +20)%
|
||||
sparseness += (rnd(0,20)-10); // -10 to +10
|
||||
looppct -= (rnd(0,10)); // subtrace 0 - 10
|
||||
|
||||
if (shape == MS_NORMAL) {
|
||||
if (onein(2)) {
|
||||
corridortype = CDT_SIMPLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// is the map lit?
|
||||
if (depth <= 5) {
|
||||
|
@ -2122,148 +2238,150 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
solidcell = map->habitat->solidcelltype;
|
||||
|
||||
// pick initial random spot
|
||||
cell = getrandomcell(map);
|
||||
setcelltype(cell, emptycell);
|
||||
cell->visited = B_TRUE;
|
||||
if (digdb) printf("- Starting (%d,%d)\n",cell->x, cell->y);
|
||||
if (corridortype == CDT_NORMAL) {
|
||||
c = getrandomcell(map);
|
||||
setcelltype(c, emptycell);
|
||||
c->visited = B_TRUE;
|
||||
if (digdb) printf("- Starting (%d,%d)\n",c->x, c->y);
|
||||
|
||||
lastdir = D_UNKNOWN;
|
||||
done = B_FALSE;
|
||||
lastdir = D_UNKNOWN;
|
||||
done = B_FALSE;
|
||||
|
||||
dir = D_NONE;
|
||||
|
||||
while (!done) {
|
||||
// get random direction based on turnpct
|
||||
dir = D_NONE;
|
||||
while (dir == D_NONE) {
|
||||
int badcount;
|
||||
if (digdb) printf("- At (%d,%d), moved %d, finding new direction...\n",cell->x, cell->y, moved);
|
||||
|
||||
dir = getnewdigdir(cell, lastdir, (moved < 2) ? 0 : turnpct, &moved);
|
||||
|
||||
badcount = 0;
|
||||
while (dir == D_NONE) {
|
||||
badcount++;
|
||||
if (badcount > 10) {
|
||||
// finish!
|
||||
done = B_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
// pick new EMPTY random spot
|
||||
cell = getrandomcell(map);
|
||||
while (!isempty(cell)) {
|
||||
cell = getrandomcell(map);
|
||||
}
|
||||
if (digdb) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",cell->x, cell->y);
|
||||
// pick a new random dir
|
||||
dir = getnewdigdir(cell, lastdir, turnpct, &moved);
|
||||
}
|
||||
if (!done) {
|
||||
if (digdb) printf("- Digging %s from (%d,%d).\n",getdirname(dir),cell->x, cell->y);
|
||||
}
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
// move to adjacent cell in the given direction
|
||||
cell = getcellindir(cell, dir);
|
||||
if (digdb) printf("- Now at (%d,%d)\n",cell->x, cell->y);
|
||||
moved++;
|
||||
while (!done) {
|
||||
// get random direction based on turnpct
|
||||
dir = D_NONE;
|
||||
while ((dir == D_NONE) && !done) {
|
||||
int badcount;
|
||||
if (digdb) printf("- At (%d,%d), moved %d, finding new direction...\n",c->x, c->y, moved);
|
||||
|
||||
// blank it
|
||||
setcelltype(cell,emptycell);
|
||||
cell->visited = B_TRUE;
|
||||
// mark surrounding cells as visited
|
||||
for (d = DC_N; d < MAXDIR_COMPASS; d++) {
|
||||
cell_t *thiscell;
|
||||
thiscell = getcellindir(cell, d);
|
||||
if (thiscell) {
|
||||
if (digdb) printf("* Marking surrounding cell in dir %d (%d,%d) as visited.\n",d, thiscell->x, thiscell->y);
|
||||
thiscell->visited = B_TRUE;
|
||||
dir = getnewdigdir(c, lastdir, (moved < 2) ? 0 : turnpct, &moved);
|
||||
|
||||
badcount = 0;
|
||||
while (dir == D_NONE) {
|
||||
badcount++;
|
||||
if (badcount > 10) {
|
||||
// finish!
|
||||
done = B_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
// pick new EMPTY random spot
|
||||
c = getrandomcell(map);
|
||||
while (!isempty(c)) {
|
||||
c = getrandomcell(map);
|
||||
}
|
||||
if (digdb) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",c->x, c->y);
|
||||
// pick a new random dir
|
||||
dir = getnewdigdir(c, lastdir, turnpct, &moved);
|
||||
}
|
||||
if (!done) {
|
||||
if (digdb) printf("- Digging %s from (%d,%d).\n",getdirname(dir),c->x, c->y);
|
||||
}
|
||||
}
|
||||
// remember last direction
|
||||
lastdir = dir;
|
||||
|
||||
// check if we have visited all valid cells
|
||||
unused = 0;
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
if (!done) {
|
||||
// move to adjacent cell in the given direction
|
||||
c = getcellindir(c, dir);
|
||||
if (digdb) printf("- Now at (%d,%d)\n",c->x, c->y);
|
||||
moved++;
|
||||
|
||||
// blank it
|
||||
setcelltype(c,emptycell);
|
||||
c->visited = B_TRUE;
|
||||
// mark surrounding cells as visited
|
||||
for (d = DC_N; d < MAXDIR_COMPASS; d++) {
|
||||
cell_t *thiscell;
|
||||
thiscell = getcellat(map, x, y);
|
||||
if (!thiscell->visited) {
|
||||
unused++;
|
||||
thiscell = getcellindir(c, d);
|
||||
if (thiscell) {
|
||||
if (digdb) printf("* Marking surrounding cell in dir %d (%d,%d) as visited.\n",d, thiscell->x, thiscell->y);
|
||||
thiscell->visited = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// remember last direction
|
||||
lastdir = dir;
|
||||
|
||||
if (!unused) {
|
||||
done = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (digdb) dblog("%d unused cell(s)\n",unused);
|
||||
//dumpmap(map);
|
||||
//getchar();
|
||||
|
||||
}
|
||||
|
||||
// use sparseness to cut down dead ends
|
||||
remove_deadends(map, sparseness);
|
||||
|
||||
// introduce loops
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
cell = getcellat(map, x, y);
|
||||
if (!cell->type->solid && countcellexits(cell, DT_ORTH) == 1) {
|
||||
// dead end - maybe make loop from here
|
||||
if (rnd(1,100) <= looppct) {
|
||||
int connected = B_FALSE;
|
||||
int loopok = B_TRUE;
|
||||
int dir;
|
||||
|
||||
// pick a random directory
|
||||
dir = getnewdigdir(cell, D_UNKNOWN,100, &moved);
|
||||
|
||||
if (dir == D_NONE) {
|
||||
// can't make a loop from here.
|
||||
loopok = B_FALSE;
|
||||
} else {
|
||||
int tries = 0;
|
||||
// if we go this dir, will we hit a
|
||||
// corridor?
|
||||
while (!isloopdirok(cell, dir)) {
|
||||
tries++;
|
||||
// tried every direction?
|
||||
if (tries >= MAXDIR_ORTH) {
|
||||
loopok = B_FALSE;
|
||||
break;
|
||||
}
|
||||
// turn...
|
||||
if (++dir >= MAXDIR_ORTH) {
|
||||
dir = 0;
|
||||
}
|
||||
// check if we have visited all valid cells
|
||||
unused = 0;
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
cell_t *thiscell;
|
||||
thiscell = getcellat(map, x, y);
|
||||
if (!thiscell->visited) {
|
||||
unused++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loopok) {
|
||||
// keep digging until we hit another corridor
|
||||
while (!connected) {
|
||||
cell_t *newcell;
|
||||
// find adjacent cell in the given direction
|
||||
newcell = getcellindir(cell, dir);
|
||||
if (!newcell) {
|
||||
connected = B_TRUE;
|
||||
} else {
|
||||
// have we hit another corridor yet?
|
||||
if (!newcell->type->solid) {
|
||||
if (!unused) {
|
||||
done = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (digdb) dblog("%d unused cell(s)\n",unused);
|
||||
//dumpmap(map);
|
||||
//getchar();
|
||||
|
||||
}
|
||||
|
||||
// use sparseness to cut down dead ends
|
||||
remove_deadends(map, sparseness);
|
||||
|
||||
// introduce loops
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
c = getcellat(map, x, y);
|
||||
if (!c->type->solid && countcellexits(c, DT_ORTH) == 1) {
|
||||
// dead end - maybe make loop from here
|
||||
if (rnd(1,100) <= looppct) {
|
||||
int connected = B_FALSE;
|
||||
int loopok = B_TRUE;
|
||||
int dir;
|
||||
|
||||
// pick a random directory
|
||||
dir = getnewdigdir(c, D_UNKNOWN,100, &moved);
|
||||
|
||||
if (dir == D_NONE) {
|
||||
// can't make a loop from here.
|
||||
loopok = B_FALSE;
|
||||
} else {
|
||||
int tries = 0;
|
||||
// if we go this dir, will we hit a
|
||||
// corridor?
|
||||
while (!isloopdirok(c, dir)) {
|
||||
tries++;
|
||||
// tried every direction?
|
||||
if (tries >= MAXDIR_ORTH) {
|
||||
loopok = B_FALSE;
|
||||
break;
|
||||
}
|
||||
// turn...
|
||||
if (++dir >= MAXDIR_ORTH) {
|
||||
dir = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loopok) {
|
||||
// keep digging until we hit another corridor
|
||||
while (!connected) {
|
||||
cell_t *newcell;
|
||||
// find adjacent cell in the given direction
|
||||
newcell = getcellindir(c, dir);
|
||||
if (!newcell) {
|
||||
connected = B_TRUE;
|
||||
} else {
|
||||
// blank adjacent cell
|
||||
setcelltype(newcell, emptycell);
|
||||
newcell->visited = B_TRUE;
|
||||
// have we hit another corridor yet?
|
||||
if (!newcell->type->solid) {
|
||||
connected = B_TRUE;
|
||||
} else {
|
||||
// blank adjacent cell
|
||||
setcelltype(newcell, emptycell);
|
||||
newcell->visited = B_TRUE;
|
||||
}
|
||||
c = newcell;
|
||||
}
|
||||
cell = newcell;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2301,8 +2419,10 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
}
|
||||
}
|
||||
|
||||
// now clear up dead ends again.
|
||||
remove_deadends(map, sparseness);
|
||||
if (corridortype == CDT_NORMAL) {
|
||||
// now clear up dead ends again.
|
||||
remove_deadends(map, sparseness);
|
||||
}
|
||||
|
||||
// link up room exits
|
||||
for (i = 0; i < map->nrooms; i++) {
|
||||
|
@ -2339,11 +2459,10 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
if (db) dblog("--> Will add %d pillars",numpillars);
|
||||
for (n = 0; n < numpillars;n++ ) {
|
||||
//dblog("----> Adding pillar %d/%d",n+1,numpillars);
|
||||
cell_t *c;
|
||||
c = getrandomroomcell(map, i);
|
||||
|
||||
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
|
||||
setcelltype(cell, CT_WALL);
|
||||
setcelltype(c, CT_WALL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2362,7 +2481,6 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
for (n = 0 ; n < numobs; n++) {
|
||||
int ntries = 0;
|
||||
int nmonsters = 0;
|
||||
cell_t *c;
|
||||
done = B_FALSE;
|
||||
while (!done) {
|
||||
c = getrandomroomcell(map, i);
|
||||
|
@ -3556,6 +3674,8 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r
|
|||
addvaultcellcontents(cell, v, x-minx,y-miny, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
markroomwalls(map, thisroom);
|
||||
}
|
||||
|
||||
if (retw) *retw = w;
|
||||
|
@ -3687,7 +3807,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
if ((roomid >= 0) && getroomid(c) == roomid) { // same room
|
||||
//if (wantfilled && c->type->solid) {
|
||||
if (c->type->solid) {
|
||||
// EXCEPTION:
|
||||
// This is an exception:
|
||||
// if startcell is a cell _inside_ the room as opposed to
|
||||
// a cell inside the room's walls.
|
||||
// in this case, we ARE allowed to travel through the room's walls.
|
||||
|
@ -3698,6 +3818,13 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
if (db) dblog(" going %s hits same room. invalid.", getdirname(d));
|
||||
break;
|
||||
}
|
||||
} else if (isroom(c) && (getroomid(c) != roomid) && (c->isroomwall != diropposite(d))) {
|
||||
// cell is in a different room, but not the correct edge
|
||||
// mark dir as invalid
|
||||
dist[d] = 999;
|
||||
sameroom[d] = B_FALSE;
|
||||
if (db) dblog(" going %s hits wrong wall of different room. invalid.", getdirname(d));
|
||||
break;
|
||||
} else if (cellwalkable(NULL, c, NULL)) {
|
||||
if (!wantfilled || c->filled) {
|
||||
// walkable and not in this vault. finished.
|
||||
|
@ -3715,13 +3842,17 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
for (n = 0; n <= 1; n++) {
|
||||
pcell = getcellindir(c, perpdir[n]);
|
||||
if (pcell) {
|
||||
if (((roomid == -1 ) || (getroomid(pcell) != roomid)) &&
|
||||
cellwalkable(NULL, pcell, NULL)) {
|
||||
if (!wantfilled || c->filled) {
|
||||
// finished.
|
||||
directendcell[d] = c;
|
||||
if (db) dblog(" can make %s path (hits adjacent empty cell at dist %d)", getdirname(d), dist[d]);
|
||||
break;
|
||||
int proomid;
|
||||
proomid = getroomid(pcell);
|
||||
if (((roomid == -1 ) || (proomid != roomid)) && cellwalkable(NULL, pcell, NULL)) {
|
||||
if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir[n]))) {
|
||||
} else {
|
||||
if (!wantfilled || c->filled) {
|
||||
// finished.
|
||||
directendcell[d] = c;
|
||||
if (db) dblog(" can make %s path (hits adjacent empty cell at dist %d)", getdirname(d), dist[d]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3797,17 +3928,15 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
int n;
|
||||
cell_t *c2;
|
||||
startdist++;
|
||||
// check left/right from this door for rooms
|
||||
// check left/right from this cell for rooms
|
||||
for (n = 0; n <= 1; n++) {
|
||||
int turndist = 0;
|
||||
c2 = getcellindir(c, perpdir[n]);
|
||||
|
||||
|
||||
while (c2) {
|
||||
int gotsolution = B_FALSE;
|
||||
turndist++;
|
||||
|
||||
|
||||
perpcell[nperpcells] = c2; // this will be used if we need to make 2 turns
|
||||
perpturncell1[nperpcells] = c;
|
||||
perpturndir1[nperpcells] = perpdir[n];
|
||||
|
@ -3825,6 +3954,13 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
if (db) dblog(" Got to an empty cell here.");
|
||||
gotsolution = B_TRUE;
|
||||
}
|
||||
} else if (isroom(c2) && (c2->isroomwall != diropposite(perpdir[n]))) {
|
||||
// wrong wall of room
|
||||
// mark dir as invalid
|
||||
dist[d] = 999;
|
||||
sameroom[d] = B_FALSE;
|
||||
if (db) dblog(" going %s hits wrong wall of different room. invalid.", getdirname(d));
|
||||
break;
|
||||
} else if (turndist > 1) {
|
||||
// check l/r too
|
||||
int perpdir2[2],nn;
|
||||
|
@ -3834,13 +3970,18 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
for (nn = 0; nn <= 1; nn++) {
|
||||
pcell = getcellindir(c2, perpdir2[nn]);
|
||||
if (pcell) {
|
||||
if ( ((roomid == -1) || (getroomid(pcell) != roomid)) &&
|
||||
int proomid;
|
||||
proomid = getroomid(pcell);
|
||||
if ( ((roomid == -1) || (proomid != roomid)) &&
|
||||
cellwalkable(NULL, pcell, NULL)) {
|
||||
if (!wantfilled || pcell->filled) {
|
||||
// finished.
|
||||
if (db) dblog(" Got to an empty cell next to us.");
|
||||
gotsolution = B_TRUE;
|
||||
break;
|
||||
if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir2[n]))) {
|
||||
} else {
|
||||
if (!wantfilled || pcell->filled) {
|
||||
// finished.
|
||||
if (db) dblog(" Got to an empty cell next to us.");
|
||||
gotsolution = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3919,6 +4060,13 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
if (db) dblog(" Got to an empty cell here.");
|
||||
gotsolution = B_TRUE;
|
||||
}
|
||||
} else if (isroom(c2) && (c2->isroomwall != diropposite(dir3[n]))) {
|
||||
// wrong wall of room
|
||||
// mark dir as invalid
|
||||
dist[d] = 999;
|
||||
sameroom[d] = B_FALSE;
|
||||
if (db) dblog(" going %s hits wrong wall of different room. invalid.", getdirname(d));
|
||||
break;
|
||||
} else if (turndist > 1) {
|
||||
// check l/r too
|
||||
int perpdir2[2],nn;
|
||||
|
@ -3928,13 +4076,19 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
for (nn = 0; nn <= 1; nn++) {
|
||||
pcell = getcellindir(c2, perpdir2[nn]);
|
||||
if (pcell) {
|
||||
if ( ((roomid == -1) || (getroomid(pcell) != roomid)) &&
|
||||
int proomid;
|
||||
proomid = getroomid(pcell);
|
||||
if ( ((roomid == -1) || (proomid != roomid)) &&
|
||||
cellwalkable(NULL, pcell, NULL)) {
|
||||
if (!wantfilled || pcell->filled) {
|
||||
// finished.
|
||||
if (db) dblog(" Got to an empty cell next to us.");
|
||||
gotsolution = B_TRUE;
|
||||
break;
|
||||
if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir2[nn]))) {
|
||||
// different room and hits wrong wall.
|
||||
} else {
|
||||
if (!wantfilled || pcell->filled) {
|
||||
// finished.
|
||||
if (db) dblog(" Got to an empty cell next to us.");
|
||||
gotsolution = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3959,7 +4113,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
if (turncell2) break;
|
||||
} // end foreach perpcell
|
||||
|
||||
// TODO: if we find a solution, fill in turncell2 and make path.
|
||||
// if we find a solution, fill in turncell2 and make path.
|
||||
if (turncell2) {
|
||||
if (db) dblog(" Twoturn solution found: Walk %s, then %s, then %s.",
|
||||
getdirname(startdir), getdirname(turndir), getdirname(turndir2));
|
||||
|
@ -4287,6 +4441,7 @@ void createroom(map_t *map, int roomid, int x1, int y1, int x2, int y2, int forc
|
|||
}
|
||||
}
|
||||
}
|
||||
markroomwalls(map, thisroom);
|
||||
}
|
||||
|
||||
// room w/h are returned in *w and *h if given.
|
||||
|
@ -4588,13 +4743,14 @@ void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *c
|
|||
|
||||
void finalisemap(map_t *map, object_t *entryob) {
|
||||
enum OBTYPE upstairtype, downstairtype;
|
||||
int i,d;
|
||||
int i,d,x,y;
|
||||
int linkedentry = B_FALSE;
|
||||
cell_t *c;
|
||||
object_t *o;
|
||||
// add staircases.
|
||||
// first dungeon level has 1 up stairs, 3 down.
|
||||
// subsequent levels always have 3 up and down stairs
|
||||
object_t *o,*nexto;
|
||||
// make sure this map has sufficient up/down staircases as defined by its
|
||||
// region type.
|
||||
//
|
||||
// first dungeon level is a special case. it has 1 up stairs, 3 down.
|
||||
switch (map->habitat->id) {
|
||||
case H_CAVE:
|
||||
upstairtype = OT_TUNNELUP;
|
||||
|
@ -4686,6 +4842,37 @@ void finalisemap(map_t *map, object_t *entryob) {
|
|||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < map->h; y++) {
|
||||
for (x = 0; x < map->w; x++) {
|
||||
c = getcellat(map, x, y);
|
||||
for (o = c->obpile->first ; o ; o = nexto) {
|
||||
nexto = o->next;
|
||||
// doors which go nowhere?
|
||||
if (isdoor(o, NULL)) {
|
||||
int dir, ok = B_FALSE;
|
||||
cell_t *c2;
|
||||
// check all directions for a cell which isn't
|
||||
// part of this room.
|
||||
for (dir = DC_N; dir <= DC_NW; dir++) {
|
||||
c2 = getcellindir(c, dir);
|
||||
if (c2 && cellwalkable(NULL, c2, NULL) && getroomid(c2) != getroomid(c)) {
|
||||
ok = B_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
killob(o);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// unlinked stairs? ie ones added from vaults. if so, link them.
|
||||
if (hasflag(o->flags, F_CLIMBABLE) && !hasflag(o->flags, F_MAPLINK)) {
|
||||
linkstairs(o, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
celltype_t *findcelltype(enum CELLTYPE cid) {
|
||||
|
@ -5488,8 +5675,8 @@ cell_t *getstairdestination(object_t *o, int *madenewmap) {
|
|||
// is there already a level of the correct depth?
|
||||
newmap = findregionmap(newregion->id, newdepth);
|
||||
if (newmap) {
|
||||
dblog("ERROR - unlinked stairs!\n");
|
||||
msg("ERROR - unlinked stairs!\n");
|
||||
dblog("ERROR - unlinked stairs! should have been linked during map creation.\n");
|
||||
msg("ERROR - unlinked stairs! should have been linked during map creation.\n");
|
||||
return NULL;
|
||||
} else {
|
||||
// generate a new map! this will fill in the destination of our stairs
|
||||
|
@ -5918,9 +6105,12 @@ int isloopdirok(cell_t *cell, int dir) {
|
|||
}
|
||||
|
||||
int isnewcellok(cell_t *cell, char *err) {
|
||||
if ( !cell) { // can't go that way
|
||||
if ( !cell ) { // can't go that way
|
||||
if (err) snprintf(err, BUFLEN,"goes off the map.");
|
||||
return B_FALSE;
|
||||
} else if ( cell->locked ) { // locked
|
||||
if (err) snprintf(err, BUFLEN,"locked.");
|
||||
return B_FALSE;
|
||||
} else if ( !cell->type->solid) { // already an empty space there
|
||||
if (err) snprintf(err, BUFLEN,"goes to an empty space (%d,%d)",cell->x,cell->y);
|
||||
return B_FALSE;
|
||||
|
@ -6071,7 +6261,7 @@ object_t *linkportal(object_t *srcportal, int wantdepth) {
|
|||
}
|
||||
|
||||
// link the staircase 'o' to a free one in adjacent maps.
|
||||
// o2 is optional. if not probided, we will try to find
|
||||
// o2 is optional. if o2 isn't provided, we will try to find
|
||||
// something to link to ourself.
|
||||
// returns TRUE if it failed because othermap doesn't exist.
|
||||
int linkstairs(object_t *o, object_t *o2) {
|
||||
|
@ -6276,6 +6466,59 @@ void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong) {
|
|||
}
|
||||
}
|
||||
|
||||
void markroomwalls(map_t *m, room_t *r) {
|
||||
int x,y;
|
||||
cell_t *c,*c2;
|
||||
// N edge
|
||||
for (x = r->x1+1; x <= r->x2-1; x++) {
|
||||
for (y = r->y1; y <= r->y2; y++) {
|
||||
c = getcellat(m, x, y);
|
||||
if (c->type->solid) {
|
||||
c2 = getcellindir(c, DC_S);
|
||||
if (c2 && !c2->type->solid) {
|
||||
c->isroomwall = DC_N;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// W edge
|
||||
for (y = r->y1+1; y <= r->y2-1; y++) {
|
||||
for (x = r->x2; x >= r->x1; x--) {
|
||||
c = getcellat(m, x, y);
|
||||
if (c->type->solid) {
|
||||
c2 = getcellindir(c, DC_W);
|
||||
if (c2 && !c2->type->solid) {
|
||||
c->isroomwall = DC_E;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// S edge
|
||||
for (x = r->x1+1; x <= r->x2-1; x++) {
|
||||
for (y = r->y2; y >= r->y1; y--) {
|
||||
c = getcellat(m, x, y);
|
||||
if (c->type->solid) {
|
||||
c2 = getcellindir(c, DC_N);
|
||||
if (c2 && !c2->type->solid) {
|
||||
c->isroomwall = DC_S;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// W edge
|
||||
for (y = r->y1+1; y <= r->y2-1; y++) {
|
||||
for (x = r->x1; x <= r->x2; x++) {
|
||||
c = getcellat(m, x, y);
|
||||
if (c->type->solid) {
|
||||
c2 = getcellindir(c, DC_E);
|
||||
if (c2 && !c2->type->solid) {
|
||||
c->isroomwall = DC_W;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mapentereffects(map_t *m) {
|
||||
int i;
|
||||
cell_t *c;
|
||||
|
|
1
map.h
1
map.h
|
@ -145,6 +145,7 @@ int linkstairs(object_t *o, object_t *o2);
|
|||
void makedoor(cell_t *cell, int openchance);
|
||||
void makelit(cell_t *c, enum LIGHTLEV how, int howlong);
|
||||
void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);
|
||||
void markroomwalls(map_t *m, room_t *r);
|
||||
void mapentereffects(map_t *m);
|
||||
void moveobtoclearcell(object_t *o);
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob);
|
||||
|
|
105
objects.c
105
objects.c
|
@ -1636,7 +1636,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
}
|
||||
break;
|
||||
case OM_MASTERWORK:
|
||||
if (isweapon(o) || isarmour(o)) {
|
||||
if (isweapon(o) || isarmour(o) || isdoor(o, NULL)) {
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_OBHP);
|
||||
if (f) {
|
||||
|
@ -1646,7 +1646,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
}
|
||||
break;
|
||||
case OM_SHODDY:
|
||||
if (isweapon(o) || isarmour(o)) {
|
||||
if (isweapon(o) || isarmour(o) || isdoor(o, NULL)) {
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_OBHP);
|
||||
if (f) {
|
||||
|
@ -4504,7 +4504,13 @@ char *getobextrainfo(object_t *o, char *buf) {
|
|||
|
||||
// charges
|
||||
f = hasflag(o->flags, F_CHARGES);
|
||||
if (f && f->known) {
|
||||
if (f) {
|
||||
int flagknown = B_FALSE;
|
||||
if (f->known) {
|
||||
flagknown = B_TRUE;
|
||||
} else if (ismagical(o) && (getskill(player, SK_CHANNELING) >= PR_MASTER)) {
|
||||
flagknown = B_TRUE;
|
||||
}
|
||||
if (!hasflag(o->flags, F_DONTSHOWCHARGES)) {
|
||||
char chargestr[BUFLEN];
|
||||
if (o->type->obclass->id == OC_GODSTONE) {
|
||||
|
@ -4991,7 +4997,11 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
|
|||
obmod_t *om;
|
||||
for (om = firstobmod ; om; om = om->next) {
|
||||
if (hasobmod(o, om)) {
|
||||
strcat(localbuf, om->prefix);
|
||||
char *p;
|
||||
p = getobmodprefix(o, om);
|
||||
if (p && strlen(p)) {
|
||||
strcat(localbuf, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8275,17 +8285,55 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
|
||||
// objects with charges...
|
||||
if (hasflag(o->flags, F_OPERUSECHARGE)) { // operating toggles on/off
|
||||
if (usecharge(o) == -1) {
|
||||
if (isplayer(lf)) {
|
||||
nothinghappens();
|
||||
if (isplayer(lf)) {
|
||||
int chargesleft;
|
||||
chargesleft = usecharge(o);
|
||||
f = hasflag(o->flags, F_CHARGES); // should always be true!
|
||||
if (chargesleft == -1) {
|
||||
if (f) f->known = B_TRUE;
|
||||
msg("Nothing happens - this item is empty.");
|
||||
// you know it's out
|
||||
f = hasflag(o->flags, F_CHARGES);
|
||||
f->known = B_TRUE;
|
||||
taketime(lf, getactspeed(lf));
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ismagical(o) && (o->pile->owner == lf)) {
|
||||
enum SKILLLEVEL slev;
|
||||
// depending on your channeling skill, you might
|
||||
// find out that it is running low.
|
||||
slev = getskill(lf, SK_CHANNELING);
|
||||
if (slev == PR_EXPERT) {
|
||||
if (f) f->known = B_TRUE;
|
||||
}
|
||||
if (slev && (chargesleft == 0)) {
|
||||
if (f) f->known = B_TRUE;
|
||||
msg("Your %s is now empty.", noprefix(obname));
|
||||
} else if (slev && chargesknown(o)) {
|
||||
if (f) f->known = B_TRUE;
|
||||
if (chargesleft == 1) {
|
||||
msg("Your %s only has one charge remaining.", noprefix(obname));
|
||||
} else {
|
||||
msg("Your %s now has %d charges remaining.", noprefix(obname), chargesleft);
|
||||
}
|
||||
} else {
|
||||
switch (slev) {
|
||||
case PR_INEPT:
|
||||
break;
|
||||
case PR_NOVICE: // notify when 1-3 charges left
|
||||
if (chargesleft <= 3) {
|
||||
msg("Your %s is running low on charges.", noprefix(obname));
|
||||
}
|
||||
break;
|
||||
case PR_BEGINNER: // charges known at 1, notify at 1-3
|
||||
if (chargesleft <= 3) {
|
||||
msg("Your %s is running low on charges.", noprefix(obname));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} // end if slev& chargesleft is 0
|
||||
} // end if chargesleft== -1 / ismagical
|
||||
} // end if isplayer
|
||||
} // end if hasflag operusecharge
|
||||
|
||||
// TODO: change to be based on item type
|
||||
// TODO: move this to the end in case 'operate' fails
|
||||
|
@ -10616,6 +10664,16 @@ int removeob(object_t *o,int howmany) {
|
|||
return rv;
|
||||
}
|
||||
|
||||
void resizeobject(object_t *o, enum LFSIZE wantsize) {
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_ARMOURSIZE);
|
||||
if (f) {
|
||||
f->val[0] = wantsize;
|
||||
} else {
|
||||
addflag(o->flags, F_ARMOURSIZE, wantsize, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void rrtorarity(enum RARITY r, int *minr, int *maxr) {
|
||||
switch (r) {
|
||||
case RR_UNIQUE:
|
||||
|
@ -12815,7 +12873,6 @@ void turnon(lifeform_t *lf, object_t *o) {
|
|||
held = B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
f = hasflag(o->flags, F_ACTIVATED);
|
||||
if (f) {
|
||||
// already on
|
||||
|
@ -13203,6 +13260,28 @@ int getcritchance(lifeform_t *lf, object_t *o, lifeform_t *victim) {
|
|||
return chance;
|
||||
}
|
||||
|
||||
int chargesknown(object_t *o) {
|
||||
flag_t *f;
|
||||
int cutoff = -2;
|
||||
f = hasflag(o->flags, F_CHARGES);
|
||||
if (f) {
|
||||
if (f->known) return B_TRUE;
|
||||
|
||||
switch (getskill(player, SK_CHANNELING)) {
|
||||
case PR_BEGINNER: cutoff = 1; break;
|
||||
case PR_ADEPT: cutoff = 3; break;
|
||||
case PR_SKILLED: cutoff = 6; break;
|
||||
case PR_EXPERT: break; // f->known will be set after use.
|
||||
case PR_MASTER: cutoff = 9999; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (f->val[0] <= cutoff) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
int getcritprotection(object_t *o) {
|
||||
flag_t *f;
|
||||
f = hasflag(o->flags, F_CRITPROTECTION);
|
||||
|
|
|
@ -34,6 +34,7 @@ int canseeob(lifeform_t *lf, object_t *o);
|
|||
object_t *canstackob(obpile_t *op, object_t *match);
|
||||
object_t *canstacknewot(obpile_t *op, objecttype_t *match);
|
||||
int changemat(object_t *o, enum MATERIAL mat);
|
||||
int chargesknown(object_t *o);
|
||||
int getcritprotection(object_t *o);
|
||||
int checkobnames(char *haystack, char *needle);
|
||||
void colourmatchob(object_t *o, lifeform_t *lf);
|
||||
|
@ -249,6 +250,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 resizeobject(object_t *o, enum LFSIZE wantsize);
|
||||
void rrtorarity(enum RARITY r, int *minr, int *maxr);
|
||||
void setblessed(object_t *o, enum BLESSTYPE wantbless);
|
||||
int sethiddenname(objecttype_t *o, char *text);
|
||||
|
|
8
save.c
8
save.c
|
@ -382,8 +382,8 @@ map_t *loadmap(char *basefile) {
|
|||
c = addcell(m, x, y);
|
||||
|
||||
// cell info
|
||||
fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
&roomid, &celltypeid, &c->known, &c->knowntime, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer,&temphab);
|
||||
fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
&roomid, &celltypeid, &c->known, &c->knowntime, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer,&c->locked, &temphab, &c->isroomwall);
|
||||
c->habitat = findhabitat(temphab);
|
||||
|
||||
c->room = findroom(m, roomid);
|
||||
|
@ -948,8 +948,8 @@ int savemap(map_t *m) {
|
|||
cell_t *c;
|
||||
c = getcellat(m, x, y);
|
||||
// cell info
|
||||
fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
c->room ? c->room->id : -1, c->type->id, c->known, c->knowntime, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer,c->habitat->id );
|
||||
fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
|
||||
c->room ? c->room->id : -1, c->type->id, c->known, c->knowntime, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer,c->locked, c->habitat->id, c->isroomwall );
|
||||
// cell objects
|
||||
for (o = c->obpile->first ; o ; o = o->next) {
|
||||
fprintf(f, "ob:%ld\n",o->id);
|
||||
|
|
55
shops.c
55
shops.c
|
@ -21,6 +21,7 @@
|
|||
#define DEF_REMCURSECOST 60
|
||||
#define DEF_BLESSCOST 50
|
||||
#define DEF_SURCHARGE 15
|
||||
#define DEF_RESIZECOST 80
|
||||
|
||||
extern enum GAMEMODE gamemode;
|
||||
extern prompt_t prompt;
|
||||
|
@ -158,6 +159,9 @@ void shop(lifeform_t *lf, object_t *vm) {
|
|||
} else if (curmenu == SM_REST) {
|
||||
shopfunc = shoprest;
|
||||
shoparg = &ndonated;
|
||||
} else if (curmenu == SM_RESIZE) {
|
||||
shopfunc = shopresize;
|
||||
shoparg = &ndonated;
|
||||
}
|
||||
|
||||
if (shopfunc) {
|
||||
|
@ -747,6 +751,57 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
|
|||
return SR_CONTINUE;
|
||||
}
|
||||
|
||||
enum SHOPRETURN shopresize(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
|
||||
object_t *o;
|
||||
char ch,buf[BUFLEN];
|
||||
int y;
|
||||
int resizecost;
|
||||
y = starty;
|
||||
|
||||
resizecost = applyshoppricemod(pctof(75, DEF_RESIZECOST), lf);
|
||||
|
||||
mvwprintw(mainwin, y, 0, "For just $%d per item, we can resize weapons or armour to fit you.", resizecost); y ++;
|
||||
mvwprintw(mainwin, y, 0, "(item quality will not be affected)"); y += 2;
|
||||
if (countmoney(player->pack) < resizecost) {
|
||||
msg("Sadly, you cannot afford the resizing fee.", resizecost);
|
||||
getch();
|
||||
return SR_BACK;
|
||||
} else {
|
||||
mvwprintw(mainwin, y, 0, "Pay to resize an item (you have $%d) [yn]? ", countmoney(lf->pack));
|
||||
}
|
||||
|
||||
ch = getch();
|
||||
if (ch != 'y') {
|
||||
return SR_BACK;
|
||||
}
|
||||
|
||||
// ask which object
|
||||
sprintf(buf, "Resize which object (you have $%d)?", countmoney(lf->pack));
|
||||
initprompt(&prompt, buf);
|
||||
for (o = player->pack->first ; o ; o = o->next) {
|
||||
if (hasflag(o->flags, F_MULTISIZE) && !armourfits(player, o, NULL)) {
|
||||
char costbuf[BUFLEN];
|
||||
getobname(o, buf, o->amt);
|
||||
sprintf(costbuf, "%-60s($%d)", buf, resizecost);
|
||||
addchoice(&prompt, o->letter, costbuf, costbuf, o, NULL);
|
||||
}
|
||||
}
|
||||
addchoice(&prompt, '-', "(nothing)", NULL, NULL, NULL);
|
||||
ch = getchoice(&prompt);
|
||||
|
||||
o = (object_t *)prompt.result;
|
||||
if (o) {
|
||||
msg("You hand over $%d.", resizecost); more();
|
||||
givemoney(player, NULL, resizecost);
|
||||
resizeobject(o, getlfsize(player)); // always go to player's size
|
||||
getobname(o, buf, 1);
|
||||
msgnocap("%c - %s", o->letter, buf);
|
||||
more();
|
||||
}
|
||||
|
||||
return SR_CONTINUE;
|
||||
}
|
||||
|
||||
enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
|
||||
char ch,obid[BUFLENSMALL],buf[BUFLEN];
|
||||
int y,i;
|
||||
|
|
1
shops.h
1
shops.h
|
@ -9,5 +9,6 @@ enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *topte
|
|||
enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
|
||||
enum SHOPRETURN shopmiracle(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
|
||||
enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
|
||||
enum SHOPRETURN shopresize(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
|
||||
enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
|
||||
|
||||
|
|
7
spell.c
7
spell.c
|
@ -1613,12 +1613,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
}
|
||||
|
||||
// resize it!
|
||||
f = hasflag(o->flags, F_ARMOURSIZE);
|
||||
if (f) {
|
||||
f->val[0] = wantsize;
|
||||
} else {
|
||||
addflag(o->flags, F_ARMOURSIZE, wantsize, NA, NA, NULL);
|
||||
}
|
||||
resizeobject(o, wantsize);
|
||||
|
||||
f = hasflag(o->flags, F_OBHP);
|
||||
if (f) {
|
||||
|
|
108
text.c
108
text.c
|
@ -18,6 +18,8 @@ extern long curtime;
|
|||
|
||||
extern lifeform_t *player;
|
||||
|
||||
extern enum GAMEMODE gamemode;
|
||||
|
||||
int needan(char *text) {
|
||||
if (isvowel(tolower(text[0]))) {
|
||||
return B_TRUE;
|
||||
|
@ -360,7 +362,7 @@ int getaccuracynum(int accpct) {
|
|||
|
||||
// returns a const char *
|
||||
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
|
||||
float pct;
|
||||
//float pct;
|
||||
enum LFSIZE ownersize = SZ_HUMAN;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
|
@ -369,7 +371,11 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
|
|||
ownersize = getlfsize(lf);
|
||||
}
|
||||
|
||||
pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
//pct = (int)(((float) dam / (float) maxhp) * 100.0);
|
||||
// base verb on amount of damage, not percentage of target.
|
||||
// reasoning: just because a monster has lots of hp, doesn't mean
|
||||
// you can only "scratch" it rather than "slice" it.
|
||||
//pct = (int)(((float) dam / 50.0) * 100.0);
|
||||
|
||||
if (wep) {
|
||||
int i;
|
||||
|
@ -380,15 +386,15 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
|
|||
if ((f->val[0] == NA) && (f->val[1] == NA)) {
|
||||
return f->text;
|
||||
} else if (f->val[0]) {
|
||||
if (pct >= f->val[0]) {
|
||||
if (dam >= f->val[0]) {
|
||||
if (f->val[1] == NA) {
|
||||
return f->text;
|
||||
} else if (pct <= f->val[1]) {
|
||||
} else if (dam <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
} else if (f->val[1]) {
|
||||
if (pct <= f->val[1]) {
|
||||
if (dam <= f->val[1]) {
|
||||
return f->text;
|
||||
}
|
||||
}
|
||||
|
@ -398,71 +404,75 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
|
|||
if (damtype == DT_ACID) {
|
||||
return "burn";
|
||||
} else if (damtype == DT_BASH) {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 2) {
|
||||
return "whack";
|
||||
} else if (pct <= 15) {
|
||||
} else if (dam <= 6) {
|
||||
if (onein(2)) {
|
||||
return "hit";
|
||||
} else {
|
||||
return "bash";
|
||||
}
|
||||
} else if (pct <= 25) {
|
||||
} else if (dam <= 12) {
|
||||
return "pummel";
|
||||
} else if (pct <= 35) {
|
||||
return "slam";
|
||||
} else {
|
||||
return "clobber";
|
||||
} else if (dam <= 18) {
|
||||
if (onein(2)) {
|
||||
return "slam";
|
||||
} else {
|
||||
return "clobber";
|
||||
}
|
||||
}
|
||||
} else if (damtype == DT_BITE) {
|
||||
if (lf && (ownersize <= SZ_SMALL)) {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 2) {
|
||||
return "nip";
|
||||
} else {
|
||||
return "bite";
|
||||
}
|
||||
} else {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 4) {
|
||||
return "gnaw";
|
||||
} else if (pct <= 30) {
|
||||
} else if (dam <= 8) {
|
||||
return "bite";
|
||||
} else {
|
||||
return "savage";
|
||||
}
|
||||
}
|
||||
} else if (damtype == DT_CHOP) {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 4) {
|
||||
return "chop";
|
||||
} else if (pct <= 15) {
|
||||
} else if (dam <= 8) {
|
||||
return "hack";
|
||||
} else {
|
||||
return "cleave";
|
||||
}
|
||||
} else if (damtype == DT_COLD) {
|
||||
if (pct <= 10) {
|
||||
if (dam <= 4) {
|
||||
return "chill";
|
||||
} else {
|
||||
return "freeze";
|
||||
}
|
||||
} else if (damtype == DT_CRUSH) {
|
||||
return "crush";
|
||||
return "crush";
|
||||
} else if (damtype == DT_ELECTRIC) {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 2) {
|
||||
return "zap";
|
||||
} else if (pct <= 15) {
|
||||
} else if (dam <= 6) {
|
||||
return "jolt";
|
||||
} else if (pct <= 20) {
|
||||
} else if (dam <= 12) {
|
||||
return "shock";
|
||||
} else if (pct <= 30) {
|
||||
} else if (dam <= 18) {
|
||||
return "electrify";
|
||||
} else {
|
||||
return "electrocute";
|
||||
}
|
||||
} else if ((damtype == DT_FIRE) || (damtype == DT_HEAT)) {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 2) {
|
||||
return "scorch";
|
||||
} else if (pct <= 20) {
|
||||
} else if (dam <= 6) {
|
||||
return "singe";
|
||||
} else if (dam <= 12) {
|
||||
return "burn";
|
||||
} else if (pct <= 40) {
|
||||
} else if (dam <= 18) {
|
||||
return "scald";
|
||||
} else {
|
||||
return "incinerate";
|
||||
|
@ -477,21 +487,21 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
|
|||
return "purify";
|
||||
}
|
||||
} else if (damtype == DT_MAGIC) {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 2) {
|
||||
return "zap";
|
||||
} else if (pct <= 15) {
|
||||
} else if (dam <= 6) {
|
||||
return "sear";
|
||||
} else if (pct <= 40) {
|
||||
} else {
|
||||
return "blast";
|
||||
}
|
||||
} else if (damtype == DT_PIERCE) {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 2) {
|
||||
return "poke";
|
||||
} else if (pct <= 15) {
|
||||
} else if (dam <= 6) {
|
||||
return "stab";
|
||||
} else if (pct <= 30) {
|
||||
} else if (dam <= 12) {
|
||||
return "pierce";
|
||||
} else if (pct <= 40) {
|
||||
} else if (dam <= 18) {
|
||||
return "spear";
|
||||
} else {
|
||||
return "deeply stab";
|
||||
|
@ -501,11 +511,11 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
|
|||
} else if (damtype == DT_PROJECTILE) {
|
||||
return "hit";
|
||||
} else if (damtype == DT_SLASH) {
|
||||
if (pct <= 5) {
|
||||
if (dam <= 2) {
|
||||
return "scratch";
|
||||
} else if (pct <= 15) {
|
||||
} else if (dam <= 6) {
|
||||
return "hit";
|
||||
} else if (pct <= 30) {
|
||||
} else if (dam <= 12) {
|
||||
return "slash";
|
||||
} else {
|
||||
return "slice";
|
||||
|
@ -909,6 +919,32 @@ char *getinjurydesc(enum BODYPART where, enum DAMTYPE dt) {
|
|||
return "";
|
||||
}
|
||||
|
||||
char *getobmodprefix(object_t *o, obmod_t *om) {
|
||||
// masterwork/shoddy doors have names based on material.
|
||||
if (isdoor(o, NULL)) {
|
||||
// player perceptive enough to notice?
|
||||
if (om->id == OM_MASTERWORK) {
|
||||
if ((gamemode == GM_GAMESTARTED) && (getskill(player, SK_PERCEPTION) < PR_BEGINNER)) {
|
||||
return NULL;
|
||||
}
|
||||
switch (o->material->id) {
|
||||
case MT_STONE: return "reinforced ";
|
||||
case MT_METAL: return "reinforced ";
|
||||
default: return "sturdy ";
|
||||
}
|
||||
} else if (om->id == OM_SHODDY) {
|
||||
if ((gamemode == GM_GAMESTARTED) && (getskill(player, SK_PERCEPTION) < PR_BEGINNER)) {
|
||||
return NULL;
|
||||
}
|
||||
switch (o->material->id) {
|
||||
case MT_STONE: return "crumbling ";
|
||||
case MT_METAL: return "rusted ";
|
||||
default: return "rotted ";
|
||||
}
|
||||
}
|
||||
}
|
||||
return om->prefix;
|
||||
}
|
||||
|
||||
char *getrarityname(enum RARITY rr) {
|
||||
switch (rr) {
|
||||
|
|
1
text.h
1
text.h
|
@ -26,6 +26,7 @@ char *getdrunktext(flag_t *drunkflag);
|
|||
char *getinjuredbpname(enum BODYPART bp);
|
||||
char *getinjuryname(enum DAMTYPE dt);
|
||||
char *getinjurydesc(enum BODYPART bp, enum DAMTYPE dt);
|
||||
char *getobmodprefix(object_t *o, obmod_t *om);
|
||||
char *getrarityname(enum RARITY rr);
|
||||
char *getregionname(char *buf, map_t *m, region_t *r, int withlevel);
|
||||
char *getreldirname(int reldir);
|
||||
|
|
Loading…
Reference in New Issue