- [+] fixed crash related to F_CASTINGSPELL

- [+] change god names to "god of xxx/yyy/zzz"
- [+] i'm pleasing the god of life somehow unknown. why?
    - [+] from sleeping!
    - [+] was checking !isasleep(god), not !isasleep(player)
- [+] ai object stealing code not working
- [+] chance to wake up when someone is stealing your objects ?
    - [+] stealer makes an easy stealth check
- [+] fix crash in steal()
- [+] when fix_reachability kills a wall, add rubble as if the wall
      fell down.
- [+] if you burn yourself on something, automatically drop it.
- [+] ai shouldn't try to wear dangerous objects.
- [+] f_hot objects count as dangerous
- [+] if metal takes fire damage, it gets F_HOT (unknown)
    - [+] touch() will burn you, and make the flag known ("red hot") 
    - [+] if you are wearing F_HOT armour, take damage from it.
    - [+] modify how heat metal spell works
    - [+] when something catches on fire, it also gains F_HOT 
    - [+] test heat metal
- [+] firebug and fire sprite should have f_extracorpse "small fire"
- [+] in makedesc_skill, only show each "at xxx level" heading once
- [+] ice wraith shuld be flying.  ghast shouldnt be levitating.
- [+] MENDING should fix rust.
- [+] BUG: ERROR - unlinked stairs! should have been linked during map
      creation.
    - [+] was on Dlev 9
    - [+] stairs were going to the swamp.... and swamp had no stairs!!!
    - [+] in finalisemap: swamp was misisng stairtypes!
This commit is contained in:
Rob Pearce 2012-02-03 05:55:19 +00:00
parent b1abb5ad76
commit c1bccc652c
15 changed files with 425 additions and 151 deletions

23
ai.c
View File

@ -934,10 +934,10 @@ int ai_handle_emergencies(lifeform_t *lf, enum ATTRBRACKET iqb) {
if (lfhasflag(lf, F_RAGE)) return B_FALSE;
// if our cell is dangerous, move away!
if (iqb >= AT_AVERAGE) {
if (celldangerous(lf, lf->cell, B_TRUE, NULL)) {
if (db) dblog("%s o O { there is something dangerous here, moving away } ", lf->race->name);
// if our cell is dangerous, move away!
moveawayfromcell = B_TRUE;
}
}
@ -1211,9 +1211,20 @@ int ai_inventory_mgt(lifeform_t *lf, int *canattack) {
object_t *curarm;
bp = lf->race->bodypart[i].id;
curarm = getarmour(lf, bp);
// is it red hot?
if (curarm && hasflag(curarm->flags, F_HOT) && !isimmuneto(lf->flags, DT_FIRE, B_FALSE)) {
if (db) dblog("%s o O { wearing a red-hot item. will try to remove it. } ", lf->race->name);
if (cantakeoff(lf, curarm)) {
if (!takeoff(lf, curarm)) {
return B_TRUE;
}
} else {
if (db) dblog("%s o O { cannot remove it. maybe cursed? } ", lf->race->name);
}
}
// do we have a better one?
for (o = lf->pack->first ; o ; o = o->next) {
if (canwear(lf, o, BP_NONE) && isbetterarmourthan(o, curarm)) {
if (!isdangerousob(o, lf, B_TRUE) && canwear(lf, o, BP_NONE) && isbetterarmourthan(o, curarm)) {
// wear this armour instead
if (!wear(lf, o)) return B_TRUE;
}
@ -1221,6 +1232,7 @@ int ai_inventory_mgt(lifeform_t *lf, int *canattack) {
}
// now check whetehr we have ANY weapon
if (curwep || lfhasflag(lf, F_HASATTACK)) {
icanattack = B_TRUE;
@ -2622,7 +2634,6 @@ int lookforobs(lifeform_t *lf) {
c = lf->los[i];
celldist = getcelldist(lf->cell, c);
if ((c != lf->cell) && !c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (aiwants_real(lf, o, &covets, &noids, oid, oidcovet, &nwantflags, wantflag, wantflagcovet) &&
@ -2697,7 +2708,7 @@ int lookforobs(lifeform_t *lf) {
} else if ((celldist == 1) && c->lf &&
(isunconscious(c->lf) || isasleep(c->lf)) &&
(getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) > IQ_ANIMAL) && !isundead(lf) && !willeatlf(lf, c->lf)) {
// intelligent enemies will loot unconscious lfs to make sure they are not a threat.
// intelligent enemies will loot unconscious/sleeping lfs to make sure they are not a threat.
//
// in this case they'll loot more than normal. even if they wouldn't normally pick up
// some of these objects, they'll assume they are good because the player was holding
@ -2722,9 +2733,9 @@ int lookforobs(lifeform_t *lf) {
}
}
// if we are in battle only go for it if we covet it
// if we are in battle with someone OTHER than this lf, then only go for it if we covet it
if (getit) {
if (target && !covets) getit = B_FALSE;
if (target && (target != c->lf) && !covets) getit = B_FALSE;
if (isdangerousob(o, lf, B_TRUE) || !aipickupok(lf, o)) getit = B_FALSE;
}
if (getit) {

28
data.c
View File

@ -2019,7 +2019,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "3d6");
addot(OT_MISTLETOE, "sprig of mistletoe", "A small cutting of mistletoe.", MT_PLANT, 0.01, OC_FLORA, SZ_TINY);
addot(OT_MISTLETOE, "sprig of mistletoe", "A small cutting of mistletoe. Druids can sacrifice these cuttings to increase their magical reservces.", MT_PLANT, 0.01, OC_FLORA, SZ_TINY);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "leaf");
addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, "");
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
@ -3213,8 +3213,8 @@ void initobjects(void) {
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_WEB, "web", "Slows down pursuers with a burst of sticky spider web.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines how much webbing is created.");
addot(OT_S_WEB, "web", "Slows down pursuers with one or more bursts of sticky spider web.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines how many webs are created.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
@ -7658,7 +7658,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "gestures imperiously");
addflag(lastrace->flags, F_CASTCHANCE, 75, NA, NA, NULL);
// god abilities
addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Purity");
addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Purity & Order");
addflag(lastrace->flags, F_FLEEONHPPCT, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_LIGHT, NA, NA, "pw:10;");
// may cast all life spells
@ -7717,7 +7717,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTSKILL, SK_ARMOUR, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_SHIELDS, PR_MASTER, NA, NULL);
// god abilities
addflag(lastrace->flags, F_GODOF, B_MALE, NA, NA, "Battle");
addflag(lastrace->flags, F_GODOF, B_MALE, NA, NA, "Battle & Honour");
addflag(lastrace->flags, F_STAMREGEN, NA, NA, NA, "10"); // ie. basically infinite
addflag(lastrace->flags, F_CANWILL, OT_A_HEAVYBLOW, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_WARCRY, NA, NA, NULL);
@ -7771,7 +7771,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTSKILL, SK_LORE_NATURE, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_LORE_DRAGONS, PR_ADEPT, NA, NULL); // ekrub hates dragons
// god abilities
addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Creation");
addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Creation & Nature");
// may cast all nature spells
for (ot = objecttype ; ot ; ot = ot->next) {
if ((ot->obclass->id == OC_SPELL) && (getspellschool(ot->id) == SS_NATURE)) {
@ -7822,7 +7822,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "waves his hand");
addflag(lastrace->flags, F_CASTCHANCE, 75, NA, NA, NULL);
// god abilities
addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Revenge");
addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Revenge & Thievery");
addflag(lastrace->flags, F_FLEEONHPPCT, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_HIDE, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_CALLWIND, NA, NA, "pw:10;");
@ -7862,7 +7862,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_MASTER, NA, NULL);
// god abilities
addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Life");
addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Life & Healing");
addflag(lastrace->flags, F_REGENERATES, 5, NA, NA, NULL);
// may cast all life spells
for (ot = objecttype ; ot ; ot = ot->next) {
@ -7964,7 +7964,7 @@ void initrace(void) {
addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "large fire");
addflag(lastrace->flags, F_RETALIATE, 2, 4, DT_FIRE, "roaring flames");
addflag(lastrace->flags, F_DTIMMUNE, DT_FIRE, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_GODOF, B_MALE, NA, NA, "Destruction");
addflag(lastrace->flags, F_GODOF, B_MALE, NA, NA, "Destruction & Fire");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "starting fires");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "burning objects");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing with fire");
@ -9086,6 +9086,7 @@ void initrace(void) {
addrace(R_PEGASUS, "pegasus", 130, 'Q', C_GREY, MT_FLESH, RC_MAGIC, "A legendary white, winged horse.");
setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
addflag(lastrace->flags, F_CANTALK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 57, NA, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, 57, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, 57, NA, NULL);
@ -9372,6 +9373,7 @@ void initrace(void) {
addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE, RC_MAGIC, "A small magical creature surrounded by crackling flames.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_EXTRACORPSE, NA, NA, NA, "small fire");
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9987,7 +9989,7 @@ void initrace(void) {
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, SV_SHOUT, NA, "croaks^croaking");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, SV_SHOUT, NA, "croaking^croaking");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, SV_SHOUT, NA, "croaks^croaking");
addflag(lastrace->flags, F_NOISETEXT, N_SPELLCAST, SV_SHOUT, NA, "gurgles loudly^a loud gurgling");
addflag(lastrace->flags, F_CANWILL, OT_A_JUMP, NA, NA, "stamcost:0;");
addflag(lastrace->flags, F_CANWILL, OT_S_FLOOD, 20, 20, "pw:6;");
@ -10049,6 +10051,7 @@ void initrace(void) {
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
addflag(lastrace->flags, F_CANTALK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 2, 4, NA, "");
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL);
@ -11379,6 +11382,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addrace(R_FIREBUG, "firebug", 2, 'x', C_RED, MT_FLESH, RC_INSECT, "Constantly burning insects which attack their victims with fire.");
setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_EXTRACORPSE, NA, NA, NA, "small fire");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
@ -11386,6 +11390,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4");
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHBURN, 3, NA, NULL);
@ -11692,6 +11697,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
@ -11714,7 +11720,6 @@ void initrace(void) {
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_LEVITATING, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
@ -11744,6 +11749,7 @@ void initrace(void) {
addflag(lastrace->flags, F_XRAYVIS, 3, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_INDUCEFEAR, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_INVISIBILITY, 40, 40, "pw:1;");
// special: ghosts gain canwill->possession if they are near

Binary file not shown.

18
defs.h
View File

@ -23,6 +23,9 @@
// Defaults
#define DEF_AIFOLLOWTIME (50) // if target lf is out of view
#define DEF_BURNTIMEMIN (3)
#define DEF_BURNTIMEMAX (6)
// for this many turns, abandon chase
//#define DEF_ANIMDELAY (1000000 / 50) // 1/100 of a second
#define DEF_ANIMDELAY (1000000 / 25) // 1/50 of a second
@ -492,6 +495,7 @@ enum SAYPHRASE {
SP_RECRUIT_DECLINE,
SP_RECRUIT_DECLINE_CANTPAY,
SP_RECRUIT_DECLINE_WONTPAY,
SP_ROBBED,
SP_SORRY,
SP_THANKS,
SP_TRADEINFO_ACCEPT,
@ -2350,7 +2354,10 @@ enum FLAG {
// v0 = enum RUSTINESS.
// object mods/effects
F_ONFIRE, // burning, also deals extra fire damage
// option text = xdx amount of damage.
// option text = xdx amount of extra damage to deal for
// weapons.
F_HOT, // object is very hot to the touch.
// v0 = amt of damage to deal if touched while gloveless
F_ENCHANTED, // weapon also deals 'text' extra fire damage
F_HEADLESS, // for corpses. can go on LFs too.
F_MASTERWORK, // weps do higher damager, armour protects better
@ -2532,6 +2539,10 @@ enum FLAG {
// text = killed by xxx
F_WASROBBED, // your stuff was stolen while you were
// unconscious. announce it when you wake up.
F_WOKENBY, // at the start of your next turn, you will wake up
// due to actions taken by lf id v0.
// if text is set, and it was the player waking up,
// then print this text.
F_TURNED, // lf turned this turn.
F_PRAYEDTO, // player has prayed to this god before.
F_HPDRAIN, // lf loses v0 hit points eath turn.
@ -2629,6 +2640,8 @@ enum FLAG {
F_CORPSETYPE, // text field specifies what corpse obtype to leave
F_CORPSEFLAG, // add flag v0 to our corpse.
// v1->v0, v2->v1, text->text
F_EXTRACORPSE, // text field specifies what additional corpse
// obtype to leave
F_MYCORPSE, // text field contains obid of my corpse.
// (for ghosts)
F_NOCORPSE, // monster's body crumbles to dust after death
@ -2840,6 +2853,8 @@ enum FLAG {
// for monsters
F_MPMOD, // this race gains/loses v0 mp each level
F_DOESNTMOVE, // this race doesn't move (but can still attack)
F_CANTALK, // this lf can talk, even if its raceclass normally
// wouldn't be able to.
F_AQUATIC, // this race can attack normally in water and suffers no
// movement penalties
F_AVIAN, // this race is an avian
@ -3495,6 +3510,7 @@ typedef struct habitat_s {
int randobpct; // % chance that 'something' is an ob rather than monster
int randvaultpct; // % chance that a room will be a vault
int maxvisrange;
enum OBTYPE upstairtype, downstairtype;
enum CELLTYPE emptycelltype,solidcelltype;
struct habitat_s *next, *prev;
} habitat_t;

View File

@ -5,6 +5,9 @@ map.c:
initmap: define via addhabitat()
finalisemap():
define up/down stair types for this map
make a new function to create this kind of habitat

2
god.c
View File

@ -1287,7 +1287,7 @@ void pleasegod(enum RACE rid, int amt) {
// announce
if (hasflag(lf->flags, F_PRAYEDTO)) {
if (!isasleep(lf)) {
if (!isasleep(player)) {
switch (rid) {
case R_GODBATTLE:
msg("You feel triumphant.");

28
io.c
View File

@ -2524,13 +2524,14 @@ int announceobflaggain(object_t *o, flag_t *f) {
}
if (f->id == F_ONFIRE) {
if ((f->id == F_ONFIRE) || (f->id == F_HOT)) {
// don't want "the flaming sword catches on fire"
wantpremods = B_FALSE;
}
real_getobname(o, obname, o->amt, wantpremods, B_FALSE, B_TRUE, B_TRUE, B_FALSE);
if (o->pile->owner) {
if (isplayer(o->pile->owner)) {
snprintf(prefix, BUFLEN, "Your %s",noprefix(obname));
@ -2553,6 +2554,14 @@ int announceobflaggain(object_t *o, flag_t *f) {
donesomething = B_TRUE;
if (o->birthtime != curtime) msg("%s start%s glowing!",prefix, OBS1(o));
break;
case F_HOT:
// you only know an object is hot if you notice the effects on the
// person wearing it.
if (hasflag(o->flags, F_EQUIPPED)) {
msg("%s glow%s red hot!", prefix, OBS1(o));
}
break;
default: // no message
break;
}
@ -5702,6 +5711,11 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, "It is on fire.\n");
strncat(retbuf, buf, HUGEBUFLEN);
}
f = hasflagknown(o->flags, F_HOT);
if (f) {
sprintf(buf, "It is extremely hot.\n");
strncat(retbuf, buf, HUGEBUFLEN);
}
if (obproduceslight(o)) {
sprintf(buf, "It is producing light.\n");
@ -6640,17 +6654,23 @@ char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite) {
for (slev = PR_INEPT; slev <= PR_MASTER; slev++) {
int found = B_FALSE;
int hilitethis = B_FALSE;
int numdescs = 0;
if ((levhilite != PR_INEPT) && (slev == levhilite)) {
hilitethis = B_TRUE;
}
for (i = 0; i < sk->nskilldesc; i++) {
if (sk->skilldesclev[i] == slev) {
numdescs++;
if (slev == PR_INEPT) {
// extra blank line after this one
snprintf(buf, BUFLEN, "%s\n\n",sk->skilldesctext[i]);
} else {
char atxlevel[BUFLEN];
snprintf(atxlevel, BUFLEN, "At %s level", getskilllevelname(sk->skilldesclev[i]));
if (numdescs == 1) {
snprintf(atxlevel, BUFLEN, "At %s level", getskilllevelname(sk->skilldesclev[i]));
} else {
snprintf(atxlevel, BUFLEN, " "); // same as last heading
}
snprintf(buf, BUFLEN, "%s%-18s%s: %s\n", // right-align "at xx level"
hilitethis ? "^w" : "", atxlevel, hilitethis ? "^n" : "",
sk->skilldesctext[i]);
@ -12191,7 +12211,7 @@ void showlfstats(lifeform_t *lf, int showall) {
centre(mainwin, C_WHITE, 0, "GODS");
y = 2;
snprintf(line, BUFLEN, "%-26s Prayed? %-22s %s","God","Piety", "Happiness");
snprintf(line, BUFLEN, "%-30s Prayed? %-22s %s","God","Piety", "Happiness");
doheading(mainwin, &y, 0, line);
@ -12264,7 +12284,7 @@ void showlfstats(lifeform_t *lf, int showall) {
strcat(pietybuf, "^n]");
}
snprintf(line, BUFLEN, "%s%s%-26s%-9s%s %s%s",
snprintf(line, BUFLEN, "%s%s%-30s%-9s%s %s%s",
blocked ? "^B" : "", // whole line is red if this god is blocked
blocked ? "" : prayedto ? "^g" : "^n",
godname,

152
lf.c
View File

@ -1488,16 +1488,18 @@ int cantakeoff(lifeform_t *lf, object_t *o) {
}
int cantalk(lifeform_t *lf) {
switch (lf->race->raceclass->id) {
case RC_DEMON:
case RC_DRAGON:
case RC_GOD:
case RC_HUMANOID:
// these ones can talk
break;
default:
return B_FALSE;
break;
if (!lfhasflag(lf, F_CANTALK)) {
switch (lf->race->raceclass->id) {
case RC_DEMON:
case RC_DRAGON:
case RC_GOD:
case RC_HUMANOID:
// these ones can talk
break;
default:
return B_FALSE;
break;
}
}
// too dumb?
@ -2775,6 +2777,13 @@ void die(lifeform_t *lf) {
addobfast(corpsecell->obpile, OT_FIRESMALL);
}
}
// some lfs have extra corpse objects
getflags(lf->flags, retflag, &nretflags, F_EXTRACORPSE, F_NONE);
for (i = 0; i < nretflags; i++) {
addob(corpsecell->obpile, retflag[i]->text);
}
}
// splatter
@ -15250,6 +15259,12 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
case SP_RECRUIT_DECLINE_WONTPAY:
rv = say(lf, "Perhaps another time, then.", volume);
break;
case SP_ROBBED:
switch (rnd(0,1)) {
case 0: rv = say(lf, "Hey! Where are my things?", volume); break;
case 1: rv = say(lf, "I've been robbed!", volume); break;
}
break;
case SP_SORRY:
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_HIGH) {
switch (rnd(0,1)) {
@ -16510,16 +16525,28 @@ void startlfturn(lifeform_t *lf) {
}
}
if (isasleep(lf) && ((f = lfhasflag(lf, F_WOKENBY)) != NULL)) {
lifeform_t *thief;
thief = findlf(lf->cell->map, f->val[0]);
if (isplayer(lf)) {
msg("%s", f->text);
}
if (thief) {
turntoface(lf, thief->cell);
}
killflagsofid(lf->flags, F_ASLEEP);
}
if (!isdead(lf) && !isunconscious(lf) && hasflag(lf->flags, F_WASROBBED)) {
if (!isdead(lf) && !isunconscious(lf) && !isasleep(lf) && hasflag(lf->flags, F_WASROBBED)) {
if (isplayer(lf)) {
if (countobs(lf->pack, B_FALSE)) {
msg("Some of your items are missing!");
msg("^wSome of your items are missing!^n"); more();
} else {
msg("All of your items are missing!");
msg("^wAll of your items are missing!^n"); more();
}
} else {
say(lf, "Hey! Where are my things?", SV_SHOUT);
sayphrase(lf, SP_ROBBED, SV_SHOUT, NA, NULL);
}
killflagsofid(lf->flags, F_WASROBBED);
}
@ -17208,7 +17235,6 @@ void startlfturn(lifeform_t *lf) {
}
if (isdead(lf)) return;
// effects from cell objects?
for (o = lf->cell->obpile->first ; o ; o = o->next) {
f = hasflag(o->flags, F_WALKDAM);
@ -17286,6 +17312,29 @@ void startlfturn(lifeform_t *lf) {
}
if (isdead(lf)) return;
// effects from pack objects
for (o = lf->pack->first ; o ; o = o->next) {
// hot equipped objects?
if (isequipped(o) && !isweapon(o)) {
f = hasflag(o->flags, F_HOT);
if (f) {
f->known = B_TRUE;
if (isplayer(lf)) {
getobname(o, buf, 1);
msg("^BYour %s burns you!^n", noprefix(buf));
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
getobname(o, buf, 1);
msg("^B%s%s %s burns it!^n", lfname, getpossessive(lfname), noprefix(buf));
}
losehp_real(lf, f->val[0], DT_HEAT, NULL, buf, B_TRUE, o, B_FALSE);
}
}
}
if (isdead(lf)) return;
// effects for/on your own flags
getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FEIGNFOOLEDBY,F_FLEEFROM,
F_GRABBEDBY, F_GRABBING, F_HIDING, F_BOOSTSPELL, F_FEIGNINGDEATH, F_HPDRAIN, F_INJURY,
@ -17558,7 +17607,7 @@ int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag) {
if (op->owner) {
getlfname(op->owner, targname);
if (isplayer(lf)) {
msg("You steal %s from %s!", getlfcol(op->owner, CC_BAD), obname, targname);
msg("^%cYou steal %s from %s!", getlfcol(op->owner, CC_BAD), obname, targname);
} else if (cansee(player, lf)) {
msg("^%c%s steals %s from %s!", getlfcol(op->owner, CC_BAD), lfname, obname, targname);
}
@ -17834,7 +17883,9 @@ int takeoff(lifeform_t *lf, object_t *o) {
}
unequipeffects(lf, o);
return B_FALSE;
}
void taketime(lifeform_t *lf, long howlong) {
@ -17979,6 +18030,7 @@ void timeeffectslf(lifeform_t *lf) {
timeeffectsob(o);
}
// holes in the floor/roof
for (dir = D_UP; dir <= D_DOWN; dir++) {
int donesomething = B_TRUE;
@ -18095,14 +18147,14 @@ int tradeknowledge(lifeform_t *lf) {
}
// return B_TRUE on failure.
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat) {
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat, int onpurpose) {
// if you have a rope or there's an adjacent wall, you can try
// to climb up
int adjwalls;
char lfname[BUFLEN];
// climbing without climb skill?
if (isplayer(lf) &&
if (isplayer(lf) && onpurpose &&
!getskill(lf, SK_CLIMBING) &&
!lfhasflag(lf, F_SPIDERCLIMB) &&
!hasobwithflag(lf->pack, F_HELPSCLIMB)) {
@ -18152,7 +18204,12 @@ int tryclimb(lifeform_t *lf, cell_t *where, char *towhat) {
}
} else { // no rope or adjacent walls
if (isplayer(lf)) {
msg("You can't reach the roof!");
if (onpurpose) {
msg("You can't reach the roof!");
} else {
// ie. you were fleeing.
msg("You try to climb upwards, but can't reach the roof!");
}
}
return B_TRUE;
}
@ -18165,9 +18222,12 @@ int tryclimb(lifeform_t *lf, cell_t *where, char *towhat) {
// returns B_TRUE if the action which involved touching this should fail
int touch(lifeform_t *lf, object_t *o) {
flag_t *f;
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
char buf[BUFLEN];
char obname[BUFLEN];
char lfname[BUFLEN];
object_t *gloves;
if ((gamemode != GM_GAMESTARTED)) return B_FALSE;
@ -18218,7 +18278,7 @@ int touch(lifeform_t *lf, object_t *o) {
snprintf(buf, BUFLEN, "touching %s",obname);
losehp(lf, 2, DT_HOLY, NULL, buf);
// drop the object if we're holding it
if (o->pile->owner == lf) {
if ((o->pile->owner == lf) && !isequipped(o)) {
drop(o, ALL);
}
return B_TRUE;
@ -18238,11 +18298,11 @@ int touch(lifeform_t *lf, object_t *o) {
}
}
gloves = getequippedob(lf->pack, BP_HANDS);
f = hasflag(o->flags, F_SHARP);
if (f) {
object_t *gloves;
gloves = getequippedob(lf->pack, BP_HANDS);
if (!gloves) {
if (isplayer(lf)) {
msg("^bOw! You cut your finger on %s.", obname);
@ -18250,32 +18310,56 @@ int touch(lifeform_t *lf, object_t *o) {
snprintf(buf, BUFLEN, "touching %s", obname);
losehp(lf, rnd(1,2), DT_SLASH, NULL, buf);
// drop the object if we're holding it
if ((o->pile->owner == lf) && !isequipped(o)) {
drop(o, ALL);
}
}
}
// flaming objects?
if (hasflag(o->flags, F_ONFIRE)) {
// flaming weapons are ok
if (!isweapon(o)) {
object_t *gloves;
// flaming or red-hot objects?
getflags(o->flags, retflag, &nretflags, F_ONFIRE, F_HOT, F_NONE); // IMPORTANT - check ONFIRE first!
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// flaming weapons are ok - only the blade is burning
if ((f->id == F_ONFIRE) && isweapon(o)) {
} else {
// wearing gloves? they get damaged.
gloves = getequippedob(lf->pack, BP_HANDS);
if (gloves) {
takedamage(gloves, 2, DT_FIRE);
if (!hasflag(gloves->flags, F_DEAD)) {
// if your gloves weren't destroyed the fire
// will go out.
killflagsofid(o->flags, F_ONFIRE);
if (f->id == F_ONFIRE) {
takedamage(gloves, 2, DT_FIRE);
if (hasflag(gloves->flags, F_DEAD)) {
gloves = NULL;
} else {
// if your gloves weren't destroyed the fire
// will go out.
killflagsofid(o->flags, F_ONFIRE);
}
}
} else {
enum DAMTYPE dt;
int dam = 3;
// otherwise YOU get damaged.
f->known = B_TRUE;
getobname(o, obname, o->amt); // get name again after making flag known
if (isplayer(lf)) {
msg("^bOw! You burn your hands on %s.",obname);
} else if (cansee(player, lf)) {
msg("%s burns itself on %s.",lfname, obname);
}
snprintf(buf, BUFLEN, "touching %s",obname);
losehp(lf, 2, DT_FIRE, NULL, buf);
if (f->id == F_ONFIRE) {
dt = DT_FIRE;
dam = rnd(2,4);
} else if (f->id == F_HOT) {
dt = DT_HEAT;
dam = f->val[0];
}
losehp(lf, dam, dt, NULL, buf);
// drop the object if we're holding it
if ((o->pile->owner == lf) && !isequipped(o)) {
drop(o, ALL);
}
return B_TRUE;
}
@ -18557,7 +18641,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
} else {
char buf[BUFLEN];
snprintf(buf, BUFLEN, "the %s", noprefix(obname));
if (tryclimb(lf, obcell, buf)) {
if (tryclimb(lf, obcell, buf, onpurpose)) {
// failed
return B_TRUE;
} else {

2
lf.h
View File

@ -424,7 +424,7 @@ void taketime(lifeform_t *lf, long howlong);
int throwat(lifeform_t *thrower, object_t *o, cell_t *where);
void timeeffectslf(lifeform_t *lf);
int tradeknowledge(lifeform_t *lf);
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat);
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat, int onpurpose);
int touch(lifeform_t *lf, object_t *o);
void turntoface(lifeform_t *lf, cell_t *dstcell);
void unequipeffects(lifeform_t *lf, object_t *o);

120
map.c
View File

@ -87,7 +87,7 @@ cell_t *addcell(map_t *m, int x, int y) {
return cell;
}
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange) {
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange, enum OBTYPE upstairtype, enum OBTYPE downstairtype) {
habitat_t *a;
// add to the end of the list
if (firsthabitat == NULL) {
@ -113,6 +113,8 @@ habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum
a->randobpct = obchance;
a->randvaultpct = vaultchance;
a->maxvisrange = maxvisrange;
a->upstairtype = upstairtype;
a->downstairtype = downstairtype;
return a;
}
@ -653,6 +655,19 @@ region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid, int
regionoutline_t *ro,*poss[MAXCANDIDATES];
int nposs = 0;
int id;
regiontype_t *rt;
rt = findregiontype(rtype);
if (rt->majorbranch) {
// check for dupes
if (findregionbytype(rtype)) {
dblog("ERROR - trying to add duplicate region for a major branch (%s)", rt->name);
msg("ERROR - trying to add duplicate region for a major branch (%s)", rt->name);
more();
raise(SIGINT); // debug
}
}
// is there already a region?
if (lastregion) {
id = lastregion->id + 1;
@ -928,6 +943,22 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
}
// change a wall into an empty cell, and add some rubble
void breakwall(cell_t *c) {
celltype_t *origtype;
int roomwall;
origtype = c->type;
roomwall = isroom(c);
setcelltype(c, c->habitat->emptycelltype);
if (origtype->solid && roomwall && onein(2)) {
switch (origtype->material->id) {
case MT_STONE: addob(c->obpile, "1-30 stones"); break;
case MT_GLASS: addob(c->obpile, "1-30 pieces of broken glass"); break;
default: break;
}
}
}
int cellhaslos(cell_t *c1, cell_t *dest) {
int deltax, deltay;
int numpixels;
@ -1758,10 +1789,12 @@ void calclight(map_t *map) {
// did any lit values within player's los change?
if (gamemode == GM_GAMESTARTED) {
int dolos = B_FALSE;
for (i = 0; i < player->nlos; i++) {
if (player->los[i]->lastlit != player->los[i]->lit) {
dolos = B_TRUE;
break;
if (!isblind(player)) {
for (i = 0; i < player->nlos; i++) {
if (player->los[i]->lastlit != player->los[i]->lit) {
dolos = B_TRUE;
break;
}
}
}
if (dolos) {
@ -2887,7 +2920,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
int i,x,y;
enum HABITAT habitat;
regionthing_t *thing[MAXOUTLINETHINGS];
int nthings = 0,failed;
int nthings = 0,failed,nstairslinked = 0;
int db = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
@ -3344,6 +3377,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// try to join up any unlinked staircases in this map.
if (db) dblog(" joining unlinked stairs...");
nstairslinked = 0;
for (y = 0; y < map->h; y++) {
for (x = 0; x < map->w; x++) {
cell_t *c;
@ -3359,6 +3393,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
dst = getstairdestination(o, NULL);
dblog(" linked '%s' to map %s",o->type->name, dst->map->name);
}
nstairslinked++;
} else {
if (db) {
dblog(" FAILED to link stairs: '%s'",o->type->name);
@ -3368,6 +3403,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
}
}
}
if (db) dblog(" linked %d stairs.", nstairslinked);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
@ -4139,17 +4175,17 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
if (db) dblog(" Making path from vault to corner, initdir=%s", getdirname(startdir));
c = getcellindir(startcell, startdir);
while (c != turncell) {
setcelltype(c, c->habitat->emptycelltype);
breakwall(c);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, startdir);
}
// clear the corner cell
setcelltype(c, c->habitat->emptycelltype);
breakwall(c);
if (db) dblog(" Making path from corner to rest of map, turndir=%s", getdirname(turndir));
// now turn and clear up to the next room/empty cell
c = getcellindir(c, turndir);
while (c != endcell) {
setcelltype(c, c->habitat->emptycelltype);
breakwall(c);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, turndir);
}
@ -4228,17 +4264,17 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
if (db) dblog(" Making path from vault to first corner, initdir=%s", getdirname(startdir));
c = getcellindir(startcell, startdir);
while (c != turncell) {
setcelltype(c, c->habitat->emptycelltype);
breakwall(c);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, startdir);
}
// clear the corner cell
setcelltype(c, c->habitat->emptycelltype);
breakwall(c);
// now turn and clear up to the next turn
if (db) dblog(" Making path from 1st corner to 2nd corner, turndir=%s", getdirname(turndir));
c = getcellindir(c, turndir);
while (c != turncell2) {
setcelltype(c, c->habitat->emptycelltype);
breakwall(c);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, turndir);
}
@ -4247,7 +4283,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
if (db) dblog(" Making path from 2nd corner to rest of map, turndir=%s", getdirname(turndir2));
c = getcellindir(c, turndir2);
while (c != endcell) {
setcelltype(c, c->habitat->emptycelltype);
breakwall(c);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, turndir2);
}
@ -4287,7 +4323,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
c = getcellindir(startcell, whichway);
//while (c && !cellwalkable(NULL, c, NULL)) {
while (c && c != directendcell[whichway]) {
setcelltype(c, c->habitat->emptycelltype);
breakwall(c);
if (ncellsadded) (*ncellsadded)++;
c = getcellindir(c, whichway);
}
@ -4295,7 +4331,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
// now make sure the START cell is empty too!
if (startcell->type->solid) {
setcelltype(startcell, startcell->habitat->emptycelltype);
breakwall(startcell);
}
return B_FALSE;
@ -4856,29 +4892,29 @@ void finalisemap(map_t *map, object_t *entryob) {
char roomlightob[BUFLEN],corridorlightob[BUFLEN];
int roomlightchance = 0;
int corridorlightfreq = 0;
int nupstairsneeded = 0,ndownstairsneeded = 0;
cell_t *c;
object_t *o,*nexto;
// make sure this map has sufficient up/down staircases as defined by its
// region type.
//
// first dungeon level is a special case. it has 1 up stairs, 3 down.
switch (map->habitat->id) {
case H_CAVE:
upstairtype = OT_TUNNELUP;
downstairtype = OT_TUNNELDOWN;
break;
case H_DUNGEON:
upstairtype = OT_STAIRSUP;
downstairtype = OT_STAIRSDOWN;
break;
default:
upstairtype = OT_NONE;
downstairtype = OT_NONE;
break;
upstairtype = map->habitat->upstairtype;
downstairtype = map->habitat->downstairtype;
nupstairsneeded = map->region->rtype->stairsperlev - countmapobs(map, upstairtype);
ndownstairsneeded = map->region->rtype->stairsperlev - countmapobs(map, downstairtype);
if ( (nupstairsneeded && (upstairtype == OT_NONE)) ||
(ndownstairsneeded && (downstairtype == OT_NONE)) ) {
dblog("ERROR - need up/down stairs, but no stairtype defined for habitat %s!", map->habitat->name);
msg("ERROR - need up/down stairs, but no stairtype defined for habitat %s!", map->habitat->name); more();
}
// UP STAIRS
if (upstairtype != OT_NONE) {
// SPECIAL CASE for first level:
if ((map->habitat->id == H_DUNGEON) && (map->depth == 1)) {
flag_t *f;
// first dungeon level. just one exit stairs
@ -4909,9 +4945,7 @@ void finalisemap(map_t *map, object_t *entryob) {
}
} else {
// up stairs on all other levels
int nneeded;
nneeded = map->region->rtype->stairsperlev - countmapobs(map, upstairtype);
for (i = 0; i < nneeded; i++) {
for (i = 0; i < nupstairsneeded; i++) {
c = NULL;
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM);
@ -4936,9 +4970,7 @@ void finalisemap(map_t *map, object_t *entryob) {
// DOWN STAIRS
if ((downstairtype != OT_NONE) && (map->depth < map->region->rtype->maxdepth)) {
int nneeded;
nneeded = map->region->rtype->stairsperlev - countmapobs(map, downstairtype);
for (i = 0; i < nneeded; i++) {
for (i = 0; i < ndownstairsneeded; i++) {
c = NULL;
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM);
@ -6028,16 +6060,16 @@ object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tfl
void initmap(void) {
// habitats
// thingchance, obchance, vaultchance, maxvisrange
addhabitat(H_DUNGEON, "dungeon", CT_CORRIDOR, CT_WALL, 3, 50, 30, 6);
addhabitat(H_CAVE, "cave", CT_DIRT, CT_WALLDIRT, 5, 60, 10, 6);
addhabitat(H_FOREST, "forest", CT_GRASS, CT_WALL, 3, 75, 0, MAXVISRANGE);
addhabitat(H_HEAVEN, "heaven", CT_CORRIDOR, CT_WALLGLASS, 5, 0, 0, MAXVISRANGE);
addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0, 5);
addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 3, 70, 0, MAXVISRANGE);
addhabitat(H_SEWER, "sewer", CT_CORRIDOR, CT_WALL, 5, 50, 0, MAXVISRANGE);
addhabitat(H_STOMACH, "stomach", CT_FLOORFLESH, CT_WALLFLESH, 5, 80, 0, MAXVISRANGE);
addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE);
// thingchance, obchance, vaultchance, maxvisrange, upstiartype, downstairtype
addhabitat(H_DUNGEON, "dungeon", CT_CORRIDOR, CT_WALL, 3, 50, 30, 6, OT_STAIRSUP, OT_STAIRSDOWN);
addhabitat(H_CAVE, "cave", CT_DIRT, CT_WALLDIRT, 5, 60, 10, 6, OT_TUNNELUP, OT_TUNNELDOWN);
addhabitat(H_FOREST, "forest", CT_GRASS, CT_WALL, 3, 75, 0, MAXVISRANGE, OT_NONE, OT_NONE);
addhabitat(H_HEAVEN, "heaven", CT_CORRIDOR, CT_WALLGLASS, 5, 0, 0, MAXVISRANGE, OT_NONE, OT_NONE);
addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0, 5, OT_NONE, OT_NONE);
addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 3, 70, 0, MAXVISRANGE, OT_NONE, OT_NONE);
addhabitat(H_SEWER, "sewer", CT_CORRIDOR, CT_WALL, 5, 50, 0, MAXVISRANGE, OT_NONE, OT_NONE);
addhabitat(H_STOMACH, "stomach", CT_FLOORFLESH, CT_WALLFLESH, 5, 80, 0, MAXVISRANGE, OT_NONE, OT_NONE);
addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE, OT_STAIRSUP, OT_STAIRSDOWN);
// cell types - solid
addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0, 50);

3
map.h
View File

@ -1,7 +1,7 @@
#include "defs.h"
cell_t *addcell(map_t *map, int x, int y);
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange);
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange, enum OBTYPE upstairtype, enum OBTYPE downstairtype);
void addhomeobs(lifeform_t *lf);
map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int amt, int autogen, int *nadded);
@ -13,6 +13,7 @@ regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum
regiontype_t *addregiontype(enum REGIONTYPE id, char *name, int pluralname, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major, int depthmod);
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);
void breakwall(cell_t *c);
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);

10
nexus.c
View File

@ -829,15 +829,15 @@ void donextturn(map_t *map) {
// finished!
p = f->text;
p = readuntil(buf, p, ';');
lfid = atoi(p);
lfid = atoi(buf);
p = readuntil(buf, p, ';');
obid = atol(p);
obid = atol(buf);
p = readuntil(buf, p, ';');
mapid = atoi(p);
mapid = atoi(buf);
p = readuntil(buf, p, ';');
x = atoi(p);
x = atoi(buf);
p = readuntil(buf, p, ';');
y = atoi(p);
y = atoi(buf);
if (lfid >= 0) {
targlf = findlf(NULL, lfid);

124
objects.c
View File

@ -5198,6 +5198,10 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
}
}
}
// other prefixes
if (hasflagknown(o->flags, F_HOT)) {
strcat(localbuf, "red-hot ");
}
}
// enchantments
@ -6550,14 +6554,14 @@ void ignite(object_t *o) {
if (!hasflag(o->flags, F_DAMAGABLE)) {
addflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
}
// on fire for 3 turns
// on fire for a while
howlong = rnd(DEF_BURNTIMEMIN,DEF_BURNTIMEMAX);
addtempflag(o->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, howlong);
}
}
}
// returns the 'armourrating' flag
flag_t *isarmour(object_t *o) {
flag_t *f;
@ -6618,6 +6622,7 @@ int isunknownbadobject(object_t *o) {
int isbetterarmourthan(object_t *a, object_t *b) {
int arma, armb;
flag_t *f;
if (!a) return B_FALSE;
if (!b) return B_TRUE;
@ -6730,7 +6735,7 @@ int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown) {
}
if (!onlyifknown || (iqb >= IQ_ANIMAL)) {
if (hasflag(o->flags, F_ONFIRE)) {
if (hasflag(o->flags, F_ONFIRE) || hasflag(o->flags, F_HOT)) {
if (!isimmuneto(lf->flags, DT_FIRE, B_FALSE)) {
return B_TRUE;
}
@ -6809,6 +6814,35 @@ int isflammable(object_t *o) {
return B_FALSE;
}
// returns amt of damage to do if touched while hot.
int isheatable(object_t *o) {
if (hasflag(o->flags, F_WET)) {
return 0;
}
switch (o->material->id) {
case MT_PAPER:
case MT_LEATHER:
case MT_CLOTH:
case MT_SILK:
case MT_PLANT:
return 2;
case MT_BONE:
case MT_STONE:
case MT_RUBBER:
case MT_WAX:
return 3;
case MT_GOLD:
case MT_SILVER:
case MT_PLASTIC:
case MT_METAL:
case MT_WIRE:
return 4;
default:
break;
}
return 0;
}
int isknown(object_t *o) {
// if id'd, return the full name
if (hasflag(o->flags, F_IDENTIFIED)) {
@ -7593,6 +7627,25 @@ int makeduller(object_t *o, int howmuch) {
return rv;
}
void makehot(object_t *o, int howmuch, int howlong) {
flag_t *f;
int seen = B_FALSE;
f = addtempflag(o->flags, F_HOT, howmuch, NA, NA, NULL, howlong);
if (isequipped(o) && o->pile->owner) {
if (isplayer(o->pile->owner) || cansee(player, o->pile->owner)) {
seen = B_TRUE;
}
}
// you only know an object is hot if you notice the effects on the
// person wearing it.
if (seen) {
f->known = B_TRUE;
} else {
f->known = B_FALSE;
}
}
void makeknown(enum OBTYPE otid) {
knowledge_t *k;
object_t *o;
@ -7696,6 +7749,9 @@ void makewet(object_t *o, int amt) {
strcpy(obnamefull, obname);
}
killflagsofid(o->flags, F_ONFIRE);
killflagsofid(o->flags, F_HOT);
if (o->material->id == MT_METAL) {
if (amt < R_RUSTY) amt = R_RUSTY;
if (amt > R_TRUSTY) amt = R_TRUSTY;
@ -7795,7 +7851,7 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
touch_battle_spoils(src);
// object being taken from an unconscious lf?
if (src->pile->owner && isunconscious(src->pile->owner)) {
if (src->pile->owner && (isunconscious(src->pile->owner) || isasleep(src->pile->owner))) {
robbedlf = src->pile->owner;
}
@ -7904,8 +7960,16 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
o->blessknown = B_TRUE;
}
if (robbedlf && !lfhasflag(robbedlf, F_WASROBBED)) {
addflag(robbedlf->flags, F_WASROBBED, B_TRUE, NA, NA, NULL);
if (robbedlf) {
if (!lfhasflag(robbedlf, F_WASROBBED)) {
addflag(robbedlf->flags, F_WASROBBED, B_TRUE, NA, NA, NULL);
}
// if you were just asleep, you might be awoken.
if (!isunconscious(robbedlf) && dst->owner && !lfhasflag(robbedlf, F_WOKENBY)) {
if (!skillcheck(dst->owner, SC_STEALTH, 13, 0)) { //easy check since target is asleep!
addflag(robbedlf->flags, F_WOKENBY, dst->owner->id, NA, NA, "^WYou awaken to someone rummaging through your pack!^n");
}
}
}
if (hasflag(o->flags, F_DOOR)) {
@ -10627,6 +10691,12 @@ int readsomething(lifeform_t *lf, object_t *o) {
destregion = findregionbytype(destthing->value);
destob = findmapobwithflagval(lf->cell->map, F_CLIMBABLE, NA, destregion->id, NA, NULL);
if (!destob) {
// doesn't exist for some reason?!?!?
dblog("Error - can't find entrance object for region!");
msg("Error - can't find entrance object for region!"); more();
return B_TRUE;
}
destcell = getoblocation(destob);
dist = getcelldist(lf->cell, destcell);
getdisttext(lf->cell, destcell, distbuf, distbufbad, dirbuf);
@ -11557,6 +11627,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
}
}
}
// actually take fire damage
// fire damage falls through to owner
if (o->pile->owner) {
@ -11608,6 +11679,16 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
}
}
// ie fire/heat
if (basedamagetype(damtype) == DT_FIRE) {
int heatamt;
heatamt = isheatable(o);
if (heatamt) {
makehot(o, heatamt, rnd(DEF_BURNTIMEMIN*4,DEF_BURNTIMEMAX*4));
}
}
// damage type creates other objects?
f = hasflagval(o->flags, F_DTCREATEOB, damtype, NA, NA, NULL);
@ -12819,7 +12900,7 @@ void timeeffectsob(object_t *o) {
// check each flag for this object...
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_MATCONVERT, F_OBHPDRAIN, F_ONFIRE,
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_MATCONVERT, F_HOT, F_OBHPDRAIN, F_ONFIRE,
F_RECHARGE, F_REVIVETIMER, F_WALKDAM, F_WET, F_NONE);
for (i = 0; i < nretflags; i++) {
object_t *oo,*nextoo;
@ -13008,22 +13089,31 @@ void timeeffectsob(object_t *o) {
//if (hasflag(o->flags, F_DEAD)) return;
}
// is object on fire?
if (f->id == F_ONFIRE) {
int wasputout = B_FALSE;
// is object on fire or hot?
if ((f->id == F_ONFIRE) || (f->id == F_HOT)) {
int willputout = B_FALSE;
// water puts out fire
for (oo = o->pile->first ; oo ; oo = nextoo) {
nextoo = oo->next;
if ((oo != o) && (oo->material->id == MT_WATER)) {
extinguish(o);
wasputout = B_TRUE;
willputout = B_TRUE;
break;
}
}
if (!wasputout) {
// if it hasn't been extinguished, fire burns
takedamage(o, 2, DT_FIRE); // TODO: don't hardcode
if (hasflag(o->flags, F_DEAD)) return;
if (willputout) {
if (f->id == F_ONFIRE) {
extinguish(o);
continue;
} else if (f->id == F_HOT) {
killflag(f);
continue;
}
} else {
// if it hasn't been extinguished, the object burns
if (f->id == F_ONFIRE) {
takedamage(o, 2, DT_FIRE); // TODO: don't hardcode
if (hasflag(o->flags, F_DEAD)) return;
}
}
}

View File

@ -190,6 +190,7 @@ flag_t *isequipped(object_t *o);
int isequippedon(object_t *o, enum BODYPART bp);
int isfirearm(object_t *o);
int isflammable(object_t *o);
int isheatable(object_t *o);
int isknown(object_t *o);
int isknownot(objecttype_t *ot);
int isheavyweapon(object_t *o);
@ -230,6 +231,7 @@ void killot(objecttype_t *ot);
int knockbackob(object_t *o, int dir, int howfar, int power, lifeform_t *pusher);
lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level);
int makeduller(object_t *o, int howmuch);
void makehot(object_t *o, int howmuch, int howlong);
void makeknown(enum OBTYPE otid);
void maketried(enum OBTYPE otid, char *triedon);
void makewet(object_t *o, int amt);

59
spell.c
View File

@ -6636,13 +6636,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *dropob[MAXPILEOBS];
// affect equipped objects
for (o = target->pack->first ; o ; o = nexto) {
int amt;
nexto = o->next;
if (ismetal(o->material->id)) {
amt = isheatable(o);
if (ismetal(o->material->id) && amt) {
int dodam = B_FALSE;
if (isequippedon(o, BP_WEAPON) || isequippedon(o, BP_SECWEAPON)) {
nburn++;
dodam++;
dropob[ndropobs++] = o;
if (!getequippedob(target->pack, BP_HANDS)) {
dropob[ndropobs++] = o;
}
donesomething = B_TRUE;
} else if (isequipped(o)) {
nburn++;
@ -6651,30 +6656,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
if (dodam) {
if (cansee(player, target)) {
char obname[BUFLEN];
char lfname[BUFLEN];
getobname(o, obname, o->amt);
getlfname(target, lfname);
msg("%s%s %s glow%s red hot!", lfname, getpossessive(lfname),
noprefix(obname), OBS1(o));
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
takedamage(o, rnd(6,12), DT_HEAT);
makehot(o, amt, rnd(3,6));
}
}
}
if (nburn && !isimmuneto(target->flags, DT_FIRE, B_FALSE)) {
if (ndropobs && !isimmuneto(target->flags, DT_FIRE, B_FALSE)) {
int i;
losehp(target, rnd(nburn,4), DT_HEAT, caster, "red-hot metal");
if (isplayer(target)) {
msg("^BThe red-hot metal burns you!");
} else if (cansee(player, target)) {
char lfname[BUFLEN];
getlfname(target, lfname);
msg("^BThe red-hot metal burns %s!", lfname);
}
for (i = 0; i < ndropobs; i++) {
if (isplayer(target)) {
char obname[BUFLEN];
getobname(dropob[i], obname, dropob[i]->amt);
msg("^BYour %s %s too hot to hold!", obname, (o->amt == 1) ? "is" : "are");
}
drop(dropob[i], dropob[i]->amt);
}
}
@ -6682,17 +6678,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
// affect objects on ground
for (o = targcell->obpile->first ; o ; o = nexto) {
int amt;
nexto = o->next;
// damage metal items on the ground
if (ismetal(o->material->id)) {
amt = isheatable(o);
if (ismetal(o->material->id) && amt) {
if (haslos(player, targcell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
donesomething = B_TRUE;
}
makehot(o, amt, rnd(3,6));
if (isplayer(caster)) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
msg("%s glow%s red hot!", obname, OBS1(o));
if (seenbyplayer) *seenbyplayer = B_TRUE;
donesomething = B_FALSE;
}
takedamage(o, rnd(6,12), DT_HEAT);
}
}
}
@ -6929,8 +6929,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
for (l = caster->cell->map->lf ; l ; l = l->next) {
if (l != caster) {
/*
if (isimmuneto(l->flags, DT_NECROTIC, B_FALSE) ||
spellresisted(l, caster, spellid, power, seenbyplayer, B_FALSE)) {
*/
if (spellresisted(l, caster, spellid, power, seenbyplayer, B_FALSE)) {
if (isplayer(l)) {
msg("Luckily, the evil doesn't seem to harm you.");
if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -7301,7 +7304,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (newsize != SZ_ANY) {
resizeobject(targob, newsize);
getobname(targob, obname, 1);
getobname(targob, newobname, 1);
if (seen) msg("%s grows into %s!", obname, newobname);
} else if (newoid == targob->id) {
if (seen) msg("%s shudders for a moment.", obname);
@ -8360,7 +8363,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = op->first ; o ; o = nexto) {
nexto = o->next;
if (getobunitweight(o) <= 5) {
if ((getobunitweight(o) <= 5) ||
((isweapon(o)) && (isequipped(o))) ) {
poss[nposs++] = o;
}
}
@ -8480,7 +8484,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
// fix dulled weapons
// fix rust and dulled weapons
if (!iscursed(o)) {
f = hasflag(o->flags, F_BONUS);
if (f && (f->val[0] < 0)) {
@ -8488,6 +8492,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster) || cansee(player, caster)) msg("%s seems more effective!", fullobname);
donesomething = B_TRUE;
}
if (killflagsofid(o->flags, F_RUSTED)) {
if (isplayer(caster) || cansee(player, caster)) msg("%s is no longer rusted!", fullobname);
donesomething = B_TRUE;
}
}
if (donesomething) {
@ -9465,6 +9473,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = targcell->obpile->first ; o ; o = nexto) {
nexto = o->next;
// special cases
// this spell isn't powerful enough to burn or heat up other things
if (isflammable(o) || (o->type->id == OT_CANDLE) || (o->type->id == OT_TORCH)) {
takedamage(o, 1, DT_FIRE);
donesomething = B_TRUE;