* [+] BUG: books lose their hidden names after load:

- [+] bug: on  load i can see in all directions, and impassable stuff
      around me is obliterated!
- [+] warn when attacking will rust your weapon (if wis high enough)
- [+] yumi should like killing injured things
- [+] bug: sandman isn't attacking or casting spells. - wasn't hostile.
* [+] bug: not able to sell gems in a jewelery store
- [+] when something casts swap places, need to redo los for the target
      too!
- [+] "you feel a wrenching sensation" should have 'more' after it.
- [+] stat bonuses for gods
    - [+] yumi  - boost wis
    - [+] glorana - boost con
    - [+] Lumara - boost iq
- [+] enchant weapon should remove rust too.
- [+] only place a pool of blood if monster is large enouhg
- [+] when mosnters steal gold, let them take more than just one!
- [+] monstres need to retain F_HOSTILE on polymorph! forgot about
      rndhostile
- [+] change some eatconfers to blood confers
    - [+] make blood splashes combine properly
    - [+] test with troll blood
    - [+] when you _kill_ something, drop more blood
    - [+] when you behead/bisect, do splatter
    - [+] in knowledge, show:  "its blood can be bottled to make xxx"
        - [+] (at skilled knowledge level)
        - [+] test....
    - [+] replace eatconfer flags with f_fillpot
    - [+] make sure monsters with fillpot actually bleed
    - [+] make slash etc damage ALWAYS cause bleed
    - [+] make projectile damage only cause bleed if the object is
          pointy (f_missiledam)
    - [+] make bashing not cause bleed
    - [+] make sure that bottling blood reduces/kills the object.
- [+] robots should bleed oil
- [+] CRASH:  during lfhasflag(dodges) - lf.c:20201 (getobname
    - [+] getting ob name of 'rdata' from celldangrous()
    - [+] but rdata->pile is bad...
    - [+] and object was a manual. why was a goblin avoiding a manual?
    - [+] celldangerous() actually set rdata to "deep water"
    - [+] ....but somehow it changed to point to a manual!!!
    - [+] getdodgecell() changed it!
- [+] bug: when a monster kills anohter:
    - [+] "the xxx hits the xxx"
    - [+] (no death message).
    - [+] either include "xxx dies". or make "xxx kills xxx".
    - [+] fixed, i think. wasn't calling getkillverb when attacker was
          a monster.
This commit is contained in:
Rob Pearce 2012-06-02 22:43:18 +00:00
parent 8377a72242
commit 200dae5175
15 changed files with 397 additions and 143 deletions

View File

@ -266,7 +266,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
}
}
}
// above average wisdom will prevent you from starting fires
// above average wisdom will prevent you from starting fires, or rusting your weapon
if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_GTAVERAGE) {
if (hasflag(c->type->material->flags, F_FLAMMABLE)) {
if (getlorelevel(player, c->lf->race->raceclass->id) >= PR_BEGINNER) {
@ -280,6 +280,21 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
}
}
}
if (c->lf->material->id == MT_WATER) {
object_t *priwep;
priwep = getweapon(lf);
if (priwep && willrust(priwep)) {
char victimname[BUFLEN],wepname[BUFLEN],buf[BUFLEN];
getlfname(c->lf, victimname);
real_getobname(priwep, wepname, priwep->amt, B_NOPREMODS,
B_NOCONDITION, B_BLINDADJUST,
B_NOBLESSINGS, B_NOUSED, B_NOSHOWALL);
snprintf(buf, BUFLEN, "Attacking %s might rust your %s - proceed anyway?",victimname, wepname);
if (!warnabout(buf)) {
return B_TRUE;
}
}
}
}
if (lfhasflag(lf, F_HASNEWLEVEL)) {
@ -1265,12 +1280,41 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// we'll need to place the severed head object
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
addflag(victim->flags, F_MUTILATED, B_TRUE, NA, NA, NULL);
if (damtypecausesbleed(damtype[i], wep)) {
bleed(victim, B_SPLATTER);
}
} else if (strstr(buf, "bisect")) {
if (victim->race->id != R_EARTHWYRM) {
addflag(victim->flags, F_MUTILATED, B_TRUE, NA, NA, NULL);
}
if (damtypecausesbleed(damtype[i], wep)) {
bleed(victim, B_SPLATTER);
}
} else {
if (damtypecausesbleed(damtype[i], wep)) {
int bloodamt = 0,n;
switch (getlfsize(victim)) {
case SZ_MINI:
if (onein(3)) bloodamt = 1;
break;
case SZ_TINY: bloodamt = rnd(0,1); break;
case SZ_SMALL: bloodamt = rnd(0,2); break;
case SZ_MEDIUM: bloodamt = rnd(1,3); break;
case SZ_HUMAN: bloodamt = rnd(3,5); break;
case SZ_LARGE: bloodamt = rnd(5,10); break;
case SZ_HUGE: bloodamt = rnd(10,15); break;
case SZ_ENORMOUS:
case SZ_MAX:
bloodamt = rnd(15,20); break;
default: bloodamt = 0; break;
}
for (n = 0; n < bloodamt; n++) {
bleed(victim, B_NOSPLATTER);
}
}
}
if ((isplayer(lf) || cansee(player, victim)) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
//if ((isplayer(lf) || cansee(player, victim)) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
if (isplayer(lf) && cansee(player, victim) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
if (!hasflag(victim->flags, F_PHANTASM)) {
// don't also say "the xx dies"
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
@ -2143,18 +2187,17 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, objec
}
}
int damtypecausesbleed(enum DAMTYPE dt) {
int damtypecausesbleed(enum DAMTYPE dt, object_t *fromob) {
switch (dt) {
case DT_PIERCE:
case DT_SLASH:
case DT_BASH:
case DT_BITE:
case DT_CHOP:
case DT_PROJECTILE:
case DT_EXPLOSIVE:
case DT_UNARMED:
case DT_FALL:
return B_TRUE;
case DT_PROJECTILE:
if (fromob && hasflag(fromob->flags, F_MISSILEDAM)) return B_TRUE;
break;
default:
break;
}

View File

@ -10,7 +10,7 @@ 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);
//void confereffects(flagpile_t *fp, lifeform_t *victim);
void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, object_t *wep, int dam, enum DAMTYPE damtype);
int damtypecausesbleed(enum DAMTYPE dt);
int damtypecausesbleed(enum DAMTYPE dt, object_t *fromob);
int damtypecausescriteffects(enum DAMTYPE dt);
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype);
void getarrange(int arating, int *min, int *max);

49
data.c
View File

@ -502,7 +502,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_COOKING, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_EVASION, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL);
// learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
@ -1573,7 +1573,9 @@ void initobjects(void) {
addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 0, DT_COMPASS, "cloud of steam");
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, B_DONTKILL, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_WATERDEEP, VT_OB, NA, NULL);
addflag(lastot->flags, F_SHRINKSTO, OT_PUDDLEWATERL, VT_OB, NA, NULL);
// blocks movement, but you can see and fire through them.
addot(OT_GATEIRON, "iron gate", "A gate comprised of a series of vertical iron bars, raised slightly above the floor.", MT_METAL, 500, OC_DFEATURE, SZ_LARGE);
@ -5661,7 +5663,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "2d4");
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_ACID, NA, NA, NULL);
addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATERL, NA, NA, NULL);
addot(OT_ACIDPUDDLE, "puddle of acid", "A small puddle of corrosive acid.", MT_ACID, 0, OC_MISC, SZ_SMALL);
@ -5676,7 +5678,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "1d4");
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_ACID, NA, NA, NULL);
addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATER, NA, NA, NULL);
addot(OT_ACIDSPLASH, "splash of acid", "A splash corrosive acid.", MT_ACID, 0, OC_MISC, SZ_SMALL);
@ -5691,7 +5693,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "1d2");
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_ACID, NA, NA, NULL);
addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL);
addot(OT_SLIMEPOOL, "pool of slime", "A deep pool of foul-smelling slime.", MT_SLIME, 300, OC_TERRAIN, SZ_HUGE);
@ -5720,7 +5722,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_FLAMMABLE, 5, NA, NA, "medium fire");
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_OIL, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_OIL, NA, NA, NULL);
addflag(lastot->flags, F_SLIPPERY, 13, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
@ -5744,7 +5746,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "0d1+100");
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, 5, NA, NULL);
addflag(lastot->flags, F_COSMETIC, B_TRUE, NA, NA, NULL);
addot(OT_MUDPOOL, "pool of mud", "A large puddle of wet mud.", MT_WATER, 60, OC_MISC, SZ_MEDIUM);
@ -5786,7 +5788,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL);
//addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1");
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+1");
addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL);
@ -5809,7 +5811,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL);
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+2");
addot(OT_BLOODSTAIN, "blood stain", "A dried stain of blood.", MT_BLOOD, 0, OC_MISC, SZ_TINY);
@ -5860,6 +5862,7 @@ void initobjects(void) {
addflag(lastot->flags, F_COSMETIC, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_BLOOD, 5, NA, NULL);
addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC, SZ_MEDIUM);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
@ -5879,6 +5882,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATERL, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_BLOOD, NA, NA, NULL);
addot(OT_SIGN, "sign", "A marker with something written on it.", MT_WOOD, 25, OC_MISC, SZ_MEDIUM);
addflag(lastot->flags, F_GLYPH, C_BROWN, '|', NA, NULL);
@ -9934,6 +9938,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 50, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_LEVITATION, NA, NA, NULL);
addrace(R_BOGGART, "bogle", 15, 'n', C_BROWN, MT_WOOD, RC_MAGIC, "An evil household fairy made of wood. They delight in sowing disease and misfortune.");
setbodytype(lastrace, BT_HUMANOID);
@ -10588,6 +10593,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_ATTRMOD, A_STR, 5, "50");
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_FIRE, NA, "50");
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addrace(R_GIANTFIREFC, "flame giant firemaster", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID, "A subspecies of flame giant who have developed the ability to command the primal volcanic fires around them.");
setbodytype(lastrace, BT_HUMANOID);
@ -10631,6 +10637,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 15, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_ATTRMOD, A_STR, 5, "50");
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_FIRE, NA, "50");
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
// TODO: storm giant
@ -11200,6 +11207,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addrace(R_KOBOLD, "kobold", 18, 'k', C_BROWN, MT_FLESH, RC_HUMANOID, "An evil humanoid race with doglike features, kobolds are known for their cowardace and prefer to attack from a distance if at all possible.");
@ -11276,6 +11284,7 @@ void initrace(void) {
addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addrace(R_LEPRECHAUN, "leprechaun", 35, 'n', C_BOLDGREEN, MT_FLESH, RC_HUMANOID, "Leprechauns are tiny Irish humans, with a love for gold and practical jokes. Known for their supernatural luck.");
setbodytype(lastrace, BT_HUMANOID);
@ -12205,6 +12214,7 @@ void initrace(void) {
addrace(R_SANDMAN, "sandman", 10, 'y', C_BROWN, MT_DIRT, RC_OTHER, "A whirling tornado of sand, with a humanoid figure dimly visible within.");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, "small dust cloud");
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "large dust cloud");
@ -12472,6 +12482,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_FIRE, NA, "25");
addflag(lastrace->flags, F_WANTSOBFLAG, F_GEM, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addrace(R_SPRITEGRAVE, "grave sprite", 5, 'n', C_GREY, MT_FLESH, RC_MAGIC, "A small magical creature made from corpse dust.");
setbodytype(lastrace, BT_HUMANOID);
@ -12550,6 +12561,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_COLD, NA, "25");
addflag(lastrace->flags, F_WANTSOBFLAG, F_GEM, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addrace(R_SPRITEWEED, "weed sprite", 5, 'n', C_ORANGE, MT_FLESH, RC_MAGIC, "The bright colour of weed sprites belies their evil nature.");
setbodytype(lastrace, BT_HUMANOID);
@ -12872,7 +12884,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 2, NA, "^gurgling");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "gurgles loudly^a loud gurgle");
addflag(lastrace->flags, F_EATCONFER, F_MUTABLE, B_TRUE, NA, "100");
addflag(lastrace->flags, F_FILLPOT, OT_POT_FISHLUNG, NA, NA, NULL);
addrace(R_PIRANHA, "piranha", 0.5, ';', C_GREEN, MT_FLESH, RC_AQUATIC, "A vicious, flesh-eating fish");
setbodytype(lastrace, BT_FISH);
@ -13072,6 +13084,7 @@ void initrace(void) {
addflag(lastrace->flags, F_TR, 1, NA, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addrace(R_FUNGUSRAGE, "ragefungus", 0.5, 'F', C_RED, MT_PLANT, RC_PLANT, "This deep red fungus protects itself by explelling rage-inducing pheremones, causing predators to attack each other instead of it.");
addbodypart(lastrace, BP_BODY, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
@ -13079,7 +13092,6 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_ANTNEST, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HARMLESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
@ -13097,6 +13109,7 @@ void initrace(void) {
addflag(lastrace->flags, F_TR, 1, NA, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_FURY, NA, NA, NULL);
addrace(R_GLUON, "gluon", 1, 'F', C_YELLOW, MT_PLANT, RC_PLANT, "A walking plant-based monster whose body is covered with a thick glue-like secretion.");
addbodypart(lastrace, BP_BODY, "stalk");
@ -13326,6 +13339,7 @@ void initrace(void) {
addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL);
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_MAGIC, NA, NA, NULL);
addrace(R_BATVAMPIRE, "vampire bat", 6, 'B', C_BLUE, MT_FLESH, RC_ANIMAL, "Bats which suck the blood of their victims.");
setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
@ -14196,6 +14210,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_COLD, NA, "20");
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addrace(R_ELEPHANT, "elephant", 4000, 'Q', C_GREY, MT_LEATHER, RC_ANIMAL, "A massive grey mammal with a long trunk and sharp tusks.");
setbodytype(lastrace, BT_QUADRAPED);
@ -14507,6 +14522,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "scuttle");
addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addrace(R_ROC, "roc", 1, 'A', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Rocs are unbelievably gargantuan birds or prey, large enough to carry a fully-grown elephant. They are generally peaceful, but deadly once provoked."); // 'A' for Avian
setbodytype(lastrace, BT_BIRD);
@ -14578,6 +14594,7 @@ void initrace(void) {
addflag(lastrace->flags, F_AQUATIC, 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);
addrace(R_SNAIL, "mottled snail", 150, 'P', C_BROWN, MT_FLESH, RC_ANIMAL, "An enormous snail, protected by a hard, scaled shell and gifted with long, sharp fangs.");
addbodypart(lastrace, BP_BODY, NULL);
addbodypart(lastrace, BP_HEAD, NULL);
@ -14899,6 +14916,7 @@ void initrace(void) {
addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, "");
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_POISON, NA, "15");
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep");
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addrace(R_SPIDERREDBACK, "giant redback", 5, 'S', C_RED, MT_FLESH, RC_ANIMAL, "A version of a giant spider with a highly painful bite.");
setbodytype(lastrace, BT_SPIDER);
lastrace->baseid = R_SPIDER;
@ -14936,6 +14954,7 @@ void initrace(void) {
addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, "");
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_POISON, NA, "10");
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep");
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addrace(R_SPIDERTOMB, "tomb spider", 5, 'S', C_BLUE, MT_FLESH, RC_ANIMAL, "Tomb spiders are truly nightmarish beings. Their skin can absorb light itself, and they can boost their own life force by consuming the flesh of their victims.");
setbodytype(lastrace, BT_SPIDER);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
@ -15102,7 +15121,6 @@ void initrace(void) {
addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL);
addrace(R_WOLFWINTER, "winter wolf", 25, 'd', C_CYAN, MT_FLESH, RC_ANIMAL, "Wolves which have lived in close proximity to the undead sometimes mutate into these frosty beasts. While their claws have become less sharp, they instead deal unnatural cold damage.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
@ -17160,6 +17178,7 @@ void initrace(void) {
addflag(r->flags, F_SEEINDARK, 10, NA, NA, NULL);
addflag(r->flags, F_SEEINVIS, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
addflag(r->flags, F_FILLPOT, OT_POT_AMBROSIA, NA, NA, NULL);
} else if (r->raceclass->id == RC_MAGIC) {
addflag(r->flags, F_NOBREATH, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
@ -17191,6 +17210,8 @@ void initrace(void) {
addflag(r->flags, F_CORPSETYPE, NA, NA, NA, "unstable power core");
addflag(r->flags, F_MORALE, 30, NA, NA, NULL);
addflag(r->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_BLOODOB, NA, NA, NA, "puddle of oil");
if (!hasflagval(r->flags, F_NOISETEXT, N_WALK, NA, NA, NULL)) {
addflag(r->flags, F_NOISETEXT, N_WALK, 2, NA, "^whirring");
}
@ -17587,11 +17608,11 @@ void initskills(void) {
addskilldesc(sk->id, PR_INEPT, "At each skill level, more information about related creatures will be shown.", B_FALSE);
addskilldesc(sk->id, PR_INEPT, "Each level also gives +1 damage and +2 accuracy against related creatures.", B_FALSE);
snprintf(buf, BUFLEN, "^gYou now know basic information about %s.^n", rc->pluralname);
snprintf(buf, BUFLEN, "^gYou now have common knowledge about %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_NOVICE, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou can now determine how much damage %s will deal.^n", rc->pluralname);
snprintf(buf, BUFLEN, "^gYou now know about the powers/abilities of %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_BEGINNER, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou can now determine how dangerous %s are.^n", rc->pluralname);
snprintf(buf, BUFLEN, "^gYou have now comprehensively studied %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_ADEPT, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou can now anticipate how %s will react.^n", rc->pluralname);
addskilldesc(sk->id, PR_SKILLED, buf, B_TRUE);

Binary file not shown.

8
defs.h
View File

@ -91,6 +91,7 @@
#define B_ONPURPOSE (-1)
#define B_NOTONPURPOSE (0)
#define B_CHANGEDIR (-1)
#define B_NOCHANGEDIR (0)
#define B_VIS (1)
#define B_UNKNOWN (0)
#define B_NOVIS (-1)
@ -102,11 +103,13 @@
#define B_DONTKILL (-1)
#define B_APPENDYOU (-1)
#define B_SPLATTER (-1)
#define B_NOSPLATTER (0)
#define B_FROMINJURY (-2)
#define B_KEEPDIR (-2)
#define B_VERT (0)
#define B_HORZ (1)
#define B_MELEEONLY (-1)
@ -427,6 +430,7 @@ enum SHOPACTION {
#define AUTO (-7654)
#define HEAVYWEPKG (5)
#define HITDIESIDES (6)
#define B_NEWINJURY (-6654)
// how quickly the game clock increments
@ -2439,6 +2443,8 @@ enum FLAG {
F_ENCHANTABLE, // object can get +1/-1 ect
F_FILLPOT, // can fill empty flasks with this object to create
// a potion of obtype v0.
// if v1 != NA, then object count must be >= v1 to
// fill from this ob.
F_GEM, // this object is a gem.
F_GODGIFT, // this was a gift form god with race v0.
F_GROWSTO, // used for spells. v0=new oid or celltype.
@ -3537,6 +3543,8 @@ enum FLAG {
// v0 = timeleft (since 'lifetime' is used for FROMSPELL)
F_INJURY, // v0 = enum injury, v1 = where (enum bp), v2 = damtype
// text is desc, ie "rib is cracked"
// special: 'obfrom' is used to determine whether this
// is a new injury.
F_INVISIBLE, // lifeform is invisible
F_INVULNERABLE,// immune to most damage
// this can apply to objects too!

81
io.c
View File

@ -1425,7 +1425,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
} else if (f->val[1] == ST_MEDITATING) {
msg("%s enter%s a trance.",lfname, isplayer(lf) ? "" : "s");
} else {
msg("%s lose%s consciousness.",lfname, isplayer(lf) ? "" : "s");
msg("^%c%s lose%s consciousness.^n",getlfcol(lf, CC_BAD), lfname, isplayer(lf) ? "" : "s");
}
}
donesomething = B_TRUE;
@ -3073,6 +3073,8 @@ object_t *doaskobject(obpile_t *op, char *prompt, char *noobtext, int *count, in
enum FLAG wantflag[MAXCANDIDATES];
va_list flags;
int nwantflags;
flag_t *sellflag[MAXCANDIDATES];
int nsellflags = 0;
// construct list of valid obclasses
va_start(flags, opts);
@ -3085,16 +3087,8 @@ object_t *doaskobject(obpile_t *op, char *prompt, char *noobtext, int *count, in
va_end(flags);
//dblog("nwantflags is %d",nwantflags);
// if selecting from a shop, we now override wantflags
if (sellshop) {
flag_t *sellflag[MAXCANDIDATES];
int nsellflags = 0;
nwantflags = 0;
getflags(sellshop->flags, sellflag, &nsellflags, F_SHOPACCEPTSFLAG, F_NONE);
for (i = 0; i < nsellflags; i++) {
wantflag[nwantflags] = sellflag[i]->val[0];
nwantflags++;
}
}
if (countobs(op, B_TRUE) <= 0) {
@ -3162,6 +3156,20 @@ object_t *doaskobject(obpile_t *op, char *prompt, char *noobtext, int *count, in
}
}
// shop flags?
if (ok && nsellflags) {
int n;
// must match one of the sellflags
ok = B_FALSE;
for (n = 0; n < nsellflags; n++) {
if (obmatchessellflag(o, sellflag[n], sellaction)) {
ok = B_TRUE;
break;
}
}
}
if (ok) {
// check for wanted flags
for (n = 0; n < nwantflags; n++) {
@ -7076,7 +7084,9 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
// knowledge known by studying this creature a little.
// eg: sleeping times, damage resist/vuln, silentmovement, morale
// ADEPT:
// everything.
// nearly everything. except....
// SKILLED:
// what their blood bottles to.
doneflags = addflagpile(NULL, NULL);
@ -7085,11 +7095,13 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
if (showextra) {
int a,n;
int curidx,donesomething;
char bonheading[BUFLEN],penheading[BUFLEN];
char bonheading[BUFLEN],penheading[BUFLEN],mischeading[BUFLEN];
int donemischeading = B_FALSE;
enum OBCLASS spellorabil[2];
sprintf(bonheading, "^%dStrengths^n:\n", C_WHITE);
sprintf(penheading, "^%dWeaknesses^n:\n", C_WHITE);
sprintf(mischeading, "^%dOther^n:\n", C_WHITE);
// stats
snprintf(buf, HUGEBUFLEN, "HD: %-3d ", gettrrace(r));
strncat(retbuf, buf, HUGEBUFLEN);
@ -7181,6 +7193,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
strncat(retbuf, "@- ", HUGEBUFLEN);
strcat(buf, "\n");
strncat(retbuf, buf, HUGEBUFLEN);
curidx++;
}
}
}
@ -7202,6 +7215,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
strncat(retbuf, "@- ", HUGEBUFLEN);
strcat(buf, "\n");
strncat(retbuf, buf, HUGEBUFLEN);
curidx++;
}
// auto bonuses from flags
@ -7432,8 +7446,46 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
if (curidx == 0) {
strncat(retbuf, "^n@None known.\n", HUGEBUFLEN);
}
}
//////////////////////////////////////////////
// other
//////////////////////////////////////////////
// auto misc from flags
for (f = r->flags->first ; f ; f = f->next) {
char buf2[BUFLEN];
strcpy(buf, "");
switch (f->id) {
case F_FILLPOT:
if (lorelev >= PR_SKILLED) {
objecttype_t *ot;
ot = findot(f->val[0]);
if (ot) {
sprintf(buf2, "Its blood can be bottled to create %s %s.",
needan(ot->name) ? "an" : "a",
ot->name);
strcat(buf, buf2);
}
}
break;
default:
break;
}
if (strlen(buf)) {
if (!donemischeading) {
strncat(retbuf, mischeading, HUGEBUFLEN);
donemischeading = B_TRUE;
}
strncat(retbuf, "@- ", HUGEBUFLEN);
strcat(buf, "\n");
strncat(retbuf, buf, HUGEBUFLEN);
curidx++;
}
}
if (donemischeading && (curidx == 0)) {
strncat(retbuf, "^n@None known.\n", HUGEBUFLEN);
}
}
free(doneflags);
return retbuf;
@ -11229,7 +11281,7 @@ void showlfarmour(lifeform_t *lf) {
void showlfstats(lifeform_t *lf, int showall) {
int y = 0, y2 = 0, x2 = 40;
int starty;
int startx,starty;
int x;
int arating, evasion;
int acc;
@ -11821,6 +11873,7 @@ void showlfstats(lifeform_t *lf, int showall) {
wattroff(mainwin, A_UNDERLINE);
y++;
starty = y;
startx = x;
/*
if (!isplayer(lf)) {
@ -12211,7 +12264,7 @@ void showlfstats(lifeform_t *lf, int showall) {
wrapprint(mainwin, &y, &x, 0, "%s %s made out of %s. ",you(lf), is(lf), mt->name);
}
if (y == starty) {
if ((y == starty) && (x == startx)) {
wrapprint(mainwin, &y, &x, 0, "Nothing obvious.");
}
} else if (mode == 'a') {

167
lf.c
View File

@ -227,7 +227,12 @@ void bleed(lifeform_t *lf, int splatter) {
object_t *o;
o = addob(lf->cell->obpile, obname);
if (hasflag(lf->flags, F_FILLPOT)) {
// override object flags
killflagsofid(o->flags, F_FILLPOT);
}
nfillpot = copyflag(o->flags, lf->flags, F_FILLPOT);
if (splatter) {
addobsinradius(lf->cell, 1, DT_COMPASS, obname, B_TRUE, NULL);
@ -272,10 +277,7 @@ void breakgrabs(lifeform_t *lf, int fromme, int tome) {
killflagsofid(grabee->flags, F_GRABBEDBY);
killflagsofid(lf->flags, F_GRABBING);
}
f = lfhasflag(lf, F_ATTACHEDTO);
if (f) {
killflag(f);
}
killflagsofid(lf->flags, F_ATTACHEDTO);
}
if (tome) {
f = lfhasflag(lf, F_GRABBEDBY);
@ -3213,6 +3215,17 @@ void die(lifeform_t *lf) {
pleasegodmaybe(R_GODDEATH, 1);
}
// killing someone with an injury is considered merciful.
// (but only for injuries which you didn't just inflict!)
getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->obfrom != B_NEWINJURY) {
pleasegodmaybe(R_GODMERCY, 5);
// only do this once.
break;
}
}
switch (lf->race->raceclass->id) {
case RC_DRAGON:
pleasegodmaybe(R_GODNATURE, 50);
@ -6890,6 +6903,49 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) {
}
}
if ((gamemode == GM_GAMESTARTED) && isplayer(lf)) {
// worshipping yumi increases wisdom based on piety
if ((attr == A_WIS) && godprayedto(R_GODMERCY)) {
enum PIETYLEV plev;
plev = getpietylev(R_GODMERCY, NULL, NULL);
switch (plev) {
case PL_ENRAGED: val -= 25; break;
case PL_FURIOUS: val -= 10; break;
case PL_ANGRY: val -= 5; break;
case PL_TOLERATED: break;
case PL_INDIFFERENT: val += 10; break;
case PL_PLEASED: val += 20 ; break;
case PL_DELIGHTED: val += 35 ; break;
case PL_ECSTATIC: val += 50 ; break;
default: break;
}
} else if ((attr == A_CON) && godprayedto(R_GODLIFE)) {
enum PIETYLEV plev;
plev = getpietylev(R_GODLIFE, NULL, NULL);
switch (plev) {
case PL_INDIFFERENT: val += 5; break;
case PL_PLEASED: val += 10 ; break;
case PL_DELIGHTED: val += 15 ; break;
case PL_ECSTATIC: val += 20 ; break;
default: break;
}
} else if ((attr == A_IQ) && godprayedto(R_GODMAGIC)) {
enum PIETYLEV plev;
plev = getpietylev(R_GODMAGIC, NULL, NULL);
switch (plev) {
case PL_ENRAGED: val -= 20; break;
case PL_FURIOUS: val -= 10; break;
case PL_ANGRY: val -= 5; break;
case PL_TOLERATED: break;
case PL_INDIFFERENT: val += 10; break;
case PL_PLEASED: val += 20 ; break;
case PL_DELIGHTED: val += 30 ; break;
case PL_ECSTATIC: val += 50 ; break;
default: break;
}
}
}
if (val < 0) val = 0;
return val;
@ -10377,7 +10433,8 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
// also, they always use fists, even if the race has claws etc.
f = lfhasflag(lf, F_HASATTACK);
if (f) {
f->val[1] = 3;
f->val[0] = OT_FISTS;
f->val[1] = 5;
}
} else if (j->id == J_PIRATE) {
flag_t *f;
@ -12109,7 +12166,7 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJUR
case IJ_EARSRINGING: desc = strdup("ears are ringing^cannot hear sounds"); break;
case IJ_TAILLACERATED: desc = strdup("tail is lacerated^chance of falling during movement"); break;
case IJ_WINGDESTROYED: desc = strdup("wings are destroyed^cannot fly"); break;
case IJ_HANDSWOLLEN: desc = strdup("hand is swolled^rings cannot be put on/removed"); break;
case IJ_HANDSWOLLEN: desc = strdup("hand is swollen^rings cannot be put on/removed"); break;
case IJ_FINGERBROKEN: desc = strdup("finger is broken^acc penalty"); break;
case IJ_SHOULDERDISLOCATED: desc = strdup("shoulder is dislocated^acc penalty, cannot use heavy weapons"); break;
case IJ_ARTERYPIERCE: desc = strdup("radial artery is pierced^constant bleeding"); break; // fatal - no description
@ -12123,7 +12180,9 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJUR
if (desc) free(desc);
return B_TRUE;
} else {
addtempflag(lf->flags, F_INJURY, inj, where, damtype, desc, howlong);
flag_t *injflag;
injflag = addtempflag(lf->flags, F_INJURY, inj, where, damtype, desc, howlong);
injflag->obfrom = B_NEWINJURY;
}
if (desc) free(desc);
@ -12175,6 +12234,30 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJUR
return B_FALSE;
}
int lfcanbekod(lifeform_t *lf) {
if (isundead(lf)) return B_FALSE;
switch (getraceclass(lf)) {
case RC_ROBOT:
case RC_GOD:
case RC_SLIME:
case RC_PLANT:
case RC_OTHER:
case RC_UNDEAD:
return B_FALSE;
default:
break;
}
if (lfhasflag(lf, F_NONCORPOREAL)) {
return B_FALSE;
}
if (isdead(lf)) {
return B_FALSE;
}
// note: not checking whether they are already unconscious
// because merciful weapons CAN still KO them in this case.
return B_TRUE;
}
int lfcanbestoned(lifeform_t *lf) {
switch (getlfmaterial(lf)) {
case MT_GAS:
@ -15126,8 +15209,9 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
killflagsofid(lf->flags, F_HIDING);
// methods of knocking unconscious
if (!isundead(lf)) {
// merciful weapons
if (!lfcanbekod(lf)) {
// merciful weapons - these will ALWAYS ko, even if
// they are already unconscious.
if (!ko && fromob) {
f = hasflag(fromob->flags, F_MERCIFUL);
if (f && (amt >= lf->hp)) {
@ -15140,7 +15224,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
// bashing damage sometimes ko's
// damage when eating corpses also does this.
if (!ko) {
if (!ko && !isunconscious(lf)) {
int threshold,kochance = 0;
int damtypeok = B_FALSE;
int playerinvolved = B_FALSE;
@ -15183,7 +15267,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
}
}
if (!ko) {
if (!ko && !isunconscious(lf)) {
if (fromlf && lfhasflag(fromlf, F_STRIKETOKO)) {
if (cansee(fromlf, lf)) {
ko = B_TRUE;
@ -15207,9 +15291,9 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
}
*/
// occasionally drop blood
if (damtypecausesbleed(damtype) && onein(3)) {
bleed(lf, B_FALSE);
// drop blood
if (damtypecausesbleed(damtype, fromob)) {
bleed(lf, B_NOSPLATTER);
}
if (hasflag(lf->flags, F_DEBUG)) {
@ -15260,7 +15344,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
}
}
if (doeffects) {
if (doeffects || ko) {
losehpeffects(lf, amt, damtype, fromlf, fromob, retaliate, ko, waskod, prelowhp);
}
@ -15321,7 +15405,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
if (fromlf) {
if (murder) {
setkillverb(lf, "Murdered");
} else if (amt >= lf->maxhp) {
} else if ((amt >= lf->maxhp) && !fromob) {
setkillverb(lf, "Slaughtered");
} else {
setkillverb(lf, "Slain");
@ -18501,14 +18585,16 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
// certain other flags are rnadom
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
getflags(lf->flags, retflag, &nretflags, F_RNDHOSTILE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_RNDHOSTILE) {
if (pctchance(f->val[0])) {
addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
if (!frompolymorph) {
getflags(lf->flags, retflag, &nretflags, F_RNDHOSTILE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_RNDHOSTILE) {
if (pctchance(f->val[0])) {
addflag(lf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
}
killflag(f);
}
killflag(f);
}
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
@ -20104,15 +20190,19 @@ void startlfturn(lifeform_t *lf) {
if (lfhasflag(lf, F_DODGES)) {
enum ERROR e;
if (celldangerous(lf, lf->cell, B_TRUE, &e)) {
object_t *avoidob = NULL;
cell_t *adj;
if ((e == E_AVOIDOB) && rdata) {
// remember this sine getdodgecell() will call
// calldangerous() again which will overwrite rdata.
avoidob = (object_t *)rdata;
}
// autododge!
adj = getdodgecell(lf);
if (adj) {
char fromx[BUFLEN];
if ((e == E_AVOIDOB) && rdata) {
object_t *o;
o = (object_t *)rdata;
getobname(o, fromx, o->amt);
getobname(avoidob, fromx, avoidob->amt);
} else {
sprintf(fromx, "danger");
}
@ -20629,9 +20719,12 @@ void startlfturn(lifeform_t *lf) {
}
}
// bleeding injuries can stain armour
// bleeding injuries can stain armour. also mark injuries as no longer new.
if ((f->id == F_INJURY) && (f->val[2] == DT_SLASH)) {
object_t *arm;
if (f->obfrom == B_NEWINJURY) f->obfrom = B_FALSE;
arm = getequippedob(lf->pack, f->val[1]);
if (arm && !hasobmod(arm, findobmod(OM_BLOODSTAINED)) && pctchance(5)) applyobmod(arm, findobmod(OM_BLOODSTAINED));
}
@ -20847,14 +20940,18 @@ int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag) {
o = (object_t *)prompt.choice[rnd(0,prompt.nchoices-1)].data;
}
if (o) {
int amt = 1;
//killflagsofid(o->flags, F_SHOPITEM);
o = moveob(o, lf->pack, 1);
if (o->type->id == OT_GOLD) {
amt = rnd(1,slev*33);
}
o = moveob(o, lf->pack, amt);
if (o) {
char obname[BUFLEN];
char lfname[BUFLEN];
char targname[BUFLEN];
getlfname(lf, lfname);
getobname(o, obname, 1);
getobname(o, obname, amt);
if (op->owner) {
getlfname(op->owner, targname);
if (isplayer(lf)) {
@ -22386,6 +22483,18 @@ int validateraces(void) {
goterror = B_TRUE;
}
}
if (f->id == F_FILLPOT) {
flag_t *f2;
if (!findot(f->val[0])) {
printf("ERROR in race '%s' - F_FILLPOT with bad object.\n", r->name);
goterror = B_TRUE;
}
f2 = hasflag(r->flags, F_BLOODOB);
if (f2 && !strlen(f2->text)) {
printf("ERROR in race '%s' - has F_FILLPOT but no bleed object.\n", r->name);
goterror = B_TRUE;
}
}
if (f->id == F_HASATTACK) {
if (!findot(f->val[0])) {
printf("ERROR in race '%s' - F_HASATTACK with bad object.\n", r->name);

1
lf.h
View File

@ -299,6 +299,7 @@ job_t *hasjob(lifeform_t *lf, enum JOB job);
int hassubjob(lifeform_t *lf, enum SUBJOB id);
void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch);
int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJURY forcetype);
int lfcanbekod(lifeform_t *lf);
int lfcanbestoned(lifeform_t *lf);
flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid);
flag_t *lfhasflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, char *text);

20
move.c
View File

@ -158,10 +158,10 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
flag_t *f;
object_t *o;
rdata = NULL;
// default
if (error) {
*error = E_OK;
rdata = NULL;
}
// never dangerous if there's someone there, since we'll
@ -1103,7 +1103,7 @@ int moveeffects(lifeform_t *lf, int moved) {
}
} else {
if (rnd(1,2) == 1) {
bleed(lf, B_FALSE);
bleed(lf, B_NOSPLATTER);
}
}
}
@ -2636,8 +2636,9 @@ void standup(lifeform_t *lf) {
}
}
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir, int onpurpose) {
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir1, int changedir2, int onpurpose) {
cell_t *cell1,*cell2;
int tempfacing;
cell1 = lf1->cell;
cell2 = lf2->cell;
@ -2653,11 +2654,12 @@ void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir, int onpurpose)
lf2->cell = cell1;
cell1->lf = lf2;
if (changedir) {
int tempfacing;
tempfacing = lf2->facing;
setfacing(lf2, lf1->facing);
setfacing(lf1, tempfacing);
tempfacing = lf1->facing;
if (changedir1) {
setfacing(lf1, lf2->facing);
}
if (changedir2) {
setfacing(lf2, tempfacing);
}
// remember that we just swapped, and this counts as a move
@ -3252,7 +3254,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
dontclearmsg = B_TRUE;
}
swapplaces(lf, lfinway, B_FALSE, onpurpose);
swapplaces(lf, lfinway, B_NOCHANGEDIR, B_NOCHANGEDIR, onpurpose);
//if (onpurpose) taketime(lf, getmovespeed(lf));
taketime(lf, getmovespeed(lf));

2
move.h
View File

@ -31,7 +31,7 @@ int isorthogonal(int dir);
int ispossiblemove(lifeform_t *lf, int dir);
int rotatedir(int origdir, enum TURNDIR whichway, int amt);
void standup(lifeform_t *lf);
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir, int onpurpose);
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir1, int changedir2, int onpurpose);
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke);
void triggertrap(lifeform_t *lf, object_t *o, object_t *trapob, cell_t *where);
int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe);

53
nexus.c
View File

@ -122,7 +122,6 @@ extern race_t **raceposs;
extern int *xpposs;
int main(int argc, char **argv) {
int newworld = B_FALSE;
object_t *o;
char welcomemsg[BUFLEN];
int ch;
@ -285,7 +284,6 @@ int main(int argc, char **argv) {
addflag(player->flags, F_CANWILL, OT_A_DEBUG, NA, NA, NULL); /////////
// make the initial level
newworld = B_TRUE;
// create world map.
wregion = findregionbytype(BH_WORLDMAP);
@ -427,35 +425,42 @@ int main(int argc, char **argv) {
calclight(player->cell->map);
// pre-calc line-of-sight for player
//precalclos(player);
player->facing = D_ALL;
if (!foundsavegame) {
player->facing = D_ALL;
}
setlosdirty(player);
// changes for anything within los/lof of player's starting pos:
// - don't want any mosnters starting here
// - don't want any impassable objects other than doors
// - don't want any locked doors
slev = getskill(player, SK_CARTOGRAPHY);
for (y = 0; y < player->cell->map->h; y++) {
for (x = 0; x < player->cell->map->w; x++) {
c = getcellat(player->cell->map, x, y);
if (c && (haslos(player, c) || haslof(player->cell, c, LOF_WALLSTOP, NULL))) {
object_t *o,*nexto;
if (c->lf && !isplayer(c->lf) && !ispetof(c->lf, player)) {
killlf(c->lf);
}
for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (hasflag(o->flags, F_IMPASSABLE) && !hasflag(o->flags, F_DOOR)) {
killob(o);
continue;
} else {
killflagsofid(o->flags, F_LOCKED);
if (!foundsavegame) {
// changes for anything within los/lof of player's starting pos:
// - don't want any mosnters starting here
// - don't want any impassable objects other than doors
// - don't want any locked doors
slev = getskill(player, SK_CARTOGRAPHY);
for (y = 0; y < player->cell->map->h; y++) {
for (x = 0; x < player->cell->map->w; x++) {
c = getcellat(player->cell->map, x, y);
if (c && (haslos(player, c) || haslof(player->cell, c, LOF_WALLSTOP, NULL))) {
object_t *o,*nexto;
if (c->lf && !isplayer(c->lf) && !ispetof(c->lf, player)) {
killlf(c->lf);
}
for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next;
if (hasflag(o->flags, F_IMPASSABLE) && !hasflag(o->flags, F_DOOR)) {
killob(o);
continue;
} else {
killflagsofid(o->flags, F_LOCKED);
}
}
}
}
}
}
needredraw = B_TRUE;
statdirty = B_TRUE;
@ -467,7 +472,7 @@ int main(int argc, char **argv) {
// make player face the direction which gives them the most visibility
// as we check, set all cells around us to start off known.
if (newworld) {
if (!foundsavegame) {
int bestdir = D_NONE;
int bestlos = -1;
for (i = DC_N; i <= DC_NW; i++) {

View File

@ -804,7 +804,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
p += strlen("lit ");
donesomething = B_TRUE;
// different materials
} else if (((mat = strmatchesmaterial(p)) != NULL) && !strstr(p, "gold coin")) {
} else if (((mat = strmatchesmaterial(p)) != NULL) && !strstr(p, "gold coin") && !strstr(p, "leather armour")) {
wantdiffmat = mat->id;
p += strlen(mat->name);
p++; // go past the space
@ -1566,7 +1566,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
}
// fill in book types
if (o && (o->type->obclass->id == OC_BOOK)) {
if (o && (o->type->obclass->id == OC_BOOK) && (gamemode != GM_LOADING)) {
hiddenname_t *hn,*selhn = NULL;
int numhiddennames;
int n,sel;
@ -1625,7 +1625,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
assert(addobfast(o->contents, oid));
}
}
} else if ((o->type->id == OT_GRIMOIRE) && (gamemode != GM_LOADING)) {
} else if (o->type->id == OT_GRIMOIRE) {
// 1 spell from each school
int i;
int nschools = -1;
@ -1742,6 +1742,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
n++;
}
}
killflagsofid(o->flags, F_HASHIDDENNAME);
addflag(o->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, selhn->text);
// don't call sethiddenname, because it acts on OBJECT TYPES not OBJECTS.
// all books are unique
@ -6090,7 +6091,7 @@ objecttype_t *real_getrandomob(map_t *map, char *buf, int forcedepth, int forceh
int amt;
flag_t *f;
int db = B_FALSE;
int partdb = B_TRUE;
int partdb = B_FALSE;
char *pluralname;
char brandname[BUFLEN];
char cursestr[BUFLEN];
@ -7495,7 +7496,12 @@ int isplainob(object_t *o) {
if (o->inscription) return B_FALSE;
if (o->blessed != B_UNCURSED) return B_FALSE;
if (isblessknown(o)) return B_FALSE;
if (isdamaged(o)) return B_FALSE;
if (isdamaged(o)) {
// splashes of liquid can combine even when 'damaged'
if (getmaterialstate(o->material->id) != MS_LIQUID) {
return B_FALSE;
}
}
return B_TRUE;
}
@ -8195,7 +8201,7 @@ void makewet(object_t *o, int amt) {
killflagsofid(o->flags, F_ONFIRE);
killflagsofid(o->flags, F_HOT);
if (o->material->id == MT_METAL) {
if (willrust(o)) {
int rustchance = 25;
f = hasflag(o->flags, F_RUSTED);
if (f) rustchance += 25;
@ -9883,24 +9889,14 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
int donedip = B_FALSE;
// anything here to fill with?
for (oo = lf->cell->obpile->first ; (oo && !donedip); oo = nextoo) {
flag_t *fillflag;
int dippable = B_FALSE;
nextoo = oo->next;
switch (oo->type->id) {
case OT_BLOODSPLASH:
case OT_SPLASHWATER:
if (oo->amt >= 5) {
dippable = B_TRUE;
}
break;
case OT_BLOODPOOL:
case OT_PUDDLEWATER:
case OT_PUDDLEWATERL:
case OT_FOUNTAIN:
dippable = B_TRUE;
break;
default:
break;
fillflag = hasflag(oo->flags, F_FILLPOT);
if (fillflag && ((fillflag->val[1] == NA) || (oo->amt >= fillflag->val[1]))) {
dippable = B_TRUE;
}
if (dippable) {
char ch;
char ques[BUFLEN];
@ -9956,22 +9952,16 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
getobname(newob, newobname, newob->amt);
msgnocap("%c - %s.",newob->letter, newobname);
}
switch (oo->type->id) {
case OT_SPLASHWATER:
case OT_BLOODSPLASH:
removeob(oo, 5);
break;
case OT_PUDDLEWATER:
if (oo->type->id == OT_FOUNTAIN) {
if (fountain_will_dryup(oo)) {
removeob(oo, oo->amt);
}
} else {
if (fillflag->val[1] != NA) {
removeob(oo, fillflag->val[1]);
} else {
removeob(oo, 1);
break;
case OT_FOUNTAIN:
if (fountain_will_dryup(oo)) {
removeob(oo, oo->amt);
}
break;
default:
break;
}
}
} else {
msg("That doesn't seem like a very good idea.");
@ -15160,6 +15150,15 @@ int cancrush(lifeform_t *lf, object_t *o) {
return B_FALSE;
}
int willrust(object_t *o) {
if (o->material->id == MT_METAL) {
if (!hasflag(o->flags, F_WATERPROOF)) {
return B_TRUE;
}
}
return B_FALSE;
}
int willshatter(enum MATERIAL mat) {
switch (mat) {
case MT_GLASS:

View File

@ -296,6 +296,7 @@ int validatehiddennames(void);
int validateobs(void);
int wepdullable(object_t *o);
int cancrush(lifeform_t *lf, object_t *o);
int willrust(object_t *o);
int willshatter(enum MATERIAL mat);
#endif

View File

@ -1351,7 +1351,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (c) {
movelf(victim, c);
} else {
swapplaces(victim, user, B_TRUE, B_FALSE);
swapplaces(victim, user, B_CHANGEDIR, B_CHANGEDIR, B_NOTONPURPOSE);
swapped = B_TRUE;
}
@ -6713,6 +6713,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (iscursed(o)) {
setblessed(o, B_UNCURSED);
}
killflagsofid(o->flags, F_RUSTED);
}
} else {
// monsters can't id things!
@ -11712,12 +11713,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("You feel a wrenching sensation!");
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (isplayer(target)) {
msg("You feel a wrenching sensation!");
msg("You feel a wrenching sensation!"); more();
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player, caster)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
swapplaces(caster, target, B_CHANGEDIR, B_ONPURPOSE);
swapplaces(caster, target, B_CHANGEDIR, B_NOCHANGEDIR, B_ONPURPOSE);
} else if ((spellid == OT_S_SUMMONANIMALSSM) ||
(spellid == OT_S_SUMMONANIMALSMD) ||
(spellid == OT_S_SUMMONANIMALSLG) ||

21
text.c
View File

@ -210,6 +210,15 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
}
verb = getattackverb(lf, wep, damtype,dam,maxhp);
// when the player is being attacked, we want:
// "the xxx hits you. you die."
// rather than
// "the xxx kills you."
if (fatal && !isplayer(victim)) {
verb = getkillverb(victim, wep, damtype, dam, maxhp);
} else {
verb = getattackverb(lf, wep, damtype,dam,maxhp);
}
strcpy(nodamstr, "");
if ((dam == 0) && (damtype != DT_TOUCH) && !lfhasflag(lf, F_PHANTASM)) {
@ -1076,11 +1085,13 @@ char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int d
float pct;
pct = (int)(((float) dam / (float) maxhp) * 100.0);
if (wep && hasflag(wep->flags, F_MERCIFUL)) {
return "knock out";
}
if (wep && wep->pile->owner && lfhasflag(wep->pile->owner, F_STRIKETOKO)) {
return "knock out";
if (!isunconscious(victim)) {
if (wep && hasflag(wep->flags, F_MERCIFUL)) {
return "knock out";
}
if (wep && wep->pile->owner && lfhasflag(wep->pile->owner, F_STRIKETOKO)) {
return "knock out";
}
}
if (victim->race->id == R_DANCINGWEAPON) {
return "defeat";