From 893540af19b6972ed77968a20bea8896d365d6c6 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Thu, 15 Nov 2012 11:39:46 +0000 Subject: [PATCH] - [+] chemistry skill lets to mix venom sacs into potions - [+] need a potion and venom sac - [+] make more things drop venom sacs - snakes etc - [+] F_EXTRACORPSE - [+] operate the venom sac ? - [+] can do this with first levle chemistry - [+] different kind of venom - blindness - [+] "blue venom sac" vs "purple venom sac" - [+] combiesn to potion of blindness - [+] more amulets - [+] common - [+] of bravery - [+] of light (common) - [+] of minor protection (common) (=5 AR - [+] energy absorbtion (absorb explosions, then pump them out) - [+] uncommon - [+] injury prvention (instead of ring) - [+] rare - [+] or major protection (not common) +10 AR - [+] had a missing eye. drunk a healing potino. - [+] Your head grows back! Your injured head has healed. - [+] objects with positive F_BONUS should never start cursed - [+] (in addobject) - [+] territorial monsters talk when you are approaching their threshold (but not within it) - [+] put this in ai_talk() - [+] if someone almost at territorial range: - [+] make f_noisetext v2 be SP_xxx. if it's set, just say this instead. - [+] it not, N_TERRITORY_APPROACH - [+] if we can talk, SP_TERRITORY_APPROACH - [+] possibilities: - [+] stay away! - [+] keep back! - [+] get away froma me! - [+] don't come any closer! - [+] that's close enough. - [+] keep your distance, stranger! - [+] out of my way! - [+] test with giant and - [+] test with insane humanoid - [+] make territorial creatures not walk too close to things, unless they are attacking or fleeing - [+] in willmove(), fail if it is too close to something - [+] ...unless we have a target lf - [+] ...or we are fleeing - [+] jumping when woozy will go to a random cell - [+] fix autoshortcuts to include starting spells - [+] still bugs with canreachbp - "The giant rat critically scratches your wizard hat." - [+] zombies shoudln't be able to talk. - [+] allow pets to "cheat" to find player's lcoation. - [+] need some kind of limit on zombie army creation - [+] no stairs - [+] areallies() on two pets returning false - [+] psychic shove - [+] push off something, or push them away - [+] l2 mental - [+] pushback power+1 cells (max power 3) - [+] different god message for first prayer. - [+] fix crash during swapplaces() - [+] sacrifice of masterwork weapons should work better. shoddy should be worse. - [+] bug: shops don't work anymore - [+] change lessen poison - power always goes to 1 - [+] replace description "spell's power is boosted when cast outside" with "boosted when cast in a forested area" - [+] minor healing problem. "at lest 2hp per power" but mxpower 10. should be maxpwer 5 - [+] wish for 'protection' should give something you can wear without penalties. - [+] locate object should give a message when none are found. --- ai.c | 27 ++++- attack.c | 2 +- data.c | 111 ++++++++++++++++---- data/hiscores.db | Bin 17408 -> 17408 bytes defs.h | 21 +++- god.c | 111 ++++++++++++++------ io.c | 8 +- lf.c | 260 ++++++++++++++++++++++++++++++++++------------- lf.h | 5 +- map.c | 34 +++++-- map.h | 3 +- move.c | 69 +++++++++++-- move.h | 2 +- nexus.c | 7 +- objects.c | 128 +++++++++++++++++++++-- objects.h | 1 + shops.c | 2 +- spell.c | 223 +++++++++++++++++++++++++++------------- text.c | 7 ++ text.h | 1 + 20 files changed, 785 insertions(+), 237 deletions(-) diff --git a/ai.c b/ai.c index 53e9519..7314711 100644 --- a/ai.c +++ b/ai.c @@ -657,7 +657,16 @@ cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *l // do we remember the player's last known location ? f = ispetortarget(lf, target); if (f) { - c = getcellat(lf->cell->map, f->val[1], f->val[2]); + if (f->id == F_PETOF) { + // cheat. + finalcell = target->cell; + if (lastx) *lastx = finalcell->x; + if (lasty) *lasty = finalcell->y; + if (lastdir) *lastdir = D_NONE; + return finalcell; + } else { + c = getcellat(lf->cell->map, f->val[1], f->val[2]); + } //if (c && cellwalkable(lf, c, NULL)) { if (c) { if (lastx) *lastx = c->x; @@ -1535,9 +1544,11 @@ int ai_healing(lifeform_t *lf) { if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; if (lfhasflag(lf, F_RAGE)) return B_FALSE; - // special cases + // special cases + // - mosquitoids and leechs will sleep when satiated. if ((lf->race->id == R_STIRGE) || (lf->race->id == R_LEECH)) { - if (ispeaceful(lf)) { + if (db) dblog(".oO { i am satiated. going to sleep. }"); + if (ispeaceful(lf) && !isundead(lf)) { int sleepval = 18; if (modcounter(lf->flags, 1) >= sleepval) { // we say that this ISNT on purpose, because otherwise @@ -2919,6 +2930,16 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG ok = B_TRUE; } } + } else if (ot->id == OT_S_PSYSHOVE) { + if (purpose == F_AICASTTOATTACK) { + if (getlfweight(lf, B_WITHOBS) >= getlfweight(victim, B_WITHOBS)) { + ok = B_TRUE; + } + } else if (purpose == F_AICASTTOFLEE) { + if (getlfweight(lf, B_WITHOBS) < getlfweight(victim, B_WITHOBS)) { + ok = B_TRUE; + } + } } else if (ot->id == OT_S_PYROMANIA) { int i; for (i = 0; i < lf->nlos; i++) { diff --git a/attack.c b/attack.c index 8e8c280..ea763f6 100644 --- a/attack.c +++ b/attack.c @@ -3321,7 +3321,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam, int isu if (pctchance(chance)) { // knock back victim dir = getdirtowards(owner->cell, victim->cell, victim, B_FALSE, DT_COMPASS); - knockback(victim, dir , 2, owner, 110, B_TRUE); + knockback(victim, dir , 2, owner, 110, B_DOANNOUNCE, B_DODAM); if (cansee(player, owner)) { f->known = B_TRUE; } diff --git a/data.c b/data.c index 4855991..74894ca 100644 --- a/data.c +++ b/data.c @@ -1522,7 +1522,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_COOKING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_ARCANA, PR_BEGINNER, NA, NULL); - addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DEMONS, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_RELICS, PR_NOVICE, NA, NULL); @@ -3465,9 +3465,17 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ANTNEST, 100, RR_COMMON, NULL); - addot(OT_POISONSAC, "venom sac", "A small sac of flesh, filled with potent venom.", MT_FLESH, 0.2, OC_FOOD, SZ_TINY); // weight normally comes from corpse type + addot(OT_POISONSAC, "purple venom sac", "A small sac of flesh, filled with potent venom. A skilled Chemist could use it to create a poisonous potion.", MT_FLESH, 0.2, OC_FOOD, SZ_TINY); // weight normally comes from corpse type + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "You can 'o'perate this to mix it into a poiton."); + addflag(lastot->flags, F_GLYPH, C_MAGENTA, '%', NA, NULL); + addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, ""); + addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, ""); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL); + addot(OT_POISONSACBL, "blue venom sac", "A small sac of flesh, filled with blindness-inducing venom. A skilled Chemist could use it to create a blindness potion.", MT_FLESH, 0.2, OC_FOOD, SZ_TINY); // weight normally comes from corpse type + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "You can 'o'perate this to mix it into a poiton."); addflag(lastot->flags, F_GLYPH, C_BLUE, '%', NA, NULL); addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, ""); + addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL); addot(OT_PSITRUFFLE, "psitruffle", "Psitruffles are extremely rare forms of truffle which can unlock potentials within a living brain. Eating one will double all experience earned for a short period thereafter.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY); addflag(lastot->flags, F_GLYPH, C_MAGENTA, '%', NA, NULL); @@ -3525,6 +3533,10 @@ void initobjects(void) { // potions + addot(OT_POT_BLINDNESS, "potion of blindness", "This dastardly concoction renders its drinker blind for a short time.", MT_GLASS, 1, OC_POTION, SZ_TINY); + addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); + addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_VALUE, 20, NA, NA, NULL); addot(OT_POT_SPIDERCLIMB, "potion of arachnid adhesion", "Temporarily allows you to climb on walls like a spider.", MT_GLASS, 1, OC_POTION, SZ_TINY); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); addflag(lastot->flags, F_VALUE, 45, NA, NA, NULL); @@ -3905,7 +3917,6 @@ void initobjects(void) { addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 1, NA, NULL); addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); - addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the chances of the zombies being friendly."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many corpses are affected."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many hit points the zombies have."); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); @@ -4174,7 +4185,7 @@ void initobjects(void) { addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addot(OT_S_GUSTOFWIND, "gust of wind", "Causes a gust of wind to blow up to ^bpower^n of the target's objects away.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, 1, NA, NA, "The chance of each object blowing away is determined by the spell's power."); - addflag(lastot->flags, F_EXTRADESC, 2, NA, NA, "This spell's power is boosted when cast outside."); + addflag(lastot->flags, F_EXTRADESC, 2, NA, NA, "This spell's power is boosted when cast in natural surroundings."); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); @@ -4672,7 +4683,7 @@ void initobjects(void) { addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - addot(OT_S_BARKSKIN, "barkskin", "Covers the caster with a skin of bark, reducing damage but making them vulnerable to fire.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_BARKSKIN, "barkskin", "Covers the caster with a skin of bark, reducing physical damage by 3 but making them vulnerable to fire.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); @@ -4727,7 +4738,7 @@ void initobjects(void) { addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER|TT_OBJECT, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); - addot(OT_S_CALLLIGHTNING, "call lightning", "Blasts a single enemy with a bolt of lightning from the sky, dealing 3d6 damage (4d6 if outdoors).", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_CALLLIGHTNING, "call lightning", "Blasts a single enemy with a bolt of lightning from the sky, dealing 3d6 damage (4d6 if in nature).", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); @@ -4759,7 +4770,7 @@ void initobjects(void) { addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_S_SLEETSTORM, "sleet storm", "Creates an cloud of sleet, hampering vision and movement.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the size of the storm."); - addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell's power is boosted when cast outside."); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell's power is boosted when cast in natural surroundings."); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); @@ -4831,7 +4842,7 @@ void initobjects(void) { addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addot(OT_S_HAILSTORM, "hail storm", "Creates an intense storm of hail, causing damage to all within.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the size of the storm."); - addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell's power is boosted when cast outside."); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell's power is boosted when cast in natural surroundings."); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); @@ -4851,7 +4862,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOFLEE, ST_SPECIAL, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l6 - addot(OT_S_LIGHTNINGSTORM, "lightning storm", "Blasts all visible enemies bolts of lightning from the sky, dealing 3d6 damage (4d6 if outdoors).", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_LIGHTNINGSTORM, "lightning storm", "Blasts all visible enemies bolts of lightning from the sky, dealing 3d6 damage (4d6 if in nature).", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines how many bolts will appear."); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); @@ -4892,6 +4903,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); @@ -4925,6 +4937,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, 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_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); @@ -4956,6 +4969,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); @@ -5048,6 +5062,16 @@ 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_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); + addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL); + addflag(lastot->flags, F_RANGE, 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_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); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Creatures with higher intelligence will take more damage."); @@ -8032,6 +8056,17 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_JUMP, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_TUMBLE, NA, NULL); addflag(lastot->flags, F_VALUE, 600, NA, NA, NULL); + + addot(OT_AMU_LIGHT, "amulet of light", "Glows with a bright, unearthly light when worn.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); + addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_PRODUCESLIGHT, 6, NA, NULL); + addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL); + + addot(OT_AMU_BRAVERY, "amulet of bravery", "Renders its wearer immune to all forms of fear.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); + addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_FEARLESS, B_TRUE, NA, NULL); + addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL); + addot(OT_AMU_ANGER, "amulet of anger", "Allows its wearer to enter a state of bezerk rage at will.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_RAGE, NA, NULL); @@ -8050,6 +8085,12 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_S_BLINK, NA, "pw:6;"); addflag(lastot->flags, F_VALUE, 600, NA, NA, NULL); + + addot(OT_AMU_ENERGYABS, "amulet of energy absorption", "This amulet is triggered by nearby explostions, which are instantly absorbed into the amulet itself, protecting the wearer from harm.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); + addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_EXPLOSIVE, NA, NULL); + addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL); + addot(OT_AMU_EVOLUTION, "amulet of evolution", "These rare amulets grant the wearer the ability to almost instantly evolve their body shape in response to danger.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); // no autoid addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_VERYRARE, NULL); @@ -8066,6 +8107,9 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_DTVULN, DT_SONIC, NA, NULL); addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL); + addot(OT_AMU_NOINJURY, "amulet of injury prevention", "Completely protects the wearer from crippling body injuries.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); + addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); + addflag(lastot->flags, F_VALUE, 600, NA, NA, NULL); addot(OT_AMU_PARANOIA, "amulet of paranoia", "Makes the caster periodically hear fake noises nearby. Or are they real....?", MT_METAL, 0.3, OC_AMULET, SZ_TINY); // no autoid! addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL); @@ -8076,6 +8120,17 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); addflag(lastot->flags, F_VALUE, 600, NA, NA, NULL); + + addot(OT_AMU_PROT_MIN, "amulet of minor protection", "Enhances its wearer's Armour Rating by 5.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); + addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_ARBOOST, 5, NA, NULL); + addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL); + + addot(OT_AMU_PROT_MAJ, "amulet of major protection", "Enhances its wearer's Armour Rating by 10.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); + addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_ARBOOST, 10, NA, NULL); + addflag(lastot->flags, F_VALUE, 600, NA, NA, NULL); + addot(OT_AMU_SLEEP, "amulet of peaceful slumber", "Blocks out all sound while the wearer sleeps.", MT_METAL, 0.3, OC_AMULET, SZ_TINY); // no autoid! addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); @@ -8197,9 +8252,6 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, ""); addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 1, NA, NULL); - addot(OT_RING_NOINJURY, "ring of injury prevention", "Completely protects the wearer from crippling body injuries.", MT_METAL, 0.1, OC_RING, SZ_MINI); - addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, ""); - addflag(lastot->flags, F_VALUE, 350, NA, NA, NULL); addot(OT_RING_DECELERATION, "ring of deceleration", "Slows down all nearby projectiles, providing protection from projectile attacks but also limiting their use.", MT_METAL, 0.1, OC_RING, SZ_MINI); addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, ""); addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_PROJECTILE, B_TRUE, NULL); @@ -9797,6 +9849,7 @@ void initrace(void) { // behaviours addbehaviour(BH_INSANE, "insane"); addflag(lastbehaviour->flags, F_TERRITORIAL, 2, NA , NA, NULL); + addflag(lastbehaviour->flags, F_NOISETEXT, N_TOOCLOSE, 3 , SP_TOOCLOSE, "rages unintelligibly^insane babbling"); addbehaviour(BH_HUNGRY, "hungry"); addflag(lastbehaviour->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS , NA, NULL); addbehaviour(BH_TIMID, "timid"); @@ -10331,7 +10384,6 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_WIS, AT_RANDOM, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CHA, AT_RANDOM, NA, NULL); addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, "gne"); - addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL); @@ -11783,6 +11835,7 @@ void initrace(void) { addrace(R_DARKMANTLE, "darklurk", 70, 'U', C_BLUE, MT_FLESH, RC_MAGIC, "A floating squid-like creature, rarely seen due to its ability to cloak itself in a magical darkness. They use their huge tentacles to grab then crush their unsuspecting prey."); addbodypart(lastrace, BP_BODY, NULL); addbodypart(lastrace, BP_LEGS, "tentacles"); + addflag(lastrace->flags, F_EXTRACORPSE, 100, NA, NA, "blue venom sac"); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_STARTHIDDENPCT, 80, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -15065,7 +15118,8 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL); - addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "growls^growling"); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "growls threateningly^a threatening growl"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "growls loudly^a loud growling"); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_JUMP, NA, NA, "stamcost:0;"); @@ -15108,6 +15162,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 5, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 5, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 10, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "growls threateningly^a threatening growl"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "roars^a roar"); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); @@ -15150,7 +15205,8 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_JUMP, NA, NA, "stamcost:0;"); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 50, NA, NA, NULL); - addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "growls^growling"); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "growls threateningly^a threatening growl"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "growls loudly^a loud growling"); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); @@ -15192,7 +15248,8 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 8, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 50, NA, NA, NULL); - addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "roars^a roar"); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "growls threateningly^a threatening growl"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "roars loudly^a loud roar"); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;"); @@ -15226,6 +15283,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "growls threateningly^a threatening growl"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "hisses^a hiss"); addflag(lastrace->flags, F_SEEINDARK, 8, NA, NA, NULL); addflag(lastrace->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL); @@ -15266,6 +15324,7 @@ void initrace(void) { addflag(lastrace->flags, F_VEGETARIAN, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SNATCH, NA, NA, "range:1;"); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 3, NA, "growls threateningly^a threatening growl"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "roars^a roar"); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL); @@ -15361,6 +15420,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "clacks its mandibles^a loud clacking"); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); @@ -15527,6 +15587,8 @@ void initrace(void) { setbodytype(lastrace, BT_QUADRAPED); addbodypart(lastrace, BP_TAIL, NULL); addflag(lastrace->flags, F_RNDHOSTILE, 10, NA, NA, NULL); + f = addflag(lastrace->flags, F_TERRITORIAL, 2, NA , NA, NULL); + addcondition(f, FC_NOCONDITION, 50); addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL); @@ -15784,6 +15846,7 @@ void initrace(void) { addflag(lastrace->flags, F_CASTCHANCE, 70, NA, NA, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 2, NA, NA, NULL); addflag(lastrace->flags, F_LEVRACE, 4, R_HAWK, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "screeches threateningly^a loud screech"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain"); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TAMABLE, 150, NA, NA, NULL); @@ -15821,6 +15884,7 @@ void initrace(void) { addflag(lastrace->flags, F_SWOOPRANGE, 3, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_LEVRACE, 8, R_HAWKBLOOD, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "screeches threateningly^a loud screech"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain"); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL); @@ -15855,6 +15919,7 @@ void initrace(void) { addflag(lastrace->flags, F_CASTCHANCE, 70, NA, NA, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 5, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "screeches threateningly^a loud screech"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain"); addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL); addflag(lastrace->flags, F_AVIAN, B_TRUE, NA, NA, NULL); @@ -15889,6 +15954,7 @@ void initrace(void) { addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "screeches"); addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "screeches threateningly^a loud screech"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain"); addflag(lastrace->flags, F_AVIAN, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); @@ -15951,8 +16017,9 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL); addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:3;"); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "bleats threateningly^an angry bleating"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 4, NA, "bleats in pain^bleating"); - addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, SV_SHOUT, NA, "bleats^an angry bleating"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, SV_SHOUT, NA, "bleats angrily^an angry bleating"); addflag(lastrace->flags, F_FLEEONHPPCT, 80, NA, NA, ""); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); @@ -16324,6 +16391,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTRESIST, DT_SLASH, NA, NA, NULL); addrace(R_SNAKE, "brown snake", 3, 's', C_BROWN, MT_FLESH, RC_ANIMAL, "Common venomous snakes."); setbodytype(lastrace, BT_SNAKE); + addflag(lastrace->flags, F_EXTRACORPSE, 50, NA, NA, "purple venom sac"); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSTAIRS, B_TRUE, NA, NA, NULL); @@ -16422,6 +16490,7 @@ void initrace(void) { setbodytype(lastrace, BT_SNAKE); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_EXTRACORPSE, 70, NA, NA, "purple venom sac"); addflag(lastrace->flags, F_NOSTAIRS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); @@ -16456,6 +16525,7 @@ void initrace(void) { setbodytype(lastrace, BT_SNAKE); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_EXTRACORPSE, 70, NA, NA, "blue venom sac"); addflag(lastrace->flags, F_NOSTAIRS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); @@ -16560,6 +16630,7 @@ void initrace(void) { setbodytype(lastrace, BT_SPIDER); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_EXTRACORPSE, 70, NA, NA, "purple venom sac"); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); @@ -16594,6 +16665,7 @@ void initrace(void) { lastrace->baseid = R_SPIDER; addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL); + addflag(lastrace->flags, F_EXTRACORPSE, 90, NA, NA, "purple venom sac"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -16633,6 +16705,7 @@ void initrace(void) { lastrace->baseid = R_SPIDER; addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL); + addflag(lastrace->flags, F_EXTRACORPSE, 90, NA, NA, "purple venom sac"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); @@ -16671,6 +16744,7 @@ void initrace(void) { setbodytype(lastrace, BT_SPIDER); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_EXTRACORPSE, 90, NA, NA, "blue venom sac"); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); @@ -16757,6 +16831,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); addflag(lastrace->flags, F_LEVRACE, 5, R_WOLF, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "growls menacingly^a menacing growl"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "growls^growling"); addflag(lastrace->flags, F_FLEEONHPPCT, 75, NA, NA, ""); @@ -16792,6 +16867,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_SNATCH, NA, NA, "range:1;"); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "growls menacingly^a menacing growl"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "growls^growling"); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, ""); @@ -19342,6 +19418,7 @@ void initskills(void) { free(lastskill->shortname); lastskill->shortname = strdup("Lore:Chem"); addskilldesc(SK_LORE_CHEMISTRY, PR_NOVICE, "^gYou can attempt to identify potions with the 'inspect' ability.^n", B_FALSE); addskillabil(SK_LORE_CHEMISTRY, PR_NOVICE, OT_A_INSPECT, NA, NULL, B_FALSE); + addskilldesc(SK_LORE_CHEMISTRY, PR_NOVICE, "^gYou can now mix venom sacs into potions to create poison.", B_TRUE); addskilldesc(SK_LORE_CHEMISTRY, PR_BEGINNER, "^gYou can now recognise very common potions.", B_TRUE); addskilldesc(SK_LORE_CHEMISTRY, PR_ADEPT, "^gYou can now recognise common potions.", B_TRUE); addskilldesc(SK_LORE_CHEMISTRY, PR_EXPERT, "^gYou can now recognise uncommon potions.", B_TRUE); diff --git a/data/hiscores.db b/data/hiscores.db index 30da5fc7172b28ec96e0f4d32b8f855a4fc247c9..3a519f6e8238aaeccaa13a268d11d6256d28dae6 100644 GIT binary patch delta 311 zcmZqZU~K4MoFL68x>4o@JF_Bl^kjApYYyft=2Yec=IG5{9D>XuEX)jyiXcJ(M96~( zxy||9Qw_v88NM+vuV)TqW@g&V{=Okw4DI`@YBr22?r6%T;C{*T`=B4Lk=A}<&)D{*muFNR|sx8mY zPbt>(R$v2~q*=)9JbAyl3{QF{NPTfZW=d+&xx!$33@6u{i%s@6 z6Pf(mQP4j_jvXjx-YClhk%T(JFEzO+ALyFo)FLFO6y%p==I1HorzsSb<|=5EWEAC> XLtUAjpOl}IqB;4aqx5EfyN#>>H>O)R delta 86 zcmZqZU~K4MoFL68xKZW>JF_fv{$zFzYYwI~##xMCnAval[2]; } + if (thispiety) { + if (hasobmod(o, findobmod(OM_MASTERWORK))) { + thispiety *= 2; + } else if (hasobmod(o, findobmod(OM_MASTERWORK))) { + thispiety /= 2; + limit(&thispiety, 1, NA); + } + } + // god of thieves only accepts untouched stuff if (ok && (god->race->id == R_GODTHIEVES)) { if (!hasflag(o->flags, F_UNTOUCHED)) { @@ -2050,38 +2059,76 @@ int prayto(lifeform_t *lf, lifeform_t *god) { // if we get here, piety is >= 100. // you get some help... plev = getpietylev(god->race->id, NULL, NULL); - switch (god->race->id) { - case R_GODBATTLE: - strcpy(assisttext, "Message received, soldier!"); - break; - case R_GODTHIEVES: - strcpy(assisttext, "What mischief have you gotten yourself into, then?"); - break; - 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; - case R_GODNATURE: - strcpy(assisttext, "Nature hears your call!"); - break; - case R_GODMAGIC: - strcpy(assisttext, "One calls upon the eldritch powers..."); - break; - case R_GODPURITY: - default: - strcpy(assisttext, "You appear in need of assistance, mortal!"); - break; + + if (!prayedtoany()) { + // special msg for first time. + switch (god->race->id) { + case R_GODBATTLE: + strcpy(assisttext, "Welcome aboard, soldier!"); + break; + case R_GODTHIEVES: + strcpy(assisttext, "Be welcome, brother of the night."); + break; + case R_GODDEATH: + strcpy(assisttext, "Serve me well, fleshling... or suffer the consequences."); + 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, "Hold life forever sacred!"); + break; + case R_GODMERCY: + strcpy(assisttext, "Welcome my child... remember mercy always."); + break; + case R_GODNATURE: + strcpy(assisttext, "Accept Nature's aid, and aid it in return."); + break; + case R_GODMAGIC: + strcpy(assisttext, "One's curiosity will be satisfied!"); + break; + case R_GODPURITY: + default: + strcpy(assisttext, "Remain pure, mortal - and reap the rewards."); + break; + } + } else { + switch (god->race->id) { + case R_GODBATTLE: + strcpy(assisttext, "Message received, soldier!"); + break; + case R_GODTHIEVES: + strcpy(assisttext, "What mischief have you gotten yourself into, then?"); + break; + 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; + case R_GODNATURE: + strcpy(assisttext, "Nature hears your call!"); + break; + case R_GODMAGIC: + strcpy(assisttext, "One calls upon the eldritch powers..."); + break; + case R_GODPURITY: + default: + strcpy(assisttext, "You appear in need of assistance, mortal!"); + break; + } } godsay(god->race->id, B_TRUE, assisttext); diff --git a/io.c b/io.c index 6718472..af56035 100644 --- a/io.c +++ b/io.c @@ -893,7 +893,8 @@ cell_t *real_askcoords(char *prompt, char *subprompt, int targettype, lifeform_t // hp if (!isplayer(c->lf)) { - if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) || + if (areallies(player, c->lf) || + isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) || (getlorelevel(player, c->lf->race->raceclass->id) >= PR_SKILLED) ) { char buf2[BUFLEN]; @@ -2575,7 +2576,8 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { break; case F_INJURY: strcpy(buf, getinjuredbpname(f->val[1])); - msg("^%c%s%s injured %s has healed.", getlfcol(lf, CC_VGOOD), lfname, getpossessive(lfname), buf); + msg("^%c%s%s injured %s %s healed.", getlfcol(lf, CC_VGOOD), lfname, getpossessive(lfname), buf, + isplural(buf) ? "have" : "has"); break; case F_INVISIBLE: if (isplayer(lf)) { @@ -11260,7 +11262,7 @@ void drawstatus(void) { setcol(statwin, C_YELLOW); wprintw(statwin, " Prone"); unsetcol(statwin, C_YELLOW); - } else if (isimmobile(player)) { + } else if (isimmobile(player) && !isdeaf(player)) { setcol(statwin, C_RED); wprintw(statwin, " Immobile"); unsetcol(statwin, C_RED); diff --git a/lf.c b/lf.c index 05548fd..b589f6e 100644 --- a/lf.c +++ b/lf.c @@ -1321,11 +1321,11 @@ int canreachbp(lifeform_t *lf, lifeform_t *victim, enum BODYPART bp) { // your reach is defined as anywhere between your feet and just over your // head. flying creatures have more leeway. if (isairborne(lf)) { - topthresh = SZ_MEDIUM; - bottomthresh = SZ_SMALL; + topthresh = 3; + bottomthresh = 2; } else { - topthresh = SZ_SMALL; - bottomthresh = SZ_TINY; + topthresh = 0; + bottomthresh = 0; } if ((bpheight < lffeet - bottomthresh) || @@ -3443,10 +3443,12 @@ void die(lifeform_t *lf) { if (cantalk(lf) && canhear(player, lf->cell, 4, NULL)) { sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL, player); } else if (!cansee(player, lf)) { - warn("You feel a profound sense of loss."); // redraw since you can "see" the pet even if it's out of sight needredraw = B_TRUE; - more(); + if (!isundead(lf)) { + warn("You feel a profound sense of loss."); + more(); + } //} else { // makenoise(lf, N_DIE); } @@ -7218,6 +7220,41 @@ object_t *getarmour(lifeform_t *lf, enum BODYPART bp) { return NULL; } +int getarmouraccpenalty(lifeform_t *lf) { + int pen = 0; + flag_t *retflag[MAXCANDIDATES],*f; + int nretflags,i; + // get adjustments for bulky armour/shield + getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if (f->id == F_ARMOURPENALTY) { + pen += adjustarmourpenalty(lf, f->val[0]); + } else if (f->id == F_SHIELDPENALTY) { + pen += adjustshieldpenalty(lf, f->val[0]); + } + } + return pen; +} + + +int getarmourevpenalty(lifeform_t *lf) { + int pen = 0; + flag_t *retflag[MAXCANDIDATES],*f; + int nretflags,i; + // get adjustments for bulky armour/shield + getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if (f->id == F_ARMOURPENALTY) { + pen += adjustarmourpenalty(lf, f->val[1]); + } else if (f->id == F_SHIELDPENALTY) { + pen += adjustshieldpenalty(lf, f->val[1]); + } + } + return pen; +} + int getarmournoise(lifeform_t *lf) { object_t *o; int volmod = 0; @@ -7759,16 +7796,8 @@ int getevasion(lifeform_t *lf) { ////////////////////////////////////////////////// // now negative modifiers ////////////////////////////////////////////////// - // get adjustments for bulky armour/shield - getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE); - for (i = 0; i < nretflags; i++) { - f = retflag[i]; - if (f->id == F_ARMOURPENALTY) { - ev -= adjustarmourpenalty(lf, f->val[1]); - } else if (f->id == F_SHIELDPENALTY) { - ev -= adjustshieldpenalty(lf, f->val[1]); - } - } + + ev -= getarmourevpenalty(lf); // you are easier to hit if you're glowing if (lfproduceslight(lf, NULL)) { @@ -8408,16 +8437,14 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) { } } + acc -= getarmouraccpenalty(lf); + // adjust for bulky armour/shield, or injuries - getflags(lf->flags, retflag, &nretflags, F_ACCURACYMOD, F_ARMOURPENALTY, F_INJURY, F_SHIELDPENALTY, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_ACCURACYMOD, F_INJURY, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; if (f->id == F_ACCURACYMOD) { acc += f->val[0]; - } else if (f->id == F_SHIELDPENALTY) { - acc -= adjustshieldpenalty(lf, f->val[0]); - } else if (f->id == F_ARMOURPENALTY) { - acc -= adjustarmourpenalty(lf, f->val[0]); } else if (f->id == F_INJURY) { switch (f->val[0]) { case IJ_FINGERBROKEN: @@ -8666,6 +8693,15 @@ int getfeetheight(lifeform_t *lf) { return howmuch; } +int getmasterid(lifeform_t *lf) { + flag_t *f; + f = lfhasflag(lf, F_PETOF); + if (f) { + return f->val[0]; + } + return -1; +} + enum SKILLLEVEL getmaxskilllevel(lifeform_t *lf, enum SKILL skid) { flag_t *f; enum SKILLLEVEL maxlev = PR_MASTER; @@ -8790,18 +8826,23 @@ int getnightvisrange(lifeform_t *lf) { // populates heartext, seetext and volume // "lf" is optional. if not given, "noiseflag" should be provided. -// returns -int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag, char *heartext,char *seetext, int *volume) { +// returns TRUE on failure +int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag, char *heartext,char *seetext, int *volume, flag_t **returnedflag) { flag_t *retflag[MAXCANDIDATES],*nflag[MAXCANDIDATES]; + flag_t *nf = NULL; int nretflags, i,nnflags = 0; int ok = B_FALSE; + // deafults if (volume) *volume = 0; if (heartext) strcpy(heartext, ""); if (seetext) strcpy(seetext, ""); + if (returnedflag) *returnedflag = NULL; - if (lf) { + if (noiseflag) { + nf = noiseflag; + } else if (lf) { if (lfhasflag(lf, F_FROZEN)) { // can't make noise if frozen! return B_TRUE; @@ -8821,23 +8862,27 @@ int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag, } if (nnflags) { - if (noiseflag) noiseflag = nflag[rnd(0,nnflags-1)]; + nf = nflag[rnd(0,nnflags-1)]; } - } + } - if (noiseflag) { + if (nf) { char verb[BUFLEN], noun[BUFLEN]; - if (volume) *volume = noiseflag->val[1]; + if (volume) *volume = nf->val[1]; - if (noiseflag->text[0] == '^') { + if (returnedflag) { + *returnedflag = nf; + } + + if (nf->text[0] == '^') { strcpy(verb, ""); - //noun = strtok_r(noiseflag->text, "^", &dummy); - strcpy(noun, noiseflag->text + 1); + //noun = strtok_r(nf->text, "^", &dummy); + strcpy(noun, nf->text + 1); } else { char *p; - p = readuntil(verb, noiseflag->text, '^'); + p = readuntil(verb, nf->text, '^'); readuntil(noun, p, '^'); // ie eol - //verb = strtok_r(noiseflag->text, "^", &dummy); + //verb = strtok_r(nf->text, "^", &dummy); //noun = strtok_r(NULL, "^", &dummy); } @@ -11342,9 +11387,9 @@ void givejob(lifeform_t *lf, enum JOB jobid) { god = findgod(R_GODLIFE); addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL); } - if (isplayer(lf)) { - addflag(lf->flags, F_SHORTCUT, getnextshortcut(lf), NA, NA, "turn undead"); - } + //if (isplayer(lf)) { + // autoshortcut(lf, OT_S_TURNUNDEAD); + //} // all starting gear is blessed for (o = lf->pack->first ; o ; o = o->next) { if (isweapon(o) || isarmour(o) || isshield(o)) { @@ -12592,7 +12637,7 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJUR getlfname(lf, lfname); - o = hasequippedobid(lf->pack, OT_RING_NOINJURY); + o = hasequippedobid(lf->pack, OT_AMU_NOINJURY); if (o) { char obname[BUFLEN]; int seen = B_FALSE; @@ -12984,6 +13029,19 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJUR return B_TRUE; } else { flag_t *injflag; + enum BODYPART newwhere; + switch (inj) { + case IJ_BLACKEYE: + case IJ_EYELIDSCRAPED: + case IJ_EYEDESTROYED: + newwhere = BP_EYES; + break; + case IJ_SHOULDERDISLOCATED: + newwhere = BP_SHOULDERS; + break; + default: newwhere = where; break; + } + injflag = addtempflag(lf->flags, F_INJURY, inj, where, damtype, desc, howlong); injflag->obfrom = B_NEWINJURY; } @@ -15023,6 +15081,9 @@ lifeform_t *makezombie(object_t *o, int power) { addflag(lf->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(lf->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); + addflag(lf->flags, F_NOTALK, B_TRUE, NA, NA, NULL); + addflag(lf->flags, F_NOSTAIRS, B_TRUE, NA, NA, NULL); + if (hasflag(o->flags, F_HEADLESS)) { // remove the head addflag(lf->flags, F_NOBODYPART, BP_HEAD, NA, NA, NULL); @@ -15044,6 +15105,7 @@ lifeform_t *makezombie(object_t *o, int power) { killflagsofid(lf->flags, F_NOISETEXT); killflagsofid(lf->flags, F_SEEINDARK); killflagsofid(lf->flags, F_TREMORSENSE); + killflagsofid(lf->flags, F_TERRITORIAL); killflagsofid(lf->flags, F_MOVESPEED); addflag(lf->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); @@ -15069,9 +15131,10 @@ lifeform_t *makezombie(object_t *o, int power) { killflagsofid(lf->flags, F_CANWILL); // modify max hp based on power + // need at least 2-4. if (power > 0) { lf->maxhp = pctof(power*10, lf->maxhp); - limit(&(lf->maxhp), 1, NA); + limit(&(lf->maxhp), rnd(2,4), NA); lf->hp = lf->maxhp; } @@ -15225,10 +15288,19 @@ void applywalkdam(lifeform_t *lf, int dam, enum DAMTYPE damtype, object_t *o, in } int areallies(lifeform_t *lf1, lifeform_t *lf2) { - if (getallegiance(lf1) == getallegiance(lf2)) { // same allegience? + int master1,master2; + master1 = getmasterid(lf1); + master2 = getmasterid(lf2); + if ((master1 == master2) && (master1 != -1)) { + // both pets of the same lf + return B_TRUE; + } else if (getallegiance(lf1) == getallegiance(lf2)) { // same allegience? if (isplayer(lf1) || isplayer(lf2)) { // if one of them is the player return B_TRUE; + } else if (ispetof(lf1, player)) { + // both pets of the player + return B_TRUE; } else { if (lf1->race->baseid == lf2->race->baseid) { return B_TRUE; @@ -15441,35 +15513,43 @@ void autolearnspellsfrombook(lifeform_t *lf, object_t *book) { !hasflagval(lf->flags, F_CANCAST, o->type->id, NA, NA, NULL) && (getspellpower(lf, o->type->id) > 0)) { addtempflag(lf->flags, F_CANCAST, o->type->id, NA, NA, NULL, FROMJOB); - if (isplayer(lf)) { - addtempflag(lf->flags, F_SHORTCUT, getnextshortcut(lf), NA, NA, o->type->name, FROMJOB); - } + //if (isplayer(lf)) { + // autoshortcut(lf, o->type->id); + //} } } } void autoshortcut(lifeform_t *lf, enum OBTYPE spellid) { flag_t *retflag[MAXCANDIDATES],*f; - int nretflags,i,found = B_FALSE; + int nretflags,i; int min = 1; objecttype_t *ot = NULL; getflags(lf->flags, retflag, &nretflags, F_CANCAST, F_CANWILL, F_NONE); - for (i = 0; i < nretflags; i++) { - f = retflag[i]; - if (f->val[0] == spellid) { - found = B_TRUE; - } - } - if (!found) { - return; - } - ot = findot(spellid); - if (ot) { - // set to lowest possible shortcut - min = getnextshortcut(lf); - if (min < 10) { - addflag(lf->flags, F_SHORTCUT, min, NA, NA, ot->name); + min = getnextshortcut(lf); + for (i = 0; (i < nretflags) && (min < 10); i++) { + f = retflag[i]; + ot = findot(f->val[0]); + if (!ot) continue; + + if (spellid == OT_NONE) { + // autoshortcut everything from your job/race + if ((f->lifetime == FROMJOB) || (f->lifetime == FROMRACE) || + (f->lifetime == FROMSKILL)) { + // if we don't already have a shortcut for this... + if (!lfhasflagval(lf, F_SHORTCUT, NA, NA, NA, ot->name)) { + addflag(lf->flags, F_SHORTCUT, min, NA, NA, ot->name); + min = getnextshortcut(lf); + } + } + } else { + // autoshortcut the given one only. + if (f->val[0] == spellid) { + // set to lowest possible shortcut + addflag(lf->flags, F_SHORTCUT, min, NA, NA, ot->name); + return; + } } } } @@ -15803,9 +15883,9 @@ int isweaponskill(enum SKILL skid) { } enum FLAG iswoozy(lifeform_t *lf) { - if (lfhasflag(lf, F_DRUNK)) return B_TRUE; - if (lfhasflag(lf, F_CONFUSED)) return B_TRUE; - if (lfhasflagval(lf, F_INJURY, IJ_CONCUSSION, NA, NA, NULL)) return B_TRUE; + if (lfhasflag(lf, F_DRUNK)) return F_DRUNK; + if (lfhasflag(lf, F_CONFUSED)) return F_CONFUSED; + if (lfhasflagval(lf, F_INJURY, IJ_CONCUSSION, NA, NA, NULL)) return F_INJURY; return F_NONE; } @@ -16911,10 +16991,15 @@ int makenauseated(lifeform_t *lf, int amt, int howlong, enum ERROR *why) { void makenoise(lifeform_t *lf, enum NOISETYPE nid) { int volume = 1; char hear[BUFLEN], see[BUFLEN]; + flag_t *nflag = NULL; - if (!getnoisedetails(lf, nid, NULL, hear, see, &volume)) { + if (!getnoisedetails(lf, nid, NULL, hear, see, &volume, &nflag)) { // success - noise(lf->cell, lf, noisetypetoclass(nid), volume, strlen(hear) ? hear : NULL, strlen(see) ? see : NULL); + if (nflag && (nflag->val[2] != NA) && cantalk(lf)) { + sayphrase(lf, nflag->val[2], volume, NA, NULL, NULL); + } else { + noise(lf->cell, lf, noisetypetoclass(nid), volume, strlen(hear) ? hear : NULL, strlen(see) ? see : NULL); + } } } @@ -17358,6 +17443,7 @@ void modstamina(lifeform_t *lf, float howmuch) { case RC_GOD: case RC_MAGIC: case RC_SLIME: + case RC_DEMON: return; default: break; } @@ -17766,7 +17852,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume, // it is closer. targlf = findlf(l->cell->map, tf->val[0]); } - if (targlf) { + if (targlf && (targlf->cell)) { // ie. not swapping places if (getcelldist(l->cell, c) < getcelldist(l->cell, targlf->cell)) { if ((volume >= 4) && onein(2)) { willrespond = B_TRUE; @@ -17776,7 +17862,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume, // will respond if the sound is closer than our target cell. cell_t *tc; tc = getcellat(l->cell->map, tf->val[1], tf->val[2]); - if (getcelldist(l->cell, c) < getcelldist(l->cell, tc)) { + if (tc && (getcelldist(l->cell, c) < getcelldist(l->cell, tc))) { willrespond = B_TRUE; } } @@ -19596,6 +19682,18 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t } rv = say(lf, buf, volume); break; + case SP_TOOCLOSE: + switch (rnd(1,7)) { + case 1: snprintf(buf, BUFLEN, "Stay away!"); break; + case 2: snprintf(buf, BUFLEN, "Keep back!"); break; + case 3: snprintf(buf, BUFLEN, "Keep your distance!"); break; + case 4: snprintf(buf, BUFLEN, "Get away from me!"); break; + case 5: snprintf(buf, BUFLEN, "That's close enough."); break; + case 6: snprintf(buf, BUFLEN, "Out of my way!"); break; + case 7: snprintf(buf, BUFLEN, "Don't come any closer!"); break; + } + rv = say(lf, buf, volume); + break; case SP_TRADEINFO_ACCEPT: p = text; p2 = buf2; @@ -19666,7 +19764,6 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { // immune to fear? if (lfhasflag(lf, F_UNDEAD)) return B_FALSE; if (isgod(lf)) return B_FALSE; - if (lfhasflag(lf, F_ASLEEP)) return B_FALSE; if (lfhasflag(lf, F_RAGE)) return B_FALSE; if (lfhasflag(lf, F_FEARLESS)) return B_FALSE; @@ -21842,7 +21939,6 @@ void startlfturn(lifeform_t *lf) { // special effects - if (lf->race->id == R_ASHKARI) { lifeform_t *otherlf; for (i = 1; i < lf->nlos; i++) { @@ -21868,6 +21964,32 @@ void startlfturn(lifeform_t *lf) { } } + f = lfhasflag(lf, F_TERRITORIAL); + if (f && !lfhasflag(lf, F_HOSTILE) && + !isinbattle(lf, B_INCLUDEDISTANT, B_FALSE) && + !isfleeing(lf) && !isplayer(lf)) { + for (i = 1 ; i < lf->nlos; i++) { + lifeform_t *otherlf; + otherlf = lf->los[i]->lf; + if (otherlf && !areallies(lf, otherlf) && cansee(lf, otherlf)) { + int dist; + dist = getcelldist(lf->cell, lf->los[i]); + if (dist == (f->val[0] + 1) || (dist == (f->val[0] + 2))) { + // nearly in range + makenoise(lf, N_TOOCLOSE); + } else if (dist <= f->val[0]) { + aiattack(lf, otherlf, aigetchasetime(lf)); + if (cansee(player, lf) && + !lfhasflagval(lf, F_NOISETEXT, N_GETANGRY, NA, NA, NULL)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("^w%s becomes aggressive!", lfname); + } + } + } + } + } + f = lfhasflag(lf, F_AUTOROTATE); if (f && (f->val[0] != 0)) { if (!gettargetlf(lf)) { @@ -24543,7 +24665,6 @@ int validateraces(void) { printf("ERROR in race '%s' - description refers to wings but race has no bp_wings.\n", r->name); goterror = B_TRUE; } - if (!hasflag(r->flags, F_SIZE)) { printf("ERROR in race '%s' - missing F_SIZE.\n", r->name); goterror = B_TRUE; @@ -25978,9 +26099,10 @@ enum SKILLLEVEL whichlevforabil(enum SKILL skid, enum OBTYPE oid) { int willattackdoors(lifeform_t *lf) { lifeform_t *targ; targ = gettargetlf(lf); + // ie. if we can see/hear our target behind the door if (targ) { int vol; - getnoisedetails(lf, N_WALK, NULL, NULL, NULL, &vol); + getnoisedetails(targ, N_WALK, NULL, NULL, NULL, &vol, NULL); if (canhear(lf, targ->cell, vol, NULL) || cansee(lf, targ)) { return B_TRUE; } diff --git a/lf.h b/lf.h index 1577548..66b3f06 100644 --- a/lf.h +++ b/lf.h @@ -156,6 +156,8 @@ int getalignmod(lifeform_t *lf); enum ALLEGIENCE getallegiance(lifeform_t *lf); int getallouterarmour(lifeform_t *lf, object_t **ob, int *nobs); object_t *getarmour(lifeform_t *lf, enum BODYPART bp); +int getarmouraccpenalty(lifeform_t *lf); +int getarmourevpenalty(lifeform_t *lf); int getarmournoise(lifeform_t *lf); int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, enum BODYPART *hitbp, int *narms); int getattackspeed(lifeform_t *lf); @@ -207,13 +209,14 @@ enum LFCONDITION getlfcondition(lifeform_t *lf); int getlfheight(lifeform_t *lf); int getlistendetectrange(lifeform_t *lf); int getfeetheight(lifeform_t *lf); +int getmasterid(lifeform_t *lf); enum SKILLLEVEL getmaxskilllevel(lifeform_t *lf, enum SKILL skid); int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions); int getmiscastchance(lifeform_t *lf); int getmorale(lifeform_t *lf); int getnextshortcut(lifeform_t *lf); int getnightvisrange(lifeform_t *lf); -int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag, char *heartext,char *seetext, int *volume); +int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag, char *heartext,char *seetext, int *volume, flag_t **returnedflag); char *getlfconditionname(enum LFCONDITION cond); object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp); //int getowing(lifeform_t *buyer, int shopid, int *retnitems); diff --git a/map.c b/map.c index 15236e1..2249fc9 100644 --- a/map.c +++ b/map.c @@ -6506,25 +6506,35 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int getradiuscells(c, range, dirtype, B_FALSE, killwalls ? LOF_DONTNEED : LOF_WALLSTOP, B_TRUE, retcell, &nretcells, B_FALSE); for (i = 0; i < nretcells; i++) { - explodesinglecell(retcell[i], dam, killwalls, o, c, fromwho); + explodesinglecell(retcell[i], dam, killwalls, o, c, fromwho, B_FALSE); } + explosion_knockback(c, range+1, dirtype, dam, fromwho); +} + +void explosion_knockback(cell_t *c, int radius, int dirtype, int dam, lifeform_t *fromwho) { + cell_t *retcell[MAXRETCELLS]; + int nretcells,i; // lfs up to 1 cell away are knocked back, if no walls in the way - getradiuscells(c, range+1, dirtype, B_FALSE, LOF_WALLSTOP, B_TRUE, retcell, &nretcells, B_FALSE); + getradiuscells(c, radius, dirtype, B_FALSE, LOF_WALLSTOP, B_TRUE, retcell, &nretcells, B_FALSE); for (i = 0; i < nretcells; i++) { cell_t *cc; int mydist; cc = retcell[i]; mydist = getcelldist(c,cc); if (cc->lf && !isdead(cc->lf)) { - int critchance; - // critical hit? 100% chance in middle, 60 at one cell, 20 at two cells - critchance = 100 - (mydist*40); - if (pctchance(critchance)) { - criticalhit(NULL, cc->lf, BP_HANDS, NULL, pctof(critchance, dam), DT_EXPLOSIVE); + if (!isimmuneto(cc->lf->flags, DT_EXPLOSIVE, B_FALSE)) { + int critchance; + // critical hit? 100% chance in middle, 60 at one cell, 20 at two cells + critchance = 100 - (mydist*40); + if (pctchance(critchance)) { + criticalhit(NULL, cc->lf, getrandomcorebp(cc->lf, NULL), + NULL, pctof(critchance, dam), DT_EXPLOSIVE); + } + // move away from centre of explosion + knockback(cc->lf, getdiraway(cc, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), + 2, fromwho, 200-(mydist*50), B_DOANNOUNCE, B_DODAM); } - // move away from centre of explosion - knockback(cc->lf, getdiraway(cc, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 2, NULL, 200-(mydist*50), B_TRUE); } } } @@ -6558,7 +6568,7 @@ void expand_cave(map_t *map, int numpasses) { // this should never be called directly - only from explodecells(). // (otherwise knockback effect won't happen) -void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre, lifeform_t *fromwho) { +void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre, lifeform_t *fromwho, int doknockback) { char obname[BUFLEN]; if (c->lf) { @@ -6582,6 +6592,10 @@ void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *c damagecell(c, dam, DT_EXPLOSIVE, fromwho); } } + + if (doknockback) { + explosion_knockback(c, 1, DT_COMPASS, dam, fromwho); + } } void finalisemap(map_t *map, object_t *entryob, int exitdir) { diff --git a/map.h b/map.h index 322b17a..8cefcc3 100644 --- a/map.h +++ b/map.h @@ -104,8 +104,9 @@ int dirtoy(int dt, int dir); int doorisvalid(object_t *o); void dumpmap(map_t *map, int showrooms); void expand_cave(map_t *map, int numpasses); -void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre, lifeform_t *fromwho); +void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre, lifeform_t *fromwho, int doknockback); void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce, lifeform_t *fromwho); +void explosion_knockback(cell_t *c, int radius, int dirtype, int dam, lifeform_t *fromwho); void finalisemap(map_t *map, object_t *entryob, int exitdir); void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags, enum BEHAVIOUR wantbehaviour, int idx); celltype_t *findcelltype(enum CELLTYPE cid); diff --git a/move.c b/move.c index 6abe369..07e93a2 100644 --- a/move.c +++ b/move.c @@ -870,7 +870,7 @@ int getwalkoffdir(lifeform_t *lf, int dir) { } // use 'n/a' for zero chance of falling. 0 means 'calculate based on distance' -int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff, int wantannounce) { +int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff, int wantannounce, int dodam) { int i,dam; char lfname[BUFLEN]; char newlfname[BUFLEN]; @@ -964,17 +964,29 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc } else { // ie door or object getobname(rdata, thing, 1); } - if (seen) msg("^%c%s slam%s into %s!^n",getlfcol(lf, CC_BAD), lfname,isplayer(lf) ? "" : "s", thing); - snprintf(buf, BUFLEN, "slamming into %s", thing); - // 1d6 dam per cell pushed - dam = rolldie(howfar, 6); - losehp(lf, dam, DT_BASH, pusher, buf); + if (seen) { + if (dodam) { + msg("^%c%s slam%s into %s!^n",getlfcol(lf, CC_BAD), lfname,isplayer(lf) ? "" : "s", thing); + } else { + msg("%s stop%s %s on %s.^n", lfname, + isplayer(lf) ? "" : "s", + isplayer(lf) ? "yourself" : "itself", thing); + } + } + if (dodam) { + // 1d6 dam per cell pushed + snprintf(buf, BUFLEN, "slamming into %s", thing); + dam = rolldie(howfar, 6); + losehp(lf, dam, DT_BASH, pusher, buf); + } // stop moving i = howfar; // don't fall mightfall = B_FALSE; - // 20% chance per cell pushed - if (pctchance(howfar*20)) criticalhit(NULL, lf, getrandomcorebp(lf, NULL), NULL, dam, DT_BASH); + if (dodam) { + // 20% chance per cell pushed + if (pctchance(howfar*20)) criticalhit(NULL, lf, getrandomcorebp(lf, NULL), NULL, dam, DT_BASH); + } break; case E_SWIMMING: case E_LFINWAY: @@ -993,7 +1005,8 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc fallcheckdiff += (momentumleft*45); } // confer our remaining momentum on to them - knockback(newcell->lf, dir, momentumleft, lf, fallcheckdiff, B_TRUE); // NOTE: recursive call + knockback(newcell->lf, dir, momentumleft, lf, fallcheckdiff, + B_DOANNOUNCE, dodam); // NOTE: recursive call } break; default: @@ -1850,6 +1863,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) { willmakenoise = B_FALSE; } } + // swapping places? if (willmakenoise) { if (isairborne(lf)) { @@ -2764,7 +2778,11 @@ void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir1, int changedir2 cell2->lf = NULL; lf2->cell = NULL; - // move you.. + // make moving lf vanish temporarily... + //cell1->lf = NULL; + //lf1->cell = NULL; + + // move you moveto(lf1, cell2, onpurpose, B_FALSE); // move them... @@ -2930,6 +2948,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { if ((reldir != RD_FORWARDS) && !lfhasflag(lf, F_AWARENESS)) { // if the given dir is behind us, just turn. if (!strafe) { + int prerotated = lf->rotated; takerotationtime(lf); setfacing(lf, dir); drawscreen(); @@ -2948,7 +2967,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { angergodmaybe(R_GODBATTLE, 5, GA_COWARD); } } - return B_FALSE; + if (isplayer(lf)) { + return B_FALSE; + } else { + // for ai, only return if this wasn't our 'free' turn action. + if (prerotated) { + return B_FALSE; + } + } } else { // player can't strafe while stuck. if (isstuck(lf) && isplayer(lf)) { @@ -3758,6 +3784,27 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) { return B_FALSE; } + // don't move anywhere which would put other non-allied lfs + // within our territorial range. + f = aihastarget(lf); + if (f && (f->id == F_TARGETLF)) { + } else { + f = lfhasflag(lf, F_TERRITORIAL); + if (f && !isfleeing(lf) && !lfhasflag(lf, F_RAGE)) { + int tdist,i; + tdist = f->val[0]; + // is there a lf in sight, who is within our territorial + // radius of the cell we are testing? + for (i = 0; i < lf->nlos; i++) { + if (lf->los[i]->lf && !areallies(lf, lf->los[i]->lf) && + (getcelldist(cell, lf->los[i]) <= tdist)) { + if (error) *error = E_WONT; + return B_FALSE; + } + } + } + } + // don't attack other monsters // or non-enemies // (unless we have targetted them) diff --git a/move.h b/move.h index a5a5a9a..6d7134d 100644 --- a/move.h +++ b/move.h @@ -13,7 +13,7 @@ int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int d int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); cell_t *getdodgecell(lifeform_t *lf); int getwalkoffdir(lifeform_t *lf, int dir); -int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff, int wantannounce); +int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff, int wantannounce, int dodam); int makeorthogonal(int dir); int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype, int keepinlof, int strafe, int onpurpose); int moveclear(lifeform_t *lf, int dir, enum ERROR *error); diff --git a/nexus.c b/nexus.c index 25a9052..7954987 100644 --- a/nexus.c +++ b/nexus.c @@ -421,8 +421,7 @@ int main(int argc, char **argv) { CC_HASOBTYPE, B_FALSE, avoidob, CC_NONE ); - initcondv(&cs2, CC_SOLID, B_TRUE, NA, - CC_HASOBTYPE, B_FALSE, avoidob, + initcondv(&cs2, CC_HASOBTYPE, B_FALSE, avoidob, CC_NONE ); @@ -445,8 +444,10 @@ int main(int argc, char **argv) { } - // set up automated shortcuts + // we always want 'cook' to be shortcut number one. autoshortcut(player, OT_A_COOK); + // populate the remainder with our other abilities + autoshortcut(player, OT_NONE); getplayernamefull(pname); snprintf(welcomemsg, BUFLEN, "Greetings %s, welcome to nexus!", pname); diff --git a/objects.c b/objects.c index 7b29eaf..8f2798f 100644 --- a/objects.c +++ b/objects.c @@ -1200,6 +1200,16 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum } } + if (bonus > 0) { + if (wantblessed == B_CURSED) { + wantblessed = B_UNCURSED; + } + } else if (bonus < 0) { + if (wantblessed == B_BLESSED) { + wantblessed = B_UNCURSED; + } + } + // override blessed status from flags... f = hasflag(ot->flags, F_STARTBLESSED); if (f) { @@ -1208,6 +1218,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum } } + // don't give nopickup objects to lifeforms if (hasflag(ot->flags, F_NOPICKUP) && where->owner) { if (db) dblog("DB: trying to give NOPICKUP object '%s' to a lifeform ('%s').", ot->name, where->owner->race->name ); @@ -3936,7 +3947,9 @@ void fragments(cell_t *centre, char *what, int speed, int howfar) { } } - limit(&maxdist, NA, howfar); + if (howfar != UNLIMITED) { + limit(&maxdist, NA, howfar); + } // pick random distance if (maxdist == 0) { @@ -9468,13 +9481,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } } - if (lfhasflag(lf, F_RAGE)) { - if (isplayer(lf)) { - msg("You are too enraged to operate anything!"); - } - return B_TRUE; - } - getobname(o, obname, 1); if ((isplayer(lf)) || cansee(player, lf)) { @@ -10911,6 +10917,83 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { taketime(lf, getactspeed(lf)); } else if (hasflag(o->flags, F_SHOP)) { shop(lf, o); + } else if ((o->type->id == OT_POISONSAC) || (o->type->id == OT_POISONSACBL)) { + object_t *oo; + if (!getskill(lf, SK_LORE_CHEMISTRY)) { + if (isplayer(lf)) msg("You don't have enough Chemistry knowledge to use this."); + return B_TRUE; + } + // construct list of possible potions + clearretobs(); + for (oo = lf->pack->first ; oo ; oo = oo->next) { + if (oo->type->obclass->id == OC_POTION) { + retobs[nretobs] = oo; + nretobs++; + } + } + if (nretobs <= 0) { + if (isplayer(lf)) { + snprintf(buf, BUFLEN, "You have nothing to mix %s into.",obname); + msg(buf); + } + return B_TRUE; + } else { + enum OBTYPE newoid = OT_POT_POISON; + switch (o->type->id) { + case OT_POISONSACBL: + newoid = OT_POT_BLINDNESS; + break; + default: + case OT_POISONSAC: + newoid = OT_POT_POISON; + break; + } + snprintf(buf, BUFLEN, "Mix %s into what",obname); + if (isplayer(lf)) { + oo = askobject(lf->pack, buf, NULL, NULL, '\0', AO_SPECIFIED); + } else { + oo = retobs[rnd(0,nretobs-1)]; + } + if (oo) { + char oldname[BUFLEN]; + // remember letter + getobname(oo, oldname, 1); + if (isplayer(lf)) { + msg("You mix %s into %s.", obname, oldname); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s mixes %s into %s.", lfname, obname, oldname); + } + if (oo->amt > 1) { + oo = splitob(o); + assert(oo); + } + killob(oo); oo = NULL; + oo = addobfast(lf->pack, newoid); + if (oo) { + if (isplayer(lf)) { + char newname[BUFLEN]; + makeknown(OT_POT_POISON); + getobname(oo, newname, oo->amt); + msgnocap("%c - %s", oo->letter, newname); + } + } else { + // should never happen... + if (isplayer(lf)) { + msg("Your %s explodes!", noprefix(oldname)); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s%s %s explodes!", lfname, getpossessive(lfname), oldname); + } + + } + } else { + if (isplayer(lf)) msg("Cancelled."); + return B_TRUE; + } + } } @@ -11429,6 +11512,15 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE } } break; + case OT_POT_BLINDNESS: + switch (potblessed) { + case B_BLESSED: i = rnd(5,10); break; + case B_CURSED: i = rnd(20,30); break; + default: + case B_UNCURSED: i = rnd(10,20); break; + } + addtempflag(lf->flags, F_BLIND, B_TRUE, NA, NA, NULL, i); + break; case OT_POT_CANINETRACKING: dospelleffects(lf, OT_S_CANINETRACKING, 5, lf, NULL, lf->cell, potblessed, seen, B_TRUE, NULL); break; @@ -11699,7 +11791,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE // get lifeforms out of the way if (c->lf) { knockback(c->lf, getdiraway(c, lf->cell, NULL, B_FALSE, DT_ORTH, B_FALSE), - 1, lf, 0, B_TRUE); + 1, lf, 0, B_DOANNOUNCE, B_DODAM); } if (!c->lf) { @@ -12931,6 +13023,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) { } } break; + case OT_POT_BLINDNESS: case OT_POT_ELEMENTIMMUNE: case OT_POT_ETHEREALNESS: case OT_POT_FISHLUNG: @@ -14344,7 +14437,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp if ((getobunitweight(o)*amt) >= getlfweight(target, B_NOOBS)) { int dir; dir = getdirtowards(srcloc, target->cell, target, B_FALSE, DT_COMPASS); - knockback(target, dir, 1, thrower, 0, B_TRUE); + knockback(target, dir, 1, thrower, 0, B_DOANNOUNCE, B_DODAM); } } @@ -14951,7 +15044,8 @@ void timeeffectsob(object_t *o) { } losehp(lf, roll(f->text), DT_PROJECTILE, creator, damstring); // lfs then get knocked away (and might take further damage from hitting something) - knockback(lf, getrandomdir(DT_COMPASS), f->val[0], creator, f->val[1], B_TRUE); + knockback(lf, getrandomdir(DT_COMPASS), f->val[0], creator, f->val[1], + B_DOANNOUNCE, B_DODAM); } // objects get knocked away for (oo = o->pile->where->obpile->first ; oo ; oo = oo->next) { @@ -16453,3 +16547,15 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob return acc; } +int wouldgivepenalty(lifeform_t *lf, flagpile_t *fp) { + flag_t *retflag[MAXCANDIDATES],*f; + int nretflags,i,pen = 0; + getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE); + for (i = 0; i < nretflags; i++) { + pen += adjustarmourpenalty(lf, f->val[0]); + pen += adjustarmourpenalty(lf, f->val[1]); + } + if (pen) return B_TRUE; + return B_FALSE; +} + diff --git a/objects.h b/objects.h index 2beca72..66998f5 100644 --- a/objects.h +++ b/objects.h @@ -310,5 +310,6 @@ int wepdullable(object_t *o); int cancrush(lifeform_t *lf, object_t *o); int willrust(object_t *o); int willshatter(enum MATERIAL mat); +int wouldgivepenalty(lifeform_t *lf, flagpile_t *fp); #endif diff --git a/shops.c b/shops.c index d74bdfb..6fe3890 100644 --- a/shops.c +++ b/shops.c @@ -176,8 +176,8 @@ void shop(lifeform_t *lf, object_t *vm) { splittime(&h, &m, &s); if (!timeisbetween(h, f->val[0], f->val[1])) { sayphrase(NULL, f->val[2], SV_TALK, hoursto12(f->val[0]), NULL, player); + return; } - return; } if (lfhasflag(lf, F_STENCH)) { diff --git a/spell.c b/spell.c index a5a166f..f939b8d 100644 --- a/spell.c +++ b/spell.c @@ -524,7 +524,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef if (inway) { // just get the lf in the way - if (getnoisedetails(inway, N_WALK, NULL, thismovetext, NULL, &vol)) { + if (getnoisedetails(inway, N_WALK, NULL, thismovetext, NULL, &vol, NULL)) { // doesn't make noise nposs = 0; } else { @@ -542,7 +542,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef for (lf = c->map->lf ; lf ; lf = lf->next) { if (lf == user) continue; // get movement text - if (getnoisedetails(lf, N_WALK, NULL, thismovetext, NULL, &vol)) continue; + if (getnoisedetails(lf, N_WALK, NULL, thismovetext, NULL, &vol, NULL)) continue; if (slev >= PR_EXPERT) { // overwrite name real_getlfnamea(lf, thismovetext, NULL, B_NOSHOWALL, B_CURRACE); @@ -1364,7 +1364,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } dist = 2 + (getskill(user, SK_ATHLETICS)/3); setfacing(target, getrandomdir(DT_COMPASS)); - knockback(target, dir, dist, user, 125, B_FALSE); + knockback(target, dir, dist, user, 125, B_NOANNOUNCE, B_DODAM); } else { if (isplayer(user)) { msg("There is no room to flip %s!", targetname); @@ -1417,7 +1417,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } // push them back - knockback(target, dir, 1, user, 25, B_TRUE); + knockback(target, dir, 1, user, 25, B_DOANNOUNCE, B_NODAM); // if we succeeded in pushing them... if (target->cell != targcell) { @@ -1621,6 +1621,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } } } + if (iswoozy(user)) { + cell_t *retcell[MAXCANDIDATES]; + int nretcells; + // change destination. + getradiuscells(user->cell, maxrange, DT_COMPASS, B_FALSE, LOF_NEED, B_FALSE, retcell, &nretcells, B_FALSE); + targcell = retcell[rnd(0,nretcells-1)]; + } if (isburdened(user)) { if (isplayer(user)) { @@ -1633,8 +1640,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } return B_TRUE; } - - // did you land on something impassable? for (o = targcell->obpile->first ; o ; o = o->next) { if (isimpassableob(o, user, getlfsize(user))) { @@ -1649,26 +1654,23 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // we now have a cell - go there! taketime(user, getactspeed(user)); + + if (!targcell || (targcell == user->cell)) { + if (isplayer(user)) { + msg("You jump on the spot."); + } else if (cansee(player, user)) { + msg("%s jumps on the spot.", username); + } + return B_FALSE; + } + origcell = user->cell; // did you land on anyone? victim = haslf(targcell); if (victim) { - cell_t *c; int acc; - getlfname(victim,victimname); - - // move them out of the way - c = getrandomadjcell(victim->cell, &ccwalkable, B_NOEXPAND); - // nowhere to move? move to where the lf jumped from! - if (c) { - movelf(victim, c, B_FALSE); - } else { - swapplaces(victim, user, B_CHANGEDIR, B_CHANGEDIR, B_NOTONPURPOSE); - swapped = B_TRUE; - } - // see if you actually landed on them or they dodge... acc = 100 - (getevasion(victim)*2); if (rnd(1,100) > acc) { @@ -1676,9 +1678,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef dodged = B_TRUE; } } - if (!swapped) { - movelf(user, targcell, B_FALSE); - } // announce if (isplayer(user)) { @@ -1705,6 +1704,26 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } } + if (victim) { + cell_t *c; + + getlfname(victim,victimname); + + // move them out of the way + c = getrandomadjcell(victim->cell, &ccwalkable, B_NOEXPAND); + // nowhere to move? move to where the lf jumped from! + if (c) { + movelf(victim, c, B_FALSE); + } else { + swapplaces(victim, user, B_CHANGEDIR, B_CHANGEDIR, B_NOTONPURPOSE); + swapped = B_TRUE; + } + + } + if (!swapped) { + movelf(user, targcell, B_FALSE); + } + // splash? for (o = targcell->obpile->first ; o ; o = o->next) { if ((o->material->id == MT_WATER) && (o->type->id != OT_PUDDLEWATER)) { @@ -1726,7 +1745,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } } - practice(user, SK_ATHLETICS, 1); } else if (abilid == OT_A_PICKLOCK) { lockpick(user, NULL, NULL, NULL); @@ -3830,7 +3848,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef if (dir != D_NONE) { // knockback too - knockback(target, dir, dam, user, 0, B_TRUE); + knockback(target, dir, dam, user, 0, B_DOANNOUNCE, B_DODAM); } } @@ -4215,7 +4233,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (nextc->lf) { targcell = nextc; target = targcell->lf; - knockback(target, dir, power, caster, 0, B_TRUE); + knockback(target, dir, power, caster, 0, B_DOANNOUNCE, B_DODAM); real_fall_from_air(targcell->lf, SZ_HUMAN + (power/4)); } else if (firstobcell) { // objects @@ -4303,14 +4321,17 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // animate corpses within lof of caster for (i = 0; i < target->nlos; i++) { targcell = target->los[i]; - if (targcell != target->cell) { - for (o = targcell->obpile->first ; o ; o = nexto) { - nexto = o->next; - if (o->type->id == OT_CORPSE) { - poss[nposs++] = o; - } + //if (targcell != target->cell) { + // DO include the cell the target is standing on, + // since makezombie() will look for adjacent cells + // to place the zombie. + for (o = targcell->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (o->type->id == OT_CORPSE) { + poss[nposs++] = o; } } + //} } for (i = 0 ; (i < power) && (nposs > 0); i++) { @@ -4320,16 +4341,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ o = poss[sel]; newlf = makezombie(o, power); if (newlf) { - if (isplayer(target)){ - if (caster && isgod(caster)) { - makefriendly(newlf, PERMENANT); - } else if (skillcheck(target, A_IQ, 100, power)) { - makefriendly(newlf, PERMENANT); - } else if (cansee(target, newlf) && - areenemies(target, newlf)) { - msg("Uh oh, you have a bad feeling about this..."); - } - } + petify(newlf, target); donesomething = B_TRUE; } // remove from list @@ -6954,7 +6966,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (retcell[i]->lf) { knockback(retcell[i]->lf, getdiraway(retcell[i], targcell, NULL, B_FALSE, DT_COMPASS, B_FALSE), - 2, target, 100+(power*10), B_TRUE); + 2, target, 100+(power*10), B_DOANNOUNCE, B_DODAM); } } } @@ -7276,7 +7288,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenwalls) { if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenwalls == 1) { - msg("A nearby wall collapse into the ground!"); + msg("A nearby wall collapses into the ground!"); } else { msg("Nearby walls collapse into the ground!"); } @@ -7848,8 +7860,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ min = 20; max = 30; break; } - amt = getspellduration(min,max,blessed) + (power*2); - limit(&amt, min, max); + amt = getspellduration(min,max,blessed); + limit(&amt, min+(power*2)-1, max); if (undead) { losehp(target, amt, DT_HOLY, caster, "the power of healing"); @@ -8204,7 +8216,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ cell_t *c; c = getrandomadjcell(targcell, &ccwalkable, B_NOEXPAND); if (c) { - knockback(targcell->lf, getdirtowards(targcell, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, 100+(power*10), B_TRUE); + knockback(targcell->lf, getdirtowards(targcell, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, + 100+(power*10), B_DOANNOUNCE, B_DODAM); } else { if (isplayer(targcell->lf)) { msg("^%cYou are impaled by an icicle!", getlfcol(targcell->lf, CC_BAD) ); @@ -9519,6 +9532,56 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f = addtempflag(caster->flags, F_MAGICARMOUR, power*4, NA, NA, "psychic barrier", FROMSPELL); f->obfrom = spellid; + } else if (spellid == OT_S_PSYSHOVE) { + if (targcell->lf) { + float targweight = 0,lfweight = 0; + char tname[BUFLEN]; + int pushpower, dirtowards, diraway; + int pushcaster = B_FALSE; + cell_t *cellaway; + + target = targcell->lf; + + pushpower = power+1; + + getlfname(target, tname); + targweight = getlfweight(target, B_WITHOBS); + lfweight = getlfweight(caster, B_WITHOBS); + + if (isplayer(caster)) { + msg("You psychically push against %s!", tname); + } else if (cansee(player, caster)) { + msg("%s psychically pushes against %s!", castername, tname); + } + + dirtowards = whichwayto(caster->cell, targcell, NULL, B_FALSE); + diraway = diropposite(dirtowards); + cellaway = getcellindir(target->cell, dirtowards); + + if (lfweight < targweight) { + pushcaster = B_TRUE; + } else if (!cellaway) { + pushcaster = B_TRUE; + } else if (issolid(cellaway) || hascloseddoor(cellaway)) { + pushcaster = B_TRUE; + } + + if (pushcaster) { + // push caster back + msg("%s %s backwards through the air!", castername, + isplayer(caster) ? "sail" : "sails"); + knockback(caster, diraway, pushpower, caster, NA, B_NOANNOUNCE, B_NODAM); // never fall + } else { + // push them away, but airborne people don't fall + knockback(target, dirtowards, pushpower, caster, 15*power, B_DOANNOUNCE, B_NODAM); // ie. 45 max falldiff + } + + if (isplayer(target) || haslos(player, target->cell)) { + if (seenbyplayer) *seenbyplayer = B_TRUE; + } + } else { + fizzle(caster); + } } else if (spellid == OT_S_PULLMETAL) { int donesomething = B_FALSE; @@ -9806,7 +9869,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (target && (power >= 7)) { int dir; dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS); - knockback(target, dir, 2, caster, 0, B_TRUE); + knockback(target, dir, 2, caster, 0, B_DOANNOUNCE, B_DODAM); } else { int donesomething = B_FALSE; object_t *nexto; @@ -10097,21 +10160,25 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } - getchoice(&prompt); - o = (object_t *)prompt.result; - while (o) { - // describe it - describeob(o); - // ask for another one + if (prompt.nchoices == 0) { + msg("Your spell does detect anything nearby."); + } else { getchoice(&prompt); o = (object_t *)prompt.result; - } + while (o) { + // describe it + describeob(o); + // ask for another one + getchoice(&prompt); + o = (object_t *)prompt.result; + } - // restore screen - needredraw = B_TRUE; - statdirty = B_TRUE; - drawscreen(); - msg("Your spell finishes."); + // restore screen + needredraw = B_TRUE; + statdirty = B_TRUE; + drawscreen(); + msg("Your spell finishes."); + } } else if (spellid == OT_S_LORE) { enum SKILL skid; skill_t *sk; @@ -10973,15 +11040,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (f->lifetime > 1) { f->lifetime--; } - // cut power in half - f->val[1] /= 2; if (f->val[1] < 1) f->val[1] = 1; + // reduce power to minimum + f->val[1] = 1; if (isplayer(target)) { msg("^%cYour %s seems less intense.",getlfcol(target, CC_GOOD),pt->name); } ndone++; } } else if (f->id == F_INCUBATING) { - f->val[1] *= 2; + f->val[1] *= 2; // take longer to incubate } } if (ndone) { @@ -12986,7 +13053,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // knock lfs away if (c->lf) { - knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 100+(power*10), B_TRUE); + knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, + 100+(power*10), B_DOANNOUNCE, B_DODAM); donesomething = B_TRUE; } } @@ -13002,7 +13070,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // knock lfs away if (c->lf) { - knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 100+(power*10), B_TRUE); + knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, + 100+(power*10), B_DOANNOUNCE, B_DODAM); donesomething = B_TRUE; } } @@ -13018,7 +13087,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // knock lfs away if (c->lf) { - knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 100+(power*10), B_TRUE); + knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, + 100+(power*10), B_DOANNOUNCE, B_DODAM); donesomething = B_TRUE; } } @@ -13034,7 +13104,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // knock lfs away if (c->lf) { - knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, 100+(power*10), B_TRUE); + knockback(c->lf, getdiraway(c, c, NULL, B_FALSE, DT_COMPASS, B_FALSE), 1, NULL, + 100+(power*10), B_DOANNOUNCE, B_DODAM); donesomething = B_TRUE; } } @@ -13086,7 +13157,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // knock backwards dir = getdirtowards(caster->cell, target->cell, target, B_FALSE, DT_COMPASS); amt = (power/3); if (amt < 2) amt = 2; - knockback(target, dir, amt, caster, 0, B_TRUE); + knockback(target, dir, amt, caster, 0, B_DOANNOUNCE, B_DODAM); // rust getallouterarmour(target, arm, &narm); for (n = 0; n < narm; n++) { @@ -13480,17 +13551,25 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ bp = poss[rnd(0,nposs-1)]; // find all associated armour for (ot = objecttype ; ot ; ot = ot->next) { - if ((ot->obclass->id == OC_ARMOUR) && hasflagval(ot->flags, F_GOESON, bp, NA, NA, NULL)) { - narms++; + if ((ot->obclass->id == OC_ARMOUR) && + hasflagval(ot->flags, F_GOESON, bp, NA, NA, NULL)) { + // make sure this armour won't give us a penalty + if (!wouldgivepenalty(target, ot->flags)) { + narms++; + } + } } if (narms) { int sel,n = 0; sel = rnd(0,narms-1); for (ot = objecttype ; ot ; ot = ot->next) { - if ((ot->obclass->id == OC_ARMOUR) && hasflagval(ot->flags, F_GOESON, bp, NA, NA, NULL)) { - if (n == sel) break; - n++; + if ((ot->obclass->id == OC_ARMOUR) && + hasflagval(ot->flags, F_GOESON, bp, NA, NA, NULL)) { + if (!wouldgivepenalty(target, ot->flags)) { + if (n == sel) break; + n++; + } } } snprintf(buf, BUFLEN, "excellent branded %s", ot->name); diff --git a/text.c b/text.c index 854ef6e..ad12d0d 100644 --- a/text.c +++ b/text.c @@ -2065,6 +2065,13 @@ char *it(lifeform_t *lf) { return "it"; } +int isplural(char *text) { + if (text[strlen(text)-1] == 's') { + return B_TRUE; + } + return B_FALSE; +} + int isvowel (char c) { switch (c) { case 'a': diff --git a/text.h b/text.h index 65696d1..4f44ee7 100644 --- a/text.h +++ b/text.h @@ -56,6 +56,7 @@ char *getweighttext(float weight, char *buf, int shortfmt); int hoursto12(int h); char *is(lifeform_t *lf); char *it(lifeform_t *lf); +int isplural(char *text); int isvowel(char c); void killplural(plural_t *w); void makegunaimstring(lifeform_t *lf, int lfid, char *retbuf);