- [+] change noise() calls to use enum sv_

- [+] make skeletons vuln to fall
- [+] sz_tiny an below objects shouldn't block doors from closing
- [+] double message for energy blast trap
- [+] scroll of charging/replenishment
- [+] random wands - maxcharges shouldn't be fixed to the start amount
      of charges. should be the highest possible start amount!
- [+] fixes to jammed door opening
- [+] flying creatures are too hard to hit.
- [+] make armour piercing be a number not a boolean on/off
- [+] make axes be armour piercing.
- [+] change display of armour piercing in io.c to reflect f->val[0]
- [+] change"of sharpness" to "of penetration", and make it use
      f_armourignore, not f_armourpiercing
- [+] You start training...  .  Your frozen battered lit torch freezes
      some more.
      Your training is interrupted!  Something burns you.
    - [+] but i didnt even have a torch!  got this msg for someone else?
- [+] Frozen by a ice sprite's frozen battered lit torch.
    - [+] don't show the condition
- [+] STILL problems with jammed doors opening on the first try
- [+] add more armour sizes for tiny etc, but leave it so that only
      medium/human/large are randomly generated.
- [+] battery - chargable things take power from this (anything with
      f_replenishable)
    - [+] do this during usecharge() 
    - [+] only if it's known.
    - [+] show charges in makedesc_ob
- [+] nullify spell (wild)
- [+] nullify wand
- [+] don't allow criticals on plants since they don't have blood,
      ribs, etc
- [+] gremlin (tools/tech/wands don't work)
This commit is contained in:
Rob Pearce 2011-12-28 05:06:47 +00:00
parent 60f6648511
commit 8d0d14b8dc
12 changed files with 589 additions and 131 deletions

View File

@ -107,20 +107,17 @@ void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *
int db = B_FALSE;
int newdam = 0;
// armour can't stop armour-piercing weapons
if (hasflag(wep->flags, F_ARMOURPIERCE)) {
reduceamt = 0;
}
// figure out reduced damage value
if (dam) {
int ar;
newdam = *dam;
ar = getarmourrating(lf, NULL, NULL, NULL);
// if you did at least one damage...
if ((*dam >= 1) && (reduceamt >= 0)) {
int lowerlimit = 0,divideby;
// reduce it.
newdam -= reduceamt;
@ -132,6 +129,8 @@ void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *
divideby = ar/2;
if (divideby <= 0) divideby = 1;
lowerlimit = (*dam / divideby);
limit(&lowerlimit, 1, NA);
limit(&newdam, lowerlimit, NA); // don't reduce too far.
}
@ -944,7 +943,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
}
}
//if (!isplayer(lf) && !isplayer(victim)) {
noise(lf->cell, lf, NC_FIGHTING, 3, "fighting.", NULL);
noise(lf->cell, lf, NC_FIGHTING, SV_SHOUT, "fighting.", NULL);
//}
if (fatal) {
if (strstr(buf, "behead")) {
@ -993,7 +992,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// don't adjust damage - we've already done that
if (wep && !isunarmed) {
char wepname[BUFLEN];
getobname(wep, wepname, 1);
real_getobname(wep, wepname, 1, B_TRUE, B_FALSE, B_FALSE, B_TRUE, B_FALSE);
/*
snprintf(buf, BUFLEN, "%s^%s %s",attackername2,
(lf == victim) ? "using" : "weilding",
@ -1637,8 +1636,9 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d
int ar,min,max;
//int pctrange;
object_t *o;
flag_t *pierce = NULL;
if (hasflag(wep->flags, F_ARMOURPIERCE)) {
if (hasflag(wep->flags, F_ARMOURIGNORE)) {
reduceamt = 0;
}
@ -1663,6 +1663,13 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d
}
}
// and if weapon is armour piercing, you always take at least its
// armourpiercing valut.
pierce = hasflag(wep->flags, F_ARMOURPIERCE);
if (pierce) {
reduceamt -= pierce->val[0];
}
if (reduceamt < 0) reduceamt = 0;
return reduceamt;
}
@ -2054,7 +2061,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
}
if (!canreach(lf, victim, &reachpenalty)) {
acc -= (15*reachpenalty);
acc -= (10*reachpenalty);
}
// modify for defender's evasion

169
data.c
View File

@ -963,8 +963,8 @@ void initobjects(void) {
addflag_real(lastbrand->flags, F_FLAMESTRIKE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_REVENGE, "of revenge", BP_WEAPON, B_UNCURSED, 0);
addflag_real(lastbrand->flags, F_REVENGE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_SHARPNESS, "of sharpness", BP_WEAPON, B_UNCURSED, 0);
addflag_real(lastbrand->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_SHARPNESS, "of penetration", BP_WEAPON, B_UNCURSED, 0);
addflag_real(lastbrand->flags, F_ARMOURIGNORE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
addbrand(BR_LIFESUCK, "of lifesucking", BP_WEAPON, B_UNCURSED, 0);
addflag_real(lastbrand->flags, F_VAMPIRIC, NA, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
@ -1162,6 +1162,7 @@ void initobjects(void) {
addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_OPERWITHOUTID, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_RNDCHARGES, 1, 8, NA, NULL);
addoc(OC_POTION, "Potions", "A strange concoction contained within a small flask.", '!', C_GREY, RR_COMMON);
@ -1847,6 +1848,7 @@ void initobjects(void) {
addflag(lastot->flags, F_CHARGES, 100, 100, NA, NULL);
addflag(lastot->flags, F_RECHARGE, 1, NA, NA, NULL);
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
// flora
addot(OT_FLOWER, "flower", "A colourful woodland flower.", MT_PLANT, 0.01, OC_FLORA, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, "");
@ -2137,7 +2139,7 @@ void initobjects(void) {
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BADOBJECT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
addot(OT_POT_ACID, "flask of battery acid", "Causes massive internal burning if ingested.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addot(OT_POT_ACID, "flask of acid", "Causes massive internal burning if ingested.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of acid");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
@ -2309,6 +2311,11 @@ void initobjects(void) {
addflag(lastot->flags, F_VALUE, 400, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 50, RR_RARE, NULL);
addot(OT_SCR_REPLENISHMENT, "scroll of replenishment", "Restores a random amount of charges to a wand.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_REPLENISH, NA, NA, NULL);
addot(OT_SCR_TELEPORT, "scroll of teleportation", "Causes the caster to teleport to a random location within the same level.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_LINKSPELL, OT_S_TELEPORT, 4, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
@ -2435,7 +2442,7 @@ 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_FALSE, LOF_NEED, NA, NULL);
addot(OT_S_DRAINLIFE, "necrotic beam", "Draws life force from the victim in order to heal the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_DRAINLIFE, "necrobeam", "Draws life force from the victim in order to heal the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The amount of life force drained is ^b1d6+power^n.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
@ -3572,6 +3579,18 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
// l4
addot(OT_S_NULLIFY, "nullify", "Permenantly removes the target's ability to use one or more spells/abilities.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the amount of spells nullified.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER|TT_DOOR, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addot(OT_S_REPLENISH, "replenish", "Restores a some amount of power to a wand.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the amount of charges restored.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
// l6
addot(OT_S_DETONATE, "detonate", "Causes a given area to explode with massive force.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the size of the explosion.");
@ -3795,6 +3814,10 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, 3, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, TR_NEEDLOF, NA, NULL);
addot(OT_WAND_NULLIFY, "wand of nullification", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, RR_RARE, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_NULLIFY, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, TR_NEEDLOF, NA, NULL);
addot(OT_WAND_REVEALHIDDEN, "wand of reveal hidden", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_REVEALHIDDEN, NA, NA, NULL);
@ -3915,6 +3938,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers");
addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out");
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_FRIDGE, "refrigerator", "An insulated household appliance, made for storing food.", MT_METAL, 120, OC_TOOLS, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
@ -3958,6 +3982,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers");
addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out");
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_LANTERNOIL, "oil lantern", "An oil-powered lantern which produces a lot of light.", MT_METAL, 1, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 55, NA, NULL);
@ -3971,6 +3996,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers");
addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out");
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_LOCKPICK, "lockpick", "An angled piece of metal, used to open locks.", MT_METAL, 0.05, OC_TOOLS, SZ_TINY);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
@ -4124,6 +4150,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers");
addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out");
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_TOWEL, "towel", "An large absorbent cloth used for drawing off moisture.", MT_CLOTH, 1.5, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 73, NA, NULL);
@ -4137,6 +4164,7 @@ void initobjects(void) {
addflag(lastot->flags, F_STACKABLE, B_FALSE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 2, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_PAPERCLIP, "paperclip", "A thin, looped wire for holding paper together.", MT_WIRE, 0.01, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_VALUE, 5, NA, NA, NULL);
@ -4163,6 +4191,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RNDCHARGES, 5, 10, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_POCKETWATCH, "pocket watch", "A portable timekeeping device made to be carried in a pocket.", MT_METAL, 0.1, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
@ -4185,6 +4214,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RNDCHARGES, 1, 5, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_LANTERNLED, "LED lantern", "A low-powered but efficient lantern which will last almost forever.", MT_METAL, 0.5, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, NULL);
@ -4197,8 +4227,15 @@ void initobjects(void) {
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
// tech - l2
addot(OT_BATTERY, "induction battery", "A power storage and provision device which automatically feeds power to nearby devices as needed.", MT_METAL, 1, OC_TECH, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addflag(lastot->flags, F_RNDCHARGES, 10, 30, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_TENT, "tent", "A easy to use, portable shelter made of fabric.", MT_CLOTH, 10, OC_TECH, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 15, 1, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
@ -4342,6 +4379,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 2, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_SKILLED, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
// tech - l5
addot(OT_TELEPAD, "teleport beacon", "A metal cone which will teleport the user to the nearest similar cone.", MT_METAL, 3, OC_TECH, SZ_MEDIUM);
@ -5610,8 +5648,9 @@ void initobjects(void) {
addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL);
addot(OT_RING_MIRACLES, "ring of miracles", "Grants a limited number of miracles to the wearer.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_CHARGES, 1, 3, NA, NULL);
addflag(lastot->flags, F_CHARGES, 1, 3, NA, NULL); // always starts with just 1 charge
addflag(lastot->flags, F_VALUE, 400, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addot(OT_RING_MPBOOST, "ring of arcane power", "Increases the power of the wearer's spells.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL);
@ -5764,7 +5803,7 @@ void initobjects(void) {
// monster weapons
addot(OT_ACIDATTACK, "acidattack", "acid attack object", MT_WATER, 0, OC_WEAPON, SZ_TINY);
addflag(lastot->flags, F_DAM, DT_ACID, 2, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 60, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL);
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL);
@ -5781,7 +5820,7 @@ void initobjects(void) {
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL);
addot(OT_TOUCHPARALYZE, "paralyzing touch", "paralyzing touch object", MT_BONE, 0, OC_WEAPON, SZ_TINY);
addflag(lastot->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_ARMOURPIERCE, 90, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_TOUCH, 1, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_HITCONFER, F_PARALYZED, SC_CON, 22, "2-4");
@ -5790,7 +5829,7 @@ void initobjects(void) {
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL);
addot(OT_TOUCHPARALYZE2, "strong paralyzing touch", "strong paralyzing touch object", MT_BONE, 0, OC_WEAPON, SZ_TINY);
addflag(lastot->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_ARMOURPIERCE, 90, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_TOUCH, 1, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_HITCONFER, F_PARALYZED, SC_CON, 30, "5-10");
@ -5814,7 +5853,7 @@ void initobjects(void) {
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_MISSILEDAM, 1, NA, NA, "");
addflag(lastot->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_ARMOURPIERCE, 10, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, "");
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL);
@ -5916,6 +5955,7 @@ void initobjects(void) {
// axes
addot(OT_AXE, "axe", "A short pole with a heavy, wedge-shaped blade for chopping.", MT_METAL, 5, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 4, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_CHOP, 6, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_BASH, 4, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
@ -5924,14 +5964,17 @@ void initobjects(void) {
addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL);
addot(OT_BATTLEAXE, "battleaxe", "An large axe specifically designed for combat.", MT_METAL, 8, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 8, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_CHOP, 11, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_BASH, 5, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 4, NA, NA, "");
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 13, 10, NULL);
addot(OT_GREATAXE, "greataxe", "An enormous axe made designed for combat.", MT_METAL, 10, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 10, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_CHOP, 18, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, NULL);
addflag(lastot->flags, F_NEEDSSPACE, B_TRUE, NA, NA, NULL);
@ -5941,6 +5984,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ATTREQ, A_STR, 15, 15, NULL);
addot(OT_HANDAXE, "hand axe", "A fast one-handed axe, ideal for throwing.", MT_METAL, 2.5, OC_WEAPON, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 4, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_CHOP, 7, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
addflag(lastot->flags, F_MISSILEDAM, 5, NA, NA, NULL);
@ -5950,6 +5994,7 @@ void initobjects(void) {
addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL);
addot(OT_HATCHET, "hatchet", "Similar to a handaxe but weighted at the head. A fast one-handed axe, ideal for throwing.", MT_METAL, 4, OC_WEAPON, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 6, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_CHOP, 8, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
@ -5958,6 +6003,7 @@ void initobjects(void) {
addflag(lastot->flags, F_CRITCHANCE, 6, NA, NA, NULL);
addot(OT_WARAXE, "war axe", "An axe made for combat.", MT_METAL, 7, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 8, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_CHOP, 12, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_BASH, 5, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
@ -6085,6 +6131,7 @@ void initobjects(void) {
// long blades
addot(OT_BASTARDSWORD, "bastard sword", "Very large, heavy sword.", MT_METAL, 8, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 2, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_SLASH, 12, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 12, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
@ -6095,6 +6142,7 @@ void initobjects(void) {
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 5, NA, NULL);
addot(OT_FALCHION, "falchion", "A single-edged heavy sword made for chopping.", MT_METAL, 6.5, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 61, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 4, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_CHOP, 11, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL);
@ -6103,6 +6151,7 @@ void initobjects(void) {
addot(OT_GREATSWORD, "greatsword", "A massive two-handed sword.", MT_METAL, 12, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 55, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 2, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_SLASH, 15, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 15, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
@ -6168,6 +6217,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 71, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_TRIPLF, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 4, NA, NA, "");
addflag(lastot->flags, F_DAM, DT_CHOP, 13, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_SLASH, 10, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
@ -6399,15 +6449,17 @@ void initobjects(void) {
addot(OT_MACE, "mace", "A weapon with a heavy head on a solid shaft used to bludgeon opponents.", MT_METAL, 10, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 9, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 4, NA, NA, "");
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 12, 10, NULL);
addflag(lastot->flags, F_CRITCHANCE, 7, NA, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 125, NA, NA, NULL);
addot(OT_MORNINGSTAR, "morningstar", "A heavy, spiked mace.", MT_METAL, 12, OC_WEAPON, SZ_MEDIUM);
addot(OT_MORNINGSTAR, "morningstar", "A heavy, spiked mace. Its weight makes it good for penetrating armour.", MT_METAL, 12, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 12, NA, NULL);
addflag(lastot->flags, F_ARMOURPIERCE, 6, NA, NA, "");
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL);
@ -7895,6 +7947,34 @@ void initrace(void) {
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL);
addrace(R_GREMLIN, "gremlin", 20, 'g', C_GREEN, MT_FLESH, RC_HUMANOID, "Small mischievous imps known for their love of sabotage.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4");
addflag(lastrace->flags, F_NUMAPPEAR, 2, 4, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 50, OC_TECH, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 50, OC_TECH, NA, "wand of wonder");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "chuckles^a chuckle");
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_GASEOUSFORM, NA, NA, "pw:3;");
// gremlins also cause tech to fail around them.
addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID, "A larger, stronger, smarter and more menacing form of a goblin.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
@ -8487,7 +8567,7 @@ void initrace(void) {
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_ACIDATTACK, 11, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_ACIDATTACK, 8, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^slurping");
addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL);
@ -8576,6 +8656,7 @@ void initrace(void) {
addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_WHITE, MT_ICE, RC_MAGIC, "A small magical creature made from freezing ice.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "sheet of ice");
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, "small puddle of water");
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -8590,8 +8671,8 @@ void initrace(void) {
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_SPELLSPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_FROSTBITE, NA, NA, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_FREEZEOB, NA, NA, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_ICICLE, NA, NA, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_FREEZEOB, 10, 10, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_ICICLE, 3, 3, "pw:1;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "gestures");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
@ -9450,6 +9531,56 @@ void initrace(void) {
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addrace(R_SLUG, "dragon slug", 150, 'P', C_GREY, MT_FLESH, RC_ANIMAL, "While dragon slugs lack the protective shell of their snail cousings, their rubbery flesh is extremely resilient. Their acid-based attacks also make them much more dangerous.");
addbodypart(lastrace, BP_BODY, NULL);
addbodypart(lastrace, BP_HEAD, NULL);
addbodypart(lastrace, BP_EYES, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_VERYSLOW, NA, NA, "");
addflag(lastrace->flags, F_MOVESPEED, SP_VERYSLOW, NA, NA, "");
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_SWAMP, NA, RR_FREQUENT, NULL);
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "7d4+1");
addflag(lastrace->flags, F_ARMOURRATING, 18, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_ACIDATTACK, 11, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^slurping");
addflag(lastrace->flags, F_DTIMMUNE, DT_ACID, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "puddle of acid");
addflag(lastrace->flags, F_DIESPLATTER, 3, NA, NA, "splash of acid");
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
addflag(lastrace->flags, F_VULNTOSALT, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addrace(R_SNAIL, "dragon snail", 150, 'P', C_BROWN, MT_FLESH, RC_ANIMAL, "An enormous snail, protected by a hard, scaled shell and gifted with long, sharp fangs.");
addbodypart(lastrace, BP_BODY, NULL);
addbodypart(lastrace, BP_HEAD, NULL);
addbodypart(lastrace, BP_EYES, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_VERYSLOW, NA, NA, "");
addflag(lastrace->flags, F_MOVESPEED, SP_VERYSLOW, NA, NA, "");
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_SWAMP, NA, RR_FREQUENT, NULL);
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4+1");
addflag(lastrace->flags, F_ARMOURRATING, 18, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 8, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
addflag(lastrace->flags, F_VULNTOSALT, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, 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_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
@ -9523,7 +9654,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addrace(R_SNAKECOBRABLACK, "black cobra", 3, 's', C_BLUE, MT_FLESH, RC_ANIMAL, "Black cobras can spit globs of venom at their prey.");
setbodytype(lastrace, BT_SNAKE);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
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_NOSMELL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9548,7 +9679,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addrace(R_SNAKECOBRAGOLDEN, "golden cobra", 3, 's', C_YELLOW, MT_FLESH, RC_ANIMAL, "Golden cobras spit a blindness-inducing venom at their enemies.");
setbodytype(lastrace, BT_SNAKE);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
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_NOSMELL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9604,6 +9735,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9779,7 +9911,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_SWALLOW, 5, 5, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "opens its mouth wide..");
addflag(lastrace->flags, F_NOISETEXT, N_WALK, SV_ROAR, NA, "^slithering");
addflag(lastrace->flags, F_NOISETEXT, N_WALK, SV_CAR, NA, "^slithering");
addflag(lastrace->flags, F_FLEEONHPPCT, 20, NA, NA, "");
addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
@ -10590,6 +10722,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_AXES, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 25, NA, NA, "buckler");
addflag(lastrace->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_FALL, NA, NA, "2d3");
addflag(lastrace->flags, F_DTRESIST, DT_PIERCE, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
@ -10864,9 +10997,11 @@ void initrace(void) {
addflag(r->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL);
addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_SLIME) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_UNDEAD) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);

Binary file not shown.

21
defs.h
View File

@ -472,8 +472,9 @@ enum SPEECHVOL {
SV_WHISPER = 1,
SV_TALK = 2,
SV_SHOUT = 3,
SV_ROAR = 4,
SV_BELLOW = 5,
SV_CAR = 4,
SV_TRUCK = 5,
SV_PLANE = 6,
};
enum SKILL {
@ -877,6 +878,7 @@ enum RACE {
R_GOBLINWAR,
R_GOBLINSHOOTER,
R_GOBLINHEXER,
R_GREMLIN,
R_HOBGOBLIN,
R_HOBGOBLINWAR,
R_KOBOLD,
@ -944,6 +946,8 @@ enum RACE {
R_NEWT,
R_PORCUPINE,
R_RAT,
R_SLUG,
R_SNAIL,
R_SNAKE,
R_SNAKECARPET,
R_SNAKECOBRABLACK,
@ -1235,6 +1239,7 @@ enum OBTYPE {
OT_SCR_ENCHANT,
OT_SCR_FREEZEOB,
OT_SCR_REMOVECURSE,
OT_SCR_REPLENISHMENT,
OT_SCR_TELEPORT,
OT_SCR_TURNUNDEAD,
OT_SCR_WISH,
@ -1430,6 +1435,8 @@ enum OBTYPE {
OT_S_ENERGYBOLT,
OT_S_ENERGYBLAST,
OT_S_FLASH,
OT_S_NULLIFY,
OT_S_REPLENISH,
// -- divine powers
OT_S_CREATEVAULT,
OT_S_GIFT,
@ -1501,6 +1508,7 @@ enum OBTYPE {
OT_WAND_INVIS,
OT_WAND_KNOCK,
OT_WAND_LIGHT,
OT_WAND_NULLIFY,
OT_WAND_POLYMORPH,
OT_WAND_REVEALHIDDEN,
OT_WAND_SLOW,
@ -1544,6 +1552,7 @@ enum OBTYPE {
OT_LANTERNLED,
OT_SOLDERINGIRON,
// tech l2
OT_BATTERY,
OT_C4,
OT_FLASHBANG,
OT_GRENADE,
@ -1834,7 +1843,6 @@ enum OBTYPE {
OT_PUSHE,
OT_PUSHS,
OT_PUSHW,
oooo
};
#define MAXBUILDINGTYPES (10)
@ -2122,6 +2130,7 @@ enum FLAG {
F_RNDCHARGES, // ob starts with between val0 and val1 charges
// this will cause F_CHARGES to be filled in
F_CHARGES, // generally the number of uses left,v0=min, v1=max
F_REPLENISHABLE, // the 'replenish' spell works on this object
F_DONTSHOWCHARGES, // don't show 'xx charges left' when id'd
F_RECHARGEWHENOFF, // get power back when you turn it off
F_RECHARGE, // get v0 charges back each turn.
@ -2280,7 +2289,9 @@ enum FLAG {
// v1->v0, v2->v1 is added to this object after it hits.
F_ACCURACY, // 100 - val0 = modify to tohit% (ie. higher is better)
F_UNARMEDWEP, // this is not a real weapon, ie. claws, teeth etc
F_ARMOURPIERCE, // goes through armour
F_ARMOURIGNORE, // armour has no effect
F_ARMOURPIERCE, // goes through armour. armour can't reduce the
// damage dealt to less than v0.
F_TWOHANDED, // weapon uses two hands to weild
F_NEEDSSPACE, // weapon needs space to swing - 75% chance of hitting
// a wall if used with < 3 empty cells around you
@ -2319,7 +2330,7 @@ enum FLAG {
F_LINKGOD, // val0 = linked god race id
// scroll flags
F_LINKSPELL, // val0 = spell this scroll will cast when read
// v1 = spell power
// v1 = spell power (optional)
// book flags
F_MANUALOF, // val0 = skill this book trains
F_LINKSCHOOL, // val0 = spellschool this book has spells from

View File

@ -16,11 +16,12 @@ e = eye
E = elemental ?
f = feline/cat
F = flora (flowers, plants, etc)
g = goblin
g = goblin / gremlin
G = large goblin
h = humanoid
H = large humanoid
i = insect
P = gastroPod
j = jelly/ooze/leech
k = kobold
m = mutant

2
god.c
View File

@ -958,7 +958,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
first = B_FALSE;
}
killflagsofid(o->flags, F_LOCKED);
noise(c, NULL, NC_OTHER, 2, "the click of a lock.", NULL);
noise(c, NULL, NC_OTHER, SV_TALK, "the click of a lock.", NULL);
}
}
}

35
io.c
View File

@ -5118,25 +5118,41 @@ char *makedesc_ob(object_t *o, char *retbuf) {
if (f) {
char sizetext[BUFLEN];
switch (f->val[0]) {
case SZ_MEDIUM:
case SZ_MINI:
snprintf(sizetext, BUFLEN, "miniature");
break;
case SZ_TINY:
snprintf(sizetext, BUFLEN, "tiny");
break;
case SZ_SMALL:
snprintf(sizetext, BUFLEN, "small");
break;
case SZ_LARGE:
snprintf(sizetext, BUFLEN, "very large");
case SZ_MEDIUM:
snprintf(sizetext, BUFLEN, "medium");
break;
case SZ_HUMAN:
default:
snprintf(sizetext, BUFLEN, "human");
break;
case SZ_LARGE:
snprintf(sizetext, BUFLEN, "large");
break;
case SZ_HUGE:
snprintf(sizetext, BUFLEN, "huge");
break;
case SZ_ENORMOUS:
snprintf(sizetext, BUFLEN, "enormous");
break;
default:
snprintf(sizetext, BUFLEN, "irregular"); // should never happen
break;
}
snprintf(buf, BUFLEN, "%sIt will only fit %s sized creatures.^n\n",
(f->val[0] != getlfsize(player)) ? "^B" : "^n", sizetext);
strncat(retbuf, buf, HUGEBUFLEN);
}
// charges remaining
if (o->type->obclass->id == OC_WAND) {
if ((o->type->obclass->id == OC_WAND) || (o->type->id == OT_BATTERY)) {
if (isidentified(o)) {
int charges;
charges = getcharges(o);
@ -5360,9 +5376,14 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, "It is ineffective in confined spaces due to its length.\n");
strncat(retbuf, buf, HUGEBUFLEN);
}
f = hasflag(o->flags, F_ARMOURIGNORE);
if (f && f->known) {
sprintf(buf, "Armour will not reduce %s damage at all.\n",OB1(o,"its","their"));
strncat(retbuf, buf, HUGEBUFLEN);
}
f = hasflag(o->flags, F_ARMOURPIERCE);
if (f && f->known) {
sprintf(buf, "Armour will not reduce %s damage.\n",OB1(o,"its","their"));
sprintf(buf, "Armour will not reduce %s damage below %d.\n",OB1(o,"its","their"), f->val[0]);
strncat(retbuf, buf, HUGEBUFLEN);
}
f = hasflag(o->flags, F_BALANCE);

46
lf.c
View File

@ -1002,10 +1002,10 @@ int canreach(lifeform_t *lf, lifeform_t *victim, int *reachpenalty) {
if (!isairborne(lf)) {
switch (isairborne(victim)) {
case F_FLYING:
sizetoreach = SZ_HUGE;
sizetoreach = SZ_HUMAN;
break;
case F_LEVITATING:
sizetoreach = SZ_HUMAN;
sizetoreach = SZ_MEDIUM;
break;
default: sizetoreach = SZ_ANY; break;
}
@ -2256,7 +2256,7 @@ void die(lifeform_t *lf) {
if ((lf->race->id == R_VAMPIRE) && !hasflag(lf->flags, F_ORIGRACE)) {
// if are asleep or killed by running water/sunlight, we will die normally
if (lfhasflag(lf, F_ASLEEP) || (lf->lastdamtype == DT_DIRECT)) {
noise(lf->cell, lf, NC_OTHER, 4, "a horrified scream!", "screams in horror!");
noise(lf->cell, lf, NC_OTHER, SV_CAR, "a horrified scream!", "screams in horror!");
} else if (findobinmap(lf->cell->map, OT_COFFIN)) { // coffin around?
// restore 1 hp
lf->hp = 1;
@ -3833,7 +3833,6 @@ int fall(lifeform_t *lf, lifeform_t *fromlf, int announce) {
getlfname(lf,lfname);
if (announce) {
if (isplayer(lf) || cansee(player, lf)) {
if (fromlf) {
@ -3849,6 +3848,11 @@ int fall(lifeform_t *lf, lifeform_t *fromlf, int announce) {
addflag(lf->flags, F_PRONE, B_TRUE, NA, NA, NULL);
loseconcentration(lf);
if (isvulnto(lf->flags, DT_FALL, B_FALSE)) {
// 0 will be repplaced with the dtvuln flag
losehp(lf, 0, DT_FALL, fromlf, "a bad fall");
}
return B_FALSE;
}
@ -13313,7 +13317,7 @@ void precalclos_new(lifeform_t *lf) {
//int db = B_FALSE;
enum SKILLLEVEL plev = PR_INEPT;
flag_t *missingeye;
long visdiameter;
//long visdiameter;
long allocamt;
@ -13345,8 +13349,10 @@ void precalclos_new(lifeform_t *lf) {
}
// ie. you can see both ways, plus your own cell
visdiameter = (MAXVISRANGE+1)*2;
allocamt = visdiameter * visdiameter;
//visdiameter = (MAXVISRANGE+1)*2;
//allocamt = visdiameter * visdiameter;
allocamt = MAX_MAPW * MAX_MAPH;
los = malloc( sizeof(cell_t *) * allocamt);
losdark = malloc( sizeof(cell_t *) * allocamt);
blocker = malloc( sizeof(cell_t *) * allocamt);
@ -13437,13 +13443,23 @@ void precalclos_new(lifeform_t *lf) {
nlos++;
assert (nlos < allocamt);
} else {
// if cell WASNT lit, add it to an array of dark "visible" cells
// (lf->darklos)
// that way we can check for these to determine whether we need to recalc our los
// when light changes.
losdark[nlosdark] = c;
nlosdark++;
assert (nlos < allocamt);
int idx,found=B_FALSE;
for (idx=0;idx<nlosdark;idx++) {
if (losdark[idx] == c) {
found = B_TRUE;
break;
}
}
if (!found) {
// if cell WASNT lit, add it to an array of dark "visible" cells
// (lf->darklos)
// that way we can check for these to determine whether we need to recalc our los
// when light changes.
losdark[nlosdark] = c;
nlosdark++;
assert (nlosdark < allocamt);
}
}
}
} else { // ie. if !c
@ -18444,7 +18460,7 @@ int weild(lifeform_t *lf, object_t *o) {
// make certain flags known
if (isplayer(lf)) {
f = hasflag(o->flags, F_ARMOURPIERCE);
f = hasflag(o->flags, F_ARMOURIGNORE);
if (f) {
msg("^gYour %s seems unnaturally sharp!",noprefix(buf));
f->known = B_TRUE;

4
map.c
View File

@ -4330,7 +4330,7 @@ void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int
}
if (!haslos(player, c)) {
noise(c, NULL, NC_OTHER, (range > 0) ? 6 : 5, "an explosion!", NULL);
noise(c, NULL, NC_OTHER, (range > 0) ? SV_PLANE : SV_TRUCK, "an explosion!", NULL);
}
for (y = c->y - range ; y <= c->y + range ; y++) {
@ -6202,7 +6202,7 @@ int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring) {
seen = B_TRUE;
} else {
// very loud
noise(c, NULL, NC_OTHER, 7, "shattering glass.", NULL);
noise(c, NULL, NC_OTHER, SV_CAR, "shattering glass.", NULL);
}
if (target) {

79
move.c
View File

@ -1437,7 +1437,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if (alarm && areenemies(lf, l) && haslof(lf->cell, l->cell, LOF_WALLSTOP, NULL) ) {
// in range of alarm? range is 3 * spell power cells.
if (getcelldist(lf->cell, l->cell) <= (alarm->val[2]*3)) {
// alarm goes off
// incredibly loud alarm goes off
noise(l->cell, NULL, NC_OTHER, 50, "a blaring siren!", NULL);
killflag(alarm);
}
@ -1464,7 +1464,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
shk = findshopkeeper(lf->cell->map, preshop);
if (shk && getowing(lf, preshop, NULL)) {
// call the guards
sayphrase(shk, SP_PAYTHREAT, SV_ROAR, NA, NULL);
sayphrase(shk, SP_PAYTHREAT, SV_CAR, NA, NULL);
didmsg = B_TRUE;
fightback(shk, lf); // shopkeeper attacks
callguards(shk, lf); // guards come running
@ -1758,6 +1758,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
}
return B_TRUE;
} else {
int wasjammed = B_FALSE;
if (lf) {
if (!canopendoors(lf)) {
if (isplayer(lf)) {
@ -1811,7 +1812,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
// stop sprinting
stopsprinting(lf);
}
} // end if lf
// trapped?
if (lf && hasflag(o->flags, F_TRAPPED)) {
@ -1831,24 +1832,26 @@ int opendoor(lifeform_t *lf, object_t *o) {
attackcell(lf, doorcell, B_TRUE);
return B_FALSE;
} else {
noise(doorcell, NULL, NC_OTHER, 2, "a door handle rattling.", NULL);
noise(doorcell, NULL, NC_OTHER, SV_TALK, "a door handle rattling.", NULL);
}
}
taketime(lf, getactspeed(lf));
touch(lf, o);
}
return B_TRUE;
} else {
} else {// ie. door not locked, but it might be jammed
int openit = B_TRUE;
f = hasflag(o->flags, F_JAMMED);
if (f && lf) {
wasjammed = B_TRUE;
openit = B_FALSE;
if (isplayer(lf) && (f->val[1] != B_TRUE)) { // not known yet
msg("The %s is jammed.", noprefix(obname));
openit = B_FALSE;
f->val[1] = B_TRUE;
} else {
// known - try to force it
int amt;
int amt = 0;
amt = getattr(lf, A_STR) - 10;
if (amt < 0) amt = 0;
@ -1874,18 +1877,20 @@ int opendoor(lifeform_t *lf, object_t *o) {
} else {
char noisebuf[BUFLEN];
sprintf(noisebuf, "%s jiggling against its hinges.", obname);
noise(doorcell, NULL, NC_OTHER, 3, noisebuf, NULL);
noise(doorcell, NULL, NC_OTHER, SV_SHOUT, noisebuf, NULL);
}
}
}
// loosen a bit
if (amt) {
f->val[0] -= amt;
if (f->val[0] <= 0) {
killflag(f);
}
}
openit = B_FALSE; // don't open the door
if (f->val[0] <= 0) {
killflag(f);
openit = B_TRUE;
} else {
openit = B_FALSE; // don't open the door
}
} // end if jammedknown
} // end if jammed
if (openit) {
@ -1899,20 +1904,40 @@ int opendoor(lifeform_t *lf, object_t *o) {
killflagsofid(o->flags, F_TRAPPED);
if (lf) {
if (isplayer(lf)) {
msg("You force %s open!",obname);
} else {
if (cansee(player, lf) && isadjacent(lf->cell, doorcell)) {
getlfname(lf, buf);
capitalise(buf);
msg("%s forces %s open!",buf, obname);
} else if (haslos(player, doorcell)) {
capitalise(obname);
msg("%s bursts open!",obname);
if (wasjammed) {
if (isplayer(lf)) {
msg("You force %s open!",obname);
} else {
char noisebuf[BUFLEN];
sprintf(noisebuf, "%s bursting open!", obname);
noise(doorcell, NULL, NC_OTHER, 4, noisebuf, NULL);
//if (cansee(player, lf) && isadjacent(lf->cell, doorcell)) {
if (cansee(player, lf)) {
getlfname(lf, buf);
capitalise(buf);
msg("%s forces %s open!",buf, obname);
} else if (haslos(player, doorcell)) {
capitalise(obname);
msg("%s bursts open!",obname);
} else {
char noisebuf[BUFLEN];
sprintf(noisebuf, "%s bursting open!", obname);
noise(doorcell, NULL, NC_OTHER, SV_CAR, noisebuf, NULL);
}
}
} else {
if (isplayer(lf)) {
msg("You open %s.",obname);
} else {
if (cansee(player, lf)) {
getlfname(lf, buf);
capitalise(buf);
msg("%s opens %s.",buf, obname);
} else if (haslos(player, doorcell)) {
capitalise(obname);
msg("%s opens.",obname);
} else {
char noisebuf[BUFLEN];
sprintf(noisebuf, "%s opening.", obname);
noise(doorcell, NULL, NC_OTHER, SV_TALK, noisebuf, NULL);
}
}
}
@ -1929,12 +1954,12 @@ int opendoor(lifeform_t *lf, object_t *o) {
// checking if we have LOS to the lifeform making
// sound, but in this case it's the door making
// the sound, not the lf.
noise(where, NULL, NC_OTHER, 2, "a door opening.", NULL);
noise(where, NULL, NC_OTHER, SV_TALK, "a door opening.", NULL);
}
}
}
return B_FALSE;
}
} // end if door locked
}
return B_FALSE;
@ -1988,7 +2013,7 @@ int closedoor(lifeform_t *lf, object_t *o) {
// any solid object other than the door?
for (oo = cell->obpile->first ; oo ; oo = oo->next) {
if ((oo != o) && (getmaterialstate(oo->material->id) == MS_SOLID)) {
if ((oo != o) && (getmaterialstate(oo->material->id) == MS_SOLID) && (getobsize(o) >= SZ_SMALL)) {
if (lf && isplayer(lf)) {
char inwayname[BUFLEN];
getobname(oo, inwayname, oo->amt);

197
objects.c
View File

@ -629,6 +629,14 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
p += strlen("cursed ");
donesomething = B_TRUE;
// armour flags
} else if (strstarts(p, "gargantuan ")) {
wantarmsize = SZ_ENORMOUS;
p += strlen("gargantuan ");
donesomething = B_TRUE;
} else if (strstarts(p, "titan-sized ")) {
wantarmsize = SZ_HUGE;
p += strlen("titan-sized ");
donesomething = B_TRUE;
} else if (strstarts(p, "giant-sized ")) {
wantarmsize = SZ_LARGE;
p += strlen("giant-sized ");
@ -637,6 +645,18 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
wantarmsize = SZ_MEDIUM;
p += strlen("half-sized ");
donesomething = B_TRUE;
} else if (strstarts(p, "baby-sized ")) {
wantarmsize = SZ_SMALL;
p += strlen("baby-sized ");
donesomething = B_TRUE;
} else if (strstarts(p, "tiny-sized ")) {
wantarmsize = SZ_TINY;
p += strlen("tiny-sized ");
donesomething = B_TRUE;
} else if (strstarts(p, "minisicule ")) {
wantarmsize = SZ_MINI;
p += strlen("minisicule ");
donesomething = B_TRUE;
// door flags
} else if (strstarts(p, "locked ")) {
doorflag[ndoorflags++] = F_LOCKED; // for doors
@ -1082,11 +1102,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
amt = rnd(f->val[0], f->val[1]);
chargeflag = hasflag(o->flags, F_CHARGES);
if (chargeflag) {
chargeflag->val[0] = amt;
chargeflag->val[1] = amt;
chargeflag->val[0] = amt; // randomly selected amt
chargeflag->val[1] = f->val[1]; // highest possible amt
chargeflag->known = B_FALSE;
} else {
chargeflag = addflag_real(o->flags, F_CHARGES, amt, amt, NA, NULL, PERMENANT, B_UNKNOWN, -1);
chargeflag = addflag_real(o->flags, F_CHARGES, amt, f->val[1], NA, NULL, PERMENANT, B_UNKNOWN, -1);
}
}
@ -1262,6 +1282,10 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
if (wantarmsize == SZ_ANY) {
// if giving to a lifeform being created, match their size
if (where->owner) {
// note: this COULD result in weird sizings other than
// medium, human or large. this is okay - other code
// will understand it. just when randomly making armour,
// only megium/human/large will appear.
wantarmsize = getlfsize(where->owner);
} else {
// random size
@ -4767,12 +4791,27 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
char sizetext[BUFLEN];
// prepend size
switch (f->val[0]) {
case SZ_MINI:
strcpy(sizetext, "miniscule");
break;
case SZ_TINY:
strcpy(sizetext, "tiny ");
break;
case SZ_SMALL:
strcpy(sizetext, "baby-sized");
break;
case SZ_MEDIUM:
strcpy(sizetext, "half-sized");
break;
case SZ_LARGE:
strcpy(sizetext, "giant-sized");
break;
case SZ_HUGE:
strcpy(sizetext, "titan-sized");
break;
case SZ_ENORMOUS:
strcpy(sizetext, "gargantuan");
break;
default:
strcpy(sizetext, "");
break;
@ -8050,24 +8089,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
}
// objects with charges...
if (hasflag(o->flags, F_OPERUSECHARGE)) { // operating toggles on/off
int chargesleft;
chargesleft = getcharges(o);
if (chargesleft > 0) {
chargesleft = usecharge(o);
// TODO: notify if getting low
} else {
if (isplayer(lf)) {
nothinghappens();
// you know it's out
f = hasflag(o->flags, F_CHARGES);
f->known = B_TRUE;
return B_FALSE;
}
}
}
// ask for target, if required
f = hasflag(o->flags, F_OPERNEEDTARGET);
if (f && !where) {
@ -8140,14 +8161,57 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
if (touch(lf, o)) {
taketime(lf, getactspeed(lf));
return B_TRUE;
}
if (hasflag(o->flags, F_DEAD)) return B_TRUE;
if (hasflag(o->flags, F_DEAD)) {
taketime(lf, getactspeed(lf));
return B_TRUE;
}
// objects with charges...
if (hasflag(o->flags, F_OPERUSECHARGE)) { // operating toggles on/off
if (usecharge(o) == -1) {
if (isplayer(lf)) {
nothinghappens();
// you know it's out
f = hasflag(o->flags, F_CHARGES);
f->known = B_TRUE;
taketime(lf, getactspeed(lf));
return B_FALSE;
}
}
}
// TODO: change to be based on item type
// TODO: move this to the end in case 'operate' fails
taketime(lf, getactspeed(lf));
// check for gremlins
if ((o->type->obclass->id == OC_TECH) || (o->type->obclass->id == OC_TOOLS) ||
(o->type->obclass->id == OC_WAND)) {
if (lf->race->id != R_GREMLIN) {
cell_t *retcell[MAXCANDIDATES],*c;
int nretcells,i;
getradiuscells(lf->cell, 5, DT_COMPASS, B_FALSE, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 0);
for (i = 0; i < nretcells; i++) {
c = retcell[i];
if (c->lf && (c->lf->race->id == R_GREMLIN)) {
if (isplayer(lf)) {
msg("Inexplicably, your %s doesn't seem to work.", noprefix(obname));
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s%s %s doesn't seem to work.", lfname, getpossessive(lfname),
noprefix(obname));
}
return B_TRUE;
}
}
}
} // end if techtype affected by gremlins
// mark obejct as tried
if (isplayer(lf)) maketried(o->type->id);
@ -8271,15 +8335,17 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
// special wands
} else if (o->type->id == OT_WAND_WONDER) {
int power;
// random power
power = rnd(1,10);
// 1 in 3 chance of targetting yourself
if (onein(3)) {
where = lf->cell;
if (lf->race->id != R_GREMLIN) {
// override power
power = rnd(1,10);
// 1 in 3 chance of targetting yourself
if (onein(3)) {
where = lf->cell;
}
}
// random effect
switch (rnd(0,21)) {
switch (rnd(0,22)) {
case 0: // butterflies around user
willid = B_TRUE;
where = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
@ -8351,6 +8417,13 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
case 21: // teleport
dospelleffects(lf, OT_S_TELEPORT, power, lf , NULL, lf->cell, o->blessed, &willid, B_FALSE);
break;
case 22: // create banana peel
if (where->type->solid) {
setcelltype(where, where->map->habitat->emptycelltype);
} else {
addob(where->obpile, "3-5 banana skins");
}
break;
//oooooooooo
}
}
@ -8375,7 +8448,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
dospelleffects(lf, OT_S_SPARK, 1, NULL, NULL, where, B_UNCURSED, &seen, B_FALSE);
// announce
if (!seen) {
noise(where, NULL, NC_OTHER, 1, "something burning.", NULL);
noise(where, NULL, NC_OTHER, SV_WHISPER, "something burning.", NULL);
}
} else if (o->type->id == OT_GODSTONEJ) {
f = hasflag(o->flags, F_CHARGES);
@ -8452,7 +8525,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
// announce
if (!seen) {
noise(where, NULL, NC_OTHER, 0, "something spraying.", NULL);
noise(where, NULL, NC_OTHER, SV_WHISPER, "something spraying.", NULL);
}
} else if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) {
object_t *oo,*nextoo;
@ -8685,7 +8758,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
if (isplayer(lf)) {
msg("You play a few notes on your panpipes.");
} else {
noise(lf->cell, lf, NC_OTHER, 3, "the sound of panpipes.", "plays a tune on its panpipes.");
noise(lf->cell, lf, NC_OTHER, SV_CAR, "the sound of panpipes.", "plays a tune on its panpipes.");
}
} else if (o->type->id == OT_PICKAXE) {
int ch,dir;
@ -9844,6 +9917,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
// only id if it does something
willid = B_FALSE;
}
case OT_SCR_REPLENISHMENT:
case OT_SCR_ENCHANT:
case OT_SCR_CREATEMONSTER:
case OT_SCR_REMOVECURSE:
@ -9869,6 +9943,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
}
break;
case OT_SCR_ENCHANT:
case OT_SCR_REPLENISHMENT:
needsob = B_TRUE;
break;
default:
@ -10581,7 +10656,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
seen = B_TRUE;
} else {
noise(where, NULL, NC_OTHER, 3, "shattering glass.", NULL);
noise(where, NULL, NC_OTHER, SV_SHOUT, "shattering glass.", NULL);
}
if (target) {
@ -11800,7 +11875,6 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
}
}
if (thrower) {
if (firearm) {
practice(thrower, SK_THROWING, 1);
@ -12137,7 +12211,7 @@ void timeeffectsob(object_t *o) {
chargeleft = usecharge(o);
// out of power?
if (chargeleft <= 0) {
if (chargeleft == -1) {
if (owner) {
// announce power loss
if (isplayer(owner)) {
@ -12459,7 +12533,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c) {
}
}
} else if (oid == OT_TRAPALARM) {
noise(c, NULL, NC_OTHER, 10, "a blaring siren!", "A blaring siren goes off!");
noise(c, NULL, NC_OTHER, 50, "a blaring siren!", "A blaring siren goes off!");
} else if ((oid == OT_TRAPARROW) || (oid == OT_TRAPARROWP)) {
int dir,bestdir = D_NONE;
cell_t *src = NULL;
@ -12508,8 +12582,10 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c) {
dblog("ERROR: arrow trap failed (no dir).");
}
} else if (oid == OT_TRAPEBLAST) {
if (haslos(player, c)) {
if (!haslos(player, c)) {
msg("A blast of energy comes out of nowhere!");
// if we DO have los, then spelleffects() will take care of the
// announcement.
}
// can't be dodged
dospelleffects(NULL, OT_S_ENERGYBLAST, 1, NULL, NULL, c, B_UNCURSED, NULL, B_TRUE);
@ -12720,26 +12796,59 @@ int uncurseob(object_t *o, int *seen) {
return B_FALSE;
}
// returns charges remaining, -1 if object doesn't have the flag
// returns charges remaining, -1 if object doesn't have the flag or is
// out of charges.
int usecharge(object_t *o) {
flag_t *f;
flag_t *f = NULL;
object_t *b;
// use power from a battery first
b = hasob(o->pile, OT_BATTERY);
if (b && isknown(b)) {
f = hasflag(b->flags, F_CHARGES);
// does the battery have charges left?
if (f && (f->val[0] <= 0)) {
f = NULL;
}
}
// if no battery, use charges from the object itself.
if (!f) {
f = hasflag(o->flags, F_CHARGES);
}
// use up the charge.
if (f && (f->val[0] > 0)) {
f->val[0]--;
} else {
// couldn't use a charge - ran out.
return -1;
}
// always return the amount of charges the _object_ has left.
// not the battery.
f = hasflag(o->flags, F_CHARGES);
if (f) {
f->val[0]--;
return f->val[0];
} else {
return 0; // since technically we didn't fail if we got here.
}
return -1;
}
// returns charges remaining, -1 if object doesn't have the flag
int usecharges(object_t *o, int amt) {
flag_t *f;
int i;
// use charges one at a time.
for (i = 0; i < amt; i++) {
if (usecharge(o) == -1) {
// ran out of power!
return -1;
}
}
// return the amount of charges which the object has left.
f = hasflag(o->flags, F_CHARGES);
if (f) {
f->val[0] -= amt;
if (f->val[0] < 0) {
f->val[0] = 0;
}
return f->val[0];
}
return -1;

139
spell.c
View File

@ -3244,6 +3244,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
}
}
}
stopsprinting(user);
// start hiding
addflag(user->flags, F_HIDING, penalty, NA, NA, NULL);
@ -4543,7 +4544,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char lfname[BUFLEN];
// automatic hit
getlfname(targcell->lf, lfname);
if (haslos(caster, targcell)) {
if (haslos(player, targcell)) {
msg("%s %s chilled!",lfname,is(targcell->lf));
}
losehp(targcell->lf, rolldie(1,8)+3, DT_COLD, caster, "a burst of coldness");
@ -6053,7 +6054,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
flag_t *f;
loc = getoblocation(o);
// announce
if (haslos(caster, loc)) {
if (haslos(player, loc)) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
msg("%s %s freeze%s some more.",
@ -6903,6 +6904,76 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (failed) {
fizzle(caster);
}
} else if (spellid == OT_S_NULLIFY) {
flag_t *retflag[MAXCANDIDATES],*poss[MAXCANDIDATES],*f;
int nretflags,i,ndone = 0,nposs;
target = targcell->lf;
if (!target) {
fizzle(caster);
}
if (isplayer(target)) {
msg("^wYou are engulfed in an anti-magic field!");
} else if (cansee(player, target)) {
char lfname[BUFLEN];
getlfname(target, lfname);
msg("^w%s is engulfed in an anti-magic field!", lfname);
}
while (ndone < power) {
// get a list of flags which could be destroyed
nposs = 0;
// for player:
// remove memorised spells
// for monsters:
// remove racial spells AND abilities
//
// abilities/spells conferred by objects are not affected.
getflags(target->flags, retflag, &nretflags, F_CANCAST, F_CANWILL, F_NONE);
for (i = 0; i < nretflags; i++) {
int ok = B_TRUE;
if (isplayer(target)) {
if (retflag[i]->id == F_CANWILL) {
ok = B_FALSE;
} else if (retflag[i]->lifetime != PERMENANT) {
ok = B_FALSE;
}
} else {
if ((retflag[i]->lifetime != FROMRACE) && (retflag[i]->lifetime != PERMENANT)) {
ok = B_FALSE;
}
}
if (ok && isplayer(target)) {
objecttype_t *ot;
ot = findot(retflag[i]->val[0]);
if (ot->obclass->id != OC_SPELL) {
ok = B_FALSE;
}
}
if (ok) {
poss[nposs++] = retflag[i];
}
}
if (!nposs) {
break;
}
f = poss[rnd(0,nposs-1)];
killflag(f);
ndone++;
}
if (isplayer(target)) {
if (!ndone) {
msg("You are unaffected.");
}
} else if (cansee(player, target)) {
char lfname[BUFLEN];
getlfname(target, lfname);
if (ndone) {
msg("%s%s powers are nullified!", lfname, getpossessive(lfname));
} else {
msg("%s is unaffected.", lfname);
}
}
} else if (spellid == OT_S_ACCELMETAL) {
char oidbuf[BUFLEN];
flag_t *f;
@ -8483,6 +8554,68 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster)) {
msg("A strange odour surrounds you...");
}
} else if (spellid == OT_S_REPLENISH) {
int incamt,newamt,maxed = B_FALSE;
char obname[BUFLEN];
flag_t *f;
if (!targob) {
if (isplayer(caster)) {
// ask for an object
targob = askobjectwithflag(caster->pack, "Replenish which object", NULL, '\0', AO_NONE, F_REPLENISHABLE);
}
}
if (!targob) {
fizzle(caster);
return B_TRUE;
}
f = hasflag(targob->flags, F_CHARGES);
if (!f) {
nothinghappens();
return B_TRUE;
}
// restores power% of maximum
incamt = pctof(power*10, f->val[1]);
limit(&incamt, 1, NA); // at least 1!
newamt = f->val[0] + incamt;
limit(&newamt, NA, f->val[1]);
if (f->val[0] == newamt) {
// already maxed
maxed = B_TRUE;
}
f->val[0] = newamt;
targcell = getoblocation(targob);
if (maxed) {
if (haslos(player, targcell)) {
nothinghappens();
}
return B_TRUE;
}
getobname(targob, obname, targob->amt);
if (targob->pile->owner) {
if (isplayer(targob->pile->owner)) {
msg("Your %s %s %s.", noprefix(obname), (targob->amt == 1) ? "pulses" : "pulse", (power < 5) ? "briefly" : "for a while");
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player,targob->pile->owner)) {
char lfname[BUFLEN];
getlfname(targob->pile->owner, lfname);
msg("%s%s %s %s %s.", lfname, getpossessive(lfname),
noprefix(obname), (targob->amt == 1) ? "pulses" : "pulse", (power < 5) ? "briefly" : "for a while");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
if (haslos(player, targcell)) {
msg("%s %s %s.", noprefix(obname), (targob->amt == 1) ? "pulses" : "pulse", (power < 5) ? "briefly" : "for a while");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
}
} else if (spellid == OT_S_REVEALHIDDEN) {
int i;
int seen = B_FALSE;
@ -10251,7 +10384,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
o = relinkob(o, newloc->obpile);
}
if (o) {
noise(caster->cell, NULL, NC_OTHER, 1, "something hitting the ground.", NULL);
noise(caster->cell, NULL, NC_OTHER, SV_WHISPER, "something hitting the ground.", NULL);
if (!isblind(caster)) {
msg("%s appear%s on the ground!", obname, OBS1(o));
}