diff --git a/ai.c b/ai.c index 8a37a2f..eb339f1 100644 --- a/ai.c +++ b/ai.c @@ -2294,6 +2294,11 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG if ((ot->id == OT_S_HASTE) && (lfhasflag(victim, F_FASTACT) || lfhasflag(victim, F_FASTACTMOVE)) ) { specificcheckok = B_FALSE; } + if (ot->id == OT_S_HEAVENARM) { + if (lfhasflag(lf, F_HEAVENARM)) { + specificcheckok = B_FALSE; + } + } if (ot->id == OT_A_HEAVYBLOW) { object_t *w; w = getweapon(lf); diff --git a/attack.c b/attack.c index 4c768a1..8b8c938 100644 --- a/attack.c +++ b/attack.c @@ -516,7 +516,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { if (attacktype == AT_LF) { if (!isgod(attacktarget)) { if (attackedfriend) { - angergodmaybe(R_GODMERCY, 100, GA_ATTACKALLY); + angergodmaybe(R_GODMERCY, 25, GA_ATTACKALLY); angergodmaybe(R_GODPURITY, 100, GA_ATTACKALLY); switch (getalignment(attacktarget)) { case AL_EVIL: @@ -529,7 +529,8 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { break; } } else if (attackedpeaceful) { - angergodmaybe(R_GODMERCY, 50, GA_ASSAULT); + angergodmaybe(R_GODMERCY, 15, GA_ASSAULT); + angergodmaybe(R_GODLIFE, 15, GA_ASSAULT); angergodmaybe(R_GODPURITY, 50, GA_ASSAULT); switch (getalignment(attacktarget)) { case AL_EVIL: @@ -542,7 +543,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { break; } } else if (attackedhelpless) { - angergodmaybe(R_GODMERCY, 50, GA_ATTACKHELPLESS); + angergodmaybe(R_GODMERCY, 15, GA_ATTACKHELPLESS); if (getalignment(attacktarget) != AL_EVIL) { angergodmaybe(R_GODPURITY, 50, GA_ATTACKHELPLESS); pleasegodmaybe(R_GODTHIEVES, 5); @@ -934,7 +935,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) // 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 && ismeleedam(damtype[i])) { + if ((dam[i] > 0) && !backstab && !critical && ismeleedam(damtype[i])) { // modify for defender's armour reduceamt = getarmourdamreduction(victim, wep, dam[i], damtype[i]); diff --git a/data.c b/data.c index fabe301..0349a78 100644 --- a/data.c +++ b/data.c @@ -2863,7 +2863,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); /////////////////// - // elemental - fire + // elemental - fire magic /////////////////// // l1 addot(OT_S_BURNINGFEET, "hotfoot", "Heats the soles of the target's feet to an uncomfortable level, dealing 1 fire damage each turn they remain still.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); @@ -3371,7 +3371,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); /////////////////// - // life / cleric spells + // life spells / cleric spells /////////////////// // l1 addot(OT_S_HEALINGMIN, "minor healing", "Restores 1-8 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); @@ -3415,6 +3415,13 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); // l4 + addot(OT_S_HEAVENARM, "divine armour", "Protects the target from damage with a holy force field.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell will prevent ^bpower * 10^n points worth of damage from any source."); + addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); + addflag(lastot->flags, F_VARPOWER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addot(OT_S_HEALINGMAJ, "major healing", "Restores 20-30 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell heals an extra 2 damage per power level."); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); @@ -6127,6 +6134,12 @@ void initobjects(void) { addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); + addot(OT_TOUCHHOLY, "holy touch", "holy touch object", MT_BONE, 0, OC_WEAPON, SZ_TINY); + addflag(lastot->flags, F_DAM, DT_HOLY, 1, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); + addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_TOUCHPARALYZE, "paralyzing touch", "paralyzing touch object", MT_BONE, 0, OC_WEAPON, SZ_TINY); addflag(lastot->flags, F_ARMOURPIERCE, 90, NA, NA, ""); addflag(lastot->flags, F_DAM, DT_TOUCH, 1, NA, NULL); @@ -7654,7 +7667,7 @@ void initrace(void) { } } addflag(lastrace->flags, F_SACRIFICEOBBLESSED, B_CURSED, NA, 5, "OB explode#S in a shower of sparks!"); - addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, NA, 10, "OB IS consumed by a shaft of holy light."); + addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, NA, 10, "OB explode#S in a shower of sparks!"); addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;"); @@ -7664,7 +7677,6 @@ void initrace(void) { addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing evil creatures"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "blessing objects"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "acts of charity"); - addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting holy spells"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "sacrificing cursed objects through prayer"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking good, peaceful or helpless creatures"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison"); @@ -7725,7 +7737,7 @@ void initrace(void) { addflag(lastrace->flags, F_SACRIFICEOBWITHFLAG, F_BATTLESPOILS, NA, 3, "OB explode#S into a shower of blood!"); addflag(lastrace->flags, F_SACRIFICEOB, OT_SPELLBOOK, NA, 10, "OB explode#S into a shower of blood!"); - addrace(R_GODNATURE, "Ekrub", 200, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Ekrub is god of nature and creation. She appears as a female figure dressed in farming clothes. Ekrub has a burning hatred of all dragonkind, who she views as abhorrent due to their destructive nature."); + addrace(R_GODNATURE, "Ekrub", 200, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Ekrub is goddess of nature and creation. She appears as a female figure dressed in farming clothes. Ekrub has a burning hatred of all dragonkind, who she views as abhorrent due to their destructive nature."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 95, NA, NA, ""); @@ -7758,7 +7770,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTSKILL, SK_LORE_NATURE, PR_MASTER, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_LORE_DRAGONS, PR_ADEPT, NA, NULL); // ekrub hates dragons // god abilities - addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Nature"); + addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Creation"); // may cast all nature spells for (ot = objecttype ; ot ; ot = ot->next) { if ((ot->obclass->id == OC_SPELL) && (getspellschool(ot->id) == SS_NATURE)) { @@ -7780,7 +7792,7 @@ void initrace(void) { addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, RC_DRAGON, 25, "Writhing vines sprout up and tear OB to pieces!"); - addrace(R_GODTHIEVES, "Felix", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Felix is the god of Thieves, Greed and Trickery. He generally appears as an overweight glutton carrying his contraband loot around in huge sacks. Despite this, he is amazingly agile and is said to be able to steal one's soul right out of their body."); + addrace(R_GODTHIEVES, "Felix", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Felix is the god of Thieves, Revenge and Greed. He generally appears as an overweight glutton carrying his contraband loot around in huge sacks. Despite this, he is amazingly agile and is said to be able to steal one's soul right out of their body."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "75"); @@ -7809,7 +7821,7 @@ void initrace(void) { addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "waves his hand"); addflag(lastrace->flags, F_CASTCHANCE, 75, NA, NA, NULL); // god abilities - addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Thieves"); + addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Revenge"); addflag(lastrace->flags, F_FLEEONHPPCT, 10, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_HIDE, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_CALLWIND, NA, NA, "pw:10;"); @@ -7829,6 +7841,51 @@ void initrace(void) { addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_MONEY, NA, 2, "OB IS consumed in a swirl of shadowy blackness."); addflag(lastrace->flags, F_SACRIFICEOBWITHFLAG, F_GEM, NA, 2, "OB IS consumed in a swirl of shadowy blackness."); + addrace(R_GODLIFE, "Glorana", 2, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Glorana is the goddess of life. She appears as a pulsating orb of holy energy."); + addbodypart(lastrace, BP_BODY, "life energy"); + addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL); + addflag(lastrace->flags, F_FLEEONHPPCT, 95, NA, NA, ""); + addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "30"); + addflag(lastrace->flags, F_STARTATT, A_AGI, NA, NA, "85"); + addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "65"); + addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "75"); + addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "65"); + addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "50"); + addflag(lastrace->flags, F_STARTASLEEPPCT, 0, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "50d4"); + addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TOUCHHOLY, 10, NA, NULL); + addflag(lastrace->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_MASTER, NA, NULL); + addflag(lastrace->flags, F_STARTSKILL, SK_LISTEN, PR_MASTER, NA, NULL); + addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_MASTER, NA, NULL); + addflag(lastrace->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_MASTER, NA, NULL); + // god abilities + addflag(lastrace->flags, F_GODOF, B_FEMALE, NA, NA, "Life"); + addflag(lastrace->flags, F_REGENERATES, 5, NA, NA, NULL); + // may cast all life spells + for (ot = objecttype ; ot ; ot = ot->next) { + if ((ot->obclass->id == OC_SPELL) && (getspellschool(ot->id) == SS_LIFE)) { + addflag(lastrace->flags, F_CANWILL, ot->id, NA, NA, "pw:10;"); + } + } + addflag(lastrace->flags, F_GODPOISON, B_FALSE, 25, NA, NULL); + addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying the undead"); + addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting holy spells"); + addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "natural healing"); + addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the destruction of healing potions"); + addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison"); + addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of necromancy"); + addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking peaceful creatures"); + addflag(lastrace->flags, F_HATESRACECLASS, RC_UNDEAD, NA, NA, NULL); + // sacrifices + addflag(lastrace->flags, F_SACRIFICEOB, OT_POT_HEALINGMIN, NA, 10, "OB IS consumed by a shaft of holy light."); + addflag(lastrace->flags, F_SACRIFICEOB, OT_POT_HEALING, NA, 20, "OB IS consumed by a shaft of holy light."); + addflag(lastrace->flags, F_SACRIFICEOB, OT_POT_HEALINGMAJ, NA, 30, "OB IS consumed by a shaft of holy light."); + addflag(lastrace->flags, F_SACRIFICEOB, OT_POT_RESTORATION, NA, 40, "OB IS consumed by a shaft of holy light."); + addflag(lastrace->flags, F_SACRIFICEOB, OT_POT_AMBROSIA, NA, 40, "OB IS consumed by a shaft of holy light."); + addflag(lastrace->flags, F_SACRIFICEOB, OT_BANDAGE, NA, 30, "OB IS consumed by a shaft of holy light."); + addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_FOOD, NA, 3, "OB IS consumed by a shaft of holy light."); addrace(R_GODDEATH, "Hecta", 100, '@', C_BOLDMAGENTA, MT_BONE, RC_GOD, "The skeletal god of death is garbed in a cloak made of pure shadow. and weilds an enormous scythe."); setbodytype(lastrace, BT_HUMANOID); @@ -7878,6 +7935,44 @@ void initrace(void) { // sacrifices addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, NA, 2, "Bony claws rise up and drag OB underground."); + addrace(R_GODFIRE, "Klikirak", 2, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Klikirak is the burning god of Fire and Destruction. He is visible only as a raging inferno of fire, destroying anything in his path."); + addbodypart(lastrace, BP_BODY, "flames"); + addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL); + addflag(lastrace->flags, F_FLEEONHPPCT, 95, NA, NA, ""); + addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "50"); + addflag(lastrace->flags, F_STARTATT, A_AGI, NA, NA, "100"); + addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "40"); + addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "40"); + addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "70"); + addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "60"); + addflag(lastrace->flags, F_STARTASLEEPPCT, 0, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "50d4"); + addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TOUCHBURN, 16, NA, NULL); + + // god abilities + // may cast all fire spells + for (ot = objecttype ; ot ; ot = ot->next) { + if ((ot->obclass->id == OC_SPELL) && (getspellschool(ot->id) == SS_FIRE)) { + addflag(lastrace->flags, F_CANWILL, ot->id, NA, NA, "pw:10;"); + } + } + addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_MASTER, NA, NULL); + addflag(lastrace->flags, F_PRODUCESLIGHT, 6, NA, NA, NULL); + addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "large fire"); + addflag(lastrace->flags, F_RETALIATE, 2, 4, DT_FIRE, "roaring flames"); + addflag(lastrace->flags, F_DTIMMUNE, DT_FIRE, B_TRUE, NA, NULL); + addflag(lastrace->flags, F_GODOF, B_MALE, NA, NA, "Destruction"); + addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "starting fires"); + addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "burning objects"); + addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing with fire"); + addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "using fire-based magic"); + addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "creating objects"); + addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "inflicting cold-based damage"); + addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "using cold-based magic"); + // sacrifices + addflag(lastrace->flags, F_SACRIFICEOBWITHFLAG, F_FLAMMABLE, NA, 10, "OB IS consumed in a burst of fire!"); addrace(R_GODMAGIC, "Lumara", 55, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Lumara is the goddess of magic. She appears as a slender elderly woman, her expression wise with age."); setbodytype(lastrace, BT_HUMANOID); @@ -7924,7 +8019,7 @@ void initrace(void) { addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_RING, NA, 10, "OB disappear#S in a swirl of multicoloured lights."); - addrace(R_GODMERCY, "Yumi", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Yumi is the goddess of Mercy and Healing. She has a calm, serene face and wears simple clothing."); + addrace(R_GODMERCY, "Yumi", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Yumi is the goddess of Mercy and Forgiveness. She has a calm, serene face and wears simple clothing."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 95, NA, NA, ""); @@ -7942,8 +8037,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "cotton shirt of health"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "cloth trousers "); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed longsword of mercy"); - addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10 blessed vials of ambrosia"); - addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "2 rings of regeneration"); + addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "ring of miracles"); addflag(lastrace->flags, F_STARTSKILL, SK_FIRSTAID, PR_MASTER, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_MASTER, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_LONGBLADES, PR_ADEPT, NA, NULL); @@ -7960,14 +8054,12 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_S_SLEEP, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;"); addflag(lastrace->flags, F_GODPOISON, B_FALSE, 25, NA, NULL); - addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "the successful casting of healing spells"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "allowing fleeing creatures to escape"); + addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "knocking enemies unconscious"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "acts of charity"); - addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "natural healing"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking the innocent or helpless"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "sneak attacks"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison"); - addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the destruction of healing potions"); // sacrifices addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_WEAPON, NA, 2, "OB IS destroyed in a flash of power."); diff --git a/data/vaults/heaven1.vlt b/data/vaults/heaven1.vlt index 829e6b6..94366db 100644 --- a/data/vaults/heaven1.vlt +++ b/data/vaults/heaven1.vlt @@ -1,31 +1,31 @@ ! realm of the gods, version 1 @id:heaven_1 @map -wgggggwwwwwwwwwwwwwwwwwwwwwwwwwwwgggggggwwwwwwwwwwwwwwwwwwwwwwwwwwwwgggggw -gg...ggwwwwwwwwwwwwwwwwwwwwwwwwwgg.....ggwwwwwwwwwwwwwwwwwwwwwwwwwwgg...gg -g.....gwwwwwwwwwwwwwwwwwwwwwwwwgg.......ggwwwwwwwwwwwwwwwwwwwwwwwwwg.....g -g.._............wwwwwwwwwwwwwwwg...._....gwwwwwwwwwwwwwwww............_..g -g.....gwwwwwwwww.wwwwwwwwwwwwwwg.........gwwwwwwwwwwwwwww.wwwwwwwwwg.....g -gg...ggwwwwwwwwww.wwwwwwwwwwwwwgg.......ggwwwwwwwwwwwwww.wwwwwwwwwwgg...gg -wgggggwwwwwwwwwwww.wwwwwwwwwwwwwgg.....ggwwwwwwwwwwwwww.wwwwwwwwwwwwgggggw -wwwwwwwwwwwwwwwwwww.wwwwwwwwwwwwwgg...ggwwwwwwwwwwwwww.wwwwwwwwwwwwwwwwwww -wwwwwwwwwwwwwwwwwwww.wwwwwwwwwwwwww...wwwwwwwwwwwwwww.wwwwwwwwwwwwwwwwwwww -wgggggwwwwwwwwwwwwwww.wwwwwwwwwww.......wwwwwwwwwwww.wwwwwwwwwwwwwwwgggggw +wgggggwwwwwwwwwwwwwwwwwwwwgggggwwwwwwwwwwwgggggwwwwwwwwwwwwwwwwwwwwwgggggw +gg...ggwwwwwwwwwwwwwwwwwwgg...ggwwwwwwwwwgg...ggwwwwwwwwwwwwwwwwwwwgg...gg +g.....gggwwwwwwwwwwwwwwwwg.....gwwwwwwwwwg.....gwwwwwwwwwwwwwwwwwggg.....g +g.._............wwwwwwwwwg.._..gwwwwwwwwwg.._..gwwwwwwwwww............_..g +g.....gggwwwwwww.wwwwwwwwg.....gwwwwwwwwwg.....gwwwwwwwww.wwwwwwwggg.....g +gg...ggwwwwwwwwww.wwwwwwwgg...ggwwwwwwwwwgg...ggwwwwwwww.wwwwwwwwwwgg...gg +wgggggwwwwwwwwwwww.wwwwwwwggg.ggwwwwwwwwwgg.gggwwwwwwww.wwwwwwwwwwwwgggggw +wwwwwwwwwwwwwwwwwww.wwwwwwwwgg.gwwwwwwwwwg.ggwwwwwwwww.wwwwwwwwwwwwwwwwwww +wwwwwwwwwwwwwwwwwwww.wwwwwwwwww.wwwwwwwww.wwwwwwwwwww.wwwwwwwwwwwwwwwwwwww +wgggggwwwwwwwwwwwwwww.wwwwwwwwww.w.....w.wwwwwwwwwww.wwwwwwwwwwwwwwwgggggw gg...ggwwwwwwwwwwwwwww.wwwwwwwwww.......wwwwwwwwwww.wwwwwwwwwwwwwwwgg...gg -g.....gwwwwwwww....................................................g.....g +g.....gggwwwwww............................................wwwwwwggg.....g g.._................................^................................._..g -g.....gwwwwwwww....................................................g.....g +g.....gggwwwwww............................................wwwwwwggg.....g gg...ggwwwwwwwwwwwwwww.wwwwwwwwww.......wwwwwwwwwww.wwwwwwwwwwwwwwwgg...gg -wgggggwwwwwwwwwwwwwww.wwwwwwwwwww.......wwwwwwwwwwww.wwwwwwwwwwwwwwwgggggw -wwwwwwwwwwwwwwwwwwww.wwwwwwwwwwwwww...wwwwwwwwwwwwwww.wwwwwwwwwwwwwwwwwwww -wwwwwwwwwwwwwwwwwww.wwwwwwwwwwwwwgg...ggwwwwwwwwwwwwww.wwwwwwwwwwwwwwwwwww -wgggggwwwwwwwwwwww.wwwwwwwwwwwwwgg.....ggwwwwwwwwwwwwww.wwwwwwwwwwwwgggggw -gg...ggwwwwwwwwww.wwwwwwwwwwwwwgg.......ggwwwwwwwwwwwwww.wwwwwwwwwwgg...gg -g.....gwwwwwwwww.wwwwwwwwwwwwwwg.........gwwwwwwwwwwwwwww.wwwwwwwwwg.....g -g.._............wwwwwwwwwwwwwwwg...._....gwwwwwwwwwwwwwwww............_..g -g.....gwwwwwwwwwwwwwwwwwwwwwwwwgg.......ggwwwwwwwwwwwwwwwwwwwwwwwwwg.....g -gg...ggwwwwwwwwwwwwwwwwwwwwwwwwwgg.....ggwwwwwwwwwwwwwwwwwwwwwwwwwwgg...gg -wgggggwwwwwwwwwwwwwwwwwwwwwwwwwwwgggggggwwwwwwwwwwwwwwwwwwwwwwwwwwwwgggggw +wgggggwwwwwwwwwwwwwww.wwwwwwwwww.w.....w.wwwwwwwwwww.wwwwwwwwwwwwwwwgggggw +wwwwwwwwwwwwwwwwwwww.wwwwwwwwww.wwwwwwwww.wwwwwwwwwww.wwwwwwwwwwwwwwwwwwww +wwwwwwwwwwwwwwwwwww.wwwwwwwwgg.gwwwwwwwwwg.ggwwwwwwwww.wwwwwwwwwwwwwwwwwww +wgggggwwwwwwwwwwww.wwwwwwwggg.ggwwwwwwwwwgg.gggwwwwwwww.wwwwwwwwwwwwgggggw +gg...ggwwwwwwwwww.wwwwwwwgg...ggwwwwwwwwwgg...ggwwwwwwww.wwwwwwwwwwgg...gg +g.....gggwwwwwww.wwwwwwwwg.....gwwwwwwwwwg.....gwwwwwwwww.wwwwwwwggg.....g +g.._............wwwwwwwwwg.._..gwwwwwwwwwg.._..gwwwwwwwwww............_..g +g.....gggwwwwwwwwwwwwwwwwg.....gwwwwwwwwwg.....gwwwwwwwwwwwwwwwwwggg.....g +gg...ggwwwwwwwwwwwwwwwwwwgg...ggwwwwwwwwwgg...ggwwwwwwwwwwwwwwwwwwwgg...gg +wgggggwwwwwwwwwwwwwwwwwwwwgggggwwwwwwwwwwwgggggwwwwwwwwwwwwwwwwwwwwwgggggw @end @legend diff --git a/defs.h b/defs.h index 2c3a47b..64b5f16 100644 --- a/defs.h +++ b/defs.h @@ -877,7 +877,7 @@ enum RACECLASS { }; #define R_GODFIRST R_GODPURITY -#define MAXGODS 7 +#define MAXGODS 9 enum RACE { R_NONE = 0, @@ -903,6 +903,8 @@ enum RACE { R_GODPURITY, // amberon - R_FIRSTGOD R_GODTHIEVES, // felix R_GODDEATH, // hecta + R_GODFIRE, // klikirak + R_GODLIFE, // glorana R_GODMERCY, // yumi R_GODNATURE, // ekrub R_GODBATTLE, // bjorn @@ -1405,6 +1407,7 @@ enum OBTYPE { OT_S_HEALING, OT_S_HEALINGMIN, OT_S_HEALINGMAJ, + OT_S_HEAVENARM, OT_S_HOLYAURA, OT_S_SMITEEVIL, OT_S_SPEAKDEAD, @@ -1820,6 +1823,7 @@ enum OBTYPE { OT_ACIDATTACK, OT_TOUCHBURN, OT_TOUCHCHILL, + OT_TOUCHHOLY, OT_TOUCHPARALYZE, OT_TOUCHPARALYZE2, // missiles / ammo @@ -2521,6 +2525,7 @@ enum FLAG { F_PIETY, // for god lifeforms - tracks player's piety with them F_HOMEMAP, // which map did this lf get created on? F_TOOKACTION, // lf purposely took action in their last turn. + F_JUSTENTERED, // lf just entered a new map. F_MOVED, // lf purposely walked/flew/swum/moved in prev turn F_HASBEENMOVED, // an object moved this lf since their last turn. F_HOTFEET, // target takes v0 damage of type v1 unless they move. @@ -2971,6 +2976,9 @@ enum FLAG { F_PARALYZED,// cannot do anything F_PRONE, // lying on the ground F_FROZEN, // made of ice + F_HEAVENARM, // prevent the next v0 damage received. + // when v0 drops to <= 0, flag goes. + // text = name of armour. F_HOLYAURA, // holy aura - attacks deal holy damage to vulnerable // enemies. F_LEARNBOOST, // +v0% xp and skillxp @@ -2995,6 +3003,7 @@ enum FLAG { F_SEEINVIS, // can see invisible things F_SPIDERCLIMB, // lf can climb at 100% success rate F_SILENTMOVE, // lf makes no noise when walking/flying + F_SIXTHSENSE, // warned about nearby enemies. v0 = power. F_STABILITY, // doesn't slip over F_STAMREGEN, // boost stamina regeneration at 'text' per turn // (this is a float) diff --git a/god.c b/god.c index 5ff7f4f..869ba39 100644 --- a/god.c +++ b/god.c @@ -35,12 +35,14 @@ int ngodlfs = 0; void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { lifeform_t *god; int piety; + enum PIETYLEV plev; int dosay = B_FALSE; god = findgod(rid); modpiety(rid, -amt); piety = getpiety(rid); + plev = getpietylev(rid, NULL, NULL); // if you have never prayed to this god before, finish now. if (!lfhasflag(god, F_PIETY)) { @@ -86,14 +88,14 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { } // announce - if (piety > 0) { // not angry yet. - godsay(rid, dosay, "You are testing my patience, mortal!"); - } else if (piety > -100) { // minor bad stuff + if (plev == PL_ANGRY) { // minor bad stuff godsay(rid,dosay, "You have angered me, mortal!"); - } else if (piety > -200) { // major bad stuff + } else if (plev == PL_FURIOUS) { // major bad stuff godsay(rid,dosay, "You go too far, mortal!"); - } else { // god will attack + } else if (plev == PL_ENRAGED) { // god will attack godsay(rid,dosay, "You will regret that!"); + } else { // not angry yet. + godsay(rid, dosay, "You are testing my patience, mortal!"); } // bad stuff @@ -132,7 +134,7 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { } // then... - if (piety > -100) { + if (plev == PL_ANGRY) { int i,n; flag_t *retflag[MAXCANDIDATES]; int nretflags; @@ -170,6 +172,14 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { } } break; + case R_GODFIRE: + msg("\"Fire will burn away your sins!\""); + dospelleffects(NULL, OT_S_FLAMEPILLAR, 4, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE); + break; + case R_GODLIFE: + msg("\"Your body shall be slow to recover from wounds...\""); + // life spells will fail + break; case R_GODMAGIC: msg("\"You can live without my gifts for a while...\""); losemp(player, player->mp); @@ -232,10 +242,11 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { default: break; } - } else if (piety > -200) { + } else if (plev == PL_FURIOUS) { object_t *o; lifeform_t *l; - int n,i; + int n,i,nretcells; + cell_t *retcell[MAXRETCELLS]; int rollagain = B_TRUE; // major bad stuff switch (god->race->id) { @@ -300,6 +311,25 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { break; } break; + case R_GODFIRE: + msg("\"Burn, infidel!\""); + dospelleffects(NULL, OT_S_FLAMEPILLAR, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE); + getradiuscells(player->cell, 1, DT_COMPASS, B_FALSE, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 0); + for (i = 0; i < nretcells; i++) { + if (!retcell[i]->type->solid) { + addobfast(retcell[i]->obpile, OT_FIRELARGE); + } + } + break; + case R_GODLIFE: + msg("\"I withdraw my gifts from you!\""); + // lower max hp by 10 + player->maxhp -= 10; + limit(&(player->maxhp), 1, NA); + if (player->hp > player->maxhp) player->hp = player->maxhp; + statdirty = B_TRUE; + // player can now never heal + break; case R_GODTHIEVES: o = getweapon(player); msg("\"Allow me to lighten your load a little...\""); @@ -403,7 +433,7 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { default: break; } - } else { + } else if (plev == PL_ENRAGED) { // god attacks! godappears(god->race->id, NULL); aiattack(god, player, PERMENANT); @@ -534,6 +564,9 @@ void dooffer(void) { addob(player->cell->obpile, splatterob); addobsinradius(player->cell, 1, DT_COMPASS, splatterob, B_TRUE); } + if (god->race->id == R_GODFIRE) { + dospelleffects(player, OT_S_FLAMEBURST, 1, NULL, NULL, player->cell, B_UNCURSED, NULL, B_FALSE); + } } else { nothinghappens(); } @@ -554,13 +587,19 @@ lifeform_t *findgod(enum RACE rid) { enum RACE getopposinggod(enum RACE rid) { switch (rid) { - case R_GODPURITY: return R_GODTHIEVES; - case R_GODTHIEVES: return R_GODPURITY; - case R_GODDEATH: return R_GODMERCY; - case R_GODMERCY: return R_GODDEATH; + //case R_GODPURITY: return R_GODCHAOS; + //case R_GODCHAOS: return R_GODPURITY; + case R_GODDEATH: return R_GODLIFE; + case R_GODLIFE: return R_GODDEATH; + + case R_GODMERCY: return R_GODTHIEVES; + case R_GODTHIEVES: return R_GODMERCY; + case R_GODBATTLE: return R_GODMAGIC; case R_GODMAGIC: return R_GODBATTLE; - // TODO: nature/destruction + + case R_GODNATURE: return R_GODFIRE; + case R_GODFIRE: return R_GODNATURE; default: break; } return R_NONE; @@ -795,7 +834,7 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { f->obfrom = god->race->id; } } else { - f = addtempflag(player->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL, FROMGODGIFT); + f = addtempflag(player->flags, F_DTRESIST, DT_NECROTIC, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; @@ -817,6 +856,104 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { } } break; + case R_GODFIRE: + while (rollagain) { + object_t *wep; + wep = getweapon(player); + rollagain = B_FALSE; + switch (rnd(1,3)) { + case 1: // weapon gains burning + if (wep) { + if (!hasobmod(wep, findobmod(OM_FLAMING))) { + applyobmod(wep, findobmod(OM_FLAMING)); + } else if (!hasflag(wep->flags, F_HASBRAND)) { + char obname[BUFLEN]; + // already burning. gains pyromania + addflag(wep->flags, F_FLAMESTRIKE, B_TRUE, NA, NA, NULL); + getobname(wep, obname, 1); + msg("Your %s glows with a brilliant heat!", noprefix(obname)); + } else { // already has pyromania. + rollagain = B_TRUE; + } + } else { + rollagain = B_TRUE; + } + break; + case 2: // fire resist/immune + if (lfhasflagval(player, F_DTRESIST, DT_FIRE, NA, NA, NULL)) { + if (lfhasflagval(player, F_DTIMMUNE, DT_FIRE, NA, NA, NULL)) { + rollagain = B_TRUE; + } else { + flag_t *f; + f = addtempflag(player->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL, FROMGODGIFT); + f->obfrom = god->race->id; + } + } else { + flag_t *f; + f = addtempflag(player->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL, FROMGODGIFT); + f->obfrom = god->race->id; + } + break; + case 3: // fire-related spellbook, or fire magic skill + if (getskill(player, SK_SS_FIRE)) { + snprintf(obtogive, BUFLEN, "spellbook of Fire Magic"); + } else { + flag_t *f; + f = giveskill(player, SK_SS_FIRE); + if (f) { + f->obfrom = god->race->id; + } else { + rollagain = B_TRUE; + } + } + break; + } + } + break; + case R_GODLIFE: + while (rollagain) { + object_t *wep; + flag_t *f; + wep = getweapon(player); + rollagain = B_FALSE; + switch (rnd(1,4)) { + case 1: // regeneration + if (lfhasflag(player, F_REGENERATES)) { + rollagain = B_TRUE; + } else { + f = addtempflag(player->flags, F_REGENERATES, 1, NA, NA, NULL, FROMGODGIFT); + f->obfrom = god->race->id; + } + break; + case 2: // learn first aid skill + f = giveskill(player, SK_FIRSTAID); + if (f) { + f->obfrom = god->race->id; + } else { + rollagain = B_TRUE; + } + break; + case 3: // life-related spellbook, or life magic skill + if (getskill(player, SK_SS_LIFE)) { + snprintf(obtogive, BUFLEN, "spellbook of Life Magic"); + } else { + flag_t *f; + f = giveskill(player, SK_SS_LIFE); + if (f) { + f->obfrom = god->race->id; + } else { + rollagain = B_TRUE; + } + } + break; + case 4: // increase max hp + player->maxhp += rollhitdice(player, B_TRUE); + statdirty = B_TRUE; + msg("\"I have increased your tolerance to injury!\""); + break; + } + } + break; case R_GODMAGIC: while (rollagain) { rollagain = B_FALSE; @@ -853,26 +990,22 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { while (rollagain) { flag_t *f; rollagain = B_FALSE; - switch (rnd(1,4)) { + switch (rnd(1,3)) { case 1: - snprintf(obtogive, BUFLEN, "3 vials of ambrosia"); + snprintf(obtogive, BUFLEN, "3-4 potions of restoration"); break; case 2: - snprintf(obtogive, BUFLEN, "ring of regeneration"); - break; - case 3: - snprintf(obtogive, BUFLEN, "ring of miracles"); - break; - case 4: // immune to disease / poison - if (lfhasflag(player, F_DISEASEIMMUNE)) { - if (lfhasflagval(player, F_DTIMMUNE, DT_POISON, NA, NA, NULL)) { - rollagain = B_TRUE; - } else { - f = addtempflag(player->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL, FROMGODGIFT); - f->obfrom = god->race->id; - } + if (hasob(player->pack, OT_RING_MIRACLES)) { + rollagain = B_TRUE; } else { - f = addtempflag(player->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL, FROMGODGIFT); + snprintf(obtogive, BUFLEN, "ring of miracles"); + } + break; + case 3: // sixth sense + if (lfhasflag(player, F_SIXTHSENSE)) { + rollagain = B_TRUE; + } else { + f = addtempflag(player->flags, F_SIXTHSENSE, B_TRUE, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; @@ -955,66 +1088,77 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { } break; case R_GODPURITY: - while (rollagain) { - flag_t *f; - rollagain = B_FALSE; - switch (rnd(1,4)) { - case 1: - snprintf(obtogive, BUFLEN, "2-4 blessed potions of water"); - break; - case 2: - snprintf(obtogive, BUFLEN, "blessed great weapon"); - break; - case 3: - snprintf(obtogive, BUFLEN, "wand of turn undead"); - break; - case 4: // holy aura - if (lfhasflag(player, F_HOLYAURA)) { - rollagain = B_TRUE; - } else { - f = addtempflag(player->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL, FROMGODGIFT); - f->obfrom = god->race->id; - f = addtempflag(player->flags, F_HOLYAURA, NA, NA, NA, NULL, FROMGODGIFT); - f->obfrom = god->race->id; - } - break; + if (!hasob(player->pack, OT_POT_RESTORATION)) { + snprintf(obtogive, BUFLEN, "2-3 blessed potions of restoration"); + } else { + while (rollagain) { + flag_t *f; + rollagain = B_FALSE; + switch (rnd(1,3)) { + case 1: + snprintf(obtogive, BUFLEN, "2-3 blessed potions of water"); + break; + case 2: + snprintf(obtogive, BUFLEN, "wand of turn undead"); + break; + case 3: // holy aura + if (lfhasflag(player, F_HOLYAURA)) { + rollagain = B_TRUE; + } else { + f = addtempflag(player->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL, FROMGODGIFT); + f->obfrom = god->race->id; + f = addtempflag(player->flags, F_HOLYAURA, NA, NA, NA, NULL, FROMGODGIFT); + f->obfrom = god->race->id; + } + break; + } } } break; case R_GODTHIEVES: while (rollagain) { + object_t *wep; rollagain = B_FALSE; - switch (rnd(1,7)) { - case 1: - if (getskill(player, SK_TECHUSAGE) >= gettechlevel(OT_LOCKHACKER)) { - snprintf(obtogive, BUFLEN, "lock hacker"); - } else { - snprintf(obtogive, BUFLEN, "3-6 blessed lockpicks"); - } - break; - case 2: - if (onein(6)) { - snprintf(obtogive, BUFLEN, "large bag of holding"); - } else { - snprintf(obtogive, BUFLEN, "bag of holding"); - } - break; - case 3: - snprintf(obtogive, BUFLEN, "safebox"); - break; - case 4: - snprintf(obtogive, BUFLEN, "wand of opening"); - break; - case 5: - snprintf(obtogive, BUFLEN, "wand of invisibility"); - break; - case 6: - snprintf(obtogive, BUFLEN, "3-6 potions of invisibility"); - break; - case 7: - snprintf(obtogive, BUFLEN, "leather boots of stealth"); - break; + wep = getweapon(player); + if (wep && !hasflag(wep->flags, F_HASBRAND)) { + char obname[BUFLEN]; + getobname(wep,obname,1); + // announce + msg("Your %s vibrates, and you suddenly thirst for vengeance!", noprefix(obname)); + addflag(wep->flags, F_REVENGE, B_TRUE, NA, NA, NULL); + } else { + switch (rnd(1,7)) { + case 1: + if (getskill(player, SK_TECHUSAGE) >= gettechlevel(OT_LOCKHACKER)) { + snprintf(obtogive, BUFLEN, "lock hacker"); + } else { + snprintf(obtogive, BUFLEN, "3-6 blessed lockpicks"); + } + break; + case 2: + if (onein(6)) { + snprintf(obtogive, BUFLEN, "large bag of holding"); + } else { + snprintf(obtogive, BUFLEN, "bag of holding"); + } + break; + case 3: + snprintf(obtogive, BUFLEN, "safebox"); + break; + case 4: + snprintf(obtogive, BUFLEN, "wand of opening"); + break; + case 5: + snprintf(obtogive, BUFLEN, "wand of invisibility"); + break; + case 6: + snprintf(obtogive, BUFLEN, "3-6 potions of invisibility"); + break; + case 7: + snprintf(obtogive, BUFLEN, "leather boots of stealth"); + break; + } } } break; @@ -1082,8 +1226,11 @@ void godsay(enum RACE rid, int says, char *format, ...) { case R_GODDEATH: strcpy(voiceverb, "grates against your mind"); break; - case R_GODTHIEVES: - strcpy(voiceverb, "whispers in your ear"); + case R_GODFIRE: + strcpy(voiceverb, "burns into your mind"); + break; + case R_GODLIFE: + strcpy(voiceverb, "chimes out from the heavens"); break; case R_GODMAGIC: strcpy(voiceverb, "enters your thoughts"); @@ -1098,6 +1245,9 @@ void godsay(enum RACE rid, int says, char *format, ...) { strcpy(voiceverb, "arrives with a gentle breeze"); } break; + case R_GODTHIEVES: + strcpy(voiceverb, "whispers in your ear"); + break; case R_GODPURITY: default: strcpy(voiceverb, "booms out from the heavens"); @@ -1143,6 +1293,16 @@ void pleasegod(enum RACE rid, int amt) { case R_GODDEATH: msg("You feel a thrill of unholy ecstasy."); break; + case R_GODFIRE: + msg("A searing heat runs through your blood."); + break; + case R_GODLIFE: + if (isdeaf(player)) { + msg("You have a feeling of holiness."); + } else { + msg("You hear a distance choir singing."); + } + break; case R_GODMAGIC: msg("You feel Lumara's presense nearby."); break; @@ -1153,7 +1313,7 @@ void pleasegod(enum RACE rid, int amt) { msg("You feel a sense of serenity."); break; case R_GODPURITY: - msg("You hear a distant choir singing."); + msg("You feel righteous."); break; case R_GODTHIEVES: msg("You feel a guilty pleasure."); @@ -1186,7 +1346,7 @@ void pleasegodmaybe(enum RACE rid, int amt) { } int prayto(lifeform_t *lf, lifeform_t *god) { - int piety,i; + int piety,i,x,y; char assisttext[BUFLEN]; taketime(lf, getactspeed(lf)); @@ -1239,6 +1399,15 @@ int prayto(lifeform_t *lf, lifeform_t *god) { case R_GODDEATH: strcpy(assisttext, "You desire a favour, fleshling?"); break; + case R_GODFIRE: + switch (rnd(1,2)) { + case 1: strcpy(assisttext, "BURN!"); break; + case 2: strcpy(assisttext, "DESTROY!"); break; + } + break; + case R_GODLIFE: + strcpy(assisttext, "You prayer is answered!"); + break; case R_GODMERCY: strcpy(assisttext, "I hear your prayer, child."); break; @@ -1363,6 +1532,8 @@ int prayto(lifeform_t *lf, lifeform_t *god) { } if (isinbattle(lf, B_TRUE)) { + int i,nretflags; + flag_t *retflag[MAXCANDIDATES]; // smite evil for (l = lf->cell->map->lf ; l ; l = l->next) { if (getalignment(l) == AL_EVIL) { @@ -1371,22 +1542,62 @@ int prayto(lifeform_t *lf, lifeform_t *god) { castspell(god, OT_S_SMITEEVIL, l, NULL, l->cell, NULL, NULL); } } - } - // turn undead + } + + // turn undead TODO: move this to 'life' god castspell(god, OT_S_TURNUNDEAD, lf, NULL, NULL, NULL, NULL); + + // remove all temporary bad status effects + getflags(player->flags, retflag, &nretflags, F_BLIND, F_CONFUSED, F_DEAF, F_CAFFEINATED, F_DRUNK, F_FROZEN, + F_GRABBEDBY, F_NAUSEATED, F_PAIN, F_POISONED, F_SLOWACT, F_SLOWMOVE, F_SLOWACTMOVE, F_NONE); + for (i = 0; i < nretflags; i++) { + if (istransitoryflag(retflag[i])) { + killflag(retflag[i]); + } + } } else { object_t *wep; + flag_t *f; int donesomething = B_FALSE; - wep = getweapon(player); - if (wep && !isblessed(wep)) { - blessob(wep); - donesomething = B_TRUE; - } + // restore original lifeform shape + if (!donesomething) { + f = lfhasflag(lf, F_ORIGRACE); + if (f) { + setrace(lf, f->val[0], B_TRUE); + donesomething = B_TRUE; + } + } + + // restore to original lifeform size + if (!donesomething) { + f = hasflag(lf->race->flags, F_SIZE); + if (f && (getlfsize(lf) != f->val[0])) { + resizelf(lf, f->val[0]); + donesomething = B_TRUE; + } + } + + // purify your food + if (!donesomething) { + if (!dospelleffects(god, OT_S_PURIFYFOOD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE)) { + donesomething = B_TRUE; + } + } + + // bless your weapon + if (!donesomething) { + wep = getweapon(player); + if (wep && !isblessed(wep)) { + blessob(wep); + donesomething = B_TRUE; + } + } + + // bless 1-3 random obs if (!donesomething) { int nposs = 0, n; object_t *o,*poss[MAXCANDIDATES]; - // bless 1-3 obs nposs = 0; n = rnd(1,3); // num to bless for (o = player->pack->first ; o ; o = o->next) { @@ -1450,6 +1661,68 @@ int prayto(lifeform_t *lf, lifeform_t *god) { } dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); break; + case R_GODFIRE: + // restore frozen weapons + o = getweapon(player); + if (o && (o->material->id == MT_ICE) && (o->material != o->type->material)) { + changemat(o, o->type->material->id); + } + // set all nearby non-cosmetic objects on fire + i = 0; + for (y = 0; y < player->cell->map->h; y++) { + for (x = 0; x < player->cell->map->w; x++) { + cell_t *c; + c = getcellat(player->cell->map, x, y); + if (c && cellhaslos(c, player->cell)) { + if (c->lf && (c->lf != player)) { + dospelleffects(NULL, OT_S_FLAMEPILLAR, 10, NULL, NULL, + c, B_BLESSED, NULL, B_TRUE); + } else if (countnoncosmeticobs(c->obpile, B_FALSE, B_FALSE)) { + addobfast(c->obpile, OT_FIRESMALL); + i++; + } + + } + } + } + if (i) { + msg("Nearby objects erupt in flames!"); more(); + } + break; + case R_GODLIFE: + if (ispoisoned(lf)) { + castspell(god, OT_S_CUREPOISON, player, NULL, player->cell, NULL, NULL); + donesomething = B_TRUE; + } + if (gethungerlevel(gethungerval(player)) >= H_PECKISH) { + dospelleffects(NULL, OT_S_SATEHUNGER, 10, player, NULL, player->cell, B_UNCURSED, NULL, B_FALSE); + donesomething = B_TRUE; + } + if (lf->mp < getmaxmp(lf)) { + gainmp(lf, getmaxmp(lf)); + donesomething = B_TRUE; + } + if (lfhasflag(lf, F_INJURY)) { + castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL); + donesomething = B_TRUE; + } + if (lf->hp < lf->maxhp) { + lf->hp = lf->maxhp; + donesomething = B_TRUE; + statdirty = B_TRUE; + + } + if (isinbattle(lf, B_TRUE)) { + enum PIETYLEV plev; + plev = getpietylev(R_GODLIFE, NULL, NULL); + if (plev >= PL_INDIFFERENT) { + dospelleffects(NULL, OT_S_HEAVENARM, plev+1, player, NULL, player->cell, B_UNCURSED, NULL, B_FALSE); + } + } + if (donesomething) { + msg("\"Rejoice in life!\""); + } + break; case R_GODTHIEVES: if (isinbattle(lf, B_TRUE)) { lifeform_t *l; @@ -1467,7 +1740,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) { case 1: // steal from your enemies for (l = lf->cell->map->lf ; l ; l = l->next) { - if ((l != lf) && areenemies(l, lf)) { + if ((l != lf) && areenemies(l, lf) && cansee(l, lf)) { object_t *wep; // confiscate their weapon wep = getweapon(l); @@ -1605,20 +1878,64 @@ int prayto(lifeform_t *lf, lifeform_t *god) { } break; case R_GODMERCY: - if (ispoisoned(lf)) { - msg("\"Let thy body be purged of toxins.\""); - castspell(god, OT_S_CUREPOISON, player, NULL, player->cell, NULL, NULL); - donesomething = B_TRUE; - } - if (gethungerlevel(gethungerval(player)) >= H_PECKISH) { - msg("\"Let thy stomach be satisfied.\""); - castspell(god, OT_S_SATEHUNGER, player, NULL, player->cell, NULL, NULL); - donesomething = B_TRUE; - } - if (islowhp(lf)) { - msg("\"Let thy wounds be healed.\""); - castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL); - donesomething = B_TRUE; + if (isinbattle(lf, B_TRUE)) { + lifeform_t *l; + int donesomething = B_FALSE; + int preventstoning = B_FALSE; + int preventparalysis = B_FALSE; + + // if something nearby could stone/petrify you, confer temporary immunity. + for (l = lf->cell->map->lf ; l ; l = l->next) { + if ((l != lf) && areenemies(l, lf) && cansee(l, lf)) { + obpile_t *op = NULL; + int nweps = 0; + object_t *wep[MAXCANDIDATES]; + flag_t *damflag[MAXCANDIDATES]; + int lastweaponidx; + if (l->race->id == R_COCKATRICE) { + preventstoning = B_TRUE; + } + getweapons(l, wep, damflag, &lastweaponidx, &op, &nweps); + for (i = 0; i < nweps; i++) { + if (hasflagval(wep[i]->flags, F_HITCONFER, F_PARALYZED, NA, NA, NULL)) { + preventparalysis = B_TRUE; + break; + } + } + if (op) killobpile(op); + } + } + if (preventstoning || preventparalysis) { + addtempflag(player->flags, F_DTIMMUNE, DT_PETRIFY, NA, NA, NULL, rnd(40,50)); + donesomething = B_TRUE; + } + + + // sleep on all enemies + if (!donesomething) { + for (l = lf->cell->map->lf ; l ; l = l->next) { + if ((l != lf) && areenemies(l, lf) && cansee(l, lf)) { + castspell(god, OT_S_SLEEP, l, NULL, l->cell, NULL, NULL); + donesomething = B_TRUE; + } + } + } + } else { + if (ispoisoned(lf)) { + msg("\"Let thy body be purged of toxins.\""); + castspell(god, OT_S_CUREPOISON, player, NULL, player->cell, NULL, NULL); + donesomething = B_TRUE; + } + if (gethungerlevel(gethungerval(player)) >= H_PECKISH) { + msg("\"Let thy stomach be satisfied.\""); + castspell(god, OT_S_SATEHUNGER, player, NULL, player->cell, NULL, NULL); + donesomething = B_TRUE; + } + if (islowhp(lf)) { + msg("\"Let thy wounds be healed.\""); + castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL); + donesomething = B_TRUE; + } } // uncurse one equipped ob @@ -1636,7 +1953,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) { msg("\"My children will bind your enemies!\""); // entangle your enemies for (l = lf->cell->map->lf ; l ; l = l->next) { - if ((l != lf) && areenemies(l, lf)) { + if ((l != lf) && areenemies(l, lf) && cansee(l, player)) { dospelleffects(NULL, OT_S_ENTANGLE, 10, NULL, NULL, l->cell, B_BLESSED, NULL, B_TRUE); } } @@ -1648,7 +1965,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) { case 3: // lightning msg("\"The powers of the sky will smite your foes!\""); for (l = lf->cell->map->lf ; l ; l = l->next) { - if ((l != lf) && areenemies(l, lf)) { + if ((l != lf) && areenemies(l, lf) && cansee(l, player)) { dospelleffects(god, OT_S_CALLLIGHTNING, 10, NULL, NULL, l->cell, B_BLESSED, NULL, B_TRUE); } } diff --git a/io.c b/io.c index e238239..e099891 100644 --- a/io.c +++ b/io.c @@ -1468,6 +1468,15 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_HEAVENARM: + if (isplayer(lf)) { // don't know if monsters get it + msg("You are surrounded by a shell of divine armour!"); + donesomething = B_TRUE; + } else { + msg("%s is surrounded by a shell of divine armour!", lfname); + donesomething = B_TRUE; + } + break; case F_HIDING: if (isplayer(lf)) { // don't know if monsters get it if (f->val[0] < 0) { @@ -1779,6 +1788,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_SIXTHSENSE: + if (isplayer(lf)) { // don't know if monsters get it + msg("You will now be warned of creatures behind you."); + donesomething = B_TRUE; + } + break; case F_SPRINTING: msg("%s %s sprinting!",lfname, isplayer(lf) ? "start" : "starts"); donesomething = B_TRUE; @@ -2159,6 +2174,15 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { donesomething = B_TRUE; } break; + case F_HEAVENARM: + if (isplayer(lf)) { // don't know if monsters get it + msg("Your shell of divine armour vanishes!"); + donesomething = B_TRUE; + } else { + msg("%s%s shield of divine armour vanishes!", lfname, getpossessive(lfname)); + donesomething = B_TRUE; + } + break; case F_HIDING: if (isplayer(lf)) { // don't know if monsters lose it msg("You are no longer hidden."); @@ -2393,6 +2417,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { msg("%s %s",lfname, isplayer(lf) ? "speed back up." : "speeds back up."); donesomething = B_TRUE; break; + case F_SIXTHSENSE: + if (isplayer(lf)) { // don't know if monsters get it + msg("You will no longer be warned of creatures behind you."); + donesomething = B_TRUE; + } + break; case F_SPIDERCLIMB: if (isplayer(lf)) { msg("Your skin is no longer adhesive."); @@ -6035,6 +6065,10 @@ char *makedesc_ob(object_t *o, char *retbuf) { sprintf(buf2, "%s prevents you from forgetting your surroundings.\n", buf); strncat(retbuf, buf2, HUGEBUFLEN); break; + case F_SIXTHSENSE: + sprintf(buf2, "%s warns you about nearby enemies.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; case F_STABILITY: sprintf(buf2, "%s prevents you from slipping over.\n", buf); strncat(retbuf, buf2, HUGEBUFLEN); @@ -11385,6 +11419,31 @@ void showlfstats(lifeform_t *lf, int showall) { y += 2; + // gods angry? + if (isplayer(lf)) { + if (godprayedto(R_GODLIFE)) { + enum PIETYLEV plev; + plev = getpietylev(R_GODLIFE, NULL, NULL); + if (plev <= PL_ANGRY) { + mvwprintw(mainwin, y, 0, "You have been cut off from Life magic.", you(lf)); + y++; + } + if (plev == PL_ANGRY) { + mvwprintw(mainwin, y, 0, "The Goddess of Life has slowed your body's natural healing.", you(lf)); + y++; + } else if ((plev == PL_FURIOUS) || (plev == PL_ENRAGED)) { + mvwprintw(mainwin, y, 0, "The Goddess of Life has nullified your body's natural healing.", you(lf)); + y++; + } + } + if (godprayedto(R_GODNATURE) && godisangry(R_GODNATURE)) { + mvwprintw(mainwin, y, 0, "You have been cut off from Nature magic.", you(lf)); + y++; + mvwprintw(mainwin, y, 0, "The Goddess of Nature has cursed you with a rotting touch.", you(lf)); + y++; + } + } + // ready to gain a level? if (lfhasflag(lf, F_STATGAINREADY)) { mvwprintw(mainwin, y, 0, "%s are ready to train your attributes.", you(lf)); @@ -11556,6 +11615,11 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "%s adhesive skin allows %s to climb walls.", your(lf), you(lf)); y++; } + f = lfhasknownflag(lf, F_SIXTHSENSE); + if (f && (f->known) && (f->lifetime != FROMRACE)) { + mvwprintw(mainwin, y, 0, "%s will be warned about nearby enemies.", you(lf)); + y++; + } f = lfhasknownflag(lf, F_STABILITY); if (f && (f->known) && (f->lifetime != FROMRACE)) { mvwprintw(mainwin, y, 0, "%s will not fall on slippery ground.", you(lf)); @@ -11997,6 +12061,11 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "Gravity is lessened around %s, preventing fall damage, increasing flight speed and reducing load.", you_l(lf)); y++; } + f = lfhasknownflag(lf, F_HEAVENARM); + if (f && (f->known)) { + mvwprintw(mainwin, y, 0, "%s %s surrounded by a shell of divine armour. ", you(lf), is(lf)); + y++; + } f = lfhasknownflag(lf, F_INVULNERABLE); if (f && (f->known)) { mvwprintw(mainwin, y, 0, "%s %s protected from all physical harm.", you(lf), is(lf)); diff --git a/lf.c b/lf.c index bfc754e..d79f959 100644 --- a/lf.c +++ b/lf.c @@ -1663,10 +1663,18 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar } } // casting a nature spell while nature god is angry at you? - if (isplayer(lf) && godprayedto(R_GODNATURE) && godisangry(R_GODNATURE) && !willflag) { - if (hasflagval(sp->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL)) { - msg("You seem to be cut off from the powers of nature magic."); - return B_FALSE; + if (isplayer(lf) && !willflag) { + if (godprayedto(R_GODNATURE) && godisangry(R_GODNATURE)) { + if (hasflagval(sp->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL)) { + msg("You seem to be cut off from the powers of nature magic."); + return B_FALSE; + } + } + if (godprayedto(R_GODLIFE) && godisangry(R_GODLIFE)) { + if (hasflagval(sp->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL)) { + msg("You seem to be cut off from the powers of life magic."); + return B_FALSE; + } } } @@ -1813,12 +1821,18 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar angergodmaybe(R_GODBATTLE, 25, GA_SPELL); } switch (school) { + case SS_COLD: + angergodmaybe(R_GODFIRE, getspelllevel(sid)*5, GA_SPELL); + break; case SS_DEATH: pleasegodmaybe(R_GODDEATH, getspelllevel(sid)); angergodmaybe(R_GODPURITY, getspelllevel(sid)*5, GA_SPELL); break; + case SS_FIRE: + pleasegodmaybe(R_GODFIRE, getspelllevel(sid)*2); + break; case SS_LIFE: - pleasegodmaybe(R_GODPURITY, getspelllevel(sid)); + pleasegodmaybe(R_GODLIFE, getspelllevel(sid)*2); angergodmaybe(R_GODDEATH, getspelllevel(sid)*5, GA_SPELL); break; case SS_NATURE: @@ -2347,6 +2361,17 @@ void die(lifeform_t *lf) { willbecomeghost = B_TRUE; } + // died after entering a new level without a chance to move? + if (isplayer(lf) && lfhasflag(lf, F_JUSTENTERED) && godprayedto(R_GODMERCY)) { + godsay(R_GODMERCY, B_TRUE, "Well, that seems unfair..."); more(); + // return to full health + lf->hp = lf->maxhp; + statdirty = B_TRUE; + // teleport away! + dospelleffects(NULL, OT_S_DISPERSAL, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE); + return; + } + if (useringofmiracles(lf, 3)) { int hunger; // return to full health @@ -2458,7 +2483,7 @@ void die(lifeform_t *lf) { case R_GODDEATH: godsay(god->race->id, B_TRUE, "Come to me, my servant..."); more(); msg("Bony claws rise up and drag your corpse underground."); more(); break; - case R_GODPURITY: + case R_GODLIFE: msg("Your spirit ascends to the heavens."); more(); break; case R_GODTHIEVES: // lose all gold / gems if (countmoney(player->pack)) { @@ -2543,7 +2568,8 @@ void die(lifeform_t *lf) { if (hasflag(lf->flags, F_KILLEDBYPLAYER)) { awardxpfor(lf,100); if ((getalignment(lf) == AL_EVIL) || isundead(lf)) { - pleasegodmaybe(R_GODPURITY, 3); + pleasegodmaybe(R_GODPURITY, 5); + pleasegodmaybe(R_GODLIFE, 5); } else if (getalignment(lf) == AL_GOOD) { pleasegodmaybe(R_GODDEATH, 3); } else { // ie. neutral @@ -2555,9 +2581,13 @@ void die(lifeform_t *lf) { pleasegodmaybe(R_GODNATURE, 50); break; default: + pleasegodmaybe(R_GODFIRE, 5); break; } + if (lf->lastdamtype == DT_FIRE) { + + } // mercy god doesn't like killing //angergodmaybe(R_GODMERCY, 1, GA_MURDER); } @@ -12681,15 +12711,13 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml prelowhp = B_TRUE; } - // check for psychic armour etc + // check for protective spells if (amt > 0) { if (isphysicaldam(damtype)) { int i; - - getflags(lf->flags, retflag, &nretflags, F_MAGICARMOUR, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_HEAVENARM, F_MAGICARMOUR, F_NONE); for (i = 0; i < nretflags; i++) { int damtaken; - f = retflag[i]; damtaken = amt; if (damtaken > f->val[0]) { @@ -12795,6 +12823,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml } } + // large damage will be stopped by a ring of miracles if ((amt >= (lf->maxhp / 2)) && (amt >= 20)) { if (useringofmiracles(lf, 1)) { @@ -12862,6 +12891,9 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml } } } + if (fromlf) { + angergodmaybe(R_GODFIRE, 25, GA_HERESY); + } } else if (damtype == DT_FIRE) { int i; // fire will cauterise slash wounds @@ -12986,10 +13018,10 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml if (!isunconscious(lf)) { // you are knocked unconscious for a _long_ time fallasleep(lf, ST_KO, rnd(50,100)); + breakgrabs(lf, B_TRUE, B_FALSE); if (fromlf && isplayer(fromlf)) { pleasegodmaybe(R_GODMERCY, 5); } - breakgrabs(lf, B_TRUE, B_FALSE); } } else { // you wake up if you were hit, unless you were unconscious! @@ -16495,6 +16527,7 @@ void startlfturn(lifeform_t *lf) { if (isplayer(lf) && lfhasflag(lf, F_DRUNK)) statdirty = B_TRUE; // clear one-turn-only flags + killflagsofid(lf->flags, F_JUSTENTERED); killflagsofid(lf->flags, F_UNSEENATTACKER); killflagsofid(lf->flags, F_DONELISTEN); killflagsofid(lf->flags, F_NOSWAP); @@ -16684,7 +16717,7 @@ void startlfturn(lifeform_t *lf) { } // sixth sense spell warnings - f = hasactivespell(lf, OT_S_SIXTHSENSE); + f = lfhasflag(lf, F_SIXTHSENSE); if (f) { cell_t *retcell[MAXCANDIDATES]; int nretcells; @@ -16696,12 +16729,12 @@ void startlfturn(lifeform_t *lf) { reldir = getrelativedir(lf, dir); if (reldir != RD_FORWARDS) { if (isplayer(lf)) { - if (f->val[2] >= 5) { + if (f->val[0] >= 5) { char buf[BUFLEN]; real_getlfnamea(retcell[i]->lf, buf, B_FALSE, B_FALSE); warn("^WYour sixth sense warns you of %s %s you!", buf, (reldir == RD_BACKWARDS) ? "behind" : "beside" ); - } else if (f->val[2] >= 3) { + } else if (f->val[0] >= 3) { warn("^WYour sixth sense warns you of %s %s %s you!", needan(retcell[i]->lf->race->raceclass->name) ? "an" : "a", retcell[i]->lf->race->raceclass->name, @@ -16710,7 +16743,7 @@ void startlfturn(lifeform_t *lf) { warn("^WYour sixth sense warns you of something %s you!", (reldir == RD_BACKWARDS) ? "behind" : "beside" ); } - if (f->val[2] >= 7) { + if (f->val[0] >= 7) { char ch; ch = askchar("Turn to face the threat", "yn","y", B_TRUE, B_FALSE); if (ch == 'y') { @@ -16720,7 +16753,7 @@ void startlfturn(lifeform_t *lf) { more(); } } - stopspell(lf, OT_S_SIXTHSENSE); + killflag(f); break; } } @@ -16761,6 +16794,10 @@ void startlfturn(lifeform_t *lf) { } } + if (hasactivespell(lf, OT_S_SIXTHSENSE) && !hasflag(lf->flags, F_SIXTHSENSE)) { + stopspell(lf, OT_S_SIXTHSENSE); + } + if (lfhasflag(lf, F_MAGSHIELD)) { object_t *nexto; // metal weapons? @@ -19104,6 +19141,15 @@ int rest(lifeform_t *lf, int onpurpose) { limit(&healtime, 1, NA); } } + if (isplayer(lf) && godprayedto(R_GODLIFE) && godisangry(R_GODLIFE)) { + enum PIETYLEV plev; + plev = getpietylev(R_GODLIFE, NULL, NULL); + if (plev <= PL_FURIOUS) { + healtime = 0; // ie. never heal! + } else { + healtime *= 2; + } + } if (f->val[0] >= healtime) { int difficulty; @@ -19131,7 +19177,7 @@ int rest(lifeform_t *lf, int onpurpose) { if (skillcheck(lf, SC_CON, difficulty, getskill(lf, SK_FIRSTAID))) { gainhp(lf, hpheal); if (isplayer(lf)) { - pleasegodmaybe(R_GODMERCY, 1); + pleasegodmaybe(R_GODLIFE, 1); } practice(lf, SK_FIRSTAID, 1); } diff --git a/map.c b/map.c index b719546..ac96e80 100644 --- a/map.c +++ b/map.c @@ -4840,7 +4840,7 @@ void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *c } - damageallobs(o, c->obpile, dam, DT_EXPLOSIVE); + damageallobs(o, c->obpile, dam, DT_EXPLOSIVE, NULL); if (killwalls) { if (c->type->solid) { diff --git a/move.c b/move.c index ec49900..640ff41 100644 --- a/move.c +++ b/move.c @@ -169,7 +169,11 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err return B_FALSE; } - wis = getattrbracket(getattr(lf, A_WIS), A_WIS, NULL); + if (lf && isplayer(lf) && godprayedto(R_GODMERCY)) { + wis = AT_VHIGH; + } else { + wis = getattrbracket(getattr(lf, A_WIS), A_WIS, NULL); + } // obvious things that you can see if (!onlyifknown || (haslos(lf, cell) && !lfhasflag(lf, F_UNDEAD))) { @@ -1083,7 +1087,6 @@ int moveeffects(lifeform_t *lf) { } } - return didmsg; } @@ -1121,10 +1124,16 @@ int movelf(lifeform_t *lf, cell_t *newcell) { } } + if (changedlev) { + // used for one of Yumi's effects + addflag(lf->flags, F_JUSTENTERED, B_TRUE, NA, NA, NULL); + } + // special effects when the player moves to a new map if (changedlev && isplayer(lf)) { object_t *o; long barrierid = -1; + // mapentereffects will give all monster on the new map // a bunch of turns to simulate time passing while the player // was away. to prevent them from blocking off the staircase cell @@ -1623,7 +1632,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) { if (isplayer(lf)) { // see/feel objects on ground int numobs; - numobs = countnoncosmeticobs(newcell->obpile, B_TRUE); + numobs = countnoncosmeticobs(newcell->obpile, B_TRUE, B_TRUE); if ((numobs == 0) && !newcell->writing) { // just clear the message buffer if (!didmsg) clearmsg(); @@ -1772,10 +1781,19 @@ int opendoor(lifeform_t *lf, object_t *o) { char buf[BUFLEN]; char obname[BUFLEN]; flag_t *f; + enum ATTRBRACKET wis = AT_AVERAGE; doorcell = o->pile->where; assert(doorcell); + if (lf) { + if (isplayer(lf) && godprayedto(R_GODMERCY)) { + wis = AT_VHIGH; + } else { + wis = getattrbracket(getattr(lf, A_WIS), A_WIS, NULL); + } + } + getobname(o, obname, 1); if (!isdoor(o, NULL)) { @@ -1820,7 +1838,7 @@ int opendoor(lifeform_t *lf, object_t *o) { cell_t *pastdoorcell; // has known trap? if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) { - if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_AVERAGE) { + if (wis >= AT_AVERAGE) { char ch; snprintf(buf, BUFLEN,"Really open %s?", obname); ch = askchar(buf,"yn","n", B_TRUE, B_FALSE); @@ -1835,7 +1853,7 @@ int opendoor(lifeform_t *lf, object_t *o) { pastdoorcell = getcellindir(doorcell, dir); if (pastdoorcell && getcellwaterdepth(pastdoorcell, NULL)) { if (getskill(lf, SK_LISTEN) || haslos(lf, pastdoorcell)) { - if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_AVERAGE) { + if (wis >= AT_AVERAGE) { char ch; snprintf(buf, BUFLEN,"%s running water behind %s. Really open it?", haslos(lf, pastdoorcell) ? "There is" : "You can hear", obname); @@ -2560,7 +2578,7 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) { // show any objects here, just like if we moved. // BUT don't let dolook() clear the msg bar if there are // no objects here. - if (isplayer(lf) && countnoncosmeticobs(lf->cell->obpile, B_TRUE)) { + if (isplayer(lf) && countnoncosmeticobs(lf->cell->obpile, B_TRUE, B_TRUE)) { dolook(lf->cell, B_FALSE); } return B_FALSE; @@ -2570,6 +2588,8 @@ void triggertrap(lifeform_t *lf, object_t *o, object_t *trapob, cell_t *where) { char triggerer[BUFLEN]; char trapname[BUFLEN]; int wants; + flag_t *wassecret = NULL; + wassecret = hasflag(trapob->flags, F_SECRET); getobname(trapob, trapname, 1); if (lf) { getlfname(lf, triggerer); @@ -2587,6 +2607,17 @@ void triggertrap(lifeform_t *lf, object_t *o, object_t *trapob, cell_t *where) { // no longer hidden killflagsofid(trapob->flags, F_SECRET); } + + if (lf && wassecret && isplayer(lf) && godprayedto(R_GODMERCY)) { + enum PIETYLEV plev; + plev = getpietylev(R_GODMERCY, NULL, NULL); + if ((plev >= PL_PLEASED) && pctchance(plev*33)) { + godsay(R_GODMERCY, B_TRUE, "We all make mistakes..."); + // bamf away + dospelleffects(NULL, OT_S_BLINK, 1, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE); + } + } + // NOTE: after trapeffects(), oo might be killed. trapeffects(trapob, trapob->type->id, where); if (lf) interrupt(lf); diff --git a/objects.c b/objects.c index 273249c..93bc129 100644 --- a/objects.c +++ b/objects.c @@ -2900,11 +2900,12 @@ int countobswithflagval(obpile_t *op, enum FLAG flagid, int val0, int val1, int return count; } -int countnoncosmeticobs(obpile_t *op, int onlyifknown) { +int countnoncosmeticobs(obpile_t *op, int onlyifknown, int includetrails) { object_t *o; int count = 0; for (o = op->first ; o ; o = o->next) { + if (hasflag(o->flags, F_TRAIL) && !includetrails) continue; if (!hasflag(o->flags, F_COSMETIC) && !hasflag(o->flags, F_SECRET)) { if (onlyifknown) { if (canseeob(player, o)) { @@ -2962,8 +2963,9 @@ int curseob(object_t *o) { return rv; } -void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype) { +void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype, lifeform_t *srclf) { object_t *o, *nexto; + int nhurt = 0; for (o = op->first ; o ; o = nexto) { nexto = o->next; @@ -2974,6 +2976,14 @@ void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype) { if ((o != srcob) && !hasflag(o->flags, F_DEAD)) { takedamage(o, howmuch, damtype); + nhurt++; + } + } + if (srclf) { + if (isplayer(srclf)) { + if (basedamagetype(damtype) == DT_FIRE) { + pleasegodmaybe(R_GODFIRE, nhurt*2); + } } } } @@ -6307,7 +6317,7 @@ char *gettopobname(cell_t *c, char *retbuf) { getobname(o, buf, o->amt); strcat(retbuf, buf); // other obs here too? - nother = countnoncosmeticobs(c->obpile, B_TRUE) - 1; + nother = countnoncosmeticobs(c->obpile, B_TRUE, B_TRUE) - 1; if (nother >= 1) { snprintf(buf, BUFLEN, " (+%d other thing%s)", nother, (nother == 1) ? "" : "s"); strcat(retbuf, buf); @@ -6638,20 +6648,8 @@ int isbetterwepthan(object_t *a, object_t *b, lifeform_t *owner) { getdamrange(b, NULL, NULL, &damb); // modify based on extra props - if (hasflag(a->flags, F_HASBRAND)) { - dama *= 3; - } - if (hasflag(a->flags, F_ONFIRE)) { - dama += 8; - } - - - if (hasflag(b->flags, F_HASBRAND)) { - damb *= 3; - } - if (hasflag(b->flags, F_ONFIRE)) { - damb += 8; - } + modifybetterwepdam(a, owner, &dama); + modifybetterwepdam(b, owner, &damb); // modify with accuracy acca = getobaccuracy(a, owner); @@ -7743,6 +7741,27 @@ void makewet(object_t *o, int amt) { } } +void modifybetterwepdam(object_t *o, lifeform_t *owner, int *dam) { + flag_t *f; + if (hasflag(o->flags, F_HASBRAND)) { + *dam *= 3; + } + if (hasflag(o->flags, F_ONFIRE)) { + *dam += 8; + } + // prefer weapons "...of xxxslaying" which match our targets + if (owner) { + f = hasflag(o->flags, F_RACESLAY); + if (f) { + lifeform_t *target; + target = gettargetlf(owner); + if (target && (getraceclass(target) == f->val[0])) { + *dam *= 3; + } + } + } +} + object_t *moveob(object_t *src, obpile_t *dst, int howmany) { return real_moveob(src, dst, howmany, B_TRUE); } @@ -11381,7 +11400,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) { case OT_POT_HEALINGMIN: case OT_POT_HEALINGMAJ: case OT_POT_AMBROSIA: - angergodmaybe(R_GODMERCY, 25, GA_ATTACKOBJECT); + angergodmaybe(R_GODLIFE, 25, GA_ATTACKOBJECT); break; default: break; @@ -12977,7 +12996,7 @@ void timeeffectsob(object_t *o) { if (f->id == F_WALKDAM) { // everything here takes damage //damageallobs(o, o->pile, f->val[0] * timespent, f->val[1]); - damageallobs(o, o->pile, roll(f->text), f->val[0]); + damageallobs(o, o->pile, roll(f->text), f->val[0], NULL); //if (hasflag(o->flags, F_DEAD)) return; } diff --git a/objects.h b/objects.h index 5c48b13..723d20a 100644 --- a/objects.h +++ b/objects.h @@ -47,9 +47,9 @@ int countobs(obpile_t *op, int onlyifknown); int countobsoftype(obpile_t *op, enum OBTYPE oid); int countobswithflag(obpile_t *op, enum FLAG flagid); int countobswithflagval(obpile_t *op, enum FLAG flagid, int val0, int val1, int val2, char *text); -int countnoncosmeticobs(obpile_t *op, int onlyifknown); +int countnoncosmeticobs(obpile_t *op, int onlyifknown, int includetrails); int curseob(object_t *o); -void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype); +void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype, lifeform_t *srclf); int doobdieconvert(object_t *o, int wantannounce); int doobtraps(object_t *o, lifeform_t *lf); void dumpobrarity(void); @@ -232,6 +232,7 @@ int makeduller(object_t *o, int howmuch); void makeknown(enum OBTYPE otid); void maketried(enum OBTYPE otid, char *triedon); void makewet(object_t *o, int amt); +void modifybetterwepdam(object_t *o, lifeform_t *owner, int *dam); object_t *moveob(object_t *src, obpile_t *dst, int howmany); object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok); void modbonus(object_t *o, int amt); diff --git a/spell.c b/spell.c index a2fb2b9..3141a10 100644 --- a/spell.c +++ b/spell.c @@ -3797,7 +3797,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // no corpse after death (so you can't keep reanimating it) addflag(lf->flags, F_NOCORPSE, NA, NA, NA, NULL); - if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 25); + if (isplayer(caster)) { + pleasegodmaybe(R_GODNATURE, 25); + angergodmaybe(R_GODFIRE, 50, GA_HERESY); + + } } else { fizzle(caster); return B_TRUE; @@ -4651,7 +4655,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else { // noone there, hit objects. - damageallobs(NULL, targcell->obpile, 0, DT_COLD); + damageallobs(NULL, targcell->obpile, 0, DT_COLD, caster); } } } @@ -4695,7 +4699,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ break; } } else { - damageallobs(NULL, retcell[i]->obpile, 0, DT_COLD); + damageallobs(NULL, retcell[i]->obpile, 0, DT_COLD, caster); } } } else if (spellid == OT_S_COMMANDUNDEAD) { @@ -4758,7 +4762,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } - if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 5); + if (isplayer(caster)) { + pleasegodmaybe(R_GODNATURE, 5); + angergodmaybe(R_GODFIRE, 50, GA_HERESY); + } } else if (spellid == OT_S_CREATEMONSTER) { lifeform_t *newlf; race_t *r = NULL; @@ -4975,7 +4982,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } if (isplayer(caster) && !frompot) { - pleasegodmaybe(R_GODMERCY, 3); + pleasegodmaybe(R_GODLIFE, 3); } } else if (spellid == OT_S_DARKNESS) { if (!targcell) targcell = caster->cell; @@ -5738,7 +5745,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("A huge pool of water appears!"); if (seenbyplayer) *seenbyplayer = B_TRUE; } - if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 5); + if (isplayer(caster)) { + pleasegodmaybe(R_GODNATURE, 5); + angergodmaybe(R_GODFIRE, 75, GA_HERESY); + } } else { failed = B_TRUE; } @@ -5954,7 +5964,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ losehp(target, rnd(1,6) + power, DT_FIRE, caster, "a dart of flame"); } } else { - damageallobs(NULL, targcell->obpile, 0, DT_FIRE); + damageallobs(NULL, targcell->obpile, 0, DT_FIRE, caster); } } else if (spellid == OT_S_FLAMEBURST) { int range = 1; @@ -5987,6 +5997,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } losehp(targcell->lf, rolldie(2,6), DT_FIRE, caster, "a burst of fire"); } + damageallobs(NULL, targcell->obpile, rolldie(2,6), DT_FIRE, caster); } } } @@ -6586,7 +6597,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (donesomething && isplayer(caster)) { if (!frompot) { - pleasegodmaybe(R_GODMERCY, 3); + pleasegodmaybe(R_GODLIFE, 3); } // god of death REALLY doesn't like healing. angergodmaybe(R_GODDEATH, 40, GA_HERESY); @@ -6692,6 +6703,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } } + } else if (spellid == OT_S_HEAVENARM) { + flag_t *f; + if (!target) target = caster; + if (lfhasflag(target, F_HEAVENARM)) { + fizzle(target); + return B_TRUE; + } + f = addtempflag(caster->flags, F_HEAVENARM, power*10, NA, NA, "divine armour", FROMSPELL); + f->obfrom = spellid; } else if (spellid == OT_S_HOLDPORTAL) { object_t *o,*oo; cell_t *c; @@ -7380,8 +7400,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } - - if (spellresisted(target, caster, spellid, power, seenbyplayer, B_FALSE)) { + if (isimmuneto(target->flags, DT_PETRIFY, B_FALSE)) { + saved = B_TRUE; + } else if (spellresisted(target, caster, spellid, power, seenbyplayer, B_FALSE)) { saved = B_TRUE; } else if (skillcheck(target, SC_STR, 20 + power, 0)) { saved = B_TRUE; @@ -8932,7 +8953,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } if (ndone && isplayer(caster) && !frompot) { - pleasegodmaybe(R_GODMERCY, 3); + pleasegodmaybe(R_GODLIFE, 3); } } else if (spellid == OT_S_LETHARGY) { int amttolose; @@ -9146,9 +9167,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } } else if (spellid == OT_S_SIXTHSENSE) { - if (isplayer(caster)) { - msg("You will now be warned of creatures behind you."); + flag_t *f; + if (!target) target = caster; + if (lfhasflag(target, F_SIXTHSENSE)) { + fizzle(target); + return B_TRUE; } + f = addtempflag(caster->flags, F_SIXTHSENSE, power, NA, NA, NULL, FROMSPELL); + f->obfrom = spellid; } else if ((spellid == OT_S_SIZEUP) || (spellid == OT_S_SIZEDOWN)) { enum LFSIZE origsize,newsize; origsize = getlfsize(caster); @@ -9418,6 +9444,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_SPARK) { object_t *o,*nexto; int donesomething = B_FALSE; + int nburnt = 0; if (haslos(player, targcell)) { if (targcell->lf && cansee(player, targcell->lf)) { @@ -9439,8 +9466,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (isflammable(o) || (o->type->id == OT_CANDLE) || (o->type->id == OT_TORCH)) { takedamage(o, 1, DT_FIRE); donesomething = B_TRUE; + nburnt++; } } + if (isplayer(caster)) pleasegodmaybe(R_GODFIRE, nburnt*2); } else if (spellid == OT_S_SPEAKDEAD) { object_t *corpse = NULL; @@ -10453,7 +10482,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("A wall of ice appears!"); if (seenbyplayer) *seenbyplayer = B_TRUE; } - if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 5); + if (isplayer(caster)) { + pleasegodmaybe(R_GODNATURE, 5); + angergodmaybe(R_GODFIRE, 50, GA_HERESY); + } } else if (spellid == OT_S_WATERJET) { char lfname[BUFLEN]; cell_t *retcell[MAXRETCELLS]; @@ -10503,7 +10535,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ addob(retcell[i]->obpile, "large puddle of water"); break; } else { - damageallobs(NULL, retcell[i]->obpile, 0, DT_WATER); + damageallobs(NULL, retcell[i]->obpile, 0, DT_WATER, caster); // add water object addob(retcell[i]->obpile, "large puddle of water"); } @@ -10854,7 +10886,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (isplayer(target)) { if (seenbyplayer) *seenbyplayer = B_TRUE; } - if (o && isplayer(caster)) pleasegodmaybe(R_GODNATURE, 5); + if (o && isplayer(caster)) { + pleasegodmaybe(R_GODNATURE, 5); + angergodmaybe(R_GODFIRE, 75, GA_HERESY); + } } else if ((spellid == OT_S_WISH) || (spellid == OT_S_GIFT)) { object_t *o; if (isplayer(caster)) { @@ -10918,7 +10953,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } if (ncreated) { - if (isplayer(caster)) pleasegodmaybe(R_GODNATURE, 10); + if (isplayer(caster)) { + pleasegodmaybe(R_GODNATURE, 10); + angergodmaybe(R_GODFIRE, 75, GA_HERESY); + } } } else { // couldn't make it appear - ob doesn't exist @@ -11644,6 +11682,9 @@ char *getspelldesc(enum OBTYPE spellid, int power, char *buf) { case OT_S_GRAVLOWER: snprintf(buf, BUFLEN, "reduces load by %dkg", power*15); break; + case OT_S_HEAVENARM: + snprintf(buf, BUFLEN, "negates %d damage", power*10); + break; case OT_S_HOLYAURA: snprintf(buf, BUFLEN, "weapons deal holy damage"); break;