diff --git a/data.c b/data.c index fdacfc4..08bca76 100644 --- a/data.c +++ b/data.c @@ -540,21 +540,20 @@ void initjobs(void) { addflag(lastjob->flags, F_CANWILL, OT_A_FEIGNDEATH, NA, NA, NULL); addflag(lastjob->flags, F_MAXATTACKS, 1, 1, NA, NULL); // this will go up later // gained abilities - // somewhere: slow falling when next to walls - // somehwere: alertness when sleeping addflag(lastjob->flags, F_LEVSKILL, 2, SK_SS_MENTAL, NA, NULL); addflag(lastjob->flags, F_LEVFLAG, 2, F_MPDICE, 1, NULL); - // 2: body control - low metabolism + addflag(lastjob->flags, F_LEVFLAG, 3, F_DTIMMUNE, DT_FALL, NULL); addflag(lastjob->flags, F_LEVSPELL, 3, OT_S_LOWERMETAB, NA, NULL); // 4: self-healing (mp), immune to haste/slow (innate) addflag(lastjob->flags, F_LEVABIL, 4, OT_A_FLURRY, NA, "pw:1;"); + addflag(lastjob->flags, F_LEVFLAG, 4, F_MEDITATES, B_TRUE, NULL); addflag(lastjob->flags, F_LEVFLAG, 5, F_DISEASEIMMUNE, B_TRUE, NULL); // 6: waterawlk via 'body equilibrium' (innate) addflag(lastjob->flags, F_LEVABIL, 6, OT_A_AIMEDSTRIKE, NA, NULL); addflag(lastjob->flags, F_LEVABIL, 7, OT_A_IRONFIST, NA, NULL); // 8: molecular manipulation (ie. lower hardness of physical obs by level-7, not lfs) (innate) addflag(lastjob->flags, F_LEVFLAG, 8, F_TREMORSENSE, NA, NULL); - // 9: resistance to charm, hypnosis, sleep (innate) + addflag(lastjob->flags, F_LEVFLAG, 9, F_NOCHARM, B_TRUE, NULL); addflag(lastjob->flags, F_LEVFLAG, 10, F_DTIMMUNE, DT_POISON, NULL); addflag(lastjob->flags, F_LEVSPELL, 11, OT_S_PSYARMOUR, NA, NULL); // 12: quivering palm (v.high mp cost OR once every 200 turns or so) @@ -2033,6 +2032,11 @@ void initobjects(void) { addflag(lastmaterial->flags, F_HARDNESS, 2, NA, NA, NULL); addflag(lastmaterial->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastmaterial->flags, F_DTVULN, DT_COLD, NA, NA, NULL); + addmaterial(MT_BRICK, "brick", 14); + addflag(lastmaterial->flags, F_HARDNESS, 4, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); + addflag(lastmaterial->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); addmaterial(MT_GOLD, "gold", 16); addflag(lastmaterial->flags, F_HARDNESS, 3, NA, NA, NULL); addmaterial(MT_DURANITE, "duranite", 20); @@ -2971,6 +2975,16 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_MISSILEDAM, NA, NA, NA, "1"); + addot(OT_BRICK, "brick", "A heavy brick.", MT_STONE, 3, OC_ROCK, SZ_TINY); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, ""); + addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_RARE, NULL); + addflag(lastot->flags, F_RARITY, H_FOREST, NA, RR_RARE, ""); + addflag(lastot->flags, F_NUMAPPEAR, 1, 5, NA, ""); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_MISSILEDAM, NA, NA, NA, "3"); // gems addot(OT_AQUAMARINE, "aquamarine stone", "An aqua-coloured gemstone.", MT_STONE, 0.2, OC_ROCK, SZ_TINY); @@ -4106,10 +4120,10 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); // l3 - addot(OT_S_AWARENESS, "heightened awareness", "This spell effectively gives the caster \"eyes in the back of their head\", expending their field of vision to a full 360 degrees.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_DETECTAURA, "detect aura", "Senses holiness or evil near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); - addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addot(OT_S_DETECTOBS, "detect objects", "Senses objects near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the detection range and spell duration."); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); @@ -4121,10 +4135,11 @@ void initobjects(void) { addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); // l4 - addot(OT_S_DETECTAURA, "detect aura", "Senses holiness or evil near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_AWARENESS, "heightened awareness", "This spell effectively gives the caster \"eyes in the back of their head\", expending their field of vision to a full 360 degrees.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); + addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); - addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addot(OT_S_LORE, "lore", "Obtain knowledge about any one species.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, 1, NA, NA, "At power I, you gain Novice level knowledge."); addflag(lastot->flags, F_EXTRADESC, 2, NA, NA, "At power II, you gain Beginner level knowledge."); @@ -5032,15 +5047,28 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_NONE, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - // l2 - addot(OT_S_ANTICIPATE, "anticipate action", "Allows the caster to automatically dodge the target's attacks.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power detemines the number of attacks dodged."); + addot(OT_S_LETHARGY, "lethargy", "Reduces the target's stamina by ^bpower^n*2.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); - addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL); - addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addot(OT_S_LOWERMETAB, "lower metabolism", "Slow your body's functions, decreasing your rate of hunger but also your movement speed.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level III: your speed penalty is reduced."); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level V: you no longer suffer a speed penalty."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + // l2 + addot(OT_S_PRECOGNITION, "precognition", "Grants the caster the ability to see a very small distance into the future, aiding evasion.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Caster gains +5 EV."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, 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_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addot(OT_S_DISORIENT, "disorient", "Spins the target around to face away from the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); @@ -5048,12 +5076,20 @@ void initobjects(void) { addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addot(OT_S_LOWERMETAB, "lower metabolism", "Slow your body's functions, decreasing your rate of hunger but also your movement speed.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level III: your speed penalty is reduced."); - addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level V: you no longer suffer a speed penalty."); + addot(OT_S_KNOWWEAKNESS, "know weakness", "Attunes the caster's mind to other peoples' weaknesses, granting a +2 damage bonus.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, 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_AICASTTOATTACK, ST_SELF, NA, NA, NULL); + addot(OT_S_MINDWHIP, "mind whip", "Directly assault a nearby target's brain, dealing 2-6 damage to intelligent creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell only functions on creatures of 'Low' or higher intelligence."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, 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_RANGE, 3, NA, NA, NULL); + addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_S_TELEKINESIS, "telekinesis", "Mentally move or manipulate nearby objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell can lift up to 10kg per power level."); @@ -5061,13 +5097,6 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL); - addot(OT_S_LETHARGY, "lethargy", "Reduces the target's stamina by ^bpower^n*2.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); - addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); - addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); - addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); - addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_S_PSYSHOVE, "psychic shove", "Telekinetically pushes against the target. Depending on relative weight, either the target or the caster will fly away.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Note: the push is not powerful enough to cause direct damage."); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); @@ -5079,7 +5108,15 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l3 - addot(OT_S_PSIBLAST, "psionic blast", "Assaults the target's brain with a mental feedback loop, dealing damage based on their intelligence.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_ANTICIPATE, "anticipate action", "Allows the caster to automatically dodge the target's attacks.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power detemines the number of attacks dodged."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_S_MFEEDBACK, "mental feedback", "Assaults the target's brain with a mental feedback loop, dealing damage based on their intelligence.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Creatures with higher intelligence will take more damage."); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); @@ -5087,6 +5124,12 @@ void initobjects(void) { addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, 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_PSIBLAST, "psionic blast", "Stuns all nearby living creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Creatures are stunned for ^bpower^n+4 turns."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); addot(OT_S_PSYARMOUR, "psychic armour", "Mentally block incoming attacks.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The psychic armour's Armour Rating is ^bpower*4^n."); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); @@ -5124,11 +5167,18 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - addot(OT_S_STUNMASS, "mass stun", "Stuns all creatures within sight.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_SLEEPMASS, "mass sleep", "Stuns all creatures within sight.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); - addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); + addot(OT_S_STASIS, "stasis", "Freezes time inside your body, preventing many effects such as poison, hunger, and even breathing.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Note that health regeneration is also prevented while in stasis."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l5 addot(OT_S_CHARM, "charm", "Causes another lifeform to temporary become friendly.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration."); @@ -9927,7 +9977,7 @@ void initrace(void) { setbodypartname(lastrace, BP_RIGHTFINGER, "right sensor"); setbodypartname(lastrace, BP_LEFTFINGER, "left sensor"); addflag(lastrace->flags, F_NAME, NA, NA, NA, "Clank"); - addflag(lastrace->flags, F_UNIQUE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_UNIQUE, 33, BH_MAINDUNGEON, 1, "4-8"); addflag(lastrace->flags, F_HOSTILE, NA, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL); @@ -15143,7 +15193,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTSKILL, SK_FLIGHT, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_CANCAST, OT_S_STUN, 3, 3, "pw:3;"); addflag(lastrace->flags, F_CANCAST, OT_S_DISORIENT, 3, 3, "pw:3;"); - addflag(lastrace->flags, F_CANCAST, OT_S_PSIBLAST, 3, 3, "pw:1;"); + addflag(lastrace->flags, F_CANCAST, OT_S_MFEEDBACK, 3, 3, "pw:1;"); 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); @@ -19515,8 +19565,9 @@ void initskills(void) { addskilldesc(SK_ENGINEERING, PR_BEGINNER, "You can now detect hollow spaces.", B_TRUE); addskilldesc(SK_ENGINEERING, PR_BEGINNER, "You can now identify trap types.", B_TRUE); addskilldesc(SK_ENGINEERING, PR_ADEPT, "You can now create barricades and basic traps.", B_TRUE); - addskilldesc(SK_ENGINEERING, PR_ADEPT, "You can now dismantle doors as well as obstacles.", B_TRUE); + addskilldesc(SK_ENGINEERING, PR_ADEPT, "You can now dismantle doors and made-made walls.", B_TRUE); addskilldesc(SK_ENGINEERING, PR_SKILLED, "You now automatically detect traps.", B_TRUE); + addskilldesc(SK_ENGINEERING, PR_SKILLED, "Your speed at dismantling walls is doubled.", B_TRUE); addskilldesc(SK_ENGINEERING, PR_EXPERT, "You can now create advanced traps.", B_TRUE); addskilldesc(SK_ENGINEERING, PR_MASTER, "You are now immune to most trap effects.", B_TRUE); addskill(SK_THROWING, "Throwing", "Your accuracy when throwing objects at things.", 50); diff --git a/defs.h b/defs.h index 610130b..bcb6d43 100644 --- a/defs.h +++ b/defs.h @@ -393,6 +393,17 @@ #define MAXDIR_MAP 15 +enum CONTAINERCONTENTS { + CC_AMMO, + CC_FOOD, + CC_FOODDRINK, + CC_GUNPOWDER, + CC_CONDIMENTS, + CC_CORPSE, + CC_WATER, + +}; + enum CELLCONDITION { CC_NONE, // @@ -1507,6 +1518,7 @@ enum MATERIAL { MT_DIRT = 30, MT_CRYSTAL = 31, MT_DURANITE = 32, + MT_BRICK = 33, }; // Object Types @@ -1582,13 +1594,14 @@ enum OBTYPE { OT_TRAPTRIP, OT_TRAPWIND, // rocks - OT_STONE, OT_ASH, OT_ASHEXPLODE, OT_ASHCONCEAL, OT_ASHINVIS, OT_ASHSLEEP, + OT_BRICK, OT_GEMOFSEEING, + OT_STONE, // gems OT_AQUAMARINE, OT_AMETHYST, @@ -1870,15 +1883,20 @@ enum OBTYPE { OT_S_HUNGER, OT_S_LETHARGY, OT_S_LOWERMETAB, + OT_S_KNOWWEAKNESS, + OT_S_MFEEDBACK, OT_S_MINDSCAN, + OT_S_MINDWHIP, OT_S_MIRRORIMAGE, OT_S_PACIFY, + OT_S_PRECOGNITION, OT_S_PSIBLAST, OT_S_PSYARMOUR, OT_S_PSYSHOVE, OT_S_SLEEP, + OT_S_SLEEPMASS, + OT_S_STASIS, OT_S_STUN, - OT_S_STUNMASS, OT_S_TELEKINESIS, OT_S_VENTRILOQUISM, // nature / enviromancy @@ -2893,6 +2911,8 @@ enum FLAG { F_HELPSCLIMB, // object gives v0 bonus to sc_climb checks. F_HELPSDIG, // object can dig. does v0 dam to cells. // also makes noise 'text' at volume v1 + F_DIGCELLTYPE, // object can dig through this celltype + F_DIGCELLMAT, // object can dig through cells of this material F_HELPSDISARM, // object gives v0 bonus to disarm trap checks. F_HELPSREPAIR, // object gives v1 bonus to repairing obejcts // made of material v0. Also decreases the @@ -3437,6 +3457,9 @@ enum FLAG { // it will be specially handled. F_CONTAINER, // this object is a container - you can use 'o' // to take stuff out or put it in. + F_CONTENTS, // v0 = enum CONTAINERCONTENTS for this container + // when object is generated, a random F_CONTENTS + // flag will be chosen. F_HOLDING, // this container is a xxx of holding and makes objects // inside become weightless F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid @@ -3887,6 +3910,9 @@ enum FLAG { // this lf does 'text' extra damage of damtype v0 // if v1 is TRUE, also deal extra damage based on // the flagpile's F_BONUS flag. + // + // if v0 is NA, damage is added to initial damage + // roll. F_EXTRADAMWITHCHARGES, // if this objects has charges remaining, // deal an extra "text" damage of type v0. F_EXTRAINFO, // knows extra info @@ -3996,6 +4022,7 @@ enum FLAG { // (but not for obs in pack) // if val2 is true, will only make light if ob // is activated! + F_STASIS, // many startlfturn effects don't happen. F_SLOWACT, // modifier for action speed F_SLOWMETAB, // hunger counter increases slower, poison cures slower. // v0 is multiplier @@ -4326,6 +4353,7 @@ enum ERROR { E_CLIMBING, E_DANGEROUS, E_INJURED, + E_STASIS, }; diff --git a/io.c b/io.c index 836f718..244ae07 100644 --- a/io.c +++ b/io.c @@ -1201,6 +1201,7 @@ cell_t *real_askcoords(char *prompt, char *subprompt, int targettype, lifeform_t return NULL; } +// returns a direction char askdir(char *prompt, int maycancel, int usedrunk) { int dirch,dir = D_NONE; dirch = askchar(prompt, "yuhjklbn.-","-", B_FALSE, maycancel); @@ -2100,6 +2101,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { msg("%s %s sprinting!",lfname, isplayer(lf) ? "start" : "starts"); donesomething = B_TRUE; break; + case F_STASIS: + if (isplayer(lf)) { // don't know if monsters get it + msg("Time within you warps and slows down!"); + donesomething = B_TRUE; + } + break; case F_STAMBOOST: if (isplayer(lf)) { msg("^gYour stamina feels boosted!"); @@ -2874,6 +2881,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_STASIS: + if (isplayer(lf)) { + msg("Time within you returns to normal."); + donesomething = B_TRUE; + } + break; case F_STAMBOOST: if (isplayer(lf)) { msg("Your stamina no longer feels boosted."); @@ -14050,6 +14063,12 @@ void showlfstats(lifeform_t *lf, int showall) { y++; } + f = hasflag_real(lf->flags, F_STASIS, B_TRUE, NULL, FROMRACE); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "Time within your body has been frozen.", you(lf)); + y++; + } + f = hasflag_real(lf->flags, F_STAMBOOST, B_TRUE, NULL, FROMRACE); if (f && (f->known)) { mvwprintw(mainwin, y, 0, "%s stamina is currently being boosted.", your(lf)); diff --git a/lf.c b/lf.c index 290ffea..b540737 100644 --- a/lf.c +++ b/lf.c @@ -2642,6 +2642,9 @@ int check_rest_ok(lifeform_t *lf) { case E_MONSTERNEARBY: msg("You cannot rest - there are monsters in view!"); break; + case E_STASIS: + msg("You cannot rest while your body is in stasis."); + break; default: msg("You cannot rest for some reason."); break; @@ -2766,28 +2769,41 @@ int continuedigging(lifeform_t *lf) { if (digob) makeopersound(lf->cell,digob); digpower = f->val[2]; + + if (getskill(lf, SK_ENGINEERING) >= PR_SKILLED) { + digpower *= 2; + } + c->hp -= digpower; if (c->hp <= 0) { if (isplayer(lf)) { - msg("You finish digging through %s %s.",needan(c->type->name) ? "an" : "a", c->type->name); + msg("You finish %s %s %s.",digob ? "digging through" : "dismantling", + needan(c->type->name) ? "an" : "a", c->type->name); needredraw = B_TRUE; } else if (cansee(player, lf)) { char lfname[BUFLEN]; getlfname(lf, lfname); - msg("%s finishes digging through %s %s.",lfname,needan(c->type->name) ? "an" : "a", c->type->name); + msg("%s finishes %s %s %s.",lfname, + digob ? "digging through" : "dismantling", + needan(c->type->name) ? "an" : "a", c->type->name); needredraw = B_TRUE; } // replace wall - setcelltype(c, c->map->habitat->emptycelltype); + //setcelltype(c, c->map->habitat->emptycelltype); + breakwall(c, NULL); // stop digging killflag(f); } else { if (isplayer(lf)) { - msg("You dig into %s %s.",needan(c->type->name) ? "an" : "a", c->type->name); + msg("You %s into %s %s.", + digob ? "dig into" : "continue dismantling", + needan(c->type->name) ? "an" : "a", c->type->name); } else if (cansee(player, lf)) { char lfname[BUFLEN]; getlfname(lf, lfname); - msg("%s digs into %s %s.",lfname,needan(c->type->name) ? "an" : "a", c->type->name); + msg("%s %s %s %s.",lfname, + digob ? "digs into" : "continues dismantling", + needan(c->type->name) ? "an" : "a", c->type->name); } } return B_FALSE; @@ -4356,25 +4372,29 @@ void dumpxp(void) { } } -int digcell(lifeform_t *lf, cell_t *c, object_t *o) { +// pass o OR ot, not both. +int digcell(lifeform_t *lf, cell_t *c, object_t *o, int dismantle) { char obname[BUFLEN]; flag_t *f; int digpower = 1; - getobname(o, obname, 1); - f = hasflag(o->flags, F_HELPSDIG); - if (f) { - digpower = f->val[0]; - } - if (!c) { return B_TRUE; } + if (o) { + f = hasflag(o->flags, F_HELPSDIG); + if (f) { + digpower = f->val[0]; + } + getobname(o, obname, 1); + } + + if (c->type->solid) { turntoface(lf, c); - if (isdiggable(c)) { + if (isdiggable(c, dismantle ? OT_A_DISMANTLE : o->type->id)) { char digoid[BUFLEN]; // start digging! - if (o) { + if (o && !dismantle) { sprintf(digoid, "%ld",o->id); } else { strcpy(digoid,""); @@ -4383,20 +4403,31 @@ int digcell(lifeform_t *lf, cell_t *c, object_t *o) { addflag(lf->flags, F_DIGGING, c->x, c->y, digpower, digoid); if (isplayer(lf)) { - msg("You start digging into %s %s.", needan(c->type->name) ? "an" : "a", c->type->name); + if (dismantle) { + msg("You start dismantling %s %s.", needan(c->type->name) ? "an" : "a", c->type->name); + } else { + msg("You start digging into %s %s.", needan(c->type->name) ? "an" : "a", c->type->name); + } needredraw = B_TRUE; } else if (cansee(player, lf)) { char lfname[BUFLEN]; getlfname(lf, lfname); - msg("%s starts digging into %s %s.", lfname, needan(c->type->name) ? "an" : "a", c->type->name); + msg("%s starts %s %s %s.", lfname, + dismantle ? "dismantling" : "digging into", + needan(c->type->name) ? "an" : "a", c->type->name); needredraw = B_TRUE; } taketime(lf, getactspeed(lf)); } else { // fail if (isplayer(lf)) { - msg("This wall is too hard to dig."); + if (dismantle) { + msg("You can only dismantle man-made walls."); + } else { + msg("This wall is too hard to dig."); + } } + return B_TRUE; } } else { // not solid int failed = B_FALSE; @@ -19402,6 +19433,11 @@ int safetorest(lifeform_t *lf) { lifeform_t *l; reason = E_OK; + if (lfhasflag(lf, F_STASIS)) { + reason = E_STASIS; + return B_FALSE; + } + for (l = lf->cell->map->lf ; l ; l = l->next) { if ((l != lf) && (areenemies(lf, l) || !isknownpeaceful(l) ) && !lfhasflag(l, F_HARMLESS) && !lfhasflag(l, F_FEIGNINGDEATH)) { @@ -21604,7 +21640,7 @@ void startlfturn(lifeform_t *lf) { enum ERROR error; object_t *o,*nexto; flag_t *f; - flag_t *asp, *sf; + flag_t *asp, *sf,*stasis = NULL; char buf[BUFLEN]; lifeform_t *l; int i; @@ -21625,6 +21661,8 @@ void startlfturn(lifeform_t *lf) { // debugging lf->redraws = 0; + stasis = lfhasflag(lf, F_STASIS); + // more debug if (isplayer(lf)) { if ((gamemode == GM_GAMESTARTED) && (getalignment(lf) != playerorigalignment)) { @@ -21765,39 +21803,42 @@ void startlfturn(lifeform_t *lf) { } - // drown? - o = hasobwithflag(lf->cell->obpile, F_DEEPWATER); - if (o) { - if (checkfordrowning(lf, o)) { - if (isdead(lf)) return; + if (!stasis) { + // drown? + o = hasobwithflag(lf->cell->obpile, F_DEEPWATER); + if (o) { + if (checkfordrowning(lf, o)) { + if (isdead(lf)) return; + } + // fixes stench + killtransitoryflags(lf->flags, F_STENCH); + } else { + // amulet of swimming? + if (hasequippedobid(lf->pack, OT_AMU_SWIMMING) && (lf->race->id == R_SWAN) && ispolymorphed(lf)) { + // revert to normal form + abilityeffects(lf, OT_A_POLYREVERT, lf->cell, lf, NULL); + } } - // fixes stench - killtransitoryflags(lf->flags, F_STENCH); - } else { - // amulet of swimming? - if (hasequippedobid(lf->pack, OT_AMU_SWIMMING) && (lf->race->id == R_SWAN) && ispolymorphed(lf)) { - // revert to normal form - abilityeffects(lf, OT_A_POLYREVERT, lf->cell, lf, NULL); + + // suffocate? + if (needstobreath(lf)) { + if (lfhasflag(lf, F_NEEDSWATER) && !hasobwithflag(lf->cell->obpile, F_DEEPWATER)) { + int dam; + if (isplayer(lf)) { + msg("^BYou are suffocating without water to breath!"); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("^%c%s is suffocating!", getlfcol(lf, CC_VBAD), lfname); + } + dam = lf->maxhp / 3; + limit(&dam, 1, NA); + losehp(lf, dam, DT_DIRECT, NULL, "suffocation"); + if (isdead(lf)) return; + } } } - // suffocate? - if (needstobreath(lf)) { - if (lfhasflag(lf, F_NEEDSWATER) && !hasobwithflag(lf->cell->obpile, F_DEEPWATER)) { - int dam; - if (isplayer(lf)) { - msg("^BYou are suffocating without water to breath!"); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("^%c%s is suffocating!", getlfcol(lf, CC_VBAD), lfname); - } - dam = lf->maxhp / 3; - limit(&dam, 1, NA); - losehp(lf, dam, DT_DIRECT, NULL, "suffocation"); - if (isdead(lf)) return; - } - } // vampire in sunlight? if ((lf->race->id == R_VAMPIRE) && isoutdoors(lf->cell->map) && !isnighttime()) { if (isplayer(lf)) { @@ -21846,7 +21887,7 @@ void startlfturn(lifeform_t *lf) { } // oooooo replace with f_bleeding ? - if (lfhasflagval(lf, F_INJURY, IJ_ARTERYPIERCE, NA, NA, NULL)) { + if (!stasis && lfhasflagval(lf, F_INJURY, IJ_ARTERYPIERCE, NA, NA, NULL)) { if (!bleedfrom(lf, BP_HANDS, B_SPLATTER)) { if (isplayer(lf)) msg("^BYou bleed!"); losehp(lf, rnd(2,8), DT_DIRECT, NULL, "blood loss"); @@ -21854,37 +21895,38 @@ void startlfturn(lifeform_t *lf) { } // get more hungry - modhunger(lf, 1); + if (!stasis) { + modhunger(lf, 1); - // regeneration - sumflags(lf->flags, F_REGENERATES, &i, NULL, NULL); - if ((tp == TP_TWILIGHTMORN) || (tp == TP_SUNRISE)) { - if (isplayer(lf) && godprayedto(R_GODLIFE)) { - i += 1; + // regeneration + sumflags(lf->flags, F_REGENERATES, &i, NULL, NULL); + if ((tp == TP_TWILIGHTMORN) || (tp == TP_SUNRISE)) { + if (isplayer(lf) && godprayedto(R_GODLIFE)) { + i += 1; + } } - } - if (i > 0) { - // heal hp - gainhp(lf, i); - } - - // MP regeneration - getflags(lf->flags, retflag, &nretflags, F_MPREGEN, F_NONE); - for (i = 0; i < nretflags; i++) { - f = retflag[i]; - if (f->id == F_MPREGEN) { - gainmp(lf, f->val[0]); + if (i > 0) { + // heal hp + gainhp(lf, i); } - } + // MP regeneration + getflags(lf->flags, retflag, &nretflags, F_MPREGEN, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if (f->id == F_MPREGEN) { + gainmp(lf, f->val[0]); + } + } - // druid gains mp from plants - if (hasjob(lf, J_DRUID)) { - int chance = 0; - // 5% per plant in sight of gaining mp - chance = countplantsinsight(lf) * 5; - if (pctchance(chance)) { - gainmp(lf, 1); + // druid gains mp from plants + if (hasjob(lf, J_DRUID)) { + int chance = 0; + // 5% per plant in sight of gaining mp + chance = countplantsinsight(lf) * 5; + if (pctchance(chance)) { + gainmp(lf, 1); + } } } @@ -21920,10 +21962,12 @@ void startlfturn(lifeform_t *lf) { } if (lossamt) modstamina(lf, -lossamt); } else { - // if we didn't take action last turn, regenerate stamina. - if (!killflagsofid(lf->flags, F_TOOKACTION) && !lfhasflag(lf, F_TRAINING)) { - if (getstamina(lf) < getmaxstamina(lf)) { - modstamina(lf, getstamregen(lf)); + if (!stasis) { + // if we didn't take action last turn, regenerate stamina. + if (!killflagsofid(lf->flags, F_TOOKACTION) && !lfhasflag(lf, F_TRAINING)) { + if (getstamina(lf) < getmaxstamina(lf)) { + modstamina(lf, getstamregen(lf)); + } } } } @@ -22245,51 +22289,53 @@ void startlfturn(lifeform_t *lf) { } } - // handle life objects - f = lfhasflag(lf, F_LIFEOB); - if (f) { - cell_t *corpseloc = NULL; - object_t *corpse; - char corpsename[BUFLEN]; + if (!stasis) { + // handle life objects + f = lfhasflag(lf, F_LIFEOB); + if (f) { + cell_t *corpseloc = NULL; + object_t *corpse; + char corpsename[BUFLEN]; - corpseloc = findnearbylifeob(lf->cell, NA, f, &corpse); - if (corpse) { - // did we find a corpse in range ? - if (corpse->type->id == OT_CORPSE) { - strcpy(corpsename, "corpse"); - } else { - strcpy(corpsename, corpse->type->name); - } - if (lf->race->id == R_GHOST) { - // give possession ability - if (isplayer(lf) && !lfhasflagval(lf, F_CANWILL, OT_S_POSSESSION, NA, NA, NULL)) { - flag_t *f2; - char pwbuf[BUFLEN]; - int power; - power = lf->level / 3; - if (power < 1) power = 1; - if (power > 10) power = 10; - snprintf(pwbuf, BUFLEN, "pw:%d;",power); - f2 = addflag(lf->flags, F_CANWILL, OT_S_POSSESSION, NA, NA, pwbuf); - f2->lifetime = FROMRACE; + corpseloc = findnearbylifeob(lf->cell, NA, f, &corpse); + if (corpse) { + // did we find a corpse in range ? + if (corpse->type->id == OT_CORPSE) { + strcpy(corpsename, "corpse"); + } else { + strcpy(corpsename, corpse->type->name); } + if (lf->race->id == R_GHOST) { + // give possession ability + if (isplayer(lf) && !lfhasflagval(lf, F_CANWILL, OT_S_POSSESSION, NA, NA, NULL)) { + flag_t *f2; + char pwbuf[BUFLEN]; + int power; + power = lf->level / 3; + if (power < 1) power = 1; + if (power > 10) power = 10; + snprintf(pwbuf, BUFLEN, "pw:%d;",power); + f2 = addflag(lf->flags, F_CANWILL, OT_S_POSSESSION, NA, NA, pwbuf); + f2->lifetime = FROMRACE; + } + } + } else { + // can't see corpse + if (lf->race->id == R_GHOST) { + flag_t *f2; + f2 = lfhasflagval(lf, F_CANWILL, OT_S_POSSESSION, NA, NA, NULL); + if (f2) killflag(f2); + } + // drain life + if (isplayer(lf)) { + msg("^BWithout your %s, you feel yourself fading into nothingness.", corpsename); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s seems to be fading from view!", lfname); + } + losehp(lf, f->val[2], DT_DIRECT, NULL, "fading into nothingness"); } - } else { - // can't see corpse - if (lf->race->id == R_GHOST) { - flag_t *f2; - f2 = lfhasflagval(lf, F_CANWILL, OT_S_POSSESSION, NA, NA, NULL); - if (f2) killflag(f2); - } - // drain life - if (isplayer(lf)) { - msg("^BWithout your %s, you feel yourself fading into nothingness.", corpsename); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s seems to be fading from view!", lfname); - } - losehp(lf, f->val[2], DT_DIRECT, NULL, "fading into nothingness"); } } @@ -22549,206 +22595,207 @@ void startlfturn(lifeform_t *lf) { } } - getflags(lf->flags, retflag, &nretflags, F_POISONED, F_NONE); - for (i = 0; i < nretflags; i++) { - poisontype_t *pt; - f = retflag[i]; - pt = findpoisontype(f->val[0]); - // chance of fighting it off - gets easier over time. - // - if ((f->lifetime > 0) && skillcheck(lf, SC_POISON, (f->lifetime * 20), -(f->val[1]*10) )) { - killflag(f); - } else { - flag_t *asleep; - int chance; - int ko; - // being asleep helps. - asleep = hasflag(lf->flags, F_ASLEEP); - ko = isunconscious(lf); - // chance of losing hp - chance = pt->dampct; - if (f->val[1] > 1) { - //+10% chance per power > 1 - chance = pctof(100 + ((f->val[1] - 1)*10), chance); - } - - if (!ko && pctchance(chance)) { - char buf[BUFLEN]; - if (isplayer(lf) || cansee(player, lf)) { - char *p; - char lfname[BUFLEN],lfnameposs[BUFLEN]; - getlfname(lf, lfname); - sprintf(lfnameposs, "%s%s",lfname, getpossessive(lfname)); - - p = strdup(pt->damverb); - if (isplayer(lf)) { - strrep(&p, "YOUR", "Your", NULL); - if (asleep) { - strrep(&p, "YOU", "You wake up and", NULL); - } else { - strrep(&p, "YOU", "You", NULL); - } - strrep(&p, "#S", "", NULL); - } else { - strrep(&p, "YOUR", lfnameposs, NULL); - if (asleep) { - char replacetext[BUFLEN]; - sprintf(replacetext, "%s wakes and", lfname); - strrep(&p, "YOU", replacetext, NULL); - } else { - strrep(&p, "YOU", lfname, NULL); - } - strrep(&p, "#S", "s", NULL); - } - - msg("%s", p); - free(p); - - if (asleep) { - int origborn; - origborn = lf->born; - lf->born = B_FALSE; // supress a second announcement of waking up - killflagsofid(lf->flags, F_ASLEEP); - lf->born = origborn; - } else { - taketime(lf, getactspeed(lf)); - } + if (!stasis) { + getflags(lf->flags, retflag, &nretflags, F_POISONED, F_NONE); + for (i = 0; i < nretflags; i++) { + poisontype_t *pt; + f = retflag[i]; + pt = findpoisontype(f->val[0]); + // chance of fighting it off - gets easier over time. + // + if ((f->lifetime > 0) && skillcheck(lf, SC_POISON, (f->lifetime * 20), -(f->val[1]*10) )) { + killflag(f); + } else { + flag_t *asleep; + int chance; + int ko; + // being asleep helps. + asleep = hasflag(lf->flags, F_ASLEEP); + ko = isunconscious(lf); + // chance of losing hp + chance = pt->dampct; + if (f->val[1] > 1) { + //+10% chance per power > 1 + chance = pctof(100 + ((f->val[1] - 1)*10), chance); } - - // special case - if (pt->id == P_TETANUS) { - enum BODYPART bp,poss[MAXBODYPARTS]; - int nposs = 0; - for (bp = 0; bp < MAXBODYPARTS; bp++) { - int ok; - switch (bp) { - case BP_LEGS: - case BP_HEAD: - case BP_HANDS: - case BP_BODY: - case BP_TAIL: - case BP_WINGS: - ok = B_TRUE; - break; - default: - ok = B_FALSE; - break; - } - if (ok && hasbp(lf, bp)) { - poss[nposs++] = bp; - } - } - if (nposs) { - object_t *oo; - bp = poss[rnd(0,nposs-1)]; - switch (bp) { - case BP_LEGS: - injure(lf, bp, DT_BASH, IJ_LEGBROKEN); - break; - case BP_HEAD: break; // no bad effects - case BP_HANDS: // drop your weapon - oo = getequippedob(lf->pack, bp); - if (oo) drop(oo, oo->amt); - break; - case BP_BODY: - if (onein(2)) { - injure(lf, bp, DT_BASH, IJ_RIBCRACKED); - } else { - if (isplayer(lf)) { - msg("^BYour spine snaps!"); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("^%c%s%s spine snaps!", getlfcol(lf, CC_VBAD), - lfname, getpossessive(lfname)); - } - losehp_real(lf, lf->maxhp, DT_DIRECT, NULL, "tetanus", B_FALSE, NULL, B_FALSE, NULL, B_FALSE, BP_NONE); - } - break; - case BP_TAIL: - injure(lf, bp, DT_BASH, IJ_TAILBROKEN); - break; - case BP_WINGS: - injure(lf, bp, DT_SLASH, IJ_WINGTORN); - break; - default: break; - } - } - } else { - snprintf(buf, BUFLEN, "%s^from %s",pt->name, f->text); - losehp(lf, pt->dam * f->val[1], DT_DIRECT, NULL, buf); - } - - if (pt->vomitob != OT_NONE) { - addobfast(lf->cell->obpile, pt->vomitob); - } - loseconcentration(lf); - } - - // extra effects - if (!ko && (f->val[0] == P_COLD)) { - if (rnd(1,100) <= 10) { - object_t *wep; - if (isplayer(lf)) { - msg("^bYou shiver uncontrollably."); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; + + if (!ko && pctchance(chance)) { + char buf[BUFLEN]; + if (isplayer(lf) || cansee(player, lf)) { + char *p; + char lfname[BUFLEN],lfnameposs[BUFLEN]; getlfname(lf, lfname); - msg("^%c%s shivers.", getlfcol(lf, CC_BAD), lfname); + sprintf(lfnameposs, "%s%s",lfname, getpossessive(lfname)); + + p = strdup(pt->damverb); + if (isplayer(lf)) { + strrep(&p, "YOUR", "Your", NULL); + if (asleep) { + strrep(&p, "YOU", "You wake up and", NULL); + } else { + strrep(&p, "YOU", "You", NULL); + } + strrep(&p, "#S", "", NULL); + } else { + strrep(&p, "YOUR", lfnameposs, NULL); + if (asleep) { + char replacetext[BUFLEN]; + sprintf(replacetext, "%s wakes and", lfname); + strrep(&p, "YOU", replacetext, NULL); + } else { + strrep(&p, "YOU", lfname, NULL); + } + strrep(&p, "#S", "s", NULL); + } + + msg("%s", p); + free(p); + + if (asleep) { + int origborn; + origborn = lf->born; + lf->born = B_FALSE; // supress a second announcement of waking up + killflagsofid(lf->flags, F_ASLEEP); + lf->born = origborn; + } else { + taketime(lf, getactspeed(lf)); + } } - wep = getweapon(lf); - if (wep) { - char wname[BUFLEN]; - getobname(wep, wname, 1); - drop(wep, wep->amt); + + // special case + if (pt->id == P_TETANUS) { + enum BODYPART bp,poss[MAXBODYPARTS]; + int nposs = 0; + for (bp = 0; bp < MAXBODYPARTS; bp++) { + int ok; + switch (bp) { + case BP_LEGS: + case BP_HEAD: + case BP_HANDS: + case BP_BODY: + case BP_TAIL: + case BP_WINGS: + ok = B_TRUE; + break; + default: + ok = B_FALSE; + break; + } + if (ok && hasbp(lf, bp)) { + poss[nposs++] = bp; + } + } + if (nposs) { + object_t *oo; + bp = poss[rnd(0,nposs-1)]; + switch (bp) { + case BP_LEGS: + injure(lf, bp, DT_BASH, IJ_LEGBROKEN); + break; + case BP_HEAD: break; // no bad effects + case BP_HANDS: // drop your weapon + oo = getequippedob(lf->pack, bp); + if (oo) drop(oo, oo->amt); + break; + case BP_BODY: + if (onein(2)) { + injure(lf, bp, DT_BASH, IJ_RIBCRACKED); + } else { + if (isplayer(lf)) { + msg("^BYour spine snaps!"); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("^%c%s%s spine snaps!", getlfcol(lf, CC_VBAD), + lfname, getpossessive(lfname)); + } + losehp_real(lf, lf->maxhp, DT_DIRECT, NULL, "tetanus", B_FALSE, NULL, B_FALSE, NULL, B_FALSE, BP_NONE); + } + break; + case BP_TAIL: + injure(lf, bp, DT_BASH, IJ_TAILBROKEN); + break; + case BP_WINGS: + injure(lf, bp, DT_SLASH, IJ_WINGTORN); + break; + default: break; + } + } + } else { + snprintf(buf, BUFLEN, "%s^from %s",pt->name, f->text); + losehp(lf, pt->dam * f->val[1], DT_DIRECT, NULL, buf); + } + + if (pt->vomitob != OT_NONE) { + addobfast(lf->cell->obpile, pt->vomitob); } loseconcentration(lf); } - } else if (f->val[0] == P_MIGRAINE) { - // sleeping will avoid all migraine effects - if (!asleep && !ko) { - object_t *lamp = NULL; - int amt; - amt = lfproduceslight(lf, &lamp); - if (amt) { - int dam; - // note: amt will be doubled due to light vulnerability, - // so half it here. - dam = amt/2; - limit(&dam, 1, NA); - losehp(lf, dam, DT_LIGHT, NULL, "a migraine"); + + // extra effects + if (!ko && (f->val[0] == P_COLD)) { + if (rnd(1,100) <= 10) { + object_t *wep; if (isplayer(lf)) { - char obname[BUFLEN]; - if (lamp) { - getobname(lamp, obname, lamp->amt); - } else { - strcpy(obname, "a body"); // noprefix will strip the 'a ' + msg("^bYou shiver uncontrollably."); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("^%c%s shivers.", getlfcol(lf, CC_BAD), lfname); + } + wep = getweapon(lf); + if (wep) { + char wname[BUFLEN]; + getobname(wep, wname, 1); + drop(wep, wep->amt); + } + loseconcentration(lf); + } + } else if (f->val[0] == P_MIGRAINE) { + // sleeping will avoid all migraine effects + if (!asleep && !ko) { + object_t *lamp = NULL; + int amt; + amt = lfproduceslight(lf, &lamp); + if (amt) { + int dam; + // note: amt will be doubled due to light vulnerability, + // so half it here. + dam = amt/2; + limit(&dam, 1, NA); + losehp(lf, dam, DT_LIGHT, NULL, "a migraine"); + if (isplayer(lf)) { + char obname[BUFLEN]; + if (lamp) { + getobname(lamp, obname, lamp->amt); + } else { + strcpy(obname, "a body"); // noprefix will strip the 'a ' + } + msg("Your head explodes in pain at the light from your %s!", noprefix(obname)); } - msg("Your head explodes in pain at the light from your %s!", noprefix(obname)); } } } } } - } + f = hasflag(lf->flags, F_NAUSEATED); + if (f) { + // chance of being delayed + if (onein(4)) { + if (isplayer(lf)) { + msg("^bYou %s!", rnd(0,1) ? "retch" : "gag"); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("^%c%s %s.", getlfcol(lf, CC_BAD), lfname, rnd(0,1) ? "retches" : "gags"); + } + taketime(lf,getactspeed(lf)); - f = hasflag(lf->flags, F_NAUSEATED); - if (f) { - // chance of being delayed - if (onein(4)) { - if (isplayer(lf)) { - msg("^bYou %s!", rnd(0,1) ? "retch" : "gag"); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("^%c%s %s.", getlfcol(lf, CC_BAD), lfname, rnd(0,1) ? "retches" : "gags"); + loseconcentration(lf); } - taketime(lf,getactspeed(lf)); - - loseconcentration(lf); } - } + } // end if !statis if (lfhasflag(lf, F_FROZEN)) { int willmelt = B_FALSE; @@ -22898,27 +22945,29 @@ void startlfturn(lifeform_t *lf) { } } - f = hasflag(o->flags, F_CAUSESCOUGH); - if (f && !isimmuneto(lf->flags, DT_POISONGAS, B_FALSE)) { - char obname[BUFLEN]; - getobname(o, obname, o->amt); - if (!skillcheck(lf, SC_CON, f->val[0] * o->amt, 0)) { - if (isplayer(lf)) { - msg("^wYou cough on %s.", obname); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s coughs on %s.",lfname, obname); + if (!stasis) { + f = hasflag(o->flags, F_CAUSESCOUGH); + if (f && !isimmuneto(lf->flags, DT_POISONGAS, B_FALSE)) { + char obname[BUFLEN]; + getobname(o, obname, o->amt); + if (!skillcheck(lf, SC_CON, f->val[0] * o->amt, 0)) { + if (isplayer(lf)) { + msg("^wYou cough on %s.", obname); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s coughs on %s.",lfname, obname); + } + taketime(lf, 5); + loseconcentration(lf); } - taketime(lf, 5); - loseconcentration(lf); + } - } - - f = hasflag(o->flags, F_STENCH); - if (f) { - makenauseated(lf, f->val[1], 2, NULL); + f = hasflag(o->flags, F_STENCH); + if (f) { + makenauseated(lf, f->val[1], 2, NULL); + } } // for flags which can occur multiple times @@ -23058,31 +23107,33 @@ void startlfturn(lifeform_t *lf) { } } - if ((f->id == F_INCUBATING) && (f->val[1] > 0)) { - f->val[1]--; - if (f->val[1] <= 0) { - // note: this functino will kill f - completeincubation(lf, f); - continue; + if (!stasis) { + if ((f->id == F_INCUBATING) && (f->val[1] > 0)) { + f->val[1]--; + if (f->val[1] <= 0) { + // note: this functino will kill f + completeincubation(lf, f); + continue; + } } - } - // 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; + // 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)); - } + 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)); + } - if (f->id == F_SIZETIMER) { - f->val[1]--; - if (f->val[1] <= 0) { - resizelf(lf, f->val[0], f->val[2]); - // resizelf will have now killed 'f'. - continue; + if (f->id == F_SIZETIMER) { + f->val[1]--; + if (f->val[1] <= 0) { + resizelf(lf, f->val[0], f->val[2]); + // resizelf will have now killed 'f'. + continue; + } } } @@ -23147,10 +23198,12 @@ void startlfturn(lifeform_t *lf) { } // recharge abilities - if ((f->id == F_CANWILL) || (f->id == F_CANCAST)) { - if (f->val[2] != NA) { - if (f->val[1] < f->val[2]) { - f->val[1]++; + if (!stasis) { + if ((f->id == F_CANWILL) || (f->id == F_CANCAST)) { + if (f->val[2] != NA) { + if (f->val[1] < f->val[2]) { + f->val[1]++; + } } } } @@ -23183,12 +23236,14 @@ void startlfturn(lifeform_t *lf) { } // end if f_target or f_targetcell // hp drain - if (f->id == F_HPDRAIN) { - losehp(lf, f->val[0], f->val[1], NULL, f->text); - if (isdead(lf)) { - break; - } - } + if (!stasis) { + if (f->id == F_HPDRAIN) { + losehp(lf, f->val[0], f->val[1], NULL, f->text); + if (isdead(lf)) { + break; + } + } + } } // end loop through lf flags // picked up your first godstone ? diff --git a/lf.h b/lf.h index a6d93fc..fbc5265 100644 --- a/lf.h +++ b/lf.h @@ -96,7 +96,7 @@ int countplantsinsight(lifeform_t *lf); void debug(lifeform_t *lf); int demandbribe(lifeform_t *lf); void die(lifeform_t *lf); -int digcell(lifeform_t *lf, cell_t *c, object_t *o); +int digcell(lifeform_t *lf, cell_t *c, object_t *o, int dismantle); int digdown(lifeform_t *lf, object_t *o); int digup(lifeform_t *lf, object_t *o); //void do_eyesight_adjust(lifeform_t *lf); diff --git a/map.c b/map.c index 255fe0d..be32730 100644 --- a/map.c +++ b/map.c @@ -1126,7 +1126,9 @@ void breakwall(cell_t *c, char *why, ...) { if (origtype->solid && roomwall && onein(2)) { switch (origtype->material->id) { case MT_STONE: addob(c->obpile, "1-30 stones"); break; + case MT_BRICK: addob(c->obpile, "1-30 bricks"); break; case MT_GLASS: addob(c->obpile, "1-30 pieces of broken glass"); break; + case MT_WOOD: addob(c->obpile, "1-30 shards of wood"); break; default: break; } } @@ -3642,14 +3644,6 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ shape = MS_NORMAL; } - - - - - // xxxxxxxxxxxxxxxxx - shape = MS_NORMAL; - - switch (shape) { case MS_NORMAL:// normal break; @@ -3806,9 +3800,6 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ } } - // xxxxxxxxxxxxxxxxx - shape = CDT_SIMPLE; - // is the map lit? if (depth < 5) { map->illumination = IL_FULLLIT; @@ -8472,7 +8463,7 @@ void initmap(void) { // cell types - solid // floorheight, hp, volmod, absorbant addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, NA, B_SOLID, B_OPAQUE, MT_STONE, 0, 50, 0, B_NOABSORB); - addcelltype(CT_WALLBRICK, "brick wall", UNI_SHADEDARK, C_ORANGE, NA, B_SOLID, B_OPAQUE, MT_STONE, 0, 40, 0, B_NOABSORB); + addcelltype(CT_WALLBRICK, "brick wall", UNI_SHADEDARK, C_ORANGE, NA, B_SOLID, B_OPAQUE, MT_BRICK, 0, 40, 0, B_NOABSORB); addcelltype(CT_WALLDIRT, "dirt wall", UNI_SHADEMED, C_BROWN, NA, B_SOLID, B_OPAQUE, MT_STONE, 0, 20, 0, B_NOABSORB); addcelltype(CT_WALLDURANITE, "duranite wall", UNI_SHADEDARK, C_MAGENTA, NA, B_SOLID, B_OPAQUE, MT_DURANITE, 0, 20000, 0, B_NOABSORB); addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, NA, B_SOLID, B_OPAQUE, MT_WOOD, 0, 30, 0, B_NOABSORB); @@ -8669,16 +8660,42 @@ int isdark(cell_t *c) { return B_FALSE; } -int isdiggable(cell_t *c) { - switch (c->type->id) { - case CT_WALLFLESH: - case CT_WALLDIRT: - case CT_WALL: - case CT_WALLWOOD: - case CT_WALLGLASS: - return B_TRUE; - default: - break; +int isdiggable(cell_t *c, enum OBTYPE withwhat) { + objecttype_t *ot; + ot = findot(withwhat); + if (!ot) { + // just check whether the cell material + // is EVER diggable. + switch (c->type->id) { + case CT_WALLFLESH: + case CT_WALLDIRT: + case CT_WALL: + case CT_WALLWOOD: + case CT_WALLGLASS: + return B_TRUE; + default: + break; + } + } else if (ot->id == OT_A_DISMANTLE) { + // using dismantle ability - only mad-made materials. + switch (c->type->material->id) { + case MT_BRICK: + case MT_WOOD: + return B_TRUE; + default: break; + } + } else { + flag_t *retflag[MAXCANDIDATES],*f; + int nretflags,i; + getflags(ot->flags, retflag, &nretflags, F_DIGCELLTYPE, F_DIGCELLMAT, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if ((f->id == F_DIGCELLTYPE) && (c->type->id == f->val[0])) { + return B_TRUE; + } else if ((f->id == F_DIGCELLMAT) && (c->type->material->id == f->val[0])) { + return B_TRUE; + } + } } return B_FALSE; } diff --git a/map.h b/map.h index 0ecdf02..9969870 100644 --- a/map.h +++ b/map.h @@ -163,7 +163,7 @@ void initmap(void); void initmaplayout(void); int isadjacent(cell_t *src, cell_t *dst); int isdark(cell_t *c); -int isdiggable(cell_t *c); +int isdiggable(cell_t *c, enum OBTYPE withwhat); int isdoor(object_t *o, int *isopen); int isempty(cell_t *c); int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph); diff --git a/objects.c b/objects.c index 9dcc4cc..d888c2c 100644 --- a/objects.c +++ b/objects.c @@ -2220,10 +2220,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum // for validation purposes if (obloc) { // containers - if (hasflag(o->flags, F_CONTAINER)) { - if (getoblocation(o)) { - givestartobs(NULL, o, o->flags); - } + f = hasflag(o->flags, F_CONTAINER); + if (f && getoblocation(o)) { + // randomly generate container contents if required. + gencontainercontents(o); + + givestartobs(NULL, o, o->flags); } // locked? @@ -4054,6 +4056,66 @@ int gethardness(enum MATERIAL matid) { return 0; } +void gencontainercontents(object_t *o) { + flag_t *retflag[MAXCANDIDATES],*f; + int nretflags = 0; + race_t *r; + char buf[BUFLEN]; + + getflags(o->flags, retflag, &nretflags, F_CONTENTS, F_NONE); + if (!nretflags) return; + + f = retflag[rnd(0,nretflags-1)]; + switch (f->val[0]) { + case CC_AMMO: + addflag(o->flags, F_STARTOB, 50, NA, NA, "1-10 arrows"); + addflag(o->flags, F_STARTOB, 50, NA, NA, "1-10 arrows"); + addflag(o->flags, F_STARTOB, 50, NA, NA, "1-10 arrows"); + addflag(o->flags, F_STARTOB, 50, NA, NA, "1-10 bolts"); + addflag(o->flags, F_STARTOB, 50, NA, NA, "1-10 bolts"); + addflag(o->flags, F_STARTOB, 50, NA, NA, "1-10 bullets"); + addflag(o->flags, F_STARTOB, 50, NA, NA, "1-10 bullets"); + break; + case CC_CORPSE: + r = getrandomraceofsize(getobsize(o)); + if (r) { + sprintf(buf, "%s corpse", r->name); + addflag(o->flags, F_STARTOB, 100, NA, NA, buf); + } + break; + case CC_CONDIMENTS: + switch (rnd(1,2)) { + default: case 1: sprintf(buf, "pinch of salt"); break; + case 2: sprintf(buf, "lump of sugar"); break; + } + addflag(o->flags, F_STARTOB, 100, 10, 20, buf); + break; + case CC_FOOD: + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + break; + case CC_FOODDRINK: + addflag(o->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_POTION, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + addflag(o->flags, F_STARTOBCLASS, 50, OC_FOOD, NA, NULL); + break; + case CC_GUNPOWDER: + addflag(o->flags, F_STARTOB, 100, 5, 20, "pile of gunpowder"); + break; + case CC_WATER: + addflag(o->flags, F_STARTOB, 100, NA, NA, "very deep water"); + break; + default: break; + } +} + void genhiddennames(void) { objecttype_t *ot; flag_t *f; @@ -4183,7 +4245,6 @@ int getbreakob(object_t *o, char *bigobname, char *smallobname) { strcpy(bigobname, ""); strcpy(smallobname, ""); - // flag overrides code below found = 0; getflags(o->flags, retflag, &nretflags, F_BREAKOB, F_NONE); @@ -5090,6 +5151,7 @@ int getmaterialvalue(enum MATERIAL mat) { case MT_PLANT: case MT_ICE: case MT_STONE: + case MT_BRICK: return 1; case MT_WATER: return 1; @@ -5621,7 +5683,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan snprintf(dname, BUFLEN, "%s", getdirname(f->val[1])); dname[0] = tolower(dname[0]); strcat(basename, dname); - } else { + } else { // ie. footprints char buf[BUFLEN]; enum SKILLLEVEL lorelev; // beginner perception and upwards gets depth @@ -5646,8 +5708,13 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan snprintf(buf, BUFLEN, "%s %s",r->name, o->type->name); strcat(basename, buf); } else if (lorelev >= PR_NOVICE) { - // novice - you just get 'animal footprints' etc - snprintf(buf, BUFLEN, "%s %s",r->raceclass->name, o->type->name); + flag_t *sf; + enum LFSIZE sz = SZ_HUMAN; + // novice - you just get 'small animal footprints' etc + sf = hasflag(r->flags, F_SIZE); + if (sf) sz = sf->val[0]; + snprintf(buf, BUFLEN, "%s %s %s",getsizetext(sz), + r->raceclass->name, o->type->name); strcat(basename, buf); } else { strcat(basename, o->type->name); @@ -11026,7 +11093,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { dir = chartodir(ch); c = getcellindir(lf->cell, dir); - if (digcell(lf, c, o)) { + if (digcell(lf, c, o, B_FALSE)) { // failed return B_TRUE; } diff --git a/objects.h b/objects.h index 2695065..6dc5d96 100644 --- a/objects.h +++ b/objects.h @@ -68,6 +68,7 @@ objecttype_t *findotn(char *name); // find objecttype by name recipe_t *findrecipefor(enum OBTYPE result); int fountain_will_dryup(object_t *o); void fragments(cell_t *centre, char *what, int speed, int howfar); +void gencontainercontents(object_t *o); void genhiddennames(void); enum LFSIZE getarmoursize(object_t *o); enum RARITY getavgrarity(flagpile_t *fp); diff --git a/spell.c b/spell.c index 1911865..afb9cde 100644 --- a/spell.c +++ b/spell.c @@ -1176,7 +1176,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef objecttype_t *newot = NULL; int numnew = 0; int dir; - char dirch; cell_t *c; object_t *o; char obname[BUFLEN]; @@ -1197,32 +1196,40 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef slev = getskill(user, SK_ENGINEERING); - dirch = askdir("Dismantle obstacle in which direction (- to cancel)", B_TRUE, B_FALSE); - if (dirch == D_NONE) { + dir = askdir("Dismantle obstacle in which direction (- to cancel)", B_TRUE, B_FALSE); + if (dir == D_NONE) { msg("Cancelled."); return B_TRUE; - } else if (dirch == D_MYSELF) { + } else if (dir == D_MYSELF) { c = user->cell; - } else { - dir = chartodir(dirch); } c = getcellindir(user->cell, dir); // antything there? o = hasobwithflag(c->obpile, F_CLIMBOBSTACLE); if (c->type->solid) { - msg("There is nothing to dismantle there."); - return B_TRUE; + if (slev >= PR_ADEPT) { + // you can try to dismantle walls. digcell() will + // check whether it is actually diggable. + } else { + msg("There is nothing you can dismantle there."); + return B_TRUE; + } } else if (!o) { if (slev >= PR_ADEPT) { // you can dismantle doors too... o = hasdoor(c); } if (!o) { - msg("There is nothing to dismantle there."); + msg("There is nothing you can dismantle there."); return B_TRUE; } } + + if (!o) { + // ie trying to dismantle a wall + return digcell(user, c, NULL, B_TRUE); + } // figrue out what to replace it with switch (o->material->id) { @@ -8501,6 +8508,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ fizzle(caster); return B_TRUE; } + } else if (spellid == OT_S_MINDWHIP) { + target = targcell->lf; + if (!target) { + fizzle(caster); + return B_TRUE; + } + if (isplayer(target)) { + msg("^%cA lash of psychic power assaults your mind!",getlfcol(target, CC_BAD)); + } else if (isplayer(caster)) { + char lfname[BUFLEN]; + getlfname(target, lfname); + msg("^%cYou psycically lash %s%s mind!", getlfcol(target, CC_BAD), + lfname, getpossessive(lfname)); + } + if (getattrbracket(getattr(target, A_IQ), A_IQ, NULL) <= AT_VLOW) { + if (isplayer(caster)) { + char tname[BUFLEN]; + getlfname(target, tname); + msg("%s is unaffected.", tname); + } + return B_TRUE; + } + losehp(target, rnd(2,6), DT_DIRECT, caster, "a psychic lash"); } else if (spellid == OT_S_MIRRORIMAGE) { int i,ndone = 0; int seen = B_FALSE; @@ -9428,7 +9458,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // now kill the caster! die(caster); } - } else if (spellid == OT_S_PSIBLAST) { + } else if (spellid == OT_S_PRECOGNITION) { + flag_t *f; + // always targetted at caster + targcell = caster->cell; + target = caster; + + f = addtempflag(caster->flags, F_EVASION, 5, NA, NA, "precognition", FROMSPELL); + f->obfrom = spellid; + } else if (spellid == OT_S_MFEEDBACK) { int dam,iq; enum ATTRBRACKET iqb; char targetname[BUFLEN]; @@ -9446,7 +9484,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ fizzle(caster); return B_TRUE; } - dam = rnd(1,(iq/5)); + dam = rnd((iq/10),(iq/5)); losehp(target, dam, DT_DIRECT, caster, "a psionic blast"); getlfname(target, targetname); if (isplayer(target)) { @@ -9454,6 +9492,31 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (cansee(player, target)) { msg("^%c%s%s brain is blasted!",getlfcol(target, CC_BAD), targetname, getpossessive(targetname)); } + } else if (spellid == OT_S_PSIBLAST) { + int range; + int x,y; + char buf[BUFLEN]; + if (caster && !targcell) targcell = caster->cell; + range = 3; + + sprintf(buf, "%s emit%s a blast of psionic power!",castername,isplayer(caster) ? "" : "s"); + animradial(targcell, range, '}', C_CYAN, DT_COMPASS, buf, "Something emits a radial blast of psionic power!"); + + if (isplayer(caster) || haslos(player, targcell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + + for (y = targcell->y - range ; y <= targcell->y + range; y++) { + for (x = targcell->x - range ; x <= targcell->x + range; x++) { + cell_t *c; + c = getcellat(targcell->map, x,y); + if (c && (getcelldist(targcell, c) <= range)) { + if (c->lf && (c->lf != caster) && haslof(targcell, c, B_FALSE, NULL)) { + stun(c->lf, 4+power); + } + } + } + } } else if (spellid == OT_S_PSYARMOUR) { flag_t *f; // always targetted at caster @@ -9848,9 +9911,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ fizzle(caster); return B_TRUE; } - - } + } else if (spellid == OT_S_KNOWWEAKNESS) { + flag_t *f; + // always targetted at caster + targcell = caster->cell; + target = caster; + + if (isplayer(caster)) { + msg("^gYour mind becomes attuned to your foes' weaknesses!"); + } + f = addtempflag(caster->flags, F_EXTRADAM, NA, NA, 2, NULL, FROMSPELL); + f->obfrom = spellid; } else if (spellid == OT_S_LEVITATION) { flag_t *f; // always targetted at caster @@ -11469,14 +11541,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_SLEEP) { int howlong; - target = targcell->lf; + if (!target) target = targcell->lf; if (lfhasflag(target, F_ASLEEP) || !cansleep(target)) { - fizzle(caster); + if (!frompot) fizzle(caster); return B_TRUE; } - if (isplayer(target)) { msg("A sudden feeling of drowsiness washes over you!"); } @@ -11904,6 +11975,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f->text = strdup(dambuf); } real_fireat(caster, o, 1, targcell, 6, NULL, B_FALSE, OT_S_SPIKEVOLLEY, NULL); + } else if (spellid == OT_S_STASIS) { + flag_t *f; + f = addtempflag(caster->flags, F_STASIS, B_TRUE, NA, NA, NULL, FROMSPELL); + f->obfrom = spellid; } else if (spellid == OT_S_STENCH) { int howlong; enum ERROR why; @@ -12082,11 +12157,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } } - } else if (spellid == OT_S_STUNMASS) { + } else if (spellid == OT_S_SLEEPMASS) { int i; int donesomething = B_FALSE; target = caster; - // stun everyone within los of caster + // sleep everyone within los of caster for (i = 0; i < target->nlos; i++) { lifeform_t *thistarg; @@ -12094,17 +12169,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ thistarg = targcell->lf; if (thistarg && (thistarg != caster)) { if (lfhasflag(thistarg, F_ASLEEP) || !ischarmable(thistarg)) { - fizzle(caster); - return B_TRUE; - } - if (spellresisted(thistarg, caster, spellid, power, seenbyplayer, B_TRUE)) { - } else { - donesomething = B_TRUE; - stun(thistarg, (power/5)+2); - if (isplayer(thistarg) || cansee(player, thistarg)) { - if (seenbyplayer) *seenbyplayer = B_TRUE; - } + continue; } + // we set frompot to B_TRUE to avoid 'fizzled' messages if there is someone + // unaffected in range. + dospelleffects(caster, OT_S_SLEEP, power+1, thistarg,NULL,NULL,blessed, + seenbyplayer, B_TRUE, NULL); } }