From ad18cf23986f2d6b20d4a8c5b1a74ad022a818bb Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Wed, 28 Sep 2011 01:05:10 +0000 Subject: [PATCH] - [+] player start objects shouldn't get random brands like silver! - [+] warn before moving/attacking with bleeding injury - [+] leg slash = hploss form move - [+] hand slash = hploss from attack - [+] warn before walking onto pentagram with blessed gear - [+] explosion should cause dt_explosion injuries? - [+] massive damage to whatever armour is there - [+] OR if no armour: - [+] limbs - [+] lose hand - [+] body - [+] collapsed lung (fitness = 0)k - [+] ribcrack (like bashing one) - [+] head - [+] ringing ears (can't hear anything for a long time) - [+] burnt eyes (blinded) - [+] bug: not seeing fall msg during move (fell due to leg injury) need 'didmsg' - [+] getrelativedir should always return FRONT when uou have f_awareness - [+] bug: shouldn't try to leave trails when inside walls - [+] announce when armour saves you from critical hits - [+] F_DONELISTEN isn't working now - i'm getting multiple "you hear buzzing to the north". - [+] N_FLY needs to act the same as N_WALK (ie. be NC_MOVEMENT) - [+] make validatespellcell() work on abilities - [+] sonic bolt - [+] mutated bat (sonar - damage) - [+] merloch (sonic scream - damage) --- attack.c | 24 +++++++++++-- attack.h | 2 +- data.c | 82 +++++++++++++++++++++++++++++++++++++------- data/hiscores.db | Bin 6144 -> 6144 bytes defs.h | 14 +++++--- doc/add_damtype.txt | 8 ++--- doc/glyphs.txt | 1 + io.c | 17 +++++++++ io.h | 1 + lf.c | 48 +++++++++++++++++++------- lf.h | 1 + map.c | 2 +- move.c | 43 +++++++++++++++++++---- objects.c | 18 ++++++---- spell.c | 44 ++++++++++++++++++++---- 15 files changed, 248 insertions(+), 57 deletions(-) diff --git a/attack.c b/attack.c index 823981e..23f9f79 100644 --- a/attack.c +++ b/attack.c @@ -60,6 +60,7 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty actualdam = dam; + /* // adjust how much damage to do to armour if ( ((armour->type->id == OT_FLAKJACKET) && (damtype == DT_PROJECTILE)) || (damtype == DT_ACID) || @@ -77,6 +78,7 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty } } } + */ // modify for rust if (rust) { @@ -172,8 +174,16 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { int attackedfriend = B_FALSE; int attackedpeaceful = B_FALSE; + // warn if attacking will cause injury + if (!force && isplayer(lf)) { + if (!confirm_injury_action(BP_HANDS, DT_SLASH, "attack")) { + return B_TRUE; + } + } + stoprunning(lf); + // anyone there? if so just attack. if (c->lf) { if (!force && isplayer(lf) && !areenemies(lf,c->lf) && (getraceclass(c->lf) != RC_PLANT)) { @@ -863,7 +873,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) adjustdamlf(victim, &dam[i], damtype[i]); //dblog("adjusted for lf to dam[%d] = %d",i,dam[i]); - if (!backstab) { + // armour doesn't reduce damage for backstabs or critical hits. + // BUT in the case of a critical hit, the armour might get + // damaged during criticalhit() + if (!backstab && !critical) { // modify for defender's armour reduceamt = getarmourdamreduction(victim, wep, dam[i], damtype[i]); @@ -1119,7 +1132,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) // critical hit effects if (critical && damtypecausescriteffects(damtype[0])) { - criticalhit(lf, victim, critpos, damtype[0]); + criticalhit(lf, victim, critpos, dam[0], damtype[0]); } // confer flags from attacker? @@ -1414,7 +1427,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) { } -void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum DAMTYPE damtype) { +void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int dam, enum DAMTYPE damtype) { object_t *o,*armour; char lfname[BUFLEN],victimname[BUFLEN],obname[BUFLEN]; // replace some dam types @@ -1457,6 +1470,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum getlfname(victim, victimname); msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname)); } + takedamage(armour, dam, damtype); } else { injure(victim, BP_BODY, damtype); } @@ -1487,6 +1501,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum getlfname(victim, victimname); msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname)); } + takedamage(armour, dam, damtype); } } else { injure(victim, BP_HEAD, damtype); @@ -1501,6 +1516,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum getlfname(victim, victimname); msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname)); } + takedamage(armour, dam, damtype); } else { injure(victim, BP_HANDS, damtype); } @@ -1521,6 +1537,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum getlfname(victim, victimname); msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname)); } + takedamage(armour, dam, damtype); } else { injure(victim, BP_LEGS, damtype); } @@ -1535,6 +1552,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum getlfname(victim, victimname); msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname)); } + takedamage(armour, dam, damtype); } else { injure(victim, hitpos, damtype); } diff --git a/attack.h b/attack.h index 22b2323..2d2bf75 100644 --- a/attack.h +++ b/attack.h @@ -6,7 +6,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force); int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag); int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag); void confereffects(flagpile_t *fp, lifeform_t *victim); -void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum DAMTYPE damtype); +void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int dam, enum DAMTYPE damtype); int damtypecausesbleed(enum DAMTYPE dt); int damtypecausescriteffects(enum DAMTYPE dt); int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype); diff --git a/data.c b/data.c index 08b22df..2d1d934 100644 --- a/data.c +++ b/data.c @@ -512,7 +512,6 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "helmet"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "suit of ring mail"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of gauntlets"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of metal boots"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "buckler"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10-20 gold coins"); // initial skills @@ -877,20 +876,13 @@ void initobjects(void) { addmaterial(MT_STONE, "stone", 10); addflag(lastmaterial->flags, F_HARDNESS, 4, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTIMMUNE, DT_BITE, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTRESIST, DT_PROJECTILE, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); addmaterial(MT_SILVER, "silver", 11); addflag(lastmaterial->flags, F_HARDNESS, 2, NA, NA, NULL); addmaterial(MT_METAL, "metal", 13); addflag(lastmaterial->flags, F_HARDNESS, 5, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTRESIST, DT_BITE, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTRESIST, DT_PIERCE, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTRESIST, DT_SLASH, NA, NA, NULL); - addflag(lastmaterial->flags, F_DTRESIST, DT_PROJECTILE, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); addmaterial(MT_GLASS, "glass", 13); addflag(lastmaterial->flags, F_HARDNESS, 2, NA, NA, NULL); addflag(lastmaterial->flags, F_DTVULN, DT_BASH, NA, NA, NULL); @@ -1155,7 +1147,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_DFEATURE, SZ_LARGE); - addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, ""); + addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, ""); addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "_"); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -2046,6 +2038,13 @@ void initobjects(void) { addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addot(OT_S_TAILWIND, "tailwind", "Propels the caster from behind, slightly speeding up movement when walking directly forwards.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l3 addot(OT_S_AIRBLAST, "airblast", "Knocks enemies back with a powerful blast of air.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell's power determines how far objects or enemies will be knocked back."); @@ -2932,6 +2931,11 @@ void initobjects(void) { addflag(lastot->flags, F_STAMCOST, 5, NA, NA, NULL); addot(OT_A_REPAIR, "repair equipment", "Repair damage done to your equipment.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addot(OT_A_SONICBOLT, "sonic bolt", "Emit a damaging burst of sound, targetted at a particular location.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_STAMCOST, 1, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addot(OT_A_SPRINT, "sprint", "You can run at high speed over short distances.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); @@ -6757,12 +6761,12 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); // fish - addrace(R_CRAB, "giant crab", 250, ';', C_ORANGE, MT_FLESH, RC_AQUATIC); + addrace(R_CRAB, "giant crab", 150, ';', C_ORANGE, MT_FLESH, RC_AQUATIC); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 20, NA, NA, NULL); // very high armour - addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4+4"); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4+4"); addflag(lastrace->flags, F_MOVESPEED, SP_VERYSLOW, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_VERYSLOW, NA, NA, ""); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); @@ -6780,6 +6784,35 @@ void initrace(void) { addflag(lastrace->flags, F_NOARMOURON, BP_LEFTFINGER, NA, NA, NULL); addflag(lastrace->flags, F_NOARMOURON, BP_HANDS, NA, NA, NULL); addflag(lastrace->flags, F_NOARMOURON, BP_FEET, NA, NA, NULL); + + addrace(R_MERLOCH, "merloch", 250, 'm', C_ORANGE, MT_FLESH, RC_AQUATIC); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); + addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 15, NA, NA, NULL); // high armour + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4+4"); + addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, ""); + addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "2d3"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "2d3"); + addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_WAIST, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_LEGS, NA, NA, NULL); + addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SONICBOLT, 5, 5, "pw:5;dam:2d6;"); + addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "pincers"); + addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); + addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + 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_NOARMOURON, BP_RIGHTFINGER, NA, NA, NULL); + addflag(lastrace->flags, F_NOARMOURON, BP_LEFTFINGER, NA, NA, NULL); + addflag(lastrace->flags, F_NOARMOURON, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_NOARMOURON, BP_FEET, NA, NA, NULL); + addrace(R_PIRANHA, "piranha", 0.5, ';', C_GREEN, MT_FLESH, RC_AQUATIC); addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6957,6 +6990,29 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings"); + addrace(R_BATMUTATED, "mutated bat", 3, 'B', C_MAGENTA, MT_FLESH, RC_ANIMAL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); + addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, 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_SIZE, SZ_SMALL, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); + addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4+2"); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, NA, NA, "1d3"); + addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SONICBOLT, 5, 5, "pw:5;dam:1d6;"); + addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_HANDS, NA, NA, NULL); + addflag(lastrace->flags, F_NOBODYPART, BP_LEGS, NA, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings"); addrace(R_BATVAMPIRE, "vampire bat", 6, 'B', C_BLUE, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL); diff --git a/data/hiscores.db b/data/hiscores.db index 8a94411f2fa0bdf2b639bc3dfd595298d005d454..4bfa493add17295b74e017aa15fbbce7e1096ba9 100644 GIT binary patch delta 120 zcmZoLXfT){&6u-M<^?;m1Ji-Y>>Tw>Ob0d=S}?J)Ff%YZY(C0m&&e#zU_O~$M9syV z0R}7_*ccdv_1zhY@{@eZ3>7>|a})Cv!V`;%GV_bPGjnoMQxuXa6%rNF^YU|Y6f#Ql SN^%p6OHzyUHW!NYGXnq^Lm>MA delta 49 zcmZoLXfT){&6vGW<^?;mJ=4+2>>TwQ3+4_5#H diff --git a/defs.h b/defs.h index 48afba0..0dec63c 100644 --- a/defs.h +++ b/defs.h @@ -369,7 +369,7 @@ enum CASTTYPE { enum NOISECLASS { NC_NONE = 0, - NC_WALK = 1, + NC_MOVEMENT = 1, NC_SPEECH = 2, NC_OTHER = 3, }; @@ -678,9 +678,10 @@ enum DAMTYPE { DT_PETRIFY = 23, DT_POISON = 24, DT_NECROTIC = 25, - DT_NONE = 26, // for direclty dealt damage, not really any type + DT_SONIC = 26, + DT_NONE = 27, // for direclty dealt damage, not really any type }; -#define MAXDAMTYPE 27 +#define MAXDAMTYPE 28 // Object Classes enum OBCLASS { @@ -822,6 +823,7 @@ enum RACE { R_XAT, // fish R_CRAB, + R_MERLOCH, R_PIRANHA, R_PIRANHAKING, R_EELELEC, @@ -835,6 +837,7 @@ enum RACE { R_ANTS, R_ANTLION, R_BAT, + R_BATMUTATED, R_BATVAMPIRE, R_BEAR, R_BEARCUB, @@ -1126,6 +1129,7 @@ enum OBTYPE { OT_S_GUSTOFWIND, OT_S_MIST, OT_S_SHATTER, + OT_S_TAILWIND, OT_S_WINDSHIELD, // -- elemental - fire OT_S_BLADEBURN, @@ -1277,6 +1281,7 @@ enum OBTYPE { OT_A_PRAY, OT_A_RAGE, OT_A_REPAIR, + OT_A_SONICBOLT, OT_A_SPRINT, OT_A_STUDYSCROLL, OT_A_STINGACID, // need to define dam in f_canwill @@ -1641,9 +1646,10 @@ enum NOISETYPE { N_GETANGRY, N_WALK, N_FLY, - N_WARCRY, N_LOWHP, N_FRUSTRATED, + N_SONICBOLT, + N_WARCRY, }; enum LFSIZE { diff --git a/doc/add_damtype.txt b/doc/add_damtype.txt index 2bcd3f3..eb300a8 100644 --- a/doc/add_damtype.txt +++ b/doc/add_damtype.txt @@ -4,6 +4,10 @@ in defs.h: in objcets.c: update getdamname() - eg. you take 5 "electrical" damage update getdamnamenoun() - eg. you are immune to "electricity" + update wepdullable() to say whether dealing this damtype to an object + will dull a weapon. + ie. hitting a door with DT_CHOP won't damage the weapon + ie. hitting a door with DT_SLASH _will_ damage the weapon in attack.c update isphysicaldam() @@ -11,9 +15,5 @@ in attack.c update getattackverb if required update getkillverb if required - update attackob() to say whether dealing this damtype to an object - will dull a weapon. - ie. hitting a door with DT_CHOP won't damage the weapon - ie. hitting a door with DT_SLASH _will_ damage the weapon diff --git a/doc/glyphs.txt b/doc/glyphs.txt index d8ab5f0..428f28e 100644 --- a/doc/glyphs.txt +++ b/doc/glyphs.txt @@ -18,6 +18,7 @@ i = insect j = jelly/ooze/leech k = kobold G = large goblin +m = mutant n = small humanoid / nymph / sprite o = orc O = ogre diff --git a/io.c b/io.c index af47638..8f022f6 100644 --- a/io.c +++ b/io.c @@ -2343,6 +2343,23 @@ int confirm_badfeeling(object_t *o) { return B_FALSE; } +// returns true if the player wants to continue (or if there is no problem) +int confirm_injury_action(enum BODYPART bp, enum DAMTYPE dt, char *actionname) { + char ch; + char ques[BUFLEN]; + + if (lfhasflagval(player, F_INJURY, NA, bp, dt, NULL) && + willbleedfrom(player, bp)) { + snprintf(ques, BUFLEN, "Your %s injury will cause damage if you %s - continue?", + getinjuredbpname(bp), actionname); + ch = askchar(ques, "yn","n", B_TRUE); + if (ch == 'n') { + return B_FALSE; + } + } + return B_TRUE; +} + lifeform_t *askgod(char *prompttext) { lifeform_t *lf = NULL; int i; diff --git a/io.h b/io.h index a6b816e..441d4ba 100644 --- a/io.h +++ b/io.h @@ -17,6 +17,7 @@ int announceflagloss(lifeform_t *lf, flag_t *f); int announceobflaggain(object_t *o, flag_t *f); void announceobflagloss(object_t *o, flag_t *f); int confirm_badfeeling(object_t *o); +int confirm_injury_action(enum BODYPART bp, enum DAMTYPE dt, char *actionname); lifeform_t *askgod(char *prompt); object_t *askobject(obpile_t *op, char *title, int *count, long opts); object_t *askobjectwithflag(obpile_t *op, char *title, int *count, long opts, enum FLAG withflag); diff --git a/lf.c b/lf.c index e68e5fd..f661532 100644 --- a/lf.c +++ b/lf.c @@ -700,10 +700,12 @@ int canhear(lifeform_t *lf, cell_t *dest, int volume) { // can't hear if you have a hostile mosnter next to you // and you're not blind. // (you're too engrossed in the battle) + /* celldist = getcelldist(lf->cell, dest); if (isplayer(lf) && isinbattle(lf)) { if (celldist != 1) return B_FALSE; } + */ map = dest->map; @@ -8737,7 +8739,7 @@ void killlf(lifeform_t *lf) { int isdeaf(lifeform_t *lf) { if (lfhasflag(lf, F_DEAF)) return B_TRUE; if (lfhasflagval(lf, F_INJURY, IJ_EARSRINGING, NA, NA, NULL)) return B_TRUE; - return B_TRUE; + return B_FALSE; } // returns second weapon if you are dual weilding @@ -9375,6 +9377,11 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) { return; } + if ((damtype == DT_SONIC) && isdeaf(lf)) { + *amt = 0; + return; + } + if (lfhasflag(lf, F_INVULNERABLE)) { switch (damtype) { case DT_DIRECT: @@ -10480,7 +10487,7 @@ void makenoise(lifeform_t *lf, enum NOISETYPE nid) { if (nid == N_WALK) { volume += getarmournoise(lf); } - noise(lf->cell, lf, (nid == N_WALK) ? NC_WALK : NC_OTHER, volume, noisetext, verb); + noise(lf->cell, lf, noisetypetoclass(nid), volume, noisetext, verb); } else { // some defaults if (nid == N_WALK) { @@ -10523,8 +10530,10 @@ void makenoise(lifeform_t *lf, enum NOISETYPE nid) { } volume += getarmournoise(lf); if (strlen(movetext)) { - noise(lf->cell, lf, (nid == N_WALK) ? NC_WALK : NC_OTHER, volume, movetext, NULL); + noise(lf->cell, lf, noisetypetoclass(nid), volume, movetext, NULL); } + } else if (nid == N_SONICBOLT) { + noise(lf->cell, lf, NC_OTHER, 5, "a ear-splitting burst of sound!", "emits an ear-splitting burst of sound!"); } else if (nid == N_WARCRY) { noise(lf->cell, lf, NC_OTHER, 4, "a blood-curdling war cry!", "shouts a blood-curdling war-cry!"); } @@ -10832,7 +10841,7 @@ int needstorest(lifeform_t *lf, char *validchars) { } // returns TRUE if the player heard it. -int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, char *text, char *seetext) { +int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume, char *text, char *seetext) { lifeform_t *l; int sounddist; int rv = B_FALSE; @@ -10861,7 +10870,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha dist = getcelldist(l->cell, c); // listen check difficulty is based on sound distance vs max hearing distance - if ((nt == NC_SPEECH) && isplayer(l)) { + if ((nclass == NC_SPEECH) && isplayer(l)) { // you always hear it, as long as you're in range difficulty = 0; } else { @@ -10902,7 +10911,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha msg("%s %s.", lfname, realseetext); rv = B_TRUE; } - } else if (text && !isdeaf(l) && ((nt != NC_WALK) || !lfhasflag(l, F_DONELISTEN))) { + } else if (text && !isdeaf(l) && ((nclass != NC_MOVEMENT) || !lfhasflag(l, F_DONELISTEN))) { // this means you can only hear one 'walk' sound per turn char textnopunc[BUFLEN]; char punc; @@ -10991,7 +11000,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha rv = B_TRUE; } // can only hear one 'walk' sound per turn. - if (isplayer(l) && (nt == NC_WALK)) { + if (isplayer(l) && (nclass == NC_MOVEMENT)) { addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL); practice(l, SK_LISTEN, 1); } @@ -11076,6 +11085,17 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha } +enum NOISECLASS noisetypetoclass(enum NOISETYPE nt) { + switch (nt) { + case N_WALK: + case N_FLY: + return NC_MOVEMENT; + default: + break; + } + return NC_OTHER; +} + // give initial equiment / skills to a lifeform void outfitlf(lifeform_t *lf) { //int db = B_FALSE; @@ -12578,11 +12598,15 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r } } } else if (ct == SC_SLIP) { - if (getequippedob(lf->pack, BP_FEET)) { - othermod += 5; - } - if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { - othermod += 25; + if (lfhasflagval(lf, F_INJURY, IJ_LEGBROKEN, NA, NA, NULL)) { + othermod -= 25; + } else { + if (getequippedob(lf->pack, BP_FEET)) { + othermod += 5; + } + if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { + othermod += 25; + } } } else if (ct == SC_FALL) { if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { diff --git a/lf.h b/lf.h index 700ba50..b643ea1 100644 --- a/lf.h +++ b/lf.h @@ -305,6 +305,7 @@ float modifybystat(float num, lifeform_t *lf, enum ATTRIB att); void modstamina(lifeform_t *lf, float howmuch); int needstorest(lifeform_t *lf, char *validchars); int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, char *text, char *seetext); +enum NOISECLASS noisetypetoclass(enum NOISETYPE nt); void outfitlf(lifeform_t *lf); void petify(lifeform_t *lf, lifeform_t *owner); int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int antannounce); diff --git a/map.c b/map.c index 6dc50be..fa1ae15 100644 --- a/map.c +++ b/map.c @@ -3712,7 +3712,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int critchance = 100 - (mydist*40); if (pctchance(critchance)) { //criticalhit(NULL, cc->lf, getrandomcorebp(cc->lf), DT_EXPLOSION); - criticalhit(NULL, cc->lf, BP_HANDS, DT_EXPLOSIVE); + criticalhit(NULL, cc->lf, BP_HANDS, pctof(critchance, dam), DT_EXPLOSIVE); } // move away from centre of explosion diff --git a/move.c b/move.c index 687132c..cd5856a 100644 --- a/move.c +++ b/move.c @@ -185,6 +185,22 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err } return B_TRUE; } + if (o->type->id == OT_PENTAGRAM) { + // this is only dangerous for the player + if (isplayer(lf)) { + object_t *oo; + // any blessed objects in your pack? + for (oo = lf->pack->first ; oo ; oo = oo->next) { + if (oo->blessknown && isblessed(oo)) { + if (error) { + *error = E_AVOIDOB; + rdata = o; + } + return B_TRUE; + } + } + } + } f = hasflag(o->flags, F_PIT); if (f && (f->val[0] == D_DOWN)) { if (!isairborne(lf)) { @@ -684,7 +700,7 @@ int getwalkoffdir(lifeform_t *lf, int dir) { // use 'n/a' for zero chance of falling. 0 means 'calculate based on distance' int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff) { - int i; + int i,dam; char lfname[BUFLEN]; char newlfname[BUFLEN]; int seen; @@ -757,12 +773,13 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc } if (seen) msg("%s slam%s into %s!",lfname,isplayer(lf) ? "" : "s", thing); snprintf(buf, BUFLEN, "slamming into %s", thing); - losehp(lf, rnd(1,6), DT_BASH, pusher, buf); + dam = roll("1d6"); + losehp(lf, dam, DT_BASH, pusher, buf); // stop moving i = howfar; // don't fall mightfall = B_FALSE; - if (onein(3)) criticalhit(NULL, lf, getrandomcorebp(lf), DT_BASH); + if (onein(3)) criticalhit(NULL, lf, getrandomcorebp(lf), dam, DT_BASH); break; case E_SWIMMING: case E_LFINWAY: @@ -2231,6 +2248,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { cell = getcellindir(lf->cell, dir); + // warn if moving will cause injury + if (onpurpose && isplayer(lf)) { + if (!confirm_injury_action(BP_LEGS, DT_SLASH, "move")) { + return B_TRUE; + } + } + + // warn before moving onto dangerous cells if (onpurpose && isplayer(lf) && !lfhasflag(lf, F_SNEAK)) { if (cell && celldangerous(lf, cell, B_TRUE, &errcode)) { char ques[BUFLEN]; @@ -2248,7 +2273,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { if (ch != 'y') { return B_TRUE; } - } + } } moveok = B_FALSE; @@ -2298,6 +2323,8 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { // now move to new cell moveto(lf, cell, rndmove ? B_FALSE : onpurpose, dontclearmsg); + + // take some time if (onpurpose) { // strafing sideways/backwards takes longer if (strafe && !lfhasflag(lf, F_AWARENESS)) { @@ -2305,10 +2332,16 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { case RD_SIDEWAYS: howlong = pctof(125, howlong); break; case RD_BACKWARDS: howlong = pctof(150, howlong); break; case RD_FORWARDS: + if (hasactivespell(lf, OT_S_TAILWIND)) { + // faster + howlong = pctof(75, howlong); + } + break; default: break; } } + limit(&howlong, SP_GODLIKE, NA); taketime(lf, howlong); if (!rndmove && !strafe) setfacing(lf, dir); // face the way we moved } @@ -2818,5 +2851,3 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) { return B_TRUE; } - - diff --git a/objects.c b/objects.c index 22d43de..ec9c8b2 100644 --- a/objects.c +++ b/objects.c @@ -906,12 +906,16 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes wantdiffmat = MT_NOTHING; } - // chance of being a different material baesd on ob flags - if (wantdiffmat == MT_NOTHING) { - getflags(ot->flags, retflag, &nretflags, F_CANBEDIFFMAT, F_NONE); - for (i = 0; i < nretflags; i++) { - if (pctchance(retflag[i]->val[1])) { - wantdiffmat = retflag[i]->val[0]; break; + // chance of being a different material based on ob flags + if ((gamemode != GM_GAMESTARTED) && isplayer(where->owner)) { + // ...but not in player's initial starting equipment + } else { + if (wantdiffmat == MT_NOTHING) { + getflags(ot->flags, retflag, &nretflags, F_CANBEDIFFMAT, F_NONE); + for (i = 0; i < nretflags; i++) { + if (pctchance(retflag[i]->val[1])) { + wantdiffmat = retflag[i]->val[0]; break; + } } } } @@ -3524,6 +3528,7 @@ char *getdamname(enum DAMTYPE damtype) { case DT_POISONGAS: return "poison gas"; case DT_PROJECTILE: return "projectile"; case DT_SLASH: return "slashing"; + case DT_SONIC: return "sonic"; case DT_TOUCH: return "touch"; case DT_UNARMED: return "unarmed"; case DT_WATER: return "water"; @@ -3560,6 +3565,7 @@ char *getdamnamenoun(enum DAMTYPE damtype) { case DT_UNARMED: return "unarmed damage"; case DT_LIGHT: return "light damage"; case DT_CRUSH: return "crushing damage"; + case DT_SONIC: return "sonic damage"; case DT_FALL: return "damage from falling"; default: return "unknown"; } diff --git a/spell.c b/spell.c index f00471d..7050980 100644 --- a/spell.c +++ b/spell.c @@ -920,6 +920,27 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // TODO: make this like eating/resting/etc ? taketime(user, getactspeed(user)); + } else if (abilid == OT_A_SONICBOLT) { + int volume; + + if (!validatespellcell(user, &targcell,TT_MONSTER, abilid, power, B_FALSE)) return B_TRUE; + target = targcell->lf; + makenoise(user, N_SONICBOLT); + + // if target can hear, they take damage + f = hasflagval(user->flags, F_NOISETEXT, N_SONICBOLT, NA, NA, NULL); + if (f) { + volume = f->val[1]; + } else { + volume = power; + } + if (target && canhear(target, user->cell, volume)) { + if (isplayer(target)) { + msg("Pain shoots through your eardrums!"); + } + losehp(target, roll(damstr), DT_SONIC, user, "a bolt of sound"); + } + } else if (abilid == OT_A_SPRINT) { flag_t *f; if (lfhasflagval(user, F_INJURY, IJ_WINDPIPECRUSHED, NA, NA, NULL)) { @@ -7313,6 +7334,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { fizzle(caster); } + } else if (spellid == OT_S_TAILWIND) { + if (!target) target = caster; + if (isplayer(target)) { + msg("A strong wind propels you forwards!"); + } else if (cansee(player, target)) { + char targname[BUFLEN]; + getlfname(target, targname); + msg("A strong wind propels %s forwards!", targname); + } } else if (spellid == OT_S_TELEPORT) { cell_t *c = NULL; lifeform_t *ally[8]; @@ -9372,25 +9402,25 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, e if (isplayer(caster)) { char buf[BUFLEN]; char buf2[BUFLEN]; - objecttype_t *ot; - ot = findot(spellid); if (maxrange == UNLIMITED) { - snprintf(buf, BUFLEN, "Where will you target your %s?", ot->name); + snprintf(buf, BUFLEN, "Where will you target your %s?", sp->name); } else { - snprintf(buf, BUFLEN, "Where will you target your %s [max range %d]?",ot->name, maxrange); + snprintf(buf, BUFLEN, "Where will you target your %s [max range %d]?",sp->name, maxrange); } - snprintf(buf2, BUFLEN, "%s->",ot->name); + snprintf(buf2, BUFLEN, "%s->",sp->name); where = askcoords(buf, buf2, targtype, caster, maxrange, needlof, needlof ? B_TRUE : B_FALSE); if (!where) { + char ques[BUFLEN]; int ch; - ch = askchar("Abandon your spell?","yn","n", B_TRUE); + snprintf(ques, BUFLEN, "Abandon your %s?", (sp->obclass->id == OC_SPELL) ? "spell" : "ability"); + ch = askchar(ques,"yn","n", B_TRUE); if (ch == 'y') { return NULL; } } } else { // TODO: fill in monster code? - fizzle(caster); + if (sp->obclass->id == OC_SPELL) fizzle(caster); return NULL; } }