diff --git a/ai.c b/ai.c index 523cd84..a7114ee 100644 --- a/ai.c +++ b/ai.c @@ -64,13 +64,15 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { // feigning death? if (lfhasflag(victim, F_FEIGNINGDEATH)) { - int penalty; - penalty = (getcelldist(lf->cell, victim->cell)-1); - if (penalty < 0) penalty = 0; - penalty *= 3; - if (!skillcheckvs(lf, SC_IQ, -penalty, victim, SC_WILL, 5+gethitdice(victim))) { - dblog(".oO { attempted target fooled me with feign death. ignoring. }"); - return B_TRUE; + if (!lfhasflagval(lf, F_ATTACHEDTO, victim->id, NA, NA, NULL)) { + int penalty; + penalty = (getcelldist(lf->cell, victim->cell)-1); + if (penalty < 0) penalty = 0; + penalty *= 3; + if (!skillcheckvs(lf, SC_IQ, -penalty, victim, SC_WILL, 5+gethitdice(victim))) { + dblog(".oO { attempted target fooled me with feign death. ignoring. }"); + return B_TRUE; + } } } @@ -740,7 +742,7 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) { /////////////////////////////////////////////// // need to heal? - if (needstorest(lf, NULL) && safetorest(lf)) { + if (needstorest(lf, NULL) && safetorest(lf) && !hasflag(lf->flags, F_RAGE)) { if (db) dblog(".oO { resting to heal }"); rest(lf, B_TRUE); return B_TRUE; @@ -2003,11 +2005,11 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG } } if (ot->id == OT_A_HIDE) { - if (lfhasflag(victim, F_HIDING)) { + if (lfhasflag(lf, F_HIDING)) { specificcheckok = B_FALSE; - } else if (lfhasflag(victim, F_FEIGNINGDEATH)) { + } else if (lfhasflag(lf, F_FEIGNINGDEATH)) { specificcheckok = B_FALSE; - } else if (!safetorest(victim)) { + } else if (!safetorest(lf)) { specificcheckok = B_FALSE; } } diff --git a/attack.c b/attack.c index c8b82a4..5980215 100644 --- a/attack.c +++ b/attack.c @@ -1111,8 +1111,8 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } // if victim was flying and took >= 40% of its hit points, it drops to the ground. - if (isphysicaldam(damtype[i]) && (dam[i] >= pctof(40, lf->maxhp))) { - fall_from_air(lf); + if (isphysicaldam(damtype[i]) && (dam[i] >= pctof(40, victim->maxhp))) { + fall_from_air(victim); } // if victim can still move... if (hasfreeaction(victim)) { diff --git a/data.c b/data.c index 714c17f..82050e4 100644 --- a/data.c +++ b/data.c @@ -367,15 +367,14 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL); + 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_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_MENTAL, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL); - addflag(lastjob->flags, F_STARTSKILL, SK_EXOTICWEPS, PR_NOVICE, NA, NULL); // learnable skills addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL); - addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_EXOTICWEPS, PR_BEGINNER, NA, NULL); // limit addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); @@ -1309,14 +1308,16 @@ void initobjects(void) { addot(OT_GRATINGFLOOR, "drainage grate", "A hatchway in the ground made of strong iron mesh.", MT_METAL, 40, OC_DFEATURE, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL); + addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "a slow drip."); addflag(lastot->flags, F_GLYPH, C_GREY, '#', NA, NULL); addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, NULL); - addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, NULL); addflag(lastot->flags, F_OPPOSITESTAIRS, OT_GRATINGROOF, NA, NA, NULL); - // TODO: add this back in ! addflag(lastot->flags, F_LOCKED, B_TRUE, 30, NA, NULL); // always starts locked addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_STENCH, B_TRUE, 1, NA, NULL); + addflag(lastot->flags, F_LOCKED, B_TRUE, 30, NA, NULL); // always starts locked addot(OT_GRATINGROOF, "drain in the roof", "An open draining grate set into the roof.", MT_NOTHING, 0, OC_DFEATURE, SZ_LARGE); addflag(lastot->flags, F_GLYPH, C_BLUE, '<', NA, NULL); @@ -1441,6 +1442,7 @@ void initobjects(void) { addot(OT_TEMPLE, "temple", "A small structure dedicated to one of the gods.", MT_METAL, 500, OC_BUILDING, SZ_LARGE); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, ""); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "voices chanting."); addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, 1, "a:speak to a deacon (earthly concerns)"); addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, 2, "b:speak to a priest (minor divine administration)"); addflag(lastot->flags, F_SHOPMENU, 2, MA_GOTOMENU, 3, "c:speak to the bishop (major divine matters)"); @@ -1653,7 +1655,7 @@ void initobjects(void) { // rocks addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_ROCK, SZ_HUGE); - addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, ""); addflag(lastot->flags, F_GLYPH, NA, '\'', NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL); addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL); @@ -4297,14 +4299,15 @@ void initobjects(void) { addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL); - addot(OT_SLIMEPOOL, "pool of slime", "A deep pool of sticky slime.", MT_SLIME, 300, OC_TERRAIN, SZ_HUGE); + addot(OT_SLIMEPOOL, "pool of slime", "A deep pool of foul-smelling slime.", MT_SLIME, 300, OC_TERRAIN, SZ_HUGE); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, C_GREEN, UNI_SOLID, NA, NULL); + addflag(lastot->flags, F_STENCH, B_TRUE, 2, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DEEPWATER, DP_MAX, NA, NA, NULL); addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL); - addot(OT_SLIMEPUDDLE, "puddle of slime", "A disgusting mass of sticky slime.", MT_SLIME, 20, OC_MISC, SZ_MEDIUM); + addot(OT_SLIMEPUDDLE, "puddle of slime", "A disgusting mass of foul-smelling slime.", MT_SLIME, 20, OC_MISC, SZ_MEDIUM); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL); @@ -4758,7 +4761,17 @@ void initobjects(void) { addot(OT_POISONPUFF, "puff of poison gas", "A small puff of poisonous gas.", MT_GAS, 0, OC_EFFECT, SZ_MEDIUM); addflag(lastot->flags, F_GLYPH, C_GREEN, UNI_SHADELIGHT, NA, NULL); - addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "disperses"); + addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); + addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_STENCH, B_TRUE, 1, NA, NULL); + addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); + + addot(OT_METHANEPUFF, "puff of methane gas", "A small puff of foul-smelling gas.", MT_GAS, 0, OC_EFFECT, SZ_MEDIUM); + addflag(lastot->flags, F_GLYPH, C_GREEN, UNI_SHADELIGHT, NA, NULL); + addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, "disperses"); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); @@ -6475,13 +6488,28 @@ void initrace(void) { // penalties addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Cannot use magic."); addflag(lastrace->flags, F_PENDESC, 1, NA, NA, "Vulnerable to Cold, Water and Electricity."); - addflag(lastrace->flags, F_PENDESC, 2, NA, NA, "Cannot wear armour on Legs, Hands, Feet or Fingers."); - addflag(lastrace->flags, F_PENDESC, 3, NA, NA, "Low Agility and Wisdom."); - addflag(lastrace->flags, F_PENDESC, 4, NA, NA, "Very low Charisma."); + addflag(lastrace->flags, F_PENDESC, 2, NA, NA, "Low Agility and Wisdom."); + addflag(lastrace->flags, F_PENDESC, 3, NA, NA, "Very low Charisma."); addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_WATER, NA, NA, "2d6"); addflag(lastrace->flags, F_DTVULN, DT_ELECTRIC, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SWIMMING, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_ALLOMANCY, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_MENTAL, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_NATURE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_AIR, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_DEATH, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_DIVINATION, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_ENCHANTMENT, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_FIRE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_GRAVITY, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_LIFE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_MODIFICATION, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_SUMMONING, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_TRANSLOCATION, NA, NA, NULL); + addflag(lastrace->flags, F_NOSKILL, SK_SS_WILD, NA, NA, NULL); // other special stuff addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_VERYRARE, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_VERYRARE, NULL); @@ -6536,7 +6564,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); // penalties - addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Below average Strength and low Wisdom, and slightly low Hit Points."); + addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Below average Strength, low Wisdom, and slightly low Hit Points."); addflag(lastrace->flags, F_PENDESC, 1, NA, NA, "Carnivorous (only eats meat)."); addflag(lastrace->flags, F_PENDESC, 2, NA, NA, "Fast metabolism."); addflag(lastrace->flags, F_PENDESC, 3, NA, NA, "Vulnerable to Magic, Water and Sonic damage."); @@ -8842,6 +8870,7 @@ void initrace(void) { setbodytype(lastrace, BT_SNAKE); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); @@ -8865,6 +8894,7 @@ void initrace(void) { addrace(R_SNAKECARPET, "carpet snake", 3, 's', C_GREY, MT_FLESH, RC_ANIMAL, "Non-venemous (but not quite harmless) snakes."); setbodytype(lastrace, BT_SNAKE); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -8887,6 +8917,7 @@ void initrace(void) { setbodytype(lastrace, BT_SNAKE); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); @@ -8910,6 +8941,7 @@ void initrace(void) { setbodytype(lastrace, BT_SNAKE); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); @@ -8934,6 +8966,7 @@ void initrace(void) { setbodytype(lastrace, BT_SNAKE); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); @@ -8959,6 +8992,7 @@ void initrace(void) { setbodytype(lastrace, BT_SNAKE); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL); @@ -8985,6 +9019,7 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_FREQUENT, NULL); addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -9011,6 +9046,7 @@ void initrace(void) { addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4+1"); @@ -9036,6 +9072,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_MASTER, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "5d4+1"); @@ -9059,6 +9096,7 @@ void initrace(void) { lastrace->baseid = R_SPIDER; addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); @@ -10477,6 +10515,7 @@ void initskills(void) { void make_basic_shop(flagpile_t *fp) { addflag(fp, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something"); addflag(fp, F_SHOPMENU, 1, MA_QUIT, NA, "q:leave"); + addflag(fp, F_MAKESNOISE, 33, 3, NA, "a cash register chiming."); } void sortcommands(void) { diff --git a/data/hiscores.db b/data/hiscores.db index 9adedf7..8459baf 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/defs.h b/defs.h index ed8e250..2cbf156 100644 --- a/defs.h +++ b/defs.h @@ -19,8 +19,10 @@ // for this many turns, abandon chase #define DEF_ANIMDELAY (1000000 / 50) // 1/100 of a second #define DEF_RESTHEALTIME (3) + #define DEF_SCREENW 80 #define DEF_SCREENH 24 + #define DEF_RAGETIME 10 #define DEF_SHOPIDENTPRICE (50) // cost to identify a just-purchased item #define DEF_VAULTMARGIN (3) @@ -131,8 +133,10 @@ #define MAXFLAGS 500 #define MAXFOLLOWLFS 15 // max # of lfs who will follow you up/down stairs #define MAXHISTORY 20 // max lines of history to keep + #define MAX_MAPW 80 -#define MAX_MAPH 20 +#define MAX_MAPH 30 + #define MAXPILEOBS 52 #define MAXRANDOMOBCANDIDATES 100 #define MAXRANDOMLFCANDIDATES 100 @@ -382,8 +386,8 @@ enum COLOUR { C_BOLDGREEN = 14, C_DARKGREY = 15, }; -#define BLUEBG 50 -#define GREENBG 100 +#define BLUEBG 30 +#define GREENBG 50 enum CASTTYPE { CT_NORMAL = 0, @@ -988,6 +992,7 @@ enum MATSTATE { MS_LIQUID, MS_GAS, MS_OTHER, + MS_ALL, }; // Object Materials @@ -1563,6 +1568,7 @@ enum OBTYPE { OT_MIST, OT_SMOKECLOUD, OT_SMOKEPUFF, + OT_METHANEPUFF, OT_POISONCLOUD, OT_POISONPUFF, OT_VINE, @@ -2071,6 +2077,10 @@ enum FLAG { // v2 = sc_dodge difficulty F_OBJECTTRAP, // this trap can go onto an object (door, chest, etc) F_SMELLY, // lfs with enhacned scent can smell this object + F_MAKESNOISE, // object periodically makes noise. + // v0 = % chance of noise. + // v1 = volume. + // f->text is the sound made. ie. "a splash." // shops F_BANNEDLF, // lfid v0 is not allowed to enter this shop F_SHOP, // this object is a shop @@ -2280,6 +2290,8 @@ enum FLAG { F_DONEDARKMSG, // tells the game not to say 'it is very dark here' F_DONELISTEN, // supress further 'you hear xx' messages this turn. // lifeform flags / lf flags / monster flags + F_NOSMELL, // lf can't smell. not affected by stench, and + // can't get enhancesmell. F_RESTINGINMOTEL, // sounds will not wake up this lf. monster won't // see them. // v0 = max time allowed to rest before checkout @@ -2707,7 +2719,10 @@ enum FLAG { F_STABILITY, // doesn't slip over F_STAMREGEN, // boost stamina regeneration at 'text' per turn // (this is a float) - F_STENCH, // creatures within v0 gain f_nauseated = v1 + F_STENCH, // on lifeforms: + // creatures within v0 gain f_nauseated = v1 + // on objects: + // creatures standing on it gain f_nauseated = v1 F_STUNNED, // cannot attack or cast spells F_TREMORSENSE, // doesn't need eyes to see, can see in dark with v0 F_PRODUCESLIGHT, // produces light of val0 radius. diff --git a/io.c b/io.c index 78bcfa4..8934f43 100644 --- a/io.c +++ b/io.c @@ -7104,6 +7104,7 @@ void initgfx(void) { } start_color(); + // 0 through 15 init_pair(C_BLACK, COLOR_BLACK, COLOR_BLACK); init_pair(C_RED, COLOR_RED, COLOR_BLACK); init_pair(C_GREEN, COLOR_GREEN, COLOR_BLACK); @@ -7113,7 +7114,6 @@ void initgfx(void) { init_pair(C_MAGENTA, COLOR_MAGENTA, COLOR_BLACK); init_pair(C_CYAN, COLOR_CYAN, COLOR_BLACK); init_pair(C_GREY, COLOR_WHITE, COLOR_BLACK); - init_pair(C_YELLOW, COLOR_YELLOW, COLOR_BLACK); init_pair(C_WHITE, COLOR_WHITE, COLOR_BLACK); init_pair(C_BOLDCYAN, COLOR_CYAN, COLOR_BLACK); @@ -7123,7 +7123,7 @@ void initgfx(void) { init_pair(C_ORANGE, COLOR_RED, COLOR_BLACK); init_pair(C_DARKGREY, COLOR_BLACK, COLOR_BLACK); - + // 30 through 45 init_pair(BLUEBG+C_BLACK, COLOR_BLACK, COLOR_BLUE); init_pair(BLUEBG+C_RED, COLOR_RED, COLOR_BLUE); init_pair(BLUEBG+C_GREEN, COLOR_GREEN, COLOR_BLUE); @@ -7141,6 +7141,7 @@ void initgfx(void) { init_pair(BLUEBG+C_BOLDGREEN, COLOR_GREEN, COLOR_BLUE); init_pair(BLUEBG+C_ORANGE, COLOR_RED, COLOR_BLUE); + // 50 through 65 init_pair(GREENBG+C_BLACK, COLOR_BLACK, COLOR_GREEN); init_pair(GREENBG+C_RED, COLOR_RED, COLOR_GREEN); init_pair(GREENBG+C_GREEN, COLOR_GREEN, COLOR_GREEN); @@ -10673,7 +10674,7 @@ void showlfstats(lifeform_t *lf, int showall) { } else { f = lfhasknownflag(lf, F_ATTRMOD); if (f && (f->known)) { - mvwprintw(mainwin, y, 0, "%s %s has been %s.", your(lf), getattrname(f->val[0]), (f->val[2] > 0) ? "increased" : "decreased"); + mvwprintw(mainwin, y, 0, "%s %s has been %s.", your(lf), getattrname(f->val[0]), (f->val[1] > 0) ? "increased" : "decreased"); y++; } } diff --git a/lf.c b/lf.c index 51035ba..546ad7a 100644 --- a/lf.c +++ b/lf.c @@ -2289,7 +2289,9 @@ void die(lifeform_t *lf) { // makenoise(lf, N_DIE); } } else if (cantalk(lf)) { - sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL); + if (pctchance(33)) { + sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL); + } } if (!hasflag(lf->flags, F_NODEATHANNOUNCE)) { @@ -3329,8 +3331,10 @@ void enhanceskills(lifeform_t *lf) { if (gainedxplev) { // special cases which happen before doing hp/mp - if (hasjob(lf, J_MONK) && (lf->level == 2)) { - addflag(lf->flags, F_MPDICE, 1, 0, NA, NULL); + if (hasjob(lf, J_MONK) && (lf->level == 2) && !lfhasflag(lf, F_NOSPELLS)) { + if (!lfhasflag(lf, F_MPDICE)) { + addflag(lf->flags, F_MPDICE, 1, 0, NA, NULL); + } } // update hp @@ -3614,59 +3618,15 @@ void enhanceskills(lifeform_t *lf) { // special case level-based job effects if (hasjob(lf, J_MONK)) { // enhance fist strength - f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL); + //f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL); + f = lfhasflag(lf, F_HASATTACK); if (f) { int newdr; - //newdr = ((lf->level+1) / 2) + 2; newdr = lf->level+2; - /* - switch(lf->level) { - case 2: - newdr = 4; break; - case 3: - newdr = 5; break; - case 4: - newdr = 6; break; - case 5: - newdr = 7; break; - case 6: - newdr = 8; break; - case 7: - newdr = 9; break; - case 8: - newdr = 10; break; - case 9: - case 10: - newdr = 11; break; - case 11: - case 12: - newdr = 12; break; - case 13: - case 14: - newdr = 13; break; - case 15: - case 16: - case 17: - newdr = 14; break; - strcpy(newtext,"4d6"); - break; - case 18: - strcpy(newtext,"6d4"); - break; - case 19: - strcpy(newtext,"5d6"); - break; - case 20: - strcpy(newtext,"8d4"); - break; - default: - strcpy(newtext,"6d6"); - break; - } - */ - if (newdr != f->val[1]) { - //if (!streq(newtext, f->text)) { - // changeflagtext(f, newtext); + if (newdr <= f->val[1]) { + // do nothing - your unarmed attack was already stronger or + // equivilant. + } else if (newdr > f->val[1]) { f->val[1] = newdr; if (isplayer(lf)) msg("^gYour unarmed attack damage has increased!"); } @@ -3690,7 +3650,7 @@ void enhanceskills(lifeform_t *lf) { } else if (lf->level >= 17) { min = 3; max = 4; } - if ((min != f->val[0]) || (max != f->val[1])) { + if ((min > f->val[0]) || (max > f->val[1])) { f->val[0] = min; f->val[1] = max; if (isplayer(lf)) msg("^gYour number of unarmed attacks has increased!"); @@ -3785,8 +3745,14 @@ int fall(lifeform_t *lf, lifeform_t *fromlf, int announce) { // if you are going to sleep on purpose, use 'gotosleep'. // this function is for when it is forced upon you by a spell, etc. int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong) { - if (lfhasflag(lf, F_ASLEEP)) { - return B_TRUE; + flag_t *f; + f = lfhasflag(lf, F_ASLEEP); + if (f) { + if (f->val[1] == how) { + return B_TRUE; + } else { + killflag(f); + } } if ((how == ST_ASLEEP) && lfhasflag(lf, F_CAFFEINATED)) { @@ -6307,12 +6273,24 @@ glyph_t *getlfglyph(lifeform_t *lf) { if (lf->cell && (getcellwaterdepth(lf->cell, player) >= DP_WAIST)) { object_t *o; + int bgcol = 0; o = hasobwithflag(lf->cell->obpile, F_DEEPWATER); switch (o->type->material->id) { - case MT_WATER: tempglyph.colour += BLUEBG; break; - case MT_SLIME: tempglyph.colour += GREENBG; break; + case MT_WATER: bgcol = BLUEBG; break; + case MT_SLIME: bgcol = GREENBG; break; default: break; } + if (bgcol) { + // avoid having the same foreground and background colour + int fixfg = B_FALSE; + if ((bgcol == BLUEBG) && (tempglyph.colour == C_BLUE)) { + fixfg = B_TRUE; + } else if ((bgcol == GREENBG) && (tempglyph.colour == C_GREEN)) { + fixfg = B_TRUE; + } + if (fixfg) tempglyph.colour = C_BLACK; + tempglyph.colour += bgcol; + } } //return &lf->race->glyph; @@ -7998,13 +7976,16 @@ void givejob(lifeform_t *lf, enum JOB jobid) { // special cases if (j->id == J_MONK) { flag_t *f; - f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL); + // monk fists do more damage + // also, they always use fists, even if the race has claws etc. + f = lfhasflag(lf, F_HASATTACK); if (f) { - // monk fists do more damage + f->val[0] = OT_FISTS; f->val[1] = 3; } } else if (j->id == J_PIRATE) { flag_t *f; + // pirate has a hook instead of a hand f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL); if (f) { f->val[0] = OT_HOOKHAND; @@ -8425,6 +8406,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { obpile_t *op; map_t *targmap; enum LFSIZE maxobsize = SZ_MAX; + int isshop = B_FALSE; if (targob) { cell_t *c; @@ -8432,6 +8414,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { c = getoblocation(targob); targmap = c->map; maxobsize = getobsize(targob); + if (hasflag(targob->flags, F_SHOP)) isshop = B_TRUE; } else { op = lf->pack; targmap = lf->cell->map; @@ -8568,6 +8551,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { // if (getrandomobofsize(targmap, buf, maxobsize)) { if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, B_TRUE, OC_NONE, DT_NONE)) { + if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); o = addob(op, buf); } } @@ -8586,6 +8570,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { } if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, B_TRUE, OC_NONE, val[1], DT_NONE)) { if (db) snprintf(buf2, BUFLEN, "finished startobdt successfuly."); + if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); o = addob(op, buf); } else { if (db) snprintf(buf2, BUFLEN, "finished startobdt, failed."); @@ -8611,6 +8596,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { if (real_getrandomob(targmap, buf, getmapdifficulty(targmap) + depthmod, NA, maxobsize, B_TRUE, val[1], OC_NONE, DT_NONE)) { if (db) snprintf(buf2, BUFLEN, "finished startobclass, success."); + if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); o = addob(op, buf); } else { //obdb = B_FALSE; @@ -11822,9 +11808,17 @@ void makefriendly(lifeform_t *who, int howlong) { int makenauseated(lifeform_t *lf, int amt, int howlong) { flag_t *f; - if (isundead(lf)) return B_TRUE; - if (!hasbp(lf, BP_HEAD)) return B_TRUE; // can't smell with no head + switch (lf->race->raceclass->id) { + case RC_HUMANOID: + case RC_ANIMAL: + break; + default: + return B_TRUE; + } + if (lfhasflag(lf, F_STENCH)) return B_TRUE; // your own smell makes you used to it + if (lfhasflag(lf, F_NOSMELL)) return B_TRUE; // can't smell it. + if (!hasbp(lf, BP_HEAD)) return B_TRUE; // can't smell with no head if (lfhasflag(lf, F_ENHANCESMELL)) amt += 2; @@ -12337,7 +12331,11 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume, *quotepos = '\0'; strcat(realseetext, "something"); } - msg("%s %s.", lfname, realseetext); + if (isdead(noisemaker)) { + msg("The dying %s %s.", noprefix(lfname), realseetext); + } else { + msg("%s %s.", lfname, realseetext); + } if ((realseetext[0] == '\0') || !strlen(realseetext)) { dblog("xxx"); } @@ -13258,6 +13256,10 @@ int startresting(lifeform_t *lf, int willtrain) { return B_TRUE; } } + if (lfhasflag(lf, F_RAGE)) { + if (isplayer(lf)) msg("You are too enraged to rest!"); + return B_TRUE; + } // stop hiding killflagsofid(lf->flags, F_HIDING); @@ -14781,12 +14783,6 @@ void startlfturn(lifeform_t *lf) { } } - - // get nauseated if in the sewer - if (lf->cell && (lf->cell->habitat->id == H_SEWER)) { - makenauseated(lf, 2, 2); - } - // get more hungry modhunger(lf, 1); @@ -15003,6 +14999,11 @@ void startlfturn(lifeform_t *lf) { if (f && f->lifetime > 0) { f->lifetime = DEF_RAGETIME/2; } else { + if (isplayer(lf)) { + char lfname[BUFLEN]; + getlfname(otherlf, lfname); + msg("The sight of %s makes your blood boil!", lfname); + } addtempflag(lf->flags, F_RAGE, B_TRUE, NA, NA, NULL, DEF_RAGETIME/2); if (getstamina(lf) < 1) setstamina(lf, 1); forceredraw(); @@ -15062,7 +15063,7 @@ void startlfturn(lifeform_t *lf) { for (l = lf->cell->map->lf ; l ; l = l->next) { if (!isdead(l) && (l != lf)) { if (l->race->baseid != lf->race->baseid) { // can't smell your own race. - // gains/loses stench? + // gains/loses nauseation? f = lfhasflag(l, F_STENCH); if (f) { int range,power; @@ -15147,7 +15148,7 @@ void startlfturn(lifeform_t *lf) { if (skillcheck(lf, SC_SEARCH, diff, mod)) { char obname[BUFLEN]; // reveal it - getobname(o, obname, o->amt); + real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_TRUE); msg("^wYou notice %s!",obname); interrupt(lf); killflag(f); @@ -15326,7 +15327,7 @@ void startlfturn(lifeform_t *lf) { } if (isdead(lf)) return; - // damage from cell objects? + // effects from cell objects? for (o = lf->cell->obpile->first ; o ; o = o->next) { f = hasflag(o->flags, F_WALKDAM); if (f) { @@ -15351,6 +15352,10 @@ void startlfturn(lifeform_t *lf) { } + f = hasflag(o->flags, F_STENCH); + if (f) { + makenauseated(lf, f->val[1], 2); + } // for flags which can occur multiple times getflags(o->flags, retflag, &nretflags, F_DEEPWATER, F_WALKDAMBP, F_NONE); @@ -15400,6 +15405,7 @@ void startlfturn(lifeform_t *lf) { if (isdead(lf)) return; + // effects for/on your own flags getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FLEEFROM, F_GRABBEDBY, F_GRABBING, F_GUNTARGET, F_BOOSTSPELL, F_FEIGNINGDEATH, F_INJURY, F_NOFLEEFROM, F_PETOF, F_SPOTTED, F_STABBEDBY, F_TARGETCELL, F_TARGETLF, F_NONE); @@ -16829,6 +16835,11 @@ int validateraces(void) { printf("ERROR in race '%s' - has NOISETEXT but no volume.\n", r->name); goterror = B_TRUE; } + } else if (f->id == F_NOSMELL) { + if (hasflag(r->flags, F_ENHANCESMELL)) { + printf("ERROR in race '%s' - has both NOSMELL and ENHANCESMELL.\n", r->name); + goterror = B_TRUE; + } } } // end foreach flag diff --git a/map.c b/map.c index 99957ad..fc07634 100644 --- a/map.c +++ b/map.c @@ -2960,20 +2960,28 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t int numon = 0; char buf[BUFLEN]; - // select room size - //roomsize = 5; - sectionsize = rnd(5,9); - // must be an odd number - if ((sectionsize % 2) == 0) sectionsize++; + corridorsize = rnd(2,3); + roomfullsize = rnd(5,9); if ((roomfullsize % 2) == 0) roomfullsize++; + sectionsize = corridorsize + roomfullsize; + roomsize = roomfullsize - 2; // don't include outer walls. - // subtract corridor size - corridorsize = rnd(2,3); - roomfullsize = sectionsize - corridorsize; - roomsize = roomsize - 2; // ie. don't include outer walls // select how many very/horz rooms - maxroomsx = (map->w - 1) / (sectionsize); - maxroomsy = (map->h - 1) / (sectionsize); + // we are being over cautious here since "sectionsize" + // is a room + corridor. + // (x-1) corridors. ie: + // Room --- Room --- Room xxx + // | | | + // | | | + // Room --- Room --- Room xxx + // x x x + // x x x + // + // == Across: 3 rooms, 2 corridors + // == Down: 2 rooms, 1 corridor + /// x = left over sectionsize + maxroomsx = ((map->w - 2) ) / (sectionsize); + maxroomsy = ((map->h - 2) ) / (sectionsize); roomcountx = maxroomsx; roomcounty = maxroomsy; @@ -2994,7 +3002,7 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t while (numon == 0) { for (ry = 0; ry < roomcounty; ry++) { for (rx = 0; rx < roomcountx; rx++) { - i = rx * ry; + i = (ry*roomcountx)+rx; if (pctchance(66)) { roomon[i] = B_TRUE; @@ -3010,7 +3018,7 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t for (ry = 0; ry < roomcounty; ry++) { rowfirst[ry] = -1; for (rx = 0; rx < roomcountx; rx++) { - i = rx * ry; + i = (ry*roomcountx)+rx; if (roomon[i]) { if (rowfirst[ry] == -1) { rowfirst[ry] = rx; @@ -3023,7 +3031,7 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t for (rx = 0; rx < roomcountx; rx++) { colfirst[rx] = -1; for (ry = 0; ry < roomcounty; ry++) { - i = rx * ry; + i = (ry*roomcountx)+rx; if (roomon[i]) { if (colfirst[rx] == -1) { colfirst[rx] = ry; @@ -3034,11 +3042,14 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t } dblog("SEWER debug:"); + dblog(" sectionsize is %d (room=%d, corridor=%d)", sectionsize, roomfullsize, corridorsize); + dblog(" roomcountx is %d, roomcounty is %d", roomcountx, roomcounty); for (ry = 0; ry < roomcounty; ry++) { char buf2[BUFLEN]; strcpy(buf, ""); for (rx = 0; rx < roomcountx; rx++) { - if (roomon[rx*ry]) { + i = (ry*roomcountx)+rx; + if (roomon[i]) { strcat(buf, "#"); } else { strcat(buf, "-"); @@ -3057,7 +3068,8 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t // add square rooms in a gridlike layout for (ry = 0; ry < roomcounty; ry++) { for (rx = 0; rx < roomcountx; rx++) { - if (roomon[rx*ry]) { + i = (ry*roomcountx)+rx; + if (roomon[i]) { int thisid; int x2,y2; thisid = map->nrooms; @@ -3117,6 +3129,7 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t } if (makewalkway) setcelltype(c, c->habitat->emptycelltype); } else if (c->type->id == CT_LOWFLOOR) { + // any water cell orthogonally surrounded by water becomes very deep int dir,surrounded = B_TRUE; for (dir = D_N; dir <= D_W; dir++) { c2 = getcellindir(c, dir); @@ -3132,7 +3145,6 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t } } - // any water cell orthogonally surrounded by water becomes very deep // now move all objects out of the water @@ -3151,8 +3163,9 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t } // add the exit. make sure it's next to a wall so it's possible to climb to. + // also ensure it's not over water. c = NULL; - while (!c || (countadjwalls(c) == 0)) { + while (!c || (countadjwalls(c) == 0) || getcellwaterdepth(c, NULL)) { c = getrandomroomcell(map, ANYROOM); assert(c); } @@ -3312,7 +3325,7 @@ void killfakes(map_t *map, cell_t *cell) { // if 'wantfilled' is set, only link to "filled" cells. // return TRUE on failure. int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) { - int db = B_TRUE; + int db = B_FALSE; int d, roomid; int poss2[MAXCANDIDATES],nposs2; int dist[MAXDIR_ORTH],hitsedge[MAXDIR_ORTH], sameroom[MAXDIR_ORTH]; @@ -3702,7 +3715,7 @@ int linkexits(map_t *m, int roomid) { int x,y,i; cell_t *poss[MAXCANDIDATES],*c; int nposs = 0; - int db = B_TRUE; + int db = B_FALSE; int nadded = 0; int minx = -1, miny = -1, maxx = -1, maxy = -1; int roomidx = -1; diff --git a/nexus.c b/nexus.c index 1da71cb..4d58553 100644 --- a/nexus.c +++ b/nexus.c @@ -467,8 +467,22 @@ int main(int argc, char **argv) { // redo light and player los calclight(player->cell->map); - player->facing = rnd(DC_N, DC_NW); - precalclos(player); + + // make player face the direction which gives them the most visibility + if (newworld) { + int bestdir = D_NONE; + int bestlos = -1; + for (i = DC_N; i <= DC_NW; i++) { + setfacing(player, i); + precalclos(player); + if (player->nlos > bestlos) { + bestlos = player->nlos; + bestdir = i; + } + } + player->facing = bestdir; + precalclos(player); + } // show level drawscreen(); @@ -1376,6 +1390,10 @@ int rollmpdice(lifeform_t *lf, int wantmax) { flag_t *retflag[MAXCANDIDATES]; int nretflags; + if (lfhasflag(lf, F_NOSPELLS)) { + return 0; + } + f = hasflag(lf->flags, F_MPDICE); if (f) { ndice = f->val[0]; @@ -1601,6 +1619,7 @@ void timeeffectsworld(map_t *map, int updategametime) { } pit = hasobwithflagval(c->obpile, F_PIT, D_DOWN, NA, NA, NULL); + if (!pit) pit = hasob(c->obpile, OT_GRATINGFLOOR); if (pit) { obsfallthrough(c, pit); } diff --git a/objects.c b/objects.c index 625ce66..4e0bb98 100644 --- a/objects.c +++ b/objects.c @@ -2558,16 +2558,17 @@ int checkobnames(char *haystack, char *needle) { void colourmatchob(object_t *o, lifeform_t *lf) { flag_t *f; - glyph_t *lfglyph; - lfglyph = getlfglyph(lf); + glyph_t *glyph; + enum COLOUR wantcol; + glyph = getlfglyph(lf); + wantcol = glyph->colour; f = hasflag(o->flags, F_GLYPH); if (f) { - f->val[1] = lfglyph->colour; + f->val[0] = wantcol; } else { - glyph_t *obglyph; - obglyph = getglyph(o); - addflag(o->flags, F_GLYPH, lfglyph->colour, obglyph->ch, NA, NULL); + glyph = getglyph(o); + addflag(o->flags, F_GLYPH, wantcol, glyph->ch, NA, NULL); } } @@ -4809,7 +4810,14 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan } if (issecretdoor(o)) { - strcat(localbuf, "secret "); + if (showall) { + strcat(localbuf, "secret "); + } else if (where) { + celltype_t *ct; + ct = findcelltype(where->map->habitat->solidcelltype); + // solid cell description + strcpy(pluralname, ct->name); + } } // object name @@ -7562,49 +7570,68 @@ flag_t *obrestrictsmovement(object_t *o, lifeform_t *lf) { // returns # objects which fell through int obsfallthrough(cell_t *c, object_t *pit) { - object_t *oo,*uphole; + object_t *oo,*nextoo,*uphole = NULL; cell_t *belowcell; char obname[BUFLEN],downholename[BUFLEN],upholename[BUFLEN]; int nfallen = 0; belowcell = getstairdestination(pit, NULL); - if (!belowcell) return 0; - uphole = hasobwithflagval(belowcell->obpile, F_PIT, D_UP, NA, NA, NULL); - getobname(pit,downholename, 1); - getobname(uphole,upholename, 1); - - for (oo = c->obpile->first ; oo ; oo = oo->next) { - if (oo == pit) continue; - if (!hasflag(oo->flags, F_NOPICKUP)) { - int canseebelowlf = B_FALSE; - // fall through! - if (haslos(player, c)) { - // player can see the top of the hole - getobname(oo,obname, oo->amt); - msg("%s fall%s through %s.", obname, - (oo->amt == 1) ? "s" : "", - downholename); - } + if (belowcell) { + uphole = hasobwithflagval(belowcell->obpile, F_PIT, D_UP, NA, NA, NULL); + getobname(uphole,upholename, 1); + } + + for (oo = c->obpile->first ; oo ; oo = nextoo) { + int canseebelowlf = B_FALSE; + char verb[BUFLEN]; + nextoo = oo->next; + + if (oo == pit) continue; + + if (hasflag(pit->flags, F_PIT)) { + //nopickup objects don't fall down pits. + if (hasflag(oo->flags, F_NOPICKUP)) continue; + strcpy(verb, "fall"); + } else if (pit->type->id == OT_GRATINGFLOOR) { + // only liquid falls through gratings + if (getmaterialstate(oo->material->id) != MS_LIQUID) continue; + strcpy(verb, "drain"); + } else { + strcpy(verb, "fall"); + } + + // fall through! + if (haslos(player, c)) { + // player can see the top of the hole + getobname(oo,obname, oo->amt); + msg("%s %s%s through %s.", obname, verb, + (oo->amt == 1) ? "s" : "", + downholename); + } + + nfallen++; + + if (belowcell) { // remember if we can see the bottom cell before the object drops if (belowcell->lf && cansee(player, belowcell->lf)) { canseebelowlf = B_TRUE; } - moveob(oo, belowcell->obpile, oo->amt); + oo = moveob(oo, belowcell->obpile, oo->amt); if (haslos(player, belowcell)) { // player can see the bottom of the hole getobname(oo,obname, oo->amt); - msg("%s fall%s through %s.", obname, + msg("%s %s%s through %s.", obname, verb, (oo->amt == 1) ? "s" : "", upholename); } // does the object hit anyone? - if (belowcell->lf) { + if (belowcell->lf && (getmaterialstate(oo->material->id) == MS_SOLID)) { lifeform_t *lf; char dambuf[BUFLEN]; lf = belowcell->lf; @@ -7620,8 +7647,8 @@ int obsfallthrough(cell_t *c, object_t *pit) { snprintf(dambuf, BUFLEN, "a falling %s", oo->type->name); losehp(lf, getthrowdam(oo) * 6, DT_PROJECTILE, NULL, dambuf); } - - nfallen++; + } else { + killob(oo); } } return nfallen; @@ -8300,27 +8327,29 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { for (oo = c->obpile->first ; oo ; oo = nextoo) { nextoo = oo->next; flag_t *f; - f = hasflag(oo->flags, F_LOCKED); - if (f) { - killflag(f); - if (isplayer(lf)) { - msg("Your %s beeps.", noprefix(obname)); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s%s %s beeps.", lfname, getpossessive(lfname), - noprefix(obname)); - } - } else { - addflag(oo->flags, F_LOCKED, B_TRUE, 20, NA, NULL); - if (isplayer(lf)) { - msg("Your %s buzzes.", noprefix(obname)); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s%s %s buzzes.", lfname, getpossessive(lfname), - noprefix(obname)); - } + if (hasflag(oo->flags, F_LOCKABLE)) { + f = hasflag(oo->flags, F_LOCKED); + if (f) { + killflag(f); + if (isplayer(lf)) { + msg("Your %s beeps.", noprefix(obname)); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s%s %s beeps.", lfname, getpossessive(lfname), + noprefix(obname)); + } + } else { + addflag(oo->flags, F_LOCKED, B_TRUE, 20, NA, NULL); + if (isplayer(lf)) { + msg("Your %s buzzes.", noprefix(obname)); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s%s %s buzzes.", lfname, getpossessive(lfname), + noprefix(obname)); + } + } } } } else { @@ -8366,12 +8395,15 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { int donesomething = B_FALSE; if (!where) { if (isplayer(lf)) msg("There is nothing to use your spanner on there!"); + } else if (where->lf) { + if (isplayer(lf)) msg("There is someone in your way!"); } else { object_t *o; char ch; flag_t *f; for (o = where->obpile->first ; o ; o = o->next) { int isopen; + // jammed doors if (isdoor(o, &isopen)) { if (!isopen) { // ie. if closed. f = hasflag(o->flags, F_JAMMED); @@ -8399,6 +8431,19 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } } } + // gratings + if ((o->type->id == OT_GRATINGFLOOR) && hasflag(o->flags, F_LOCKED)) { + char obname[BUFLEN]; + getobname(o, obname, 1); + ch = askchar("It looks like you could remove the bolts. Do so", "yn", "y", B_TRUE, B_FALSE); + if (ch == 'y') { + msg("You remove the cover from %s.", obname); + killflagsofid(o->flags, F_LOCKED); + killflagsofid(o->flags, F_LOCKABLE); + taketime(lf, getactspeed(lf)); + donesomething = B_TRUE; + } + } } } if (!donesomething) { @@ -11633,15 +11678,13 @@ void timeeffectsob(object_t *o) { if (location) { - //buildings/shops make noise - if (o->type->obclass->id == OC_BUILDING) { - if (onein(3)) { - char noisebuf[BUFLEN]; - switch (o->type->id) { - case OT_TEMPLE: strcpy(noisebuf, "voices chanting."); break; - default: strcpy(noisebuf, "a cash register chiming."); break; - } - noise(location, NULL, NC_OTHER, 3, noisebuf, NULL); + // object makes noise? + f = hasflag(o->flags, F_MAKESNOISE); + if (f && pctchance(f->val[0])) { + // these are generally just to notify the player that something + // is nearby, so don't make noises the the player is already there. + if (location != player->cell) { + noise(location, NULL, NC_OTHER, f->val[1], f->text, NULL); } } // does object's material change cell type? diff --git a/spell.c b/spell.c index 509b938..72193bd 100644 --- a/spell.c +++ b/spell.c @@ -3580,8 +3580,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_CANINETRACKING) { int howlong; - howlong = getspellduration(20,30,blessed) + (power*10); - addtempflag(caster->flags, F_ENHANCESMELL, 4, NA, NA, NULL, howlong); + if (hasflag(caster->flags, F_NOSMELL)) { + if (isplayer(caster)) { + nothinghappens(); + } else { + fizzle(caster); + } + } else { + howlong = getspellduration(20,30,blessed) + (power*10); + addtempflag(caster->flags, F_ENHANCESMELL, 4, NA, NA, NULL, howlong); + } } else if (spellid == OT_S_CONFISCATE) { char ch = 'a'; char obname[BUFLEN]; @@ -6944,22 +6952,32 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int gotit = B_FALSE; int dooropen; if (isdoor(o, &dooropen)) { + // closed door? if (!dooropen) { gotit = B_TRUE; } } else { + // something else impassable gotit = B_TRUE; } - if (gotit) { if (haslos(player, targcell)) { getobname(o, buf, o->amt); msg("%s %s!",isplayer(caster) ? "You blast" : "Something blasts", buf); + if (seenbyplayer) *seenbyplayer = B_TRUE; } addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL); - if (seenbyplayer) *seenbyplayer = B_TRUE; donesomething = B_TRUE; } + } else if (hasflag(o->flags, F_LOCKED)) { + // unlock it + if (haslos(player, targcell)) { + getobname(o, buf, 1); + msg("%s unlocks.", buf); + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + killflagsofid(o->flags, F_LOCKED); + donesomething = B_TRUE; } }