- [+] 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.
This commit is contained in:
Rob Pearce 2012-11-15 11:39:46 +00:00
parent ca132c87c7
commit 893540af19
20 changed files with 785 additions and 237 deletions

25
ai.c
View File

@ -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;
@ -1536,8 +1545,10 @@ int ai_healing(lifeform_t *lf) {
if (lfhasflag(lf, F_RAGE)) return B_FALSE;
// 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++) {

View File

@ -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;
}

111
data.c
View File

@ -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);

Binary file not shown.

21
defs.h
View File

@ -88,6 +88,12 @@
#define B_TRUE (-1)
#define B_MAYBE (-2)
#define B_DODAM (-1)
#define B_NODAM (0)
#define B_DOANNOUNCE (-1)
#define B_NOANNOUNCE (0)
#define B_NORANGED (0)
#define B_RANGED (-1)
@ -695,6 +701,7 @@ enum SAYPHRASE {
SP_ROBBED,
SP_SORRY,
SP_THANKS,
SP_TOOCLOSE,
SP_TRADEINFO_ACCEPT,
SP_TRADEINFO_CANCEL,
SP_TRADEINFO_DECLINE_ALREADYDONE,
@ -1624,6 +1631,7 @@ enum OBTYPE {
OT_ONION,
OT_PASSIONFRUIT,
OT_POISONSAC,
OT_POISONSACBL,
OT_PSITRUFFLE,
OT_ROASTMEAT,
OT_RUMBALL,
@ -1641,6 +1649,7 @@ enum OBTYPE {
OT_POT_ACID,
OT_POT_ACROBATICS,
OT_POT_AMBROSIA,
OT_POT_BLINDNESS,
OT_POT_BLOOD,
OT_POT_BLOODC,
OT_POT_CANINETRACKING,
@ -1851,6 +1860,7 @@ enum OBTYPE {
OT_S_PACIFY,
OT_S_PSIBLAST,
OT_S_PSYARMOUR,
OT_S_PSYSHOVE,
OT_S_SLEEP,
OT_S_STUN,
OT_S_STUNMASS,
@ -2259,15 +2269,21 @@ enum OBTYPE {
OT_AMU_ACROBAT,
OT_AMU_ANGER,
OT_AMU_BLOOD,
OT_AMU_BRAVERY,
OT_AMU_CHEF,
OT_AMU_CHOKING,
OT_AMU_ESCAPE,
OT_AMU_ENERGYABS,
OT_AMU_EVOLUTION,
OT_AMU_FALLING,
OT_AMU_FLIGHT,
OT_AMU_LIGHT,
OT_AMU_LISTEN,
OT_AMU_NOINJURY,
OT_AMU_PARANOIA,
OT_AMU_PIETY,
OT_AMU_PROT_MIN,
OT_AMU_PROT_MAJ,
OT_AMU_SLEEP,
OT_AMU_SOULS,
OT_AMU_SPELLBOOST,
@ -2298,7 +2314,6 @@ enum OBTYPE {
OT_RING_MIRACLES,
OT_RING_SPELLBOOST,
OT_RING_MPREGEN,
OT_RING_NOINJURY,
OT_RING_PROTFIRE,
OT_RING_PROTCOLD,
OT_RING_REFLECTION,
@ -2529,6 +2544,7 @@ enum NOISETYPE {
N_SONICBOLT,
N_WARCRY,
N_SPELLCAST,
N_TOOCLOSE,
};
enum LFSIZE {
@ -3586,6 +3602,9 @@ enum FLAG {
// eg. "shouts^a shout"
// if this flag occurs more than once with
// the same v0, a random one is selected.
// if val2 is not NA, then ignore 'text'
// and just call say() with
// SAYPHRASE val2 (SP_xxx)
F_SPELLCASTTEXT, // text is announcement for spellcast
// if text is empty, then don't announce
// this lf's spell casting at all.

111
god.c
View File

@ -662,6 +662,15 @@ void dooffer(void) {
thispiety = f->val[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);

8
io.c
View File

@ -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);

258
lf.c
View File

@ -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;
}

5
lf.h
View File

@ -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);

34
map.c
View File

@ -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) {

3
map.h
View File

@ -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);

69
move.c
View File

@ -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)

2
move.h
View File

@ -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);

View File

@ -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);

128
objects.c
View File

@ -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;
}

View File

@ -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

View File

@ -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)) {

223
spell.c
View File

@ -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);

7
text.c
View File

@ -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':

1
text.h
View File

@ -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);