- [+] 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:
Rob Pearce 2012-01-09 04:02:26 +00:00
parent 6d57f7ebe3
commit e1b569f306
15 changed files with 801 additions and 289 deletions

36
data.c
View File

@ -1246,6 +1246,7 @@ void initobjects(void) {
addflag(lastobjectclass->flags, F_UNIQUE, NA, NA, NA, NULL); addflag(lastobjectclass->flags, F_UNIQUE, NA, NA, NA, NULL);
addflag(lastobjectclass->flags, F_INVULNERABLE, B_TRUE, 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_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); addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addoc(OC_CORPSE, "Corpses", "Dead flesh which was once living.", '%', C_GREY, RR_NEVER); 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_OBHP, 20, 20, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_BASH, NA, 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_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); addot(OT_DOORIRON, "iron door", "A strong iron door.", MT_METAL, 300, OC_DFEATURE, SZ_LARGE);
// GLYPH here is a special case in getglyph // 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_CONTAINER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something"); 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, 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++) { for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_ARMOUR, RANDOM, NULL); 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_CONTAINER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something"); 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, 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++) { for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_WEAPON, RANDOM, NULL); 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_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_UNARMED, 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_UNARMEDWEP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ATTACKVERB, NA, 5, NA, "scratch"); addflag(lastot->flags, F_ATTACKVERB, NA, 2, NA, "scratch");
addflag(lastot->flags, F_ATTACKVERB, 6, 15, NA, "scrape"); addflag(lastot->flags, F_ATTACKVERB, 3, 6, NA, "scrape");
addflag(lastot->flags, F_ATTACKVERB, 16, NA, NA, "rake"); addflag(lastot->flags, F_ATTACKVERB, 7, NA, NA, "rake");
addot(OT_TEETH, "teeth", "teeth object", MT_BONE, 0, OC_WEAPON, SZ_TINY); 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); 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_DAM, DT_SLASH, 2, NA, NULL);
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, 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, NA, 2, NA, "scratch");
addflag(lastot->flags, F_ATTACKVERB, 6, 15, NA, "claw"); addflag(lastot->flags, F_ATTACKVERB, 3, 6, NA, "claw");
addflag(lastot->flags, F_ATTACKVERB, 16, 30, NA, "tear"); addflag(lastot->flags, F_ATTACKVERB, 7, 12, NA, "tear");
addflag(lastot->flags, F_ATTACKVERB, 31, 40, NA, "rake"); addflag(lastot->flags, F_ATTACKVERB, 13, 18, NA, "rake");
addflag(lastot->flags, F_ATTACKVERB, 41, 50, NA, "gouge"); addflag(lastot->flags, F_ATTACKVERB, 19, 24, NA, "gouge");
addflag(lastot->flags, F_ATTACKVERB, 51, NA, NA, "shred"); addflag(lastot->flags, F_ATTACKVERB, 25, NA, NA, "shred");
addflag(lastot->flags, F_KILLVERB, 70, NA, NA, "disembowel"); addflag(lastot->flags, F_KILLVERB, 70, NA, NA, "disembowel");
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_NONE, 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); 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_DAM, DT_BASH, 2, NA, NULL);
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, 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_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, 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); 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 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, "^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, "^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, "^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, "^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, "^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, "^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); 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_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); addskilldesc(SK_CLIMBING, PR_NOVICE, "You gain the 'climb walls' ability. Cannot attack while climbing.", B_FALSE);

26
defs.h
View File

@ -5,6 +5,7 @@
// MACROS // MACROS
#define MAXOF(a,b) (a > b ? a : b) #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 OB1(o,one,many) (o->amt == 1) ? one : many
#define OBS1(o) (o->amt == 1) ? "s" : "" #define OBS1(o) (o->amt == 1) ? "s" : ""
#define OBNOS1(o) (o->amt == 1) ? "" : "s" #define OBNOS1(o) (o->amt == 1) ? "" : "s"
@ -1986,6 +1987,7 @@ enum FLAG {
F_NONE = 0, // dummy flag F_NONE = 0, // dummy flag
// map flags // map flags
F_MAPCOORDS, // v0+v1 are x/y coords for this map area 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_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2
F_NEWWATERDEPTH, // temp flag for the spread of f_deepwater obs. F_NEWWATERDEPTH, // temp flag for the spread of f_deepwater obs.
// v0+1 are x/y, v2 is new depth. // v0+1 are x/y, v2 is new depth.
@ -2272,11 +2274,11 @@ enum FLAG {
F_SHODDY, // weps do less damage, armour protects less. F_SHODDY, // weps do less damage, armour protects less.
// weapon flags // weapon flags
F_ATTACKVERB, // text=verb for attacking. ie. "hit" "slash" "sting" etc 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. // between v0 and v1.
// should always be singular // should always be singular
F_KILLVERB, // text=verb for a fatal attacking. ie. "kill" "behead" 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. // between v0 and v1.
// should always be singular // should always be singular
F_OBATTACKDELAY, // how long weapon takes to attack F_OBATTACKDELAY, // how long weapon takes to attack
@ -2753,6 +2755,7 @@ enum FLAG {
// if v2 is set, means we are sleeping on // if v2 is set, means we are sleeping on
// purpose and will wake up when at full hp/mp/etc. // purpose and will wake up when at full hp/mp/etc.
// ie. "resting" // 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_ATTACHEDTO, // you are attached to lf id v0, and will move with it
F_AWARENESS, // you can see 360 degrees around yourself F_AWARENESS, // you can see 360 degrees around yourself
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn) F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
@ -3438,6 +3441,19 @@ typedef struct hiddennamewithcol_s {
enum COLOUR col; enum COLOUR col;
} hiddennamewithcol_t; } 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 { typedef struct cell_s {
map_t *map; // pointer back to map map_t *map; // pointer back to map
int x,y; // map coords int x,y; // map coords
@ -3455,12 +3471,15 @@ typedef struct cell_s {
char *writing; char *writing;
int writinglifetime; int writinglifetime;
int locked; // cannot make rooms on top of this.
// lifeform pile // lifeform pile
struct lifeform_s *lf; struct lifeform_s *lf;
// known to player? // known to player?
int known; int known;
struct glyph_s knownglyph; struct glyph_s knownglyph;
int knowntime; int knowntime;
int isroomwall;
// FOR CONSTRUCTION // FOR CONSTRUCTION
int visited; int visited;
@ -3527,6 +3546,7 @@ typedef struct lifeform_s {
int mp,maxmp; int mp,maxmp;
float stamina; float stamina;
int alive; int alive;
int lastdamlf; // id of lf who just hurt us
char *lastdam; char *lastdam;
char *killverb; char *killverb;
struct material_s *material; struct material_s *material;
@ -3852,6 +3872,8 @@ enum SHOPMENU {
SM_MIRACLE = -6, SM_MIRACLE = -6,
// motels // motels
SM_REST = -7, SM_REST = -7,
// weapon/armour shops
SM_RESIZE = -8,
}; };
enum SHOPRETURN { enum SHOPRETURN {

2
flag.c
View File

@ -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_RUNNING:
case F_TRAINING: case F_TRAINING:
case F_AUTOCMD: case F_AUTOCMD:
case F_PRODUCESLIGHT:
break; break;
case F_ASLEEP: case F_ASLEEP:
if (f->val[2] == NA) { // ie. sleeping, not resting if (f->val[2] == NA) { // ie. sleeping, not resting
@ -972,6 +973,7 @@ void killflag(flag_t *f) {
case F_RUNNING: case F_RUNNING:
case F_TRAINING: case F_TRAINING:
case F_AUTOCMD: case F_AUTOCMD:
case F_PRODUCESLIGHT:
break; break;
case F_ASLEEP: case F_ASLEEP:
if (f->val[2] != NA) { // ie. resting if (f->val[2] != NA) { // ie. resting

73
io.c
View File

@ -5357,42 +5357,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
strncat(retbuf, buf, HUGEBUFLEN); 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); f = hasflag(o->flags, F_PICKLOCKS);
if (f) { if (f) {
sprintf(buf, "You can use it to pick locks.\n"); 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 } // 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 // skip line
strncat(retbuf, "\n", HUGEBUFLEN); strncat(retbuf, "\n", HUGEBUFLEN);

84
lf.c
View File

@ -2290,6 +2290,11 @@ void die(lifeform_t *lf) {
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags; int nretflags;
cell_t *corpsecell; cell_t *corpsecell;
lifeform_t *killer = NULL;
if (lf->lastdamlf != -1) {
killer = findlf(lf->cell->map, lf->lastdamlf);
}
if (cansee(player, lf)) { if (cansee(player, lf)) {
needredraw = B_TRUE; needredraw = B_TRUE;
@ -2416,6 +2421,8 @@ void die(lifeform_t *lf) {
} }
} }
} else { } else {
lifeform_t *minion[MAXCANDIDATES];
int nminions = 0;
// intelligent monsters will say something // intelligent monsters will say something
if (!hasflag(lf->flags, F_NODEATHSPEECH)) { if (!hasflag(lf->flags, F_NODEATHSPEECH)) {
if (ispetof(lf, player)) { if (ispetof(lf, player)) {
@ -2473,6 +2480,19 @@ void die(lifeform_t *lf) {
// mercy god doesn't like killing // mercy god doesn't like killing
//angergodmaybe(R_GODMERCY, 1, GA_MURDER); //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 // determine where to drop objects
@ -4270,7 +4290,6 @@ int flee(lifeform_t *lf) {
real_getlfname(lf, lfname, B_FALSE); real_getlfname(lf, lfname, B_FALSE);
// are we fleeing? // are we fleeing?
getflags(lf->flags, retflag, &nretflags, F_FLEEFROM, F_NONE); getflags(lf->flags, retflag, &nretflags, F_FLEEFROM, F_NONE);
@ -8723,9 +8742,11 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
addflag(lf->flags, F_PHOTOMEM, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_PHOTOMEM, B_TRUE, NA, NA, NULL);
} }
if (f->val[1] == PR_MASTER) { if (f->val[1] == PR_MASTER) {
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 = addflag(lf->flags, F_CANWILL, OT_S_MAPPING, 50, 50, "pw:1;");
newf->lifetime = FROMSKILL; newf->lifetime = FROMSKILL;
} }
}
} else if (id == SK_COOKING) { } else if (id == SK_COOKING) {
if (f->val[1] == PR_ADEPT) { if (f->val[1] == PR_ADEPT) {
if (isplayer(lf)) { if (isplayer(lf)) {
@ -9053,8 +9074,6 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
case RANDOM: depthmod = rnd(0,MAXDEPTH); break; case RANDOM: depthmod = rnd(0,MAXDEPTH); break;
default: 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 (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"); if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water");
o = addob(op, buf); o = addob(op, buf);
@ -9103,7 +9122,6 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
} else { } else {
if (db) snprintf(buf2, BUFLEN, "finished startobwepsk, failed."); if (db) snprintf(buf2, BUFLEN, "finished startobwepsk, failed.");
} }
//assert(strlen(buf) > 0);
} }
} else if (id == F_STARTOBCLASS) { } else if (id == F_STARTOBCLASS) {
if (rnd(1,100) <= val[0]) { if (rnd(1,100) <= val[0]) {
@ -9120,7 +9138,6 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
} }
//obdb = B_TRUE; //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, if (real_getrandomob(targmap, buf, getmapdifficulty(targmap) + depthmod, NA, maxobsize, SK_NONE, B_TRUE,
val[1], OC_NONE, DT_NONE)) { val[1], OC_NONE, DT_NONE)) {
if (db) snprintf(buf2, BUFLEN, "finished startobclass, success."); 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; //obdb = B_FALSE;
if (db) snprintf(buf2, BUFLEN, "finished startobclass. couldnt find an object."); 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. // TODO: maybe add object to temp cell, then MOVE it to the destination pile.
// this will make sure the right checks happen. // 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 // not worth any points
addflag(o->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL); 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! // 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) { int gotosleep(lifeform_t *lf, int onpurpose) {
char lightid[BUFLEN];
strcpy(lightid, "");
if (lfhasflag(lf, F_CAFFEINATED)) { if (lfhasflag(lf, F_CAFFEINATED)) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("Your caffeine high prevents you from sleeping."); msg("Your caffeine high prevents you from sleeping.");
} }
return B_TRUE; return B_TRUE;
} }
if (onpurpose) taketime(lf, getactspeed(lf)); if (onpurpose) {
addflag(lf->flags, F_ASLEEP, B_TRUE, lfhasflag(lf, F_MEDITATES) ? ST_MEDITATING : ST_ASLEEP, onpurpose ? B_TRUE : NA, NULL); 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; 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->alive = B_TRUE;
a->lastdam = strdup("nothing"); a->lastdam = strdup("nothing");
a->lastdamtype = DT_NONE; a->lastdamtype = DT_NONE;
a->lastdamlf = -1;
a->damlastturn = 0; a->damlastturn = 0;
a->mplastturn = 0; a->mplastturn = 0;
a->stamlastturn = 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... // fill in lastdam...
lf->lastdamtype = damtype; lf->lastdamtype = damtype;
if (fromlf) {
lf->lastdamlf = fromlf->id;
} else {
lf->lastdamlf = -1;
}
// if they died // if they died
if (lf->hp <= 0) { if (lf->hp <= 0) {
//if (!fromlf || (fromlf == player)) { //if (!fromlf || (fromlf == player)) {
@ -18167,7 +18218,18 @@ int rest(lifeform_t *lf, int onpurpose) {
killflagsofid(lf->flags, F_TRAINING); killflagsofid(lf->flags, F_TRAINING);
rf = isresting(lf); 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; wantclearmsg = B_FALSE;
} }
} }

341
map.c
View File

@ -69,6 +69,7 @@ cell_t *addcell(map_t *m, int x, int y) {
setcelltype(cell, cell->habitat->solidcelltype); setcelltype(cell, cell->habitat->solidcelltype);
cell->lf = NULL; cell->lf = NULL;
cell->room = NULL; cell->room = NULL;
cell->locked = B_FALSE;
cell->lit = L_NOTLIT; cell->lit = L_NOTLIT;
cell->origlit = L_NOTLIT; cell->origlit = L_NOTLIT;
cell->littimer = 0; cell->littimer = 0;
@ -81,6 +82,7 @@ cell_t *addcell(map_t *m, int x, int y) {
cell->knownglyph.colour = C_GREY; cell->knownglyph.colour = C_GREY;
cell->visited = B_FALSE; cell->visited = B_FALSE;
cell->filled = B_FALSE; cell->filled = B_FALSE;
cell->isroomwall = D_NONE;
return cell; return cell;
} }
@ -1536,7 +1538,8 @@ object_t *gettopobject(cell_t *where, int forglyph) {
for (o = where->obpile->first ; o ; o = o->next) { for (o = where->obpile->first ; o ; o = o->next) {
flag_t *f; flag_t *f;
// ignore hidden traps, but not secret doors // 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_INVISOB)) {
} else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) { } else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) {
} else if (forglyph && hasflag(o->flags, F_NOGLYPH)) { } else if (forglyph && hasflag(o->flags, F_NOGLYPH)) {
@ -1560,7 +1563,8 @@ object_t *gettopobject(cell_t *where, int forglyph) {
// appear first. // appear first.
for (o = where->obpile->last ; o ; o = o->prev) { for (o = where->obpile->last ; o ; o = o->prev) {
if (o->type->obclass->id == sortorder[c]) { 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_INVISOB)) {
} else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) { } else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) {
} else if (forglyph && hasflag(o->flags, F_NOGLYPH)) { } 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) { if (cell->room) {
valid = B_FALSE; valid = B_FALSE;
} }
// - overlap a 'locked' cell
if (cell->locked) {
valid = B_FALSE;
}
// is this cell adjacent to an empty cell and not a // is this cell adjacent to an empty cell and not a
// corner (ie. a valid door location) // 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) { void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) {
int wantrooms = B_TRUE; int wantrooms = B_TRUE;
int d; int d;
int x,y; int x,y,w,h;
enum MAPSHAPE shape = MS_NORMAL;
int i; int i;
int done,unused; int done,unused;
int dir; int dir;
int lastdir; int lastdir;
int numrooms = 0; int numrooms = 0;
cell_t *cell, *c; cell_t *c,*centre;
//object_t *o; //object_t *o;
int db = B_TRUE; int db = B_TRUE;
int digdb = B_FALSE; 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 looppct = DEF_LOOPPCT;
int minrooms = MINROOMS; int minrooms = MINROOMS;
int maxrooms = MAXROOMS; int maxrooms = MAXROOMS;
enum CORRIDORTYPE corridortype = CDT_NORMAL;
int moved = 0; int moved = 0;
enum CELLTYPE emptycell,solidcell; enum CELLTYPE emptycell,solidcell;
char buf[BUFLEN];
// fill entire maze with walls // fill entire maze with walls
for (y = 0; y < map->h; y++) { 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? // is the map lit?
if (depth <= 5) { if (depth <= 5) {
@ -2122,10 +2238,11 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
solidcell = map->habitat->solidcelltype; solidcell = map->habitat->solidcelltype;
// pick initial random spot // pick initial random spot
cell = getrandomcell(map); if (corridortype == CDT_NORMAL) {
setcelltype(cell, emptycell); c = getrandomcell(map);
cell->visited = B_TRUE; setcelltype(c, emptycell);
if (digdb) printf("- Starting (%d,%d)\n",cell->x, cell->y); c->visited = B_TRUE;
if (digdb) printf("- Starting (%d,%d)\n",c->x, c->y);
lastdir = D_UNKNOWN; lastdir = D_UNKNOWN;
done = B_FALSE; done = B_FALSE;
@ -2135,11 +2252,11 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
while (!done) { while (!done) {
// get random direction based on turnpct // get random direction based on turnpct
dir = D_NONE; dir = D_NONE;
while (dir == D_NONE) { while ((dir == D_NONE) && !done) {
int badcount; int badcount;
if (digdb) printf("- At (%d,%d), moved %d, finding new direction...\n",cell->x, cell->y, moved); if (digdb) printf("- At (%d,%d), moved %d, finding new direction...\n",c->x, c->y, moved);
dir = getnewdigdir(cell, lastdir, (moved < 2) ? 0 : turnpct, &moved); dir = getnewdigdir(c, lastdir, (moved < 2) ? 0 : turnpct, &moved);
badcount = 0; badcount = 0;
while (dir == D_NONE) { while (dir == D_NONE) {
@ -2151,32 +2268,32 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
} }
// pick new EMPTY random spot // pick new EMPTY random spot
cell = getrandomcell(map); c = getrandomcell(map);
while (!isempty(cell)) { while (!isempty(c)) {
cell = getrandomcell(map); c = getrandomcell(map);
} }
if (digdb) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",cell->x, cell->y); if (digdb) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",c->x, c->y);
// pick a new random dir // pick a new random dir
dir = getnewdigdir(cell, lastdir, turnpct, &moved); dir = getnewdigdir(c, lastdir, turnpct, &moved);
} }
if (!done) { if (!done) {
if (digdb) printf("- Digging %s from (%d,%d).\n",getdirname(dir),cell->x, cell->y); if (digdb) printf("- Digging %s from (%d,%d).\n",getdirname(dir),c->x, c->y);
} }
} }
if (!done) { if (!done) {
// move to adjacent cell in the given direction // move to adjacent cell in the given direction
cell = getcellindir(cell, dir); c = getcellindir(c, dir);
if (digdb) printf("- Now at (%d,%d)\n",cell->x, cell->y); if (digdb) printf("- Now at (%d,%d)\n",c->x, c->y);
moved++; moved++;
// blank it // blank it
setcelltype(cell,emptycell); setcelltype(c,emptycell);
cell->visited = B_TRUE; c->visited = B_TRUE;
// mark surrounding cells as visited // mark surrounding cells as visited
for (d = DC_N; d < MAXDIR_COMPASS; d++) { for (d = DC_N; d < MAXDIR_COMPASS; d++) {
cell_t *thiscell; cell_t *thiscell;
thiscell = getcellindir(cell, d); thiscell = getcellindir(c, d);
if (thiscell) { if (thiscell) {
if (digdb) printf("* Marking surrounding cell in dir %d (%d,%d) as visited.\n",d, thiscell->x, thiscell->y); if (digdb) printf("* Marking surrounding cell in dir %d (%d,%d) as visited.\n",d, thiscell->x, thiscell->y);
thiscell->visited = B_TRUE; thiscell->visited = B_TRUE;
@ -2214,8 +2331,8 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
// introduce loops // introduce loops
for (y = 0; y < map->h; y++) { for (y = 0; y < map->h; y++) {
for (x = 0; x < map->w; x++) { for (x = 0; x < map->w; x++) {
cell = getcellat(map, x, y); c = getcellat(map, x, y);
if (!cell->type->solid && countcellexits(cell, DT_ORTH) == 1) { if (!c->type->solid && countcellexits(c, DT_ORTH) == 1) {
// dead end - maybe make loop from here // dead end - maybe make loop from here
if (rnd(1,100) <= looppct) { if (rnd(1,100) <= looppct) {
int connected = B_FALSE; int connected = B_FALSE;
@ -2223,7 +2340,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
int dir; int dir;
// pick a random directory // pick a random directory
dir = getnewdigdir(cell, D_UNKNOWN,100, &moved); dir = getnewdigdir(c, D_UNKNOWN,100, &moved);
if (dir == D_NONE) { if (dir == D_NONE) {
// can't make a loop from here. // can't make a loop from here.
@ -2232,7 +2349,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
int tries = 0; int tries = 0;
// if we go this dir, will we hit a // if we go this dir, will we hit a
// corridor? // corridor?
while (!isloopdirok(cell, dir)) { while (!isloopdirok(c, dir)) {
tries++; tries++;
// tried every direction? // tried every direction?
if (tries >= MAXDIR_ORTH) { if (tries >= MAXDIR_ORTH) {
@ -2251,7 +2368,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
while (!connected) { while (!connected) {
cell_t *newcell; cell_t *newcell;
// find adjacent cell in the given direction // find adjacent cell in the given direction
newcell = getcellindir(cell, dir); newcell = getcellindir(c, dir);
if (!newcell) { if (!newcell) {
connected = B_TRUE; connected = B_TRUE;
} else { } else {
@ -2263,7 +2380,8 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
setcelltype(newcell, emptycell); setcelltype(newcell, emptycell);
newcell->visited = B_TRUE; newcell->visited = B_TRUE;
} }
cell = newcell; c = newcell;
}
} }
} }
} }
@ -2301,8 +2419,10 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
} }
} }
if (corridortype == CDT_NORMAL) {
// now clear up dead ends again. // now clear up dead ends again.
remove_deadends(map, sparseness); remove_deadends(map, sparseness);
}
// link up room exits // link up room exits
for (i = 0; i < map->nrooms; i++) { 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); if (db) dblog("--> Will add %d pillars",numpillars);
for (n = 0; n < numpillars;n++ ) { for (n = 0; n < numpillars;n++ ) {
//dblog("----> Adding pillar %d/%d",n+1,numpillars); //dblog("----> Adding pillar %d/%d",n+1,numpillars);
cell_t *c;
c = getrandomroomcell(map, i); c = getrandomroomcell(map, i);
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) { 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++) { for (n = 0 ; n < numobs; n++) {
int ntries = 0; int ntries = 0;
int nmonsters = 0; int nmonsters = 0;
cell_t *c;
done = B_FALSE; done = B_FALSE;
while (!done) { while (!done) {
c = getrandomroomcell(map, i); 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); addvaultcellcontents(cell, v, x-minx,y-miny, rotation);
} }
} }
markroomwalls(map, thisroom);
} }
if (retw) *retw = w; 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 ((roomid >= 0) && getroomid(c) == roomid) { // same room
//if (wantfilled && c->type->solid) { //if (wantfilled && c->type->solid) {
if (c->type->solid) { if (c->type->solid) {
// EXCEPTION: // This is an exception:
// if startcell is a cell _inside_ the room as opposed to // if startcell is a cell _inside_ the room as opposed to
// a cell inside the room's walls. // a cell inside the room's walls.
// in this case, we ARE allowed to travel through 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)); if (db) dblog(" going %s hits same room. invalid.", getdirname(d));
break; 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)) { } else if (cellwalkable(NULL, c, NULL)) {
if (!wantfilled || c->filled) { if (!wantfilled || c->filled) {
// walkable and not in this vault. finished. // walkable and not in this vault. finished.
@ -3715,8 +3842,11 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
for (n = 0; n <= 1; n++) { for (n = 0; n <= 1; n++) {
pcell = getcellindir(c, perpdir[n]); pcell = getcellindir(c, perpdir[n]);
if (pcell) { if (pcell) {
if (((roomid == -1 ) || (getroomid(pcell) != roomid)) && int proomid;
cellwalkable(NULL, pcell, NULL)) { 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) { if (!wantfilled || c->filled) {
// finished. // finished.
directendcell[d] = c; directendcell[d] = c;
@ -3727,6 +3857,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
} }
} }
} }
}
// check next cell // check next cell
c = getcellindir(c, d); // getting the same cell! c = getcellindir(c, d); // getting the same cell!
} }
@ -3797,17 +3928,15 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
int n; int n;
cell_t *c2; cell_t *c2;
startdist++; startdist++;
// check left/right from this door for rooms // check left/right from this cell for rooms
for (n = 0; n <= 1; n++) { for (n = 0; n <= 1; n++) {
int turndist = 0; int turndist = 0;
c2 = getcellindir(c, perpdir[n]); c2 = getcellindir(c, perpdir[n]);
while (c2) { while (c2) {
int gotsolution = B_FALSE; int gotsolution = B_FALSE;
turndist++; turndist++;
perpcell[nperpcells] = c2; // this will be used if we need to make 2 turns perpcell[nperpcells] = c2; // this will be used if we need to make 2 turns
perpturncell1[nperpcells] = c; perpturncell1[nperpcells] = c;
perpturndir1[nperpcells] = perpdir[n]; 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."); if (db) dblog(" Got to an empty cell here.");
gotsolution = B_TRUE; 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) { } else if (turndist > 1) {
// check l/r too // check l/r too
int perpdir2[2],nn; int perpdir2[2],nn;
@ -3834,8 +3970,12 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
for (nn = 0; nn <= 1; nn++) { for (nn = 0; nn <= 1; nn++) {
pcell = getcellindir(c2, perpdir2[nn]); pcell = getcellindir(c2, perpdir2[nn]);
if (pcell) { if (pcell) {
if ( ((roomid == -1) || (getroomid(pcell) != roomid)) && int proomid;
proomid = getroomid(pcell);
if ( ((roomid == -1) || (proomid != roomid)) &&
cellwalkable(NULL, pcell, NULL)) { cellwalkable(NULL, pcell, NULL)) {
if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir2[n]))) {
} else {
if (!wantfilled || pcell->filled) { if (!wantfilled || pcell->filled) {
// finished. // finished.
if (db) dblog(" Got to an empty cell next to us."); if (db) dblog(" Got to an empty cell next to us.");
@ -3846,6 +3986,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
} }
} }
} }
}
if (gotsolution) { if (gotsolution) {
if (db) dblog(" Solution found: Walk %d %s, then %d %s.", if (db) dblog(" Solution found: Walk %d %s, then %d %s.",
startdist, getdirname(startdir), startdist, getdirname(startdir),
@ -3919,6 +4060,13 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
if (db) dblog(" Got to an empty cell here."); if (db) dblog(" Got to an empty cell here.");
gotsolution = B_TRUE; 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) { } else if (turndist > 1) {
// check l/r too // check l/r too
int perpdir2[2],nn; int perpdir2[2],nn;
@ -3928,8 +4076,13 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
for (nn = 0; nn <= 1; nn++) { for (nn = 0; nn <= 1; nn++) {
pcell = getcellindir(c2, perpdir2[nn]); pcell = getcellindir(c2, perpdir2[nn]);
if (pcell) { if (pcell) {
if ( ((roomid == -1) || (getroomid(pcell) != roomid)) && int proomid;
proomid = getroomid(pcell);
if ( ((roomid == -1) || (proomid != roomid)) &&
cellwalkable(NULL, pcell, NULL)) { cellwalkable(NULL, pcell, NULL)) {
if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir2[nn]))) {
// different room and hits wrong wall.
} else {
if (!wantfilled || pcell->filled) { if (!wantfilled || pcell->filled) {
// finished. // finished.
if (db) dblog(" Got to an empty cell next to us."); if (db) dblog(" Got to an empty cell next to us.");
@ -3940,6 +4093,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
} }
} }
} }
}
if (gotsolution) { if (gotsolution) {
turncell = perpturncell1[i]; turncell = perpturncell1[i];
turndir = perpturndir1[i]; turndir = perpturndir1[i];
@ -3959,7 +4113,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
if (turncell2) break; if (turncell2) break;
} // end foreach perpcell } // 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 (turncell2) {
if (db) dblog(" Twoturn solution found: Walk %s, then %s, then %s.", if (db) dblog(" Twoturn solution found: Walk %s, then %s, then %s.",
getdirname(startdir), getdirname(turndir), getdirname(turndir2)); 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. // 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) { void finalisemap(map_t *map, object_t *entryob) {
enum OBTYPE upstairtype, downstairtype; enum OBTYPE upstairtype, downstairtype;
int i,d; int i,d,x,y;
int linkedentry = B_FALSE; int linkedentry = B_FALSE;
cell_t *c; cell_t *c;
object_t *o; object_t *o,*nexto;
// add staircases. // make sure this map has sufficient up/down staircases as defined by its
// first dungeon level has 1 up stairs, 3 down. // region type.
// subsequent levels always have 3 up and down stairs //
// first dungeon level is a special case. it has 1 up stairs, 3 down.
switch (map->habitat->id) { switch (map->habitat->id) {
case H_CAVE: case H_CAVE:
upstairtype = OT_TUNNELUP; 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) { 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? // is there already a level of the correct depth?
newmap = findregionmap(newregion->id, newdepth); newmap = findregionmap(newregion->id, newdepth);
if (newmap) { if (newmap) {
dblog("ERROR - unlinked stairs!\n"); dblog("ERROR - unlinked stairs! should have been linked during map creation.\n");
msg("ERROR - unlinked stairs!\n"); msg("ERROR - unlinked stairs! should have been linked during map creation.\n");
return NULL; return NULL;
} else { } else {
// generate a new map! this will fill in the destination of our stairs // generate a new map! this will fill in the destination of our stairs
@ -5918,9 +6105,12 @@ int isloopdirok(cell_t *cell, int dir) {
} }
int isnewcellok(cell_t *cell, char *err) { 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."); if (err) snprintf(err, BUFLEN,"goes off the map.");
return B_FALSE; 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 } 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); if (err) snprintf(err, BUFLEN,"goes to an empty space (%d,%d)",cell->x,cell->y);
return B_FALSE; 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. // 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. // something to link to ourself.
// returns TRUE if it failed because othermap doesn't exist. // returns TRUE if it failed because othermap doesn't exist.
int linkstairs(object_t *o, object_t *o2) { 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) { void mapentereffects(map_t *m) {
int i; int i;
cell_t *c; cell_t *c;

1
map.h
View File

@ -145,6 +145,7 @@ int linkstairs(object_t *o, object_t *o2);
void makedoor(cell_t *cell, int openchance); void makedoor(cell_t *cell, int openchance);
void makelit(cell_t *c, enum LIGHTLEV how, int howlong); void makelit(cell_t *c, enum LIGHTLEV how, int howlong);
void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong); void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);
void markroomwalls(map_t *m, room_t *r);
void mapentereffects(map_t *m); void mapentereffects(map_t *m);
void moveobtoclearcell(object_t *o); void moveobtoclearcell(object_t *o);
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob); enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob);

View File

@ -1636,7 +1636,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
break; break;
case OM_MASTERWORK: case OM_MASTERWORK:
if (isweapon(o) || isarmour(o)) { if (isweapon(o) || isarmour(o) || isdoor(o, NULL)) {
flag_t *f; flag_t *f;
f = hasflag(o->flags, F_OBHP); f = hasflag(o->flags, F_OBHP);
if (f) { if (f) {
@ -1646,7 +1646,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
break; break;
case OM_SHODDY: case OM_SHODDY:
if (isweapon(o) || isarmour(o)) { if (isweapon(o) || isarmour(o) || isdoor(o, NULL)) {
flag_t *f; flag_t *f;
f = hasflag(o->flags, F_OBHP); f = hasflag(o->flags, F_OBHP);
if (f) { if (f) {
@ -4504,7 +4504,13 @@ char *getobextrainfo(object_t *o, char *buf) {
// charges // charges
f = hasflag(o->flags, F_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)) { if (!hasflag(o->flags, F_DONTSHOWCHARGES)) {
char chargestr[BUFLEN]; char chargestr[BUFLEN];
if (o->type->obclass->id == OC_GODSTONE) { 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; obmod_t *om;
for (om = firstobmod ; om; om = om->next) { for (om = firstobmod ; om; om = om->next) {
if (hasobmod(o, om)) { 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... // objects with charges...
if (hasflag(o->flags, F_OPERUSECHARGE)) { // operating toggles on/off if (hasflag(o->flags, F_OPERUSECHARGE)) { // operating toggles on/off
if (usecharge(o) == -1) {
if (isplayer(lf)) { if (isplayer(lf)) {
nothinghappens(); 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 // you know it's out
f = hasflag(o->flags, F_CHARGES);
f->known = B_TRUE;
taketime(lf, getactspeed(lf)); taketime(lf, getactspeed(lf));
return B_FALSE; 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: change to be based on item type
// TODO: move this to the end in case 'operate' fails // TODO: move this to the end in case 'operate' fails
@ -10616,6 +10664,16 @@ int removeob(object_t *o,int howmany) {
return rv; 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) { void rrtorarity(enum RARITY r, int *minr, int *maxr) {
switch (r) { switch (r) {
case RR_UNIQUE: case RR_UNIQUE:
@ -12815,7 +12873,6 @@ void turnon(lifeform_t *lf, object_t *o) {
held = B_TRUE; held = B_TRUE;
} }
f = hasflag(o->flags, F_ACTIVATED); f = hasflag(o->flags, F_ACTIVATED);
if (f) { if (f) {
// already on // already on
@ -13203,6 +13260,28 @@ int getcritchance(lifeform_t *lf, object_t *o, lifeform_t *victim) {
return chance; 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) { int getcritprotection(object_t *o) {
flag_t *f; flag_t *f;
f = hasflag(o->flags, F_CRITPROTECTION); f = hasflag(o->flags, F_CRITPROTECTION);

View File

@ -34,6 +34,7 @@ int canseeob(lifeform_t *lf, object_t *o);
object_t *canstackob(obpile_t *op, object_t *match); object_t *canstackob(obpile_t *op, object_t *match);
object_t *canstacknewot(obpile_t *op, objecttype_t *match); object_t *canstacknewot(obpile_t *op, objecttype_t *match);
int changemat(object_t *o, enum MATERIAL mat); int changemat(object_t *o, enum MATERIAL mat);
int chargesknown(object_t *o);
int getcritprotection(object_t *o); int getcritprotection(object_t *o);
int checkobnames(char *haystack, char *needle); int checkobnames(char *haystack, char *needle);
void colourmatchob(object_t *o, lifeform_t *lf); 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); void removedeadobs(obpile_t *op);
int removeob(object_t *o, int howmany); int removeob(object_t *o, int howmany);
object_t *relinkob(object_t *src, obpile_t *dst); 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 rrtorarity(enum RARITY r, int *minr, int *maxr);
void setblessed(object_t *o, enum BLESSTYPE wantbless); void setblessed(object_t *o, enum BLESSTYPE wantbless);
int sethiddenname(objecttype_t *o, char *text); int sethiddenname(objecttype_t *o, char *text);

8
save.c
View File

@ -382,8 +382,8 @@ map_t *loadmap(char *basefile) {
c = addcell(m, x, y); c = addcell(m, x, y);
// cell info // cell info
fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", 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,&temphab); &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->habitat = findhabitat(temphab);
c->room = findroom(m, roomid); c->room = findroom(m, roomid);
@ -948,8 +948,8 @@ int savemap(map_t *m) {
cell_t *c; cell_t *c;
c = getcellat(m, x, y); c = getcellat(m, x, y);
// cell info // cell info
fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", 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->habitat->id ); 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 // cell objects
for (o = c->obpile->first ; o ; o = o->next) { for (o = c->obpile->first ; o ; o = o->next) {
fprintf(f, "ob:%ld\n",o->id); fprintf(f, "ob:%ld\n",o->id);

55
shops.c
View File

@ -21,6 +21,7 @@
#define DEF_REMCURSECOST 60 #define DEF_REMCURSECOST 60
#define DEF_BLESSCOST 50 #define DEF_BLESSCOST 50
#define DEF_SURCHARGE 15 #define DEF_SURCHARGE 15
#define DEF_RESIZECOST 80
extern enum GAMEMODE gamemode; extern enum GAMEMODE gamemode;
extern prompt_t prompt; extern prompt_t prompt;
@ -158,6 +159,9 @@ void shop(lifeform_t *lf, object_t *vm) {
} else if (curmenu == SM_REST) { } else if (curmenu == SM_REST) {
shopfunc = shoprest; shopfunc = shoprest;
shoparg = &ndonated; shoparg = &ndonated;
} else if (curmenu == SM_RESIZE) {
shopfunc = shopresize;
shoparg = &ndonated;
} }
if (shopfunc) { if (shopfunc) {
@ -747,6 +751,57 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
return SR_CONTINUE; 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) { enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
char ch,obid[BUFLENSMALL],buf[BUFLEN]; char ch,obid[BUFLENSMALL],buf[BUFLEN];
int y,i; int y,i;

View File

@ -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 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 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 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); enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);

View File

@ -1613,12 +1613,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
// resize it! // resize it!
f = hasflag(o->flags, F_ARMOURSIZE); resizeobject(o, wantsize);
if (f) {
f->val[0] = wantsize;
} else {
addflag(o->flags, F_ARMOURSIZE, wantsize, NA, NA, NULL);
}
f = hasflag(o->flags, F_OBHP); f = hasflag(o->flags, F_OBHP);
if (f) { if (f) {

100
text.c
View File

@ -18,6 +18,8 @@ extern long curtime;
extern lifeform_t *player; extern lifeform_t *player;
extern enum GAMEMODE gamemode;
int needan(char *text) { int needan(char *text) {
if (isvowel(tolower(text[0]))) { if (isvowel(tolower(text[0]))) {
return B_TRUE; return B_TRUE;
@ -360,7 +362,7 @@ int getaccuracynum(int accpct) {
// returns a const char * // returns a const char *
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) { char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
float pct; //float pct;
enum LFSIZE ownersize = SZ_HUMAN; enum LFSIZE ownersize = SZ_HUMAN;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags = 0; int nretflags = 0;
@ -369,7 +371,11 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
ownersize = getlfsize(lf); 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) { if (wep) {
int i; 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)) { if ((f->val[0] == NA) && (f->val[1] == NA)) {
return f->text; return f->text;
} else if (f->val[0]) { } else if (f->val[0]) {
if (pct >= f->val[0]) { if (dam >= f->val[0]) {
if (f->val[1] == NA) { if (f->val[1] == NA) {
return f->text; return f->text;
} else if (pct <= f->val[1]) { } else if (dam <= f->val[1]) {
return f->text; return f->text;
} }
} }
} else if (f->val[1]) { } else if (f->val[1]) {
if (pct <= f->val[1]) { if (dam <= f->val[1]) {
return f->text; return f->text;
} }
} }
@ -398,47 +404,49 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
if (damtype == DT_ACID) { if (damtype == DT_ACID) {
return "burn"; return "burn";
} else if (damtype == DT_BASH) { } else if (damtype == DT_BASH) {
if (pct <= 5) { if (dam <= 2) {
return "whack"; return "whack";
} else if (pct <= 15) { } else if (dam <= 6) {
if (onein(2)) { if (onein(2)) {
return "hit"; return "hit";
} else { } else {
return "bash"; return "bash";
} }
} else if (pct <= 25) { } else if (dam <= 12) {
return "pummel"; return "pummel";
} else if (pct <= 35) { } else if (dam <= 18) {
if (onein(2)) {
return "slam"; return "slam";
} else { } else {
return "clobber"; return "clobber";
} }
}
} else if (damtype == DT_BITE) { } else if (damtype == DT_BITE) {
if (lf && (ownersize <= SZ_SMALL)) { if (lf && (ownersize <= SZ_SMALL)) {
if (pct <= 5) { if (dam <= 2) {
return "nip"; return "nip";
} else { } else {
return "bite"; return "bite";
} }
} else { } else {
if (pct <= 5) { if (dam <= 4) {
return "gnaw"; return "gnaw";
} else if (pct <= 30) { } else if (dam <= 8) {
return "bite"; return "bite";
} else { } else {
return "savage"; return "savage";
} }
} }
} else if (damtype == DT_CHOP) { } else if (damtype == DT_CHOP) {
if (pct <= 5) { if (dam <= 4) {
return "chop"; return "chop";
} else if (pct <= 15) { } else if (dam <= 8) {
return "hack"; return "hack";
} else { } else {
return "cleave"; return "cleave";
} }
} else if (damtype == DT_COLD) { } else if (damtype == DT_COLD) {
if (pct <= 10) { if (dam <= 4) {
return "chill"; return "chill";
} else { } else {
return "freeze"; return "freeze";
@ -446,23 +454,25 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
} else if (damtype == DT_CRUSH) { } else if (damtype == DT_CRUSH) {
return "crush"; return "crush";
} else if (damtype == DT_ELECTRIC) { } else if (damtype == DT_ELECTRIC) {
if (pct <= 5) { if (dam <= 2) {
return "zap"; return "zap";
} else if (pct <= 15) { } else if (dam <= 6) {
return "jolt"; return "jolt";
} else if (pct <= 20) { } else if (dam <= 12) {
return "shock"; return "shock";
} else if (pct <= 30) { } else if (dam <= 18) {
return "electrify"; return "electrify";
} else { } else {
return "electrocute"; return "electrocute";
} }
} else if ((damtype == DT_FIRE) || (damtype == DT_HEAT)) { } else if ((damtype == DT_FIRE) || (damtype == DT_HEAT)) {
if (pct <= 5) { if (dam <= 2) {
return "scorch"; return "scorch";
} else if (pct <= 20) { } else if (dam <= 6) {
return "singe";
} else if (dam <= 12) {
return "burn"; return "burn";
} else if (pct <= 40) { } else if (dam <= 18) {
return "scald"; return "scald";
} else { } else {
return "incinerate"; return "incinerate";
@ -477,21 +487,21 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
return "purify"; return "purify";
} }
} else if (damtype == DT_MAGIC) { } else if (damtype == DT_MAGIC) {
if (pct <= 5) { if (dam <= 2) {
return "zap"; return "zap";
} else if (pct <= 15) { } else if (dam <= 6) {
return "sear"; return "sear";
} else if (pct <= 40) { } else {
return "blast"; return "blast";
} }
} else if (damtype == DT_PIERCE) { } else if (damtype == DT_PIERCE) {
if (pct <= 5) { if (dam <= 2) {
return "poke"; return "poke";
} else if (pct <= 15) { } else if (dam <= 6) {
return "stab"; return "stab";
} else if (pct <= 30) { } else if (dam <= 12) {
return "pierce"; return "pierce";
} else if (pct <= 40) { } else if (dam <= 18) {
return "spear"; return "spear";
} else { } else {
return "deeply stab"; 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) { } else if (damtype == DT_PROJECTILE) {
return "hit"; return "hit";
} else if (damtype == DT_SLASH) { } else if (damtype == DT_SLASH) {
if (pct <= 5) { if (dam <= 2) {
return "scratch"; return "scratch";
} else if (pct <= 15) { } else if (dam <= 6) {
return "hit"; return "hit";
} else if (pct <= 30) { } else if (dam <= 12) {
return "slash"; return "slash";
} else { } else {
return "slice"; return "slice";
@ -909,6 +919,32 @@ char *getinjurydesc(enum BODYPART where, enum DAMTYPE dt) {
return ""; 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) { char *getrarityname(enum RARITY rr) {
switch (rr) { switch (rr) {

1
text.h
View File

@ -26,6 +26,7 @@ char *getdrunktext(flag_t *drunkflag);
char *getinjuredbpname(enum BODYPART bp); char *getinjuredbpname(enum BODYPART bp);
char *getinjuryname(enum DAMTYPE dt); char *getinjuryname(enum DAMTYPE dt);
char *getinjurydesc(enum BODYPART bp, 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 *getrarityname(enum RARITY rr);
char *getregionname(char *buf, map_t *m, region_t *r, int withlevel); char *getregionname(char *buf, map_t *m, region_t *r, int withlevel);
char *getreldirname(int reldir); char *getreldirname(int reldir);