- [+] make ring of invisibility also drain your hp!

- [+] monster with tremorsense can 'hear'
- [+] allow attacking of wall cells with normal melee attacks
    - [+] glass should shatter
- [+] option: stop running on hearing a sound
- [+] make describerace use downline().
- [+] make certain strengths and weaknesses not show up in player
      selection
- [+] An uncursed manriki wraps around the hawk.  The hawk falls to the
      ground.
      A black bear comes into view.
      You critically scratch #.  The black bear roars.
    - [+] check construct_hit_string.
    - [+] i was hitting a hawk.
- [+] still some entrances overlapping glyphs.
    - [+] genericise checking code in fix_Reachabilty
    - [+] Also: in fix_reachability, disallow linking to cells which:
        - [+] are adjacent to a door
        - [+] are part of a vault with maintain_edge, and are 't marked
              as exits.
    - [+] looking a bit better now...
- [+] incorrect glyph colour for animated zombies
- [+] grow/shrink potions? to change lf size to fit armour.
    - [+] resizelf()
    - [+] modification spell (l2)
        - [+] grow
        - [+] shrink
    - [+] potions
        - [+] cursed growth does shrink
- [+] make rare monsters / objects only sometimes be known.
This commit is contained in:
Rob Pearce 2012-01-12 01:28:07 +00:00
parent 4cff04558c
commit bbaca368e7
31 changed files with 788 additions and 232 deletions

202
attack.c
View File

@ -157,6 +157,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
AT_NONE = 0, AT_NONE = 0,
AT_LF = 1, AT_LF = 1,
AT_OB = 2, AT_OB = 2,
AT_WALL = 3,
} attacktype = AT_NONE; } attacktype = AT_NONE;
void *attacktarget; void *attacktarget;
int attacklfid = -1; int attacklfid = -1;
@ -279,31 +280,16 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
attacktype = AT_OB; attacktype = AT_OB;
attacktarget = o; attacktarget = o;
} else { } else {
// TODO: attack wall?
if (!lfhasflag(lf, F_HURRICANESTRIKE)) { if (!lfhasflag(lf, F_HURRICANESTRIKE)) {
/* if (c->type->solid) {
flag_t *sf; attacktype = AT_WALL;
lifeform_t *stomachlf = NULL; attacktarget = c;
sf = hasflag(lf->cell->map->flags, F_STOMACHOF);
if (sf) {
stomachlf = findlf(NULL, sf->val[0]);
}
// we ARE allowed to attack stomach walls.
if (sf && stomachlf && (c->type->id == CT_WALLFLESH)) {
attacktype = AT_LF;
attacktarget = stomachlf;
} else { } else {
// not allowed to attack normal walls
if (isplayer(lf)) { if (isplayer(lf)) {
msg("There is nothing there to attack!"); msg("There is nothing there to attack!");
} }
return B_TRUE; return B_TRUE;
} }
*/
if (isplayer(lf)) {
msg("There is nothing there to attack!");
}
return B_TRUE;
} // end if !hurricanestrike } // end if !hurricanestrike
} }
} }
@ -450,6 +436,12 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
attacksdone = maxattacks; attacksdone = maxattacks;
break; break;
} }
} else if (attacktype == AT_WALL) {
if (attackwall(lf, (cell_t *)attacktarget, wep[i], damflag[i])) {
// failed
attacksdone = maxattacks;
break;
}
} }
attacksdone++; attacksdone++;
@ -680,7 +672,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
object_t *armour; object_t *armour;
char noun[BUFLEN]; char noun[BUFLEN];
critpos = getrandomcorebp(victim, lf); critpos = getrandomcorebp(victim, lf);
if (critpos != BP_NONE) { if (critpos == BP_NONE) {
strcpy(victimbpname, victimname);
} else {
armour = getequippedob(victim->pack, critpos); armour = getequippedob(victim->pack, critpos);
if (armour) { if (armour) {
char armname[BUFLEN]; char armname[BUFLEN];
@ -711,7 +705,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
getlfname(victim, victimname); getlfname(victim, victimname);
} }
// weapon passing through ghosts etc? // weapon passing through ghosts etc?
if (hit) { if (hit) {
if (lfhasflag(victim, F_NONCORPOREAL) && if (lfhasflag(victim, F_NONCORPOREAL) &&
@ -1402,13 +1395,17 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
if (isplayer(lf) && hasflag(o->flags, F_LOCKED)) { if (isplayer(lf) && hasflag(o->flags, F_LOCKED)) {
angergodmaybe(R_GODTHIEVES, 25, GA_MONEY); angergodmaybe(R_GODTHIEVES, 25, GA_MONEY);
} }
if (isdeadob(o)) {
break;
}
} // end foreach damtype } // end foreach damtype
if (!isdeadob(o)) {
// special weapon effects, as long as you're not doing a heavy blow // special weapon effects, as long as you're not doing a heavy blow
if (!lfhasflag(lf, F_HEAVYBLOW) && dam[0]) { if (!lfhasflag(lf, F_HEAVYBLOW) && dam[0]) {
wepeffects(wep->flags, obloc, damflag, dam[0]); wepeffects(wep->flags, obloc, damflag, dam[0]);
} }
}
if (isunarmed) { if (isunarmed) {
// touch effects // touch effects
@ -1426,6 +1423,169 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
return B_FALSE; return B_FALSE;
} }
int attackwall(lifeform_t *lf, cell_t *c, object_t *wep, flag_t *damflag) {
int dam[100];
enum DAMTYPE damtype[100];
int ndam = 0;
char attackername[BUFLEN];
char obname[BUFLEN];
int isunarmed = B_FALSE;
char buf[BUFLEN];
int i;
int maxhp;
moveeffects(lf);
if (isdead(lf)) return B_TRUE;
maxhp = c->type->hp;
// get names
getlfname(lf, attackername);
// don't need to figure out accuracy - we always hit.
// determine damage
ndam = 0;
//if (unarmedflag && (unarmedflag->val[0] != NA)) {
dam[ndam] = getdamroll(wep, NULL, damflag);
// modify for strength
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
dam[ndam] = (int)((float)dam[ndam] * getstrdammod(lf));
}
// damtype?
damtype[ndam] = getdamtype(wep);
ndam++;
// don't need to check for blessed vs mosnters
// determine extra damage
getextradamwep(wep, &dam[0], &damtype[0], &ndam);
getextradamlf(lf, &dam[0], &damtype[0], &ndam);
for (i = 0; i < ndam; i++) {
// announce the hit
construct_hit_string(lf, NULL, attackername, c->type->name, NULL, wep, damtype[i], dam[i], maxhp, i, B_FALSE, B_FALSE, B_FALSE, isunarmed, buf);
if (strlen(buf)) {
msg("%s", buf);
}
if (!isplayer(lf) && !cansee(player, lf)) {
char noisebuf[BUFLEN];
int vol;
switch (c->type->material->id) {
case MT_METAL:
strcpy(noisebuf, "a metallic clanging.");
vol = 4;
break;
case MT_GLASS:
strcpy(noisebuf, "cracking glass.");
vol = 4;
break;
case MT_WOOD:
case MT_DRAGONWOOD:
strcpy(noisebuf, "splintering wood.");
vol = 4;
break;
case MT_BONE:
case MT_STONE:
strcpy(noisebuf, "a dull thumping.");
vol = 3;
break;
case MT_GOLD:
case MT_SILVER:
case MT_LEATHER:
strcpy(noisebuf, "a dull thumping.");
vol = 2;
break;
case MT_PAPER:
case MT_WETPAPER:
case MT_RUBBER:
strcpy(noisebuf, "a dull thumping.");
vol = 1;
break;
default:
strcpy(noisebuf, "something being hit.");
vol = 3;
break;
}
noise(c, NULL, NC_OTHER, vol, noisebuf, NULL);
}
if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(c->type->material->flags, F_HARDNESS)) {
object_t *gloves;
gloves = getequippedob(lf->pack, BP_HANDS);
if (gloves && hasflag(gloves->flags, F_HARDNESS)) {
// ok
} else if ((c->type->material->id == MT_WOOD) && (getskill(lf, SK_UNARMED) >= PR_ADEPT)) {
// ok
} else {
char buf[BUFLEN];
snprintf(buf, BUFLEN, "punching %s", obname);
if ( losehp(lf, 1, DT_BASH, lf, buf)) {
if (isplayer(lf)) {
msg("^bOw!");
}
}
}
}
// smash wood bonus
if ((wep->type->id == OT_FISTS) &&
(c->type->material->id == MT_WOOD) &&
(getskill(lf, SK_UNARMED) >= PR_ADEPT)) {
dam[i] += rnd(1,6);
}
// adjust dam
adjustdammaterial(&dam[i], damtype[i], c->type->material->id);
if (dam[i] > 0) {
// wall loses hp
c->hp -= dam[i];
if (c->hp <= 0) {
char cellname[BUFLEN];
int shattered = B_FALSE;
enum MATERIAL cellmat;
// remember cell properties
sprintf(cellname, "%s %s", needan(c->type->name) ? "An" : "A", c->type->name);
cellmat = c->type->material->id;
// cell dies (have to do this before calling fragments())
setcelltype(c, c->map->habitat->emptycelltype);
// announce
if (haslos(player, c)) {
msg("%s %s!", cellname, shattered ? "shatters" : "is destroyed");
}
// shatter?
if (willshatter(cellmat)) {
char what[BUFLEN];
shattered = B_TRUE;
noise(c, NULL, NC_OTHER, SV_CAR, "something shattering.", NULL);
if (getshardobname(cellmat, what)) {
fragments(c, what, 0, 3); // TODO: use speed so shards will hit lfs
}
}
break;
}
}
} // end foreach damtype
// no special weapon effects on cells.
// weapon gets damaged ?
if (wep && (ndam > 0)) {
if (wepdullable(wep)) {
// weapon gets duller
if (rnd(1,2)) makeduller(wep, 1);
}
}
return B_FALSE;
}
enum DAMTYPE basedamagetype(enum DAMTYPE dt) { enum DAMTYPE basedamagetype(enum DAMTYPE dt) {
switch (dt) { switch (dt) {
case DT_HEAT: case DT_HEAT:

View File

@ -5,6 +5,7 @@ void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *
int attackcell(lifeform_t *lf, cell_t *c, int force); int attackcell(lifeform_t *lf, cell_t *c, int force);
int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag); int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag);
int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag); int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag);
int attackwall(lifeform_t *lf, cell_t *c, object_t *wep, flag_t *damflag);
enum DAMTYPE basedamagetype(enum DAMTYPE dt); enum DAMTYPE basedamagetype(enum DAMTYPE dt);
int check_for_block(lifeform_t *lf, lifeform_t *victim, int dam, enum DAMTYPE damtype, int difficulty, char *attackname); int check_for_block(lifeform_t *lf, lifeform_t *victim, int dam, enum DAMTYPE damtype, int difficulty, char *attackname);
//void confereffects(flagpile_t *fp, lifeform_t *victim); //void confereffects(flagpile_t *fp, lifeform_t *victim);

26
data.c
View File

@ -2189,6 +2189,9 @@ void initobjects(void) {
addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL);
addot(OT_POT_CANINETRACKING, "potion of canine tracking", "Mimics the effects of a 'canine tracking' spell.", MT_GLASS, 1, OC_POTION, SZ_TINY); addot(OT_POT_CANINETRACKING, "potion of canine tracking", "Mimics the effects of a 'canine tracking' spell.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addot(OT_POT_GROWTH, "potion of growth", "A magical liquid which causes the imbiber's body to instantly undergo rapid growth.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-10 health to whoever drinks it.", MT_GLASS, 1, OC_POTION, SZ_TINY); addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-10 health to whoever drinks it.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
@ -2830,7 +2833,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
// l2 // l2
addot(OT_S_BLADEBURN, "bladeburn", "Ignites the target's bladed weapon, causing it to temporarily deal fire damage. The spell's power determines how long it will last.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_BLADEBURN, "bladeburn", "Ignites the caster's weapon, causing it to temporarily deal fire damage. The spell's power determines how long it will last.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines its duration."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines its duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
@ -3467,6 +3470,14 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
// l2 // l2
addot(OT_S_SIZEUP, "unnatural growth", "Causes the caster's body to grow in size.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addot(OT_S_SIZEDOWN, "unnatural shrinkage", "Causes the caster's body to shrink in size.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addot(OT_S_DARKNESS, "darkness", "Permenantly darkens the area around the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_DARKNESS, "darkness", "Permenantly darkens the area around the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power III, you can control where the darkness appears."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power III, you can control where the darkness appears.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power VIII, the darkness becomes permenant."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power VIII, the darkness becomes permenant.");
@ -3485,6 +3496,7 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
// l3 // l3
addot(OT_S_INVISIBILITY, "invisibility", "Temporarily renders the target invisible.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_INVISIBILITY, "invisibility", "Temporarily renders the target invisible.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines how long the invisibility will last."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines how long the invisibility will last.");
@ -5290,7 +5302,6 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 5, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 5, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 10, 10, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_FIRE, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_FIRE, NA, NULL);
addflag(lastot->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); addflag(lastot->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL); addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
@ -5781,9 +5792,10 @@ void initobjects(void) {
addflag(lastot->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_IDWHENUSED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_IDWHENUSED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 350, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 350, NA, NA, NULL);
addot(OT_RING_INVIS, "ring of invisibility", "Renders the wearer invisible.", MT_METAL, 0.1, OC_RING, SZ_MINI); addot(OT_RING_INVIS, "ring of invisibility", "Renders the wearer invisible - but drains the wearer's health at the same time.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, ""); addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_INVISIBLE, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_INVISIBLE, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_HPDRAIN, 1, DT_DIRECT, "life force draining");
addflag(lastot->flags, F_VALUE, 400, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 400, NA, NA, NULL);
addot(OT_RING_INVULN, "ring of invulnerability", "Grants the caster complete immunity to physical harm.", MT_METAL, 0.1, OC_RING, SZ_MINI); addot(OT_RING_INVULN, "ring of invulnerability", "Grants the caster complete immunity to physical harm.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_EQUIPCONFER, F_INVULNERABLE, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_INVULNERABLE, NA, NA, NULL);
@ -6984,6 +6996,7 @@ void initobjects(void) {
void initoptions(void) { void initoptions(void) {
addoption(OPT_ALWAYSSHOWTRAILS, "always show trail objects", B_FALSE); addoption(OPT_ALWAYSSHOWTRAILS, "always show trail objects", B_FALSE);
addoption(OPT_STOPRUNONNOISE, "stop running if sound heard", B_TRUE);
} }
void initrace(void) { void initrace(void) {
@ -8871,7 +8884,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^slurping"); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^slurping");
addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of acid"); addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of acid");
addflag(lastrace->flags, F_DIESPLATTER, 3, NA, NA, "splash of acid"); addflag(lastrace->flags, F_DIESPLATTER, 3, 0, NA, "splash of acid");
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOFLEE, 5, NA, NA, NULL); addflag(lastrace->flags, F_NOFLEE, 5, NA, NA, NULL);
@ -9008,6 +9021,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL);
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_REVIVETIMER, 0, 25, R_TROLL, NULL);
addrace(R_XAT, "xat", 2, 'x', C_BROWN, MT_FLESH, RC_ANIMAL, "Xats are wild pigs with the claws of a dog."); addrace(R_XAT, "xat", 2, 'x', C_BROWN, MT_FLESH, RC_ANIMAL, "Xats are wild pigs with the claws of a dog.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
@ -9875,7 +9889,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^slurping"); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^slurping");
addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of acid"); addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of acid");
addflag(lastrace->flags, F_DIESPLATTER, 3, NA, NA, "splash of acid"); addflag(lastrace->flags, F_DIESPLATTER, 3, 0, NA, "splash of acid");
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
@ -9908,7 +9922,7 @@ void initrace(void) {
addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of slime"); addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of slime");
addflag(lastrace->flags, F_DIESPLATTER, 3, NA, NA, "puddle of slime"); addflag(lastrace->flags, F_DIESPLATTER, 3, 0, NA, "puddle of slime");
addrace(R_SNAKE, "brown snake", 3, 's', C_BROWN, MT_FLESH, RC_ANIMAL, "Common venomous snakes."); addrace(R_SNAKE, "brown snake", 3, 's', C_BROWN, MT_FLESH, RC_ANIMAL, "Common venomous snakes.");
setbodytype(lastrace, BT_SNAKE); setbodytype(lastrace, BT_SNAKE);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);

Binary file not shown.

22
defs.h
View File

@ -65,6 +65,8 @@
// Booleans // Booleans
#define B_FALSE (0) #define B_FALSE (0)
#define B_TRUE (-1) #define B_TRUE (-1)
#define B_MAYBE (-2)
#define B_FORCE (-2) #define B_FORCE (-2)
#define B_ONPURPOSE (-1) #define B_ONPURPOSE (-1)
#define B_CHANGEDIR (-1) #define B_CHANGEDIR (-1)
@ -1213,6 +1215,7 @@ enum OBTYPE {
OT_POT_EXPERIENCE, OT_POT_EXPERIENCE,
OT_POT_FURY, OT_POT_FURY,
OT_POT_GASEOUSFORM, OT_POT_GASEOUSFORM,
OT_POT_GROWTH,
OT_POT_HEALING, OT_POT_HEALING,
OT_POT_HEALINGMIN, OT_POT_HEALINGMIN,
OT_POT_HEALINGMAJ, OT_POT_HEALINGMAJ,
@ -1394,6 +1397,8 @@ enum OBTYPE {
OT_S_POLYMORPH, OT_S_POLYMORPH,
OT_S_POLYMORPHRND, OT_S_POLYMORPHRND,
OT_S_QUICKENSTONE, OT_S_QUICKENSTONE,
OT_S_SIZEUP,
OT_S_SIZEDOWN,
// nature / enviromancy // nature / enviromancy
OT_S_BARKSKIN, OT_S_BARKSKIN,
OT_S_CALLLIGHTNING, OT_S_CALLLIGHTNING,
@ -2083,6 +2088,9 @@ enum FLAG {
F_NOQUALITY, // can't be masterwork / shoddy F_NOQUALITY, // can't be masterwork / shoddy
F_CORPSEOF, // this is a corpse of montype val0. F_CORPSEOF, // this is a corpse of montype val0.
// text is how it died. // text is how it died.
F_REVIVETIMER, // v0 = cur, v1 = max. v0 incremenets each tick.
// when v0 == v1, this object changes into lf of race
// v2.
F_DTCONVERT, // damtype val0 converts this to f->text F_DTCONVERT, // damtype val0 converts this to f->text
F_DTCREATEOB, // damtype val0 creates object f->text here F_DTCREATEOB, // damtype val0 creates object f->text here
// v1 = radius to burst in // v1 = radius to burst in
@ -2392,8 +2400,12 @@ enum FLAG {
// v0 is the order in which these are displayed (0-5) // v0 is the order in which these are displayed (0-5)
F_BONDESC, // text=extra description for playable races. F_BONDESC, // text=extra description for playable races.
// v0 is the display order. // v0 is the display order.
// v1=true means 'don't display this one during
// player race selection)
F_PENDESC, // text=extra description for playable races. F_PENDESC, // text=extra description for playable races.
// v0 is the display order. // v0 is the display order.
// v1=true means 'don't display this one during
// player race selection)
//F_SPELLLETTER, // text[0] = letter to cast this spell //F_SPELLLETTER, // text[0] = letter to cast this spell
F_AICASTTOFLEE, // AI can cast this spell to help flee/heal F_AICASTTOFLEE, // AI can cast this spell to help flee/heal
// v0 is who to target // v0 is who to target
@ -2435,6 +2447,9 @@ enum FLAG {
// unconscious. announce it when you wake up. // unconscious. announce it when you wake up.
F_TURNED, // lf turned this turn. F_TURNED, // lf turned this turn.
F_PRAYEDTO, // player has prayed to this god before. F_PRAYEDTO, // player has prayed to this god before.
F_HPDRAIN, // lf loses v0 hit points eath turn.
// v1 = damtype
// text = killer damage string
F_GAVEMONEY, // v0 tracks how much money we gave away this turn F_GAVEMONEY, // v0 tracks how much money we gave away this turn
// used for r_godgreed anger effects. // used for r_godgreed anger effects.
F_CLIMBING, // lf is currently climbing a wall F_CLIMBING, // lf is currently climbing a wall
@ -2600,6 +2615,8 @@ enum FLAG {
// e = exits // e = exits
// s = shops // s = shops
// t = traps // t = traps
// o = rare Objects
// m = rare Monsters
// eg: text=="st" means they know of shops+traps // eg: text=="st" means they know of shops+traps
F_NOJOBTEXT, // this lf's name is 'a xxx', not 'a xxx wizard' etc F_NOJOBTEXT, // this lf's name is 'a xxx', not 'a xxx wizard' etc
F_LASTDIR, // this is the last direction we moved. F_LASTDIR, // this is the last direction we moved.
@ -2707,6 +2724,7 @@ enum FLAG {
F_DIESPLATTER, // this lf will splatter objcets of type 'text' F_DIESPLATTER, // this lf will splatter objcets of type 'text'
// when it dies. // when it dies.
// v0 = max distance to splatter (or UNLIMITED) // v0 = max distance to splatter (or UNLIMITED)
// v1 = how fast to shoot objects (0 = just place them)
// text = type of object to splatter // text = type of object to splatter
F_OBESE, // double base weight for race! F_OBESE, // double base weight for race!
F_ORIGRACE, // original player race (if you polymorphed) F_ORIGRACE, // original player race (if you polymorphed)
@ -2967,6 +2985,9 @@ enum FLAG {
// v0 is pct chance of door (as opposed to empty // v0 is pct chance of door (as opposed to empty
// doorway with no door). // doorway with no door).
F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms
F_MAINTAINEDGE, // when calling fixreachability(), only allow
// corridors to enter this vault through cells
// marked as exits.
F_NORANDOM, // this vault does not randomly appear F_NORANDOM, // this vault does not randomly appear
// OR this spell doesn't apear in books // OR this spell doesn't apear in books
F_VAULTATOB, // v0/1=x/y, v2=pctchance, text=obname F_VAULTATOB, // v0/1=x/y, v2=pctchance, text=obname
@ -3262,6 +3283,7 @@ typedef struct warning_s {
enum OPTION { enum OPTION {
OPT_ALWAYSSHOWTRAILS, OPT_ALWAYSSHOWTRAILS,
OPT_STOPRUNONNOISE,
}; };
typedef struct option_s { typedef struct option_s {

6
flag.c
View File

@ -469,8 +469,10 @@ int fpisbad(flagpile_t *fp) {
} }
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) { // returns # of flags copied
int copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) {
flag_t *f; flag_t *f;
int ndone = 0;
for (f = src->first ; f ; f = f->next) { for (f = src->first ; f ; f = f->next) {
// gone past the requrested id's number - ie. it's not there. // gone past the requrested id's number - ie. it's not there.
if (f->id > id) break; if (f->id > id) break;
@ -487,8 +489,10 @@ void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) {
f->altval->val[2], f->altval->val[2],
f->altval->text); f->altval->text);
} }
ndone++;
} }
} }
return ndone;
} }
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) { void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {

2
flag.h
View File

@ -14,7 +14,7 @@ void changeflagtext(flag_t *f, char *newtext);
void checkmapflags(map_t *m); void checkmapflags(map_t *m);
int fpisbad(flagpile_t *fp); int fpisbad(flagpile_t *fp);
void checkflagpile(flagpile_t *fp); void checkflagpile(flagpile_t *fp);
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id); int copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int countflags(flagpile_t *fp); int countflags(flagpile_t *fp);
int flagcausesloscalc(enum FLAG fid); int flagcausesloscalc(enum FLAG fid);

60
io.c
View File

@ -3472,6 +3472,7 @@ void describeob(object_t *o) {
void describerace(enum RACE rid) { void describerace(enum RACE rid) {
char buf[BUFLEN]; char buf[BUFLEN];
char *buf2; char *buf2;
char ch;
int x,y; int x,y;
race_t *r; race_t *r;
cls(); cls();
@ -3487,16 +3488,18 @@ void describerace(enum RACE rid) {
wmove(mainwin, 2, 0); wmove(mainwin, 2, 0);
buf2 = malloc(HUGEBUFLEN * sizeof(char)); buf2 = malloc(HUGEBUFLEN * sizeof(char));
makedesc_race(rid, buf2, B_TRUE); makedesc_race(rid, buf2, B_TRUE, B_FALSE);
//textwithcol(mainwin, buf2); //textwithcol(mainwin, buf2);
getyx(mainwin,y,x); getyx(mainwin,y,x);
wrapprint(mainwin, &y, &x, "%s", buf2); ch = wrapprint(mainwin, &y, &x, "%s", buf2);
free(buf2); free(buf2);
wrefresh(mainwin); wrefresh(mainwin);
// wait for key // wait for key, unless we quit from the 'more' prompt
if (ch != 27) {
getch(); getch();
}
real_clearmsg(B_TRUE); real_clearmsg(B_TRUE);
restoregamewindows(); restoregamewindows();
} }
@ -4163,6 +4166,7 @@ void docomms_areainfo(char *who, flagpile_t *fp, lifeform_t *lf) {
} }
} }
// veryrare objects // veryrare objects
if (strchr(knowflag->text, 'o')) {
ndone = 0; ndone = 0;
for (y = 0; y < player->cell->map->h ; y++) { for (y = 0; y < player->cell->map->h ; y++) {
for (x = 0; x < player->cell->map->w; x++) { for (x = 0; x < player->cell->map->w; x++) {
@ -4179,6 +4183,7 @@ void docomms_areainfo(char *who, flagpile_t *fp, lifeform_t *lf) {
} }
} }
if (ndone) needredraw = B_TRUE; if (ndone) needredraw = B_TRUE;
}
// staircases // staircases
if (strchr(knowflag->text, 'e')) { if (strchr(knowflag->text, 'e')) {
ndone = 0; ndone = 0;
@ -4252,6 +4257,7 @@ void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf) {
totdone += ndone; totdone += ndone;
} }
// veryrare monsters // veryrare monsters
if (strchr(knowflag->text, 'm')) {
gethitdicerange(getmapdifficulty(player->cell->map), &min,&max, RARITYVARIANCELF, B_FALSE); gethitdicerange(getmapdifficulty(player->cell->map), &min,&max, RARITYVARIANCELF, B_FALSE);
ndone = 0; ndone = 0;
@ -4283,6 +4289,7 @@ void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf) {
} }
} }
totdone += ndone; totdone += ndone;
}
msg("\"I know of no %sdangers in this area.\"", (totdone) ? "other " : ""); msg("\"I know of no %sdangers in this area.\"", (totdone) ? "other " : "");
@ -6110,7 +6117,7 @@ char *makedesc_ob(object_t *o, char *retbuf) {
return retbuf; return retbuf;
} }
char *makedesc_race(enum RACE rid, char *retbuf, int showextra) { char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel) {
race_t *r; race_t *r;
char buf[HUGEBUFLEN]; char buf[HUGEBUFLEN];
flag_t *retflag[MAXCANDIDATES],*f; flag_t *retflag[MAXCANDIDATES],*f;
@ -6176,8 +6183,11 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
if (f->val[0] == curidx) { if (f->val[0] == curidx) {
if ((f->val[1] == B_TRUE) && forplayersel) {
} else {
snprintf(buf, HUGEBUFLEN, "@- %s\n", f->text); snprintf(buf, HUGEBUFLEN, "@- %s\n", f->text);
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
}
donesomething = B_TRUE; donesomething = B_TRUE;
curidx++; curidx++;
break; break;
@ -6264,7 +6274,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
case F_ENHANCESMELL: sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break; case F_ENHANCESMELL: sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break;
case F_FLYING: sprintf(buf, "Can fly at will"); break; case F_FLYING: sprintf(buf, "Can fly at will"); break;
case F_HEAVYBLOW: sprintf(buf, "Attacks will knock enemies backwards"); break; case F_HEAVYBLOW: sprintf(buf, "Attacks will knock enemies backwards"); break;
case F_HUMANOID: sprintf(buf, "Can use weapons and armour."); break; case F_HUMANOID: if (!forplayersel) sprintf(buf, "Can use weapons and armour."); break;
case F_LEVITATING: sprintf(buf, "Can levitate at will"); break; case F_LEVITATING: sprintf(buf, "Can levitate at will"); break;
case F_MEDITATES: sprintf(buf, "Meditates to retain awareness while sleeping."); break; case F_MEDITATES: sprintf(buf, "Meditates to retain awareness while sleeping."); break;
case F_MPMOD: if (f->val[0] > 0) sprintf(buf, "+%d Mana", f->val[0]); break; case F_MPMOD: if (f->val[0] > 0) sprintf(buf, "+%d Mana", f->val[0]); break;
@ -6313,8 +6323,11 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
if (f->val[0] == curidx) { if (f->val[0] == curidx) {
if ((f->val[1] == B_TRUE) && forplayersel) {
} else {
snprintf(buf, HUGEBUFLEN, "@- %s\n", f->text); snprintf(buf, HUGEBUFLEN, "@- %s\n", f->text);
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
}
donesomething = B_TRUE; donesomething = B_TRUE;
curidx++; curidx++;
break; break;
@ -6330,7 +6343,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
switch (f->id) { switch (f->id) {
case F_CARNIVORE: sprintf(buf, "Will only eat meat."); break; case F_CARNIVORE: sprintf(buf, "Will only eat meat."); break;
case F_DEAF: sprintf(buf, "Deaf"); break; case F_DEAF: sprintf(buf, "Deaf"); break;
case F_DIURNAL: sprintf(buf, "Sleeps at night."); break; case F_DIURNAL: if (!forplayersel) sprintf(buf, "Sleeps at night."); break;
case F_DTVULN: case F_DTVULN:
if (!hasflag(doneflags, F_DTVULN)) { if (!hasflag(doneflags, F_DTVULN)) {
if (f->val[0] == DT_ALL) { if (f->val[0] == DT_ALL) {
@ -6362,7 +6375,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
break; break;
case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break; case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break;
case F_NEEDSWATER: sprintf(buf, "Will suffocate without water"); break; case F_NEEDSWATER: sprintf(buf, "Will suffocate without water"); break;
case F_NOCTURNAL: sprintf(buf, "Sleeps during the day."); break; case F_NOCTURNAL: if (!forplayersel) sprintf(buf, "Sleeps during the day."); break;
case F_NOPACK: sprintf(buf, "Cannot carry objects."); break; case F_NOPACK: sprintf(buf, "Cannot carry objects."); break;
case F_SIZE: case F_SIZE:
if (hasflag(r->flags, F_HUMANOID) && (f->val[0] != SZ_HUMAN)) { if (hasflag(r->flags, F_HUMANOID) && (f->val[0] != SZ_HUMAN)) {
@ -6373,7 +6386,9 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
sprintf(buf, "Will not leave its home territory."); break; sprintf(buf, "Will not leave its home territory."); break;
break; break;
case F_TAMABLE: case F_TAMABLE:
sprintf(buf, "Susceptible to bribery."); break; if (!forplayersel) {
sprintf(buf, "Susceptible to bribery.");
}
break; break;
case F_VEGETARIAN: sprintf(buf, "Will not eat meat."); break; case F_VEGETARIAN: sprintf(buf, "Will not eat meat."); break;
case F_VISRANGEMOD: if (f->val[0] < 0) sprintf(buf, "Reduced vision range (%d)", f->val[0]); break; case F_VISRANGEMOD: if (f->val[0] < 0) sprintf(buf, "Reduced vision range (%d)", f->val[0]); break;
@ -8331,7 +8346,9 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
// only print if on the page // only print if on the page
if ((i >= first) && !atbottom) { if ((i >= first) && !atbottom) {
// show heading first // show heading first
wattron(mainwin, A_REVERSE);
mvwprintw(mainwin, y, 0, "%s", curheading); mvwprintw(mainwin, y, 0, "%s", curheading);
wattroff(mainwin, A_REVERSE);
y++; y++;
} }
doneheading = B_TRUE; doneheading = B_TRUE;
@ -12064,20 +12081,21 @@ int warnabout(char *what) {
} }
// @ = tab // @ = tab
void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) { char wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) {
char word[HUGEBUFLEN],buf[HUGEBUFLEN]; char word[HUGEBUFLEN],buf[HUGEBUFLEN];
char *p; char *p;
va_list args; va_list args;
int w,nspaces = 0; int w,nspaces = 0,h;
int first = B_TRUE; int first = B_TRUE;
va_start(args, format); va_start(args, format);
vsnprintf( buf, HUGEBUFLEN, format, args ); vsnprintf( buf, HUGEBUFLEN, format, args );
va_end(args); va_end(args);
if (!strlen(buf)) return; if (!strlen(buf)) return '\0';
w = getmaxx(win); w = getmaxx(win);
h = getmaxy(win);
// remember the amount of spaces at the end // remember the amount of spaces at the end
p = buf + strlen(buf) - 1; p = buf + strlen(buf) - 1;
@ -12105,7 +12123,25 @@ void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) {
*x = 0; *x = 0;
} }
} }
if (gamemode == GM_GAMESTARTED) {
if (*y >= h-2) {
char ch;
centre(win,C_WHITE, h-1, "--More--");
ch = getch();
if (ch == 27) { // esc
return ch;
} else {
// clear window
wclear(win);
*y = 0;
*x = 0;
}
}
}
wmove(win, *y, *x); wmove(win, *y, *x);
if (first) { if (first) {
first = B_FALSE; first = B_FALSE;
} else if (*x != 0) { } else if (*x != 0) {
@ -12137,6 +12173,8 @@ void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) {
//wattroff(win, A_BOLD); //wattroff(win, A_BOLD);
setcol(win, C_GREY); setcol(win, C_GREY);
getyx(win, *y, *x); getyx(win, *y, *x);
return '\0';
} }

4
io.h
View File

@ -106,7 +106,7 @@ int keycodetokey(int keycode, int escseqok);
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints); void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints);
char *makedesc_god(lifeform_t *god, char *retbuf); char *makedesc_god(lifeform_t *god, char *retbuf);
char *makedesc_ob(object_t *o, char *retbuf); char *makedesc_ob(object_t *o, char *retbuf);
char *makedesc_race(enum RACE rid, char *retbuf, int showextra); char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel);
char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite); char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite);
char *makedesc_spell(objecttype_t *ot, char *retbuf); char *makedesc_spell(objecttype_t *ot, char *retbuf);
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard,int mpcutoff); void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard,int mpcutoff);
@ -136,4 +136,4 @@ void tombstone(lifeform_t *lf);
void updatestatus(void); void updatestatus(void);
int updateviewfor(cell_t *cell); int updateviewfor(cell_t *cell);
int warnabout(char *what); int warnabout(char *what);
void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ); char wrapprint(WINDOW *win, int *y, int *x, char *format, ... );

198
lf.c
View File

@ -1,6 +1,7 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <math.h> #include <math.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -2546,10 +2547,10 @@ void die(lifeform_t *lf) {
if (vaporised) { if (vaporised) {
switch (rnd(1,2)) { switch (rnd(1,2)) {
case 1: case 1:
fragments(corpsecell, "chunk of flesh", 2, UNLIMITED); fragments(corpsecell, "chunk of flesh", 0, UNLIMITED);
break; break;
case 2: case 2:
fragments(corpsecell, "pool of blood", 2, UNLIMITED); fragments(corpsecell, "pool of blood", 0, UNLIMITED);
break; break;
} }
} else if ((lf->lastdamtype == DT_BASH) && lfhasflag(lf, F_FROZEN)) { } else if ((lf->lastdamtype == DT_BASH) && lfhasflag(lf, F_FROZEN)) {
@ -2620,6 +2621,11 @@ void die(lifeform_t *lf) {
copyflag(corpse->flags, lf->flags, F_KNOWSABOUT); copyflag(corpse->flags, lf->flags, F_KNOWSABOUT);
copyflag(corpse->flags, lf->flags, F_HOMEMAP); copyflag(corpse->flags, lf->flags, F_HOMEMAP);
// some corpses will regenerate...
if (copyflag(corpse->flags, lf->flags, F_REVIVETIMER)) {
killflagsofid(corpse->flags, F_OBHPDRAIN);
}
// corpse of a player pet? // corpse of a player pet?
if (ispetof(lf, player)) { if (ispetof(lf, player)) {
addflag(corpse->flags, F_PETOF, player->id, NA, NA, NULL); addflag(corpse->flags, F_PETOF, player->id, NA, NA, NULL);
@ -2634,6 +2640,14 @@ void die(lifeform_t *lf) {
} }
} }
// inherit size from lf
f = hasflag(corpse->flags, F_SIZE);
if (f) {
f->val[0] = getlfsize(lf);
} else {
addflag(corpse->flags, F_SIZE, getlfsize(lf), NA, NA, NULL);
}
// remember what killed us. // remember what killed us.
f = hasflag(corpse->flags, F_CORPSEOF); f = hasflag(corpse->flags, F_CORPSEOF);
if (f) { if (f) {
@ -2659,7 +2673,7 @@ void die(lifeform_t *lf) {
flag_t *f; flag_t *f;
f = lfhasflag(lf, F_DIESPLATTER); f = lfhasflag(lf, F_DIESPLATTER);
if (f) { if (f) {
fragments(corpsecell, f->text, 1, f->val[0]); fragments(corpsecell, f->text, f->val[1], f->val[0]);
} }
} }
} // end if corpsecell } // end if corpsecell
@ -2754,6 +2768,13 @@ void genareaknowledge(flagpile_t *fp, int chancemod) {
if (pctchance(75 + chancemod)) { if (pctchance(75 + chancemod)) {
strcat(knownstuff, "e"); strcat(knownstuff, "e");
} }
// rare monsters/objects? (highish chance)
if (pctchance(60 + chancemod)) {
strcat(knownstuff, "o");
}
if (pctchance(60 + chancemod)) {
strcat(knownstuff, "m");
}
// shops? (med chance) // shops? (med chance)
if (pctchance(50 + chancemod)) { if (pctchance(50 + chancemod)) {
strcat(knownstuff, "s"); strcat(knownstuff, "s");
@ -4664,13 +4685,13 @@ void gainxp(lifeform_t *lf, long amt) {
lf->xp += amt; lf->xp += amt;
if (isplayer(lf)) statdirty = B_TRUE; if (isplayer(lf)) statdirty = B_TRUE;
assert(lf->xp >= 0); assert(lf->xp >= 0);
}
// skill xp // skill xp
if (isplayer(lf)) { if (isplayer(lf)) {
int amtneeded; long amtneeded;
amtneeded = getspforpoint(lf); amtneeded = getspforpoint(lf);
assert(amtneeded > 0);
lf->skillxp += amt; lf->skillxp += amt;
@ -4680,20 +4701,23 @@ void gainxp(lifeform_t *lf, long amt) {
lf->skillxp -= amtneeded; lf->skillxp -= amtneeded;
if (isplayer(lf)) statdirty = B_TRUE; if (isplayer(lf)) statdirty = B_TRUE;
} }
// debug!
if (newskillpoints >= 3) {
raise(SIGINT);
}
} }
if (doxp) {
// ready for next level? can only go up ONE level. // ready for next level? can only go up ONE level.
if (lf->xp >= getxpforlev(lf->level + 1)) { if (lf->xp >= getxpforlev(lf->level + 1)) {
gainlevel(lf, B_FALSE); // this will increment 'newlevel' gainlevel(lf, B_FALSE); // this will increment 'newlevel'
} }
}
if (newskillpoints) { if (newskillpoints) {
lf->skillpoints += newskillpoints; lf->skillpoints += newskillpoints;
msg("^GYou feel ready to learn a new skill!"); msg("^GYou feel ready to learn a new skill!");
lf->totskillpoints += newskillpoints; lf->totskillpoints += newskillpoints;
} }
} }
}
int fovlist_contains(int *endx, int *endy, int nendcells, int x, int y) { int fovlist_contains(int *endx, int *endy, int nendcells, int x, int y) {
int i; int i;
@ -6610,6 +6634,7 @@ glyph_t *getlfglyph(lifeform_t *lf) {
tempglyph.colour = lf->race->glyph.colour; tempglyph.colour = lf->race->glyph.colour;
} else if ((f = lfhasflag(lf, F_GLYPH)) != NULL) { } else if ((f = lfhasflag(lf, F_GLYPH)) != NULL) {
tempglyph.ch = f->val[1]; tempglyph.ch = f->val[1];
tempglyph.colour = f->val[0];
} else { } else {
tempglyph = lf->race->glyph; tempglyph = lf->race->glyph;
} }
@ -7030,6 +7055,7 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
char lname[BUFLEN]; char lname[BUFLEN];
job_t *j; job_t *j;
flag_t *f; flag_t *f;
enum LFSIZE size,racesize;
// 'the' or 'your' ? // 'the' or 'your' ?
@ -7051,6 +7077,24 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
// construct description string // construct description string
strcpy(descstring, ""); strcpy(descstring, "");
// has their size changed?
f = hasflag(lf->race->flags, F_SIZE);
if (f) {
racesize = f->val[0];
} else {
racesize = SZ_HUMAN; // default
}
size = getlfsize(lf);
if (size != racesize) {
if (size == SZ_HUMAN) {
strcat(descstring, "human-sized ");
} else {
strcat(descstring, getsizetext(size));
strcat(descstring, " ");
}
}
if (lfhasflag(lf, F_FROZEN)) { if (lfhasflag(lf, F_FROZEN)) {
strcat(descstring, "frozen "); strcat(descstring, "frozen ");
} }
@ -10557,6 +10601,8 @@ void killlf(lifeform_t *lf) {
} }
int isdeaf(lifeform_t *lf) { int isdeaf(lifeform_t *lf) {
if (lfhasflag(lf, F_TREMORSENSE)) return B_FALSE;
if (lfhasflag(lf, F_DEAF)) return B_TRUE; if (lfhasflag(lf, F_DEAF)) return B_TRUE;
if (isresting(lf) && lfhasflag(lf, F_RESTINGINMOTEL)) return B_TRUE; if (isresting(lf) && lfhasflag(lf, F_RESTINGINMOTEL)) return B_TRUE;
if (lfhasflagval(lf, F_INJURY, IJ_EARSRINGING, NA, NA, NULL)) return B_TRUE; if (lfhasflagval(lf, F_INJURY, IJ_EARSRINGING, NA, NA, NULL)) return B_TRUE;
@ -13257,6 +13303,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
// you can see the cell which made the noise // you can see the cell which made the noise
if (seetext) { if (seetext) {
msg("%s", seetext); msg("%s", seetext);
rv = B_TRUE;
} }
} else if (text && !isdeaf(l) && ((nclass != NC_MOVEMENT) || !lfhasflag(l, F_DONELISTEN))) { } else if (text && !isdeaf(l) && ((nclass != NC_MOVEMENT) || !lfhasflag(l, F_DONELISTEN))) {
// this means you can only hear one 'walk' sound per turn // this means you can only hear one 'walk' sound per turn
@ -13328,7 +13375,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
rv = B_TRUE; rv = B_TRUE;
} }
// can only hear one 'walk' sound per turn. // can only hear one 'walk' sound per turn.
if (isplayer(l) && (nclass == NC_MOVEMENT)) { if (nclass == NC_MOVEMENT) {
addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL); addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL);
practice(l, SK_LISTEN, 1); practice(l, SK_LISTEN, 1);
} }
@ -13415,6 +13462,12 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
} else { // can't hear the sound. } else { // can't hear the sound.
} }
} // end for each lf on map } // end for each lf on map
if (rv == B_TRUE) {
if (getoption(OPT_STOPRUNONNOISE)) {
stoprunning(player);
}
}
return rv; return rv;
} }
@ -16009,7 +16062,6 @@ void startlfturn(lifeform_t *lf) {
} }
// sixth sense spell warnings // sixth sense spell warnings
f = hasactivespell(lf, OT_S_SIXTHSENSE); f = hasactivespell(lf, OT_S_SIXTHSENSE);
if (f) { if (f) {
cell_t *retcell[MAXCANDIDATES]; cell_t *retcell[MAXCANDIDATES];
@ -16559,7 +16611,7 @@ void startlfturn(lifeform_t *lf) {
// effects for/on your own flags // effects for/on your own flags
getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FEIGNFOOLEDBY,F_FLEEFROM, getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FEIGNFOOLEDBY,F_FLEEFROM,
F_GRABBEDBY, F_GRABBING, F_GUNTARGET, F_BOOSTSPELL, F_FEIGNINGDEATH, F_INJURY, F_GRABBEDBY, F_GRABBING, F_GUNTARGET, F_BOOSTSPELL, F_FEIGNINGDEATH, F_HPDRAIN, F_INJURY,
F_NOFLEEFROM, F_PETOF, F_SPOTTED, F_STABBEDBY, F_TARGETCELL, F_TARGETLF, F_NONE); F_NOFLEEFROM, F_PETOF, F_SPOTTED, F_STABBEDBY, F_TARGETCELL, F_TARGETLF, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
@ -16696,6 +16748,14 @@ void startlfturn(lifeform_t *lf) {
} }
} }
} // end if f_target or f_targetcell } // end if f_target or f_targetcell
// hp drain
if (f->id == F_HPDRAIN) {
losehp(lf, f->val[0], DT_DIRECT, NULL, f->text);
if (isdead(lf)) {
break;
}
}
} // end loop through lf flags } // end loop through lf flags
} }
@ -17004,7 +17064,6 @@ lifeform_t *summonmonster(lifeform_t *caster, cell_t *c, enum RACE rid, char *ra
int takeoff(lifeform_t *lf, object_t *o) { int takeoff(lifeform_t *lf, object_t *o) {
flag_t *f;
char obname[BUFLEN]; char obname[BUFLEN];
char buf[BUFLEN]; char buf[BUFLEN];
@ -17066,19 +17125,7 @@ int takeoff(lifeform_t *lf, object_t *o) {
} }
// lose flags unequipeffects(lf, o);
loseobflags(lf, o, F_EQUIPCONFER);
f = hasflag(o->flags, F_CREATEDBYSPELL);
if (f) stopspell(lf, f->val[0]);
if (obproduceslight(o)) {
calclight((getoblocation(o))->map);
setlosdirty(lf);
//precalclos(lf);
drawscreen();
}
return B_FALSE; return B_FALSE;
} }
@ -17432,6 +17479,29 @@ void turntoface(lifeform_t *lf, cell_t *dstcell) {
setfacing(lf, getdirtowards(lf->cell, dstcell, NULL, B_FALSE, DT_ORTH) ); setfacing(lf, getdirtowards(lf->cell, dstcell, NULL, B_FALSE, DT_ORTH) );
} }
void unequipeffects(lifeform_t *lf, object_t *o) {
flag_t *f;
// lose flags
loseobflags(lf, o, F_EQUIPCONFER);
if (obproduceslight(o)) {
calclight((getoblocation(o))->map);
setlosdirty(lf);
//precalclos(lf);
drawscreen();
}
if (o->type->id == OT_ENERGYBLADE) {
stopspell(lf, OT_S_SUMMONWEAPON);
// object might be dead now, so stop.
return;
}
f = hasflag(o->flags, F_CREATEDBYSPELL);
if (f) {
stopspell(lf, f->val[0]);
}
}
void unsummon(lifeform_t *lf, int vanishobs) { void unsummon(lifeform_t *lf, int vanishobs) {
lifeform_t *creator = NULL; lifeform_t *creator = NULL;
@ -17530,19 +17600,7 @@ int unweild(lifeform_t *lf, object_t *o) {
} }
} }
// lose flags unequipeffects(lf, o);
loseobflags(lf, o, F_EQUIPCONFER);
if (obproduceslight(o)) {
calclight((getoblocation(o))->map);
setlosdirty(lf);
//precalclos(lf);
drawscreen();
}
if (o->type->id == OT_ENERGYBLADE) {
stopspell(lf, OT_S_SUMMONWEAPON);
}
return B_FALSE; return B_FALSE;
} }
@ -18109,6 +18167,72 @@ int validateraces(void) {
return goterror; return goterror;
} }
// returns TRUE on error
int resizelf(lifeform_t *lf, enum LFSIZE newsize) {
flag_t *f;
enum LFSIZE origsize;
int changedir;
char lfname[BUFLEN];
object_t *o,*nexto;
getlfname(lf, lfname);
f = hasflag(lf->flags, F_SIZE);
if (f) {
origsize = f->val[0];
} else {
origsize = SZ_HUMAN; // default
}
if (origsize == newsize) {
return B_TRUE;
} else if (newsize > origsize) {
changedir = 1;
} else {
changedir = -1;
}
if (f) {
f->val[0] = newsize;
} else {
addflag(lf->flags, F_SIZE, newsize, NA, NA, NULL);
}
// announce
if (isplayer(lf)) {
msg("Your body %s unnaturally!", (changedir == 1) ? "grows" : "shrinks");
} else if (cansee(player, lf)) {
msg("%s %s unnaturally!", lfname, (changedir == 1) ? "grows" : "shrinks");
}
// effects on objects, armour etc
for (o = lf->pack->first ; o ; o = nexto) {
nexto = o->next;
// object is now the wrong size?
if (isequipped(o) && isarmour(o)) {
if (!armourfits(lf, o, NULL)) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
if (isplayer(lf)) {
msg("Your %s no longer fits!", noprefix(obname));
} else if (cansee(player, lf)) {
msg("%s%s %s no longer fits!", lfname, getpossessive(lfname), noprefix(obname));
}
killflagsofid(o->flags, F_EQUIPPED);
unequipeffects(lf, o);
if (isplayer(lf)) statdirty = B_TRUE; // might have impacted AR
}
}
// object is now too big to hold?
if (canpickup(lf, o, o->amt) == E_TOOBIG) {
drop(o, o->amt);
continue;
}
}
return B_FALSE;
}
int rest(lifeform_t *lf, int onpurpose) { int rest(lifeform_t *lf, int onpurpose) {
flag_t *f; flag_t *f;
flag_t *ff; flag_t *ff;

2
lf.h
View File

@ -368,6 +368,7 @@ int readytotrain(lifeform_t *lf);
int recruit(lifeform_t *lf); int recruit(lifeform_t *lf);
void refreshlevelabilities(lifeform_t *lf); void refreshlevelabilities(lifeform_t *lf);
void relinklf(lifeform_t *src, map_t *dst); void relinklf(lifeform_t *src, map_t *dst);
int resizelf(lifeform_t *lf, enum LFSIZE newsize);
int rest(lifeform_t *lf, int onpurpose); int rest(lifeform_t *lf, int onpurpose);
void setskillused(lifeform_t *lf, enum SKILL skid); void setskillused(lifeform_t *lf, enum SKILL skid);
int startclimbing(lifeform_t *lf); int startclimbing(lifeform_t *lf);
@ -416,6 +417,7 @@ void timeeffectslf(lifeform_t *lf);
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat); int tryclimb(lifeform_t *lf, cell_t *where, char *towhat);
int touch(lifeform_t *lf, object_t *o); int touch(lifeform_t *lf, object_t *o);
void turntoface(lifeform_t *lf, cell_t *dstcell); void turntoface(lifeform_t *lf, cell_t *dstcell);
void unequipeffects(lifeform_t *lf, object_t *o);
void unpoison(lifeform_t *lf); void unpoison(lifeform_t *lf);
void unsummon(lifeform_t *lf, int vanishobs); void unsummon(lifeform_t *lf, int vanishobs);
int unweild(lifeform_t *lf, object_t *o); int unweild(lifeform_t *lf, object_t *o);

208
map.c
View File

@ -805,6 +805,7 @@ void adjustcellglyphforlight(cell_t *c, glyph_t *g) {
int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance) { int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance) {
int i,d; int i,d;
cell_t *poss[MAXCANDIDATES], *cell[MAXCANDIDATES]; // TODO: should this be maxroomw * maxroomh ? cell_t *poss[MAXCANDIDATES], *cell[MAXCANDIDATES]; // TODO: should this be maxroomw * maxroomh ?
int possdir[MAXCANDIDATES];
int ncells = 0, npossible = 0; int ncells = 0, npossible = 0;
int doorsadded = 0; int doorsadded = 0;
int db = B_TRUE; int db = B_TRUE;
@ -835,11 +836,13 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
makedoor(cell[i], dooropenchance); makedoor(cell[i], dooropenchance);
} else { } else {
setcelltype(cell[i], cell[i]->habitat->emptycelltype); setcelltype(cell[i], cell[i]->habitat->emptycelltype);
cell[i]->isroomwall = compassdir(d);
addflag(map->flags, F_ROOMEXIT, roomid, cell[i]->x, cell[i]->y, "from autodoors, only way out"); addflag(map->flags, F_ROOMEXIT, roomid, cell[i]->x, cell[i]->y, "from autodoors, only way out");
} }
} else { } else {
// otherwise mark this as a _potential_ door location. // otherwise mark this as a _potential_ door location.
poss[npossible] = cell[i]; poss[npossible] = cell[i];
possdir[npossible] = d;
npossible++; npossible++;
} }
} }
@ -857,6 +860,7 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
setcelltype(poss[sel], poss[sel]->habitat->emptycelltype); setcelltype(poss[sel], poss[sel]->habitat->emptycelltype);
addflag(map->flags, F_ROOMEXIT, roomid, poss[sel]->x, poss[sel]->y, "from autodoors, potential location"); addflag(map->flags, F_ROOMEXIT, roomid, poss[sel]->x, poss[sel]->y, "from autodoors, potential location");
} }
poss[sel]->isroomwall = compassdir(possdir[sel]);
doorsadded++; doorsadded++;
} }
@ -888,7 +892,7 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
} }
sel = rnd(0,nposs-1); sel = rnd(0,nposs-1);
used[poss[sel]] = B_TRUE; used[poss[sel]] = B_TRUE;
dodoor[ndodoors++] = poss[sel]; dodoor[ndodoors] = poss[sel];
} }
// actually make the doors // actually make the doors
@ -906,6 +910,7 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
addflag(map->flags, F_ROOMEXIT, roomid, cell[sel]->x, cell[sel]->y, "from autodoors, forced at end"); addflag(map->flags, F_ROOMEXIT, roomid, cell[sel]->x, cell[sel]->y, "from autodoors, forced at end");
doorsadded++; doorsadded++;
} }
cell[sel]->isroomwall = d;
} }
} }
} }
@ -1041,6 +1046,63 @@ int cellhaslos(cell_t *c1, cell_t *dest) {
return B_TRUE; return B_TRUE;
} }
// is the given cell a wall of a vault with maintain_edge, and not marked as an exit?
int cellisfixedvaultwall(cell_t *c) {
if ( getcellvault(c) &&
c->type->solid &&
hasflag(c->room->vault->flags, F_MAINTAINEDGE) &&
!hasflagval(c->map->flags, F_ROOMEXIT, c->room->id, c->x, c->y, NULL) ) {
return B_TRUE;
}
return B_FALSE;
}
// returns B_TRUE, B_FALSE or B_MAYBE
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom) {
int db = B_TRUE;
if ((srcroomid >= 0) && (getroomid(c) == srcroomid) && c->type->solid && startcell->type->solid) {
// hits a wall of the same room,
// and start cell NOT one inside the room.
// invalid
if (insameroom) *insameroom = B_TRUE;
if (db) dblog(" going %s hits wall of same room. invalid.", getdirname(dir));
return B_FALSE;
} else if (isroom(c) && (getroomid(c) != srcroomid) && (c->isroomwall != diropposite(dir))) {
// cell is in a different room, but not the correct edge
// invalid
if (insameroom) *insameroom = B_FALSE;
if (db) dblog(" going %s hits wrong wall of different room. invalid.", getdirname(dir));
return B_FALSE;
} else if (cellisfixedvaultwall(c)) {
// cell is a wall of a maintain_edge vault, and not an exit cell
// invalid
if (insameroom) *insameroom = B_FALSE;
if (db) dblog(" going %s hits non-exit wall maintain_edge vault. invalid.", getdirname(dir));
return B_FALSE;
} else if (isroom(c) && (getroomid(c) != srcroomid) && c->type->solid && countadjdoors(c) ) {
// cell is the wall of a different room, and adjacent to a door.
// invalid
if (insameroom) *insameroom = B_FALSE;
if (db) dblog(" going %s hits wall adjacent to door. invalid.", getdirname(dir));
return B_FALSE;
} else if (cellwalkable(NULL, c, NULL)) {
if (getroomid(c) == srcroomid) {
// invalid
if (insameroom) *insameroom = B_TRUE;
if (db) dblog(" going %s hits empty cell of same room. invalid.", getdirname(dir));
return B_FALSE;
} else {
if (!wantfilled || c->filled) {
// walkable and not in this vault. finished.
// valid.
return B_TRUE;
}
}
}
return B_MAYBE;
}
void clearcell(cell_t *c) { void clearcell(cell_t *c) {
// kill everything there - (lifeforms && objects) // kill everything there - (lifeforms && objects)
if (c->lf && !isplayer(c->lf)) { if (c->lf && !isplayer(c->lf)) {
@ -1820,6 +1882,20 @@ int countadjrooms(cell_t *cell) {
return count; return count;
} }
int countadjdoors(cell_t *cell) {
int d;
int doors = 0;
for (d = DC_N; d <= DC_NW; d++) {
cell_t *newcell;
newcell = getcellindir(cell, d);
if (newcell || hasobwithflag(newcell->obpile, F_DOOR)) {
doors++;
}
}
return doors;
}
int countadjwalls(cell_t *cell) { int countadjwalls(cell_t *cell) {
int d; int d;
int walls = 0; int walls = 0;
@ -3742,64 +3818,57 @@ void killmap(map_t *m) {
// if 'wantfilled' is set, only link to "filled" cells. // if 'wantfilled' is set, only link to "filled" cells.
// return TRUE on failure. // return TRUE on failure.
int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) { int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
int db = B_FALSE; int db = B_TRUE;
int d, roomid; int d, roomid,startd,endd;
int poss2[MAXCANDIDATES],nposs2; int poss2[MAXCANDIDATES],nposs2;
int dist[MAXDIR_ORTH],hitsedge[MAXDIR_ORTH], sameroom[MAXDIR_ORTH]; int dist[MAXDIR_ORTH],hitsedge[MAXDIR_ORTH], sameroom[MAXDIR_ORTH];
cell_t *directendcell[MAXDIR_ORTH]; cell_t *directendcell[MAXDIR_ORTH];
int mindist = 999,maxdist = -1; int mindist = 999,maxdist = -1;
cell_t *c; cell_t *c;
int forcedir = D_NONE;
if (ncellsadded) *ncellsadded = 0; if (ncellsadded) *ncellsadded = 0;
if (db) dblog(" calling linkexit() for cell at %d,%d", startcell->x, startcell->y);
roomid = getroomid(startcell); roomid = getroomid(startcell);
if (db) dblog(" calling linkexit() for cell at %d,%d in roomid %d", startcell->x, startcell->y, roomid);
for (d = D_N; d <= D_W; d++) { for (d = D_N; d <= D_W; d++) {
hitsedge[d] = B_TRUE; hitsedge[d] = B_TRUE;
directendcell[d] = NULL; directendcell[d] = NULL;
} }
// link it. starting from the door, count the number of cells in // link it.
// if our cell is marked specifically as a room exit, our first direction MUST be out the
// door.
if (startcell->isroomwall != D_NONE) {
forcedir = startcell->isroomwall;
startd = forcedir;
endd = forcedir;
} else {
startd = D_N; endd = D_W;
}
// otherwise, starting from the door, count the number of cells in
// each direction until we hit an empty (walkable) cell which isn't a room. // each direction until we hit an empty (walkable) cell which isn't a room.
// if we hit a cell of this roomid, mark this dir as invalid. // if we hit a cell of this roomid, mark this dir as invalid.
for (d = D_N; d <= D_W; d++) { for (d = startd; d <= endd; d++) {
dist[d] = 0; dist[d] = 0;
hitsedge[d] = B_FALSE; hitsedge[d] = B_FALSE;
sameroom[d] = B_FALSE; sameroom[d] = B_FALSE;
c = getcellindir(startcell, d); c = getcellindir(startcell, d);
while (c) { while (c) {
int rv;
dist[d]++; dist[d]++;
if ((roomid >= 0) && getroomid(c) == roomid) { // same room
//if (wantfilled && c->type->solid) { rv = cellokforreachability(startcell, c, roomid, d, wantfilled, &(sameroom[d]));
if (c->type->solid) { if (rv == B_FALSE) {
// 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.
} else {
// mark dir as invalid
dist[d] = 999; dist[d] = 999;
sameroom[d] = B_TRUE;
if (db) dblog(" going %s hits same room. invalid.", getdirname(d));
break; break;
} } else if (rv == B_TRUE) {
} 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.
directendcell[d] = c; directendcell[d] = c;
if (db) dblog(" can make %s path (hits empty cell at dist %d)", getdirname(d), dist[d]); if (db) dblog(" can make %s path (hits empty cell at dist %d)", getdirname(d), dist[d]);
break; } else { // ie. rv == B_MAYBE
}
} else {
int perpdir[2],n; int perpdir[2],n;
cell_t *pcell = NULL; cell_t *pcell = NULL;
perpdir[0] = d - 1; if (perpdir[0] < D_N) perpdir[0] = D_W; perpdir[0] = d - 1; if (perpdir[0] < D_N) perpdir[0] = D_W;
@ -3813,6 +3882,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
proomid = getroomid(pcell); proomid = getroomid(pcell);
if (((roomid == -1 ) || (proomid != roomid)) && cellwalkable(NULL, pcell, NULL)) { if (((roomid == -1 ) || (proomid != roomid)) && cellwalkable(NULL, pcell, NULL)) {
if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir[n]))) { if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir[n]))) {
} else if (cellisfixedvaultwall(pcell)) {
} else { } else {
if (!wantfilled || c->filled) { if (!wantfilled || c->filled) {
// finished. // finished.
@ -3855,6 +3925,11 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
int nstartposs = 0; int nstartposs = 0;
// no good directions. // no good directions.
if (db) dblog(" No directions lead to valid cells. Trying turns."); if (db) dblog(" No directions lead to valid cells. Trying turns.");
if (forcedir != D_NONE) {
startdir = forcedir;
} else {
// starting at the LONGEST distance, traverse up each dir, // starting at the LONGEST distance, traverse up each dir,
// branching off looking for rooms. // branching off looking for rooms.
@ -3873,6 +3948,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
if (nstartposs) { if (nstartposs) {
startdir = startposs[rnd(0,nstartposs-1)]; startdir = startposs[rnd(0,nstartposs-1)];
} }
}
if (wantfilled) { if (wantfilled) {
// if startdir is D_NONE here, it means that we've called // if startdir is D_NONE here, it means that we've called
@ -3902,6 +3978,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
while (c2) { while (c2) {
int gotsolution = B_FALSE; int gotsolution = B_FALSE;
int rv;
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
@ -3909,25 +3986,12 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
perpturndir1[nperpcells] = perpdir[n]; perpturndir1[nperpcells] = perpdir[n];
nperpcells++; nperpcells++;
if ((roomid >= 0) && (getroomid(c2) == roomid)) { rv = cellokforreachability(startcell, c2, roomid, perpdir[n], wantfilled, NULL);
if (wantfilled && c2->type->solid) {
// see EXCEPTION above. if (rv == B_FALSE) {
} else {
// hits same room, not ok.
break; break;
} } else if (rv == B_TRUE) {
} else if (cellwalkable(NULL, c2, NULL)) {
if (!wantfilled || c2->filled) {
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;
@ -3942,6 +4006,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
if ( ((roomid == -1) || (proomid != roomid)) && if ( ((roomid == -1) || (proomid != roomid)) &&
cellwalkable(NULL, pcell, NULL)) { cellwalkable(NULL, pcell, NULL)) {
if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir2[n]))) { if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir2[n]))) {
} else if (cellisfixedvaultwall(pcell)) {
} else { } else {
if (!wantfilled || pcell->filled) { if (!wantfilled || pcell->filled) {
// finished. // finished.
@ -4013,27 +4078,16 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
c2 = getcellindir(perpcell[i], dir3[n]); c2 = getcellindir(perpcell[i], dir3[n]);
while (c2) { while (c2) {
int gotsolution = B_FALSE; int gotsolution = B_FALSE;
int rv;
turndist++; turndist++;
if (db) dblog_nocr("(%d,%d)",c2->x,c2->y); if (db) dblog_nocr("(%d,%d)",c2->x,c2->y);
if ((roomid >= 0) && (getroomid(c2) == roomid)) {
if (wantfilled && c2->type->solid) { rv = cellokforreachability(startcell, c2, roomid, perpdir[n], wantfilled, NULL);
// see EXCEPTION above.
} else { if (rv == B_FALSE) {
// hits same room, not ok.
break; break;
} } else if (rv == B_TRUE) {
} else if (cellwalkable(NULL, c2, NULL)) {
if (!wantfilled || c2->filled) {
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;
@ -4049,6 +4103,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
cellwalkable(NULL, pcell, NULL)) { cellwalkable(NULL, pcell, NULL)) {
if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir2[nn]))) { if ((proomid >= 0) && (pcell->isroomwall != diropposite(perpdir2[nn]))) {
// different room and hits wrong wall. // different room and hits wrong wall.
} else if (cellisfixedvaultwall(pcell)) {
} else { } else {
if (!wantfilled || pcell->filled) { if (!wantfilled || pcell->filled) {
// finished. // finished.
@ -4167,7 +4222,7 @@ int linkexits(map_t *m, int roomid) {
int x,y,i; int x,y,i;
cell_t *poss[MAXCANDIDATES],*c; cell_t *poss[MAXCANDIDATES],*c;
int nposs = 0; int nposs = 0;
int db = B_FALSE; int db = B_TRUE;
int nadded = 0; int nadded = 0;
int minx = -1, miny = -1, maxx = -1, maxy = -1; int minx = -1, miny = -1, maxx = -1, maxy = -1;
int roomidx = -1; int roomidx = -1;
@ -4225,15 +4280,14 @@ int linkexits(map_t *m, int roomid) {
for (i = 0; i < nposs; i++) { for (i = 0; i < nposs; i++) {
int ncorridors = 0,d; int ncorridors = 0,d;
if (db) dblog("exit at %d,%d:",poss[i]->x, poss[i]->y); if (db) dblog("exit #%d at %d,%d: (%s)",i, poss[i]->x, poss[i]->y,
(poss[i]->isroomwall != D_NONE) ? getdirname(poss[i]->isroomwall) : "nodir");
// if exit is solid and COMPLETELY surrounded by solid, ignore it. // if exit is solid and COMPLETELY surrounded by solid, ignore it.
if (poss[i]->type->solid && (countcellexits(poss[i], DT_ORTH) == 0)){ if (poss[i]->type->solid && (countcellexits(poss[i], DT_ORTH) == 0)){
if (db) dblog("cell is solid and surrounded by solids. ignoring."); if (db) dblog("cell is solid and surrounded by solids. ignoring.");
continue; continue;
} }
if (db) dblog("linking exit #%d",i);
for (d = D_N; d <= D_W; d++) { for (d = D_N; d <= D_W; d++) {
c = getcellindir(poss[i], d); c = getcellindir(poss[i], d);
if (c && cellwalkable(NULL, c, NULL) && (getroomid(c) != roomid)) { if (c && cellwalkable(NULL, c, NULL) && (getroomid(c) != roomid)) {
@ -5595,6 +5649,20 @@ cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id) {
return cell; return cell;
} }
int compassdir(int orthdir) {
switch (orthdir) {
case D_N:
return DC_N;
case D_S:
return DC_S;
case D_E:
return DC_E;
case D_W:
return DC_W;
}
return D_NONE;
}
int getrandomdir(int dirtype) { int getrandomdir(int dirtype) {
if (dirtype == DT_ORTH) { if (dirtype == DT_ORTH) {

4
map.h
View File

@ -14,6 +14,8 @@ regiontype_t *addregiontype(enum REGIONTYPE id, char *name, int pluralname, enum
void adjustcellglyphforlight(cell_t *c, glyph_t *col); void adjustcellglyphforlight(cell_t *c, glyph_t *col);
int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance); int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance);
int cellhaslos(cell_t *c1, cell_t *dest); int cellhaslos(cell_t *c1, cell_t *dest);
int cellisfixedvaultwall(cell_t *c);
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom);
void clearcell(cell_t *c); void clearcell(cell_t *c);
void clearcell_exceptflags(cell_t *c, ...); void clearcell_exceptflags(cell_t *c, ...);
int doelementspread(cell_t *c); int doelementspread(cell_t *c);
@ -39,9 +41,11 @@ void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, i
object_t *gettopobject(cell_t *where, int forglyph); object_t *gettopobject(cell_t *where, int forglyph);
void calclight(map_t *map); void calclight(map_t *map);
int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int *by, int force); int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int *by, int force);
int compassdir(int orthdir);
int countadjcellsoftype(cell_t *cell, int id); int countadjcellsoftype(cell_t *cell, int id);
int countadjrooms(cell_t *cell); int countadjrooms(cell_t *cell);
int countadjcellswithflag(cell_t *cell, enum FLAG fid, int dirtype); int countadjcellswithflag(cell_t *cell, enum FLAG fid, int dirtype);
int countadjdoors(cell_t *cell);
int countadjwalls(cell_t *cell); int countadjwalls(cell_t *cell);
int countcellexits(cell_t *cell, int dirtype); int countcellexits(cell_t *cell, int dirtype);
int countcellexitsfor(lifeform_t *lf); int countcellexitsfor(lifeform_t *lf);

View File

@ -215,7 +215,7 @@ int main(int argc, char **argv) {
if (hasflag(r->flags, F_PLAYABLE)) { if (hasflag(r->flags, F_PLAYABLE)) {
char *longdesc; char *longdesc;
longdesc = malloc(HUGEBUFLEN * sizeof(char)); longdesc = malloc(HUGEBUFLEN * sizeof(char));
makedesc_race(r->id, longdesc, B_TRUE ); makedesc_race(r->id, longdesc, B_TRUE, B_TRUE );
addchoice(&prompt, ch++, r->name, NULL, r, longdesc); addchoice(&prompt, ch++, r->name, NULL, r, longdesc);
free(longdesc); free(longdesc);
} }
@ -355,6 +355,7 @@ int main(int argc, char **argv) {
} }
if (sb1) { if (sb1) {
addflag(player->flags, F_CANCAST, sb1->contents->first->type->id, NA, NA, NULL); addflag(player->flags, F_CANCAST, sb1->contents->first->type->id, NA, NA, NULL);
addflag(sb1->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
} }
initprompt(&prompt, "Select your secondary spell school:"); initprompt(&prompt, "Select your secondary spell school:");
@ -388,6 +389,7 @@ int main(int argc, char **argv) {
} }
if (sb2) { if (sb2) {
addflag(player->flags, F_CANCAST, sb2->contents->first->type->id, NA, NA, NULL); addflag(player->flags, F_CANCAST, sb2->contents->first->type->id, NA, NA, NULL);
addflag(sb2->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
} }
identify(sb1); identify(sb1);
identify(sb2); identify(sb2);

View File

@ -3378,8 +3378,15 @@ void fragments(cell_t *centre, char *what, int speed, int howfar) {
done = B_FALSE; done = B_FALSE;
while (!done) { while (!done) {
c = getcellindir(c, dir); c = getcellindir(c, dir);
if (c && cellwalkable(NULL, c, NULL)) { if (c) {
if (cellwalkable(NULL, c, NULL)) {
maxdist++; maxdist++;
} else {
if (c->lf && !c->type->solid) {
maxdist++;
}
done = B_TRUE;
}
} else { } else {
done = B_TRUE; done = B_TRUE;
} }
@ -3412,10 +3419,19 @@ void fragments(cell_t *centre, char *what, int speed, int howfar) {
break; break;
} }
} }
if (speed) {
object_t *o;
// add object then fire it
o = addob(centre->obpile, what);
if (o) {
fireat(NULL, o, o->amt, dst, speed, NULL);
}
} else {
// add object // add object
addob(dst->obpile, what); addob(dst->obpile, what);
} }
} }
}
int gethardness(enum MATERIAL matid) { int gethardness(enum MATERIAL matid) {
material_t *m; material_t *m;
@ -4576,6 +4592,20 @@ cell_t *getobpilelocation(obpile_t *op) {
return NULL; return NULL;
} }
// note: should have an entry here for everything which willshatter()
char *getshardobname(enum MATERIAL mid, char *buf) {
switch (mid) {
case MT_GLASS:
strcpy(buf, "piece of broken glass");
break;
case MT_ICE:
strcpy(buf, "chunk of ice");
break;
default: return NULL;
}
return buf;
}
char *getshopobname(object_t *o, char *buf, int count) { char *getshopobname(object_t *o, char *buf, int count) {
if (gettechlevel(o->type->id) > getskill(player, SK_TECHUSAGE)) { if (gettechlevel(o->type->id) > getskill(player, SK_TECHUSAGE)) {
// unidentified tech - hide the name // unidentified tech - hide the name
@ -9765,6 +9795,13 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
case OT_POT_GASEOUSFORM: case OT_POT_GASEOUSFORM:
dospelleffects(lf, OT_S_GASEOUSFORM, (potblessed) ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE); dospelleffects(lf, OT_S_GASEOUSFORM, (potblessed) ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE);
break; break;
case OT_POT_GROWTH:
if (iscursed(o)) {
dospelleffects(lf, OT_S_SIZEDOWN, 1, lf, NULL, lf->cell, B_UNCURSED, seen, B_TRUE);
} else {
dospelleffects(lf, OT_S_SIZEUP, 1, lf, NULL, lf->cell, B_UNCURSED, seen, B_TRUE);
}
break;
case OT_POT_HEALING: case OT_POT_HEALING:
dospelleffects(lf, OT_S_HEALING,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE); dospelleffects(lf, OT_S_HEALING,potblessed ? 5 : 1, lf, NULL, lf->cell, potblessed, seen, B_TRUE);
break; break;
@ -10933,6 +10970,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
case OT_POT_ELEMENTIMMUNE: case OT_POT_ELEMENTIMMUNE:
case OT_POT_ETHEREALNESS: case OT_POT_ETHEREALNESS:
case OT_POT_GASEOUSFORM: case OT_POT_GASEOUSFORM:
case OT_POT_GROWTH:
case OT_POT_LEVITATION: case OT_POT_LEVITATION:
case OT_POT_POISON: case OT_POT_POISON:
case OT_POT_POLYMORPH: case OT_POT_POLYMORPH:
@ -12390,7 +12428,8 @@ void timeeffectsob(object_t *o) {
// check each flag for this object... // check each flag for this object...
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_MATCONVERT, F_OBHPDRAIN, F_ONFIRE, F_RECHARGE, F_WALKDAM, F_WET, F_NONE); getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_MATCONVERT, F_OBHPDRAIN, F_ONFIRE,
F_RECHARGE, F_REVIVETIMER, F_WALKDAM, F_WET, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
object_t *oo,*nextoo; object_t *oo,*nextoo;
f = retflag[i]; f = retflag[i];
@ -12531,6 +12570,44 @@ void timeeffectsob(object_t *o) {
} }
} }
} }
// regenerates into a lf?
if (f->id == F_REVIVETIMER) {
cell_t *obloc = NULL;
obloc = getoblocation(o);
f->val[0]++;
limit(&f->val[0], 0, f->val[1]);
if (f->val[0] >= f->val[1]) {
lifeform_t *lf;
cell_t *lfloc = NULL;
if (obloc) {
if (obloc->lf) {
lfloc = getrandomadjcell(obloc, WE_WALKABLE, B_NOEXPAND);
} else {
lfloc = obloc;
}
}
if (lfloc) {
// revive!
lf = addmonster(lfloc, f->val[2], NULL, B_FALSE, 1, B_FALSE, NULL);
// corpse vanishes
removeob(o, o->amt);
// announce
if (haslos(player, lfloc) || haslos(player, obloc)) {
msg("%s comes to life!", obname);
interrupt(player);
}
return;
}
} else if ((f->val[1] - f->val[0]) <= 10) {
if (haslos(player, obloc)) {
// pass a perception chekc to see it moving...
if (skillcheck(player, SC_SEARCH, 20, 0)) {
msg("%s twitches.", obname);
}
}
}
}
// damaging objects here will damage other objects // damaging objects here will damage other objects
if (f->id == F_WALKDAM) { if (f->id == F_WALKDAM) {

View File

@ -122,6 +122,7 @@ char *getobextrainfo(object_t *o, char *buf);
cell_t *getoblocation(object_t *o); cell_t *getoblocation(object_t *o);
cell_t *getobpilelocation(obpile_t *op); cell_t *getobpilelocation(obpile_t *op);
char *getobname(object_t *o, char *buf, int count); char *getobname(object_t *o, char *buf, int count);
char *getshardobname(enum MATERIAL mid, char *buf);
char *getshopobname(object_t *o, char *buf, int count); char *getshopobname(object_t *o, char *buf, int count);
char *getobnametrue(object_t *o, char *buf, int count); char *getobnametrue(object_t *o, char *buf, int count);
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int showall); char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int showall);

24
spell.c
View File

@ -8772,6 +8772,30 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster)) { if (isplayer(caster)) {
msg("You will now be warned of creatures behind you."); msg("You will now be warned of creatures behind you.");
} }
} else if ((spellid == OT_S_SIZEUP) || (spellid == OT_S_SIZEDOWN)) {
enum LFSIZE origsize,newsize;
origsize = getlfsize(caster);
if (spellid == OT_S_SIZEUP) {
if (origsize >= SZ_ENORMOUS) {
fizzle(caster);
return B_TRUE;
}
newsize = origsize + 1;
} else { // ie. sizedown
if (origsize <= SZ_MINI) {
fizzle(caster);
return B_TRUE;
}
newsize = origsize - 1;
}
if (resizelf(caster, newsize)) {
// failed
fizzle(caster);
return B_TRUE;
}
if (isplayer(caster) || cansee(player, caster)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (spellid == OT_S_SLEEP) { } else if (spellid == OT_S_SLEEP) {
int howlong; int howlong;
target = targcell->lf; target = targcell->lf;

View File

@ -1330,6 +1330,9 @@ int handleline(vault_t *v, char *line) {
} else { } else {
dblog("invalid goesin() definition: '%s'", line); dblog("invalid goesin() definition: '%s'", line);
} }
} else if (streq(line, "maintainedge")) {
addflag(v->flags, F_MAINTAINEDGE, B_TRUE, NA, NA, NULL);
ok = B_TRUE;
} else if (strstarts(line, "margin")) { } else if (strstarts(line, "margin")) {
char *p; char *p;
p = line + 6; p = line + 6;

View File

@ -21,5 +21,6 @@ X:exit
goesin:dungeon goesin:dungeon
mayrotate mayrotate
rarity:vrare rarity:vrare
maintainedge
@end @end

View File

@ -22,5 +22,6 @@ scatter(3,1,-4,-2) mon:bear cub:1-3:50
goesin:dungeon goesin:dungeon
mayrotate mayrotate
rarity:uncommon rarity:uncommon
maintainedge
@end @end

View File

@ -35,5 +35,6 @@ scatter(1,1,-2,-2) ob:wooden footstool:0-3
scatter(1,1,-2,-2) ob:random food:0-2 scatter(1,1,-2,-2) ob:random food:0-2
mayflipx mayflipx
tag:caveboss tag:caveboss
maintainedge
@end @end

View File

@ -16,5 +16,6 @@ m:mon:sleeping random
goesin:dungeon goesin:dungeon
mayrotate mayrotate
rarity:uncommon rarity:uncommon
maintainedge
@end @end

View File

@ -19,8 +19,8 @@
@flags @flags
goesin:dungeon goesin:dungeon
autodoors:50
autopop autopop
rarity:frequent rarity:frequent
maintainedge
@end @end

View File

@ -17,5 +17,6 @@ x:exit
@flags @flags
goesin:dungeon goesin:dungeon
rarity:frequent rarity:frequent
maintainedge
@end @end

View File

@ -17,4 +17,5 @@ x:exit
goesin:dungeon goesin:dungeon
rarity:frequent rarity:frequent
mayrotate mayrotate
maintainedge
@end @end

View File

@ -26,5 +26,6 @@ shrine
norandom norandom
mayrotate mayrotate
goesin:dungeon goesin:dungeon
maintainedge
@end @end

View File

@ -33,5 +33,6 @@ atoneof(10,1)(10,3)(10,5) ob:portal to lv1
scatter(1,1,-2,-2) ob:wooden footstool:0-3 scatter(1,1,-2,-2) ob:wooden footstool:0-3
scatter(1,1,-2,-2) ob:random food:0-2 scatter(1,1,-2,-2) ob:random food:0-2
mayrotate mayrotate
maintainedge
@end @end

View File

@ -42,5 +42,6 @@ scatter(0,0,-1,-1) ob:common weapon:4-5
mayrotate mayrotate
! mayscale ! mayscale
rarity:rare rarity:rare
maintainedge
@end @end

View File

@ -15,5 +15,6 @@ o:ob:1-5 random tools
@flags @flags
goesin:dungeon goesin:dungeon
rarity:uncommon rarity:uncommon
maintainedge
@end @end

View File

@ -15,5 +15,6 @@ o:ob:1-5 random technology
@flags @flags
goesin:dungeon goesin:dungeon
rarity:uncommon rarity:uncommon
maintainedge
@end @end

View File

@ -20,5 +20,6 @@ mayrotate
rarity:vrare rarity:vrare
! don't link to rest of map. ie this can be in the middle of nowhere. ! don't link to rest of map. ie this can be in the middle of nowhere.
nolink nolink
maintainedge
@end @end