- [+] increase damage for missiles

- [+] retain items on polymorph if new race has f_nopack or nobodypart
      for equipped stuff
    - [+] move obs to lf->polypack
    - [+] save this!
- [+] fix bugs with remembering/restoring stats on polyrevert.
- [+] scroll of permenance should make conferred attribute changes
      permenant
- [+] change strength damage mod to be range -2 to 2 (instead of a
      percentage)
- [+] corrected poison/methane gas difference.
- [+] hecta gift: necromancy books
- [+] damagecell()
    - [+] make rock walls turn to rubble ("50-100 stones")
- [+] change to lore skill: incrase damage by a fixed amount, not a
      percentage.
- [+] felix effect: evaulation (identify obs)
- [+] god piety should never change once thy are ignoring you.
- [+] shields should protect against crit hits
- [+] hecta no longer gives unholy water? 
- [+] I'm able to use OT_A_SHIELDBASH with 0 stamina.
- [+] CRASH during loading
    - [+] fixed
    - [+] ...but check for more....
- [+] quaff potion of fury - "you're too tired to do that right now"
- [+] player was being prompted for locaiton when monster tried to wear
      a bandage.
- [+] closing iron gates is making them opaque.
    - [+] only add blocksview if the objectTYPE has it.
- [+] fountains of experience not drying up.
- [+] looking for tracks on stairs.  never finding any!!
- [+] shop descriptions not working anymore.
- [+] left hand got destroyed by explosion.
    - [+] i then wore a ring... and it went on "left finger"!
- [+] all spell effects should cease just before death.
- [+] crystal shield/armour shouldn't call wear() but rather just set
      f_equipped directly.
- [+] bedrooms/kitchens should have tiled or carpet floors?
    - [+] tiled = less stability (especially with water!!)
    - [+] carpet = more stability
- [+] fire skeleton
- [+] firebug
- [+] ice wraith
- [+] winter wolf
- [+] skoob (snowman)
- [+] crymidia can cast crystal spells
- [+] blastbug
- [+] bilco - casts flood at itself.
- [+] rubber-like things
    - [+] slug
    - [+] snail
This commit is contained in:
Rob Pearce 2012-01-24 20:38:59 +00:00
parent 4a32308310
commit 5f4454d56a
20 changed files with 951 additions and 397 deletions

38
ai.c
View File

@ -394,15 +394,24 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
int aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim, lifeform_t **spelllf, cell_t **spellcell, object_t **spellob, enum FLAG purpose) {
int specialcase = B_FALSE;
flag_t *f;
enum SPELLTARGET spelltarg = ST_NONE;
// default - at victim.
if (spelllf) *spelllf = victim;
if (spellcell) *spellcell = victim->cell;
if (spellob) *spellob = NULL;
f = lfhasflagval(lf, F_AISPELLTARGETOVERRIDE, spelltype->id, NA, NA, NULL);
if (f) {
spelltarg = f->val[1];
} else {
f = hasflag(spelltype->flags, purpose);
if (f) {
switch (f->val[0]) {
spelltarg = f->val[0];
}
}
switch (spelltarg) {
case ST_VICTIM:
// at victim.
if (spelllf) *spelllf = victim;
@ -436,6 +445,8 @@ int aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim
case ST_SPECIAL:
specialcase = B_TRUE;
break;
case ST_NONE:
break;
}
if (specialcase) {
@ -567,7 +578,6 @@ int aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim
}
}
}
}
return B_FALSE;
}
@ -1962,14 +1972,24 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
char why[BUFLEN];
if (reason == E_NOMP) {
strcpy(why, "not enough mp");
} else if (reason == E_CLIMBING) {
strcpy(why, "climbing");
} else if (reason == E_NOSTAM) {
strcpy(why, "not enough stamina");
} else if (reason == E_LOWIQ) {
strcpy(why, "lowiq");
} else if (reason == E_PRONE) {
strcpy(why, "prone");
} else if (reason == E_SWIMMING) {
strcpy(why, "swimming");
} else if (reason == E_TOOPOWERFUL) {
strcpy(why, "spell too powerful");
} else if (reason == E_NOTREADY) {
strcpy(why, "abil not ready");
} else if (reason == E_NEEDGRAB) {
strcpy(why, "needs grab");
} else if (reason == E_INJURED) {
strcpy(why, "injured");
} else {
strcpy(why, "unknown reason");
}
@ -2252,6 +2272,15 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
specificcheckok = B_FALSE;
}
}
if (ot->id == OT_S_ICECRUST) {
object_t *wep;
wep = getweapon(lf);
if (!wep) {
specificcheckok = B_FALSE;
} else if (hasflag(wep->flags, F_FROZEN)) {
specificcheckok = B_FALSE;
}
}
if ((ot->id == OT_S_INVISIBILITY) && lfhasflag(victim, F_INVISIBLE)) {
specificcheckok = B_FALSE;
}
@ -2297,6 +2326,11 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
specificcheckok = B_FALSE;
}
}
if (ot->id == OT_S_SUMMONWEAPON) {
if (getweapon(lf)) {
specificcheckok = B_FALSE;
}
}
if ((ot->id == OT_A_SWOOP) || (ot->id == OT_A_CHARGE)) {
cell_t *adjcell;
flag_t *willflag, *srflag;

View File

@ -781,7 +781,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (!willheal) {
enum SKILLLEVEL slev;
float loremult;
float loreadd = 0;
// blessed vs undead
adjustdamforblessings(&(dam[0]), victim, wep->blessed);
@ -806,11 +806,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// bonus for knowledge about the other lf's race? applied LAST.
slev = getlorelevel(lf, victim->race->raceclass->id);
if (slev == PR_INEPT) {
loremult = 1;
loreadd = 0;
} else {
loremult = 1 + (slev * 0.1);
loreadd = slev;
}
dam[0] = (int) ( (float)dam[0] * loremult );
dam[0] = (int) ( (float)dam[0] + loreadd );
}
if (aidb) dblog(".oO { dealing %d %s damage }", dam[0], getdamname(damtype[0]));
@ -1293,7 +1293,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
// modify for strength
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
dam[ndam] = (int)((float)dam[ndam] * getstrdammod(lf));
dam[ndam] += getstrdammod(lf);
}
// damtype?
@ -1443,7 +1443,7 @@ int attackwall(lifeform_t *lf, cell_t *c, object_t *wep, flag_t *damflag) {
// modify for strength
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
dam[ndam] = (int)((float)dam[ndam] * getstrdammod(lf));
dam[ndam] += getstrdammod(lf);
}
// damtype?
@ -2044,35 +2044,21 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) {
return dam;
}
// returns a multiplier
float getstrdammod(lifeform_t *lf) {
float mod = 0;
float base;
// <9 = penalty
// 9,10,11,12 = average
// >12 = bonus
// returns amt of hp to modify damage by. (in range -3 to 3)
int getstrdammod(lifeform_t *lf) {
int mod = 0;
int base;
base = getattr(lf, A_STR);
if ((base >= 45) && (base <= 60)) {
mod = 1;
mod = 0;
} else if (base > 60) {
base -= 60; // ie. 0 - 40
mod = 1 + (base / 12.0); // ie. up to 1.3 / +30%
mod = base / 13;
} else { // ie. 0 through 44
// 0 = 0.1
// 5 = 0.2
// 10 = 0.3
// 15 = 0.4
// 20 = 0.5
// 25 = 0.6
// 30 = 0.7
// 35 = 0.8
// 40 = 0.9
mod = ((base/5) * 0.1); // ie. 10 -> 0.2 or 15 -> 0.3
mod += 0.1; // ie. 10 -> 0.3 or 15 -> 0.4
base = 45 - base;
mod = base / 13;
}
return mod;
}

View File

@ -24,7 +24,7 @@ void getdamrange(object_t *o, flag_t *f, int *min, int *max);
//float getdamreducepct(float armourrating);
int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag);
//int getunarmeddamroll(flag_t *f);
float getstrdammod(lifeform_t *lf);
int getstrdammod(lifeform_t *lf);
//obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
int ismeleedam(enum DAMTYPE damtype);
int isphysicaldam(enum DAMTYPE damtype);

300
data.c
View File

@ -686,15 +686,17 @@ void initjobs(void) {
addjob(J_ROGUE, "Rogue", "Rogues (sometimes known as \"thieves\") are criminals who are skilled in the appropriation of valuable goods. They can hide in the shadows, stab unsuspecting victims in the back and foil the most cunning traps.");
// stats
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, -15, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 20, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, -10, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 15, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_CON, -10, NA, NULL);
// initial objects
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "dagger");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather cloak");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "5 lockpicks");
// initial skills
addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CLIMBING, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_STEALTH, PR_BEGINNER, NA, NULL);
@ -708,6 +710,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_THROWING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_BEGINNER, NA, NULL);
// learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_ARMOUR, PR_NOVICE, NA, NULL); // limit
addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, PR_SKILLED, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_PERCEPTION, PR_SKILLED, NA, NULL);
@ -965,7 +968,7 @@ void initobjects(void) {
addobmod(OM_SHODDY,"shoddy");
addflag_real(lastobmod->flags, F_SHODDY, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
addobmod(OM_POISONED,"poisoned");
addflag_real(lastobmod->flags, F_HITCONFER, F_POISONED, SC_POISON, 30, "15-30", PERMENANT, B_KNOWN, -1);
addflag_real(lastobmod->flags, F_HITCONFER, F_POISONED, SC_POISON, 40, "15-30", PERMENANT, B_KNOWN, -1);
addflag_real(lastobmod->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL, PERMENANT, B_KNOWN, -1);
addobmod(OM_WET1,"damp");
addflag_real(lastobmod->flags, F_WET, W_DAMP, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
@ -2851,7 +2854,7 @@ void initobjects(void) {
// elemental - fire
///////////////////
// l1
addot(OT_S_SPARK, "flambe", "Creates very hot but short lived burst of flame around the target, dealing 1-6 fire damage to creatures and objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_SPARK, "flambe", "Creates very hot but short lived burst of flame around the target, dealing 2d2 fire damage to creatures and objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
@ -2960,6 +2963,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
// l3
addot(OT_S_CRYSTALSHIELD, "crystalline shield", "Summons a shield of ice crystals to protect you from missiles.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how effective the shield is.");
@ -2968,6 +2972,7 @@ void initobjects(void) {
addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addot(OT_S_COLDRAY, "cold ray", "Shoots a blast of ice cold air, dealing 3d6 cold damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how difficult the ray is to dodge.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
@ -3243,6 +3248,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_CASTINGTIME, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
///////////////////
// gravity
@ -3604,13 +3610,15 @@ void initobjects(void) {
addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SUMMONWEAPON, "summon weapon", "Summons a blade of pure magic into your hands. Deals 1-^bpower^n damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_SUMMONWEAPON, "summon weapon", "Summons a blade of pure magic into your hands.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines its Damage Rating.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL);
addflag(lastot->flags, F_VARPOWER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
// l2
addot(OT_S_CREATEFOOD, "sultan's feast", "Creates a meal in the target location.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines how much food is created.");
@ -3764,6 +3772,14 @@ void initobjects(void) {
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);
// l5
addot(OT_S_DETONATEDELAY, "delayed detonation", "Causes a given area to explode after a short delay.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// 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.");
@ -3771,7 +3787,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 6, 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_DONTNEED, NA, NULL);
// divine powers (spells/abilities)
addot(OT_A_BLINDALL, "nosight", "Make everyone on the level blind.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
@ -4810,6 +4826,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
//addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1");
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+1");
addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL);
addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool of water.", MT_WATER, 20, OC_MISC, SZ_MEDIUM);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
@ -5143,7 +5160,6 @@ void initobjects(void) {
addflag(lastot->flags, F_WALKDAM, DT_HEAT, NA, NA, "1d1+1");
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addot(OT_SLEETSTORM, "storm of sleet", "An intense storm of sleet. Hampers movement", MT_GAS, 0, OC_EFFECT, SZ_LARGE);
addflag(lastot->flags, F_GLYPH, C_CYAN, UNI_SHADEMED, NA, NULL);
addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL);
@ -5215,7 +5231,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_STENCH, B_TRUE, 1, NA, NULL);
addflag(lastot->flags, F_WALKDAM, DT_POISONGAS, NA, NA, "1d2");
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addot(OT_METHANEPUFF, "puff of methane gas", "A small puff of foul-smelling gas.", MT_GAS, 0, OC_EFFECT, SZ_MEDIUM);
@ -5225,7 +5241,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_WALKDAM, DT_POISONGAS, NA, NA, "1d2");
addflag(lastot->flags, F_STENCH, B_TRUE, 1, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addot(OT_HAILSTORM, "hail storm", "An intense storm of damaging hail.", MT_GAS, 0, OC_EFFECT, SZ_LARGE);
@ -5264,6 +5280,17 @@ void initobjects(void) {
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes");
addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL);
addot(OT_VIBCLOUD, "vibrating cloud", "A cloud of unstable molecules.", MT_GAS, 0, OC_EFFECT, SZ_LARGE);
addflag(lastot->flags, F_GLYPH, C_ORANGE, UNI_SHADEMED, NA, NULL);
addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL);
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
addflag(lastot->flags, F_EXPLODEONDEATH, NA, 2, NA, "8d2");
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addot(OT_VINE, "entangling vine", "A living vine which grasps nearby creature", MT_SILK, 0.1, OC_EFFECT, SZ_HUMAN);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 82, RR_UNCOMMON, NULL);
@ -5693,6 +5720,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
killflagsofid(lastot->flags, F_ENCHANTABLE);
addot(OT_SPECTACLES, "pair of spectacles", "Eyewear with special lenses to enhance your vision.", MT_GLASS, 0.01, OC_ARMOUR, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
@ -5702,6 +5730,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, 1, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
killflagsofid(lastot->flags, F_ENCHANTABLE);
addot(OT_SUNGLASSES, "pair of sunglasses", "Tinted eyewear to protect against sunlight.", MT_GLASS, 0.01, OC_ARMOUR, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
@ -5713,6 +5742,7 @@ void initobjects(void) {
addflag(lastot->flags, F_TINTED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
killflagsofid(lastot->flags, F_ENCHANTABLE);
addot(OT_EYEPATCH, "eyepatch", "A small patch of black material which covers one eye. Scary looking.", MT_CLOTH, 0.01, OC_ARMOUR, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL);
@ -5721,6 +5751,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SCARY, 2, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -2, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 50, NA, NA, NULL);
killflagsofid(lastot->flags, F_ENCHANTABLE);
// armour - shields
addot(OT_BUCKLER, "buckler", "A small, unobtrusive wooden shield.", MT_WOOD, 3.00, OC_ARMOUR, SZ_SMALL);
@ -5730,6 +5761,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
// similar to a buckler, but repairable, lighter, and less durable
addot(OT_SHIELDHIDE, "hide shield", "A small shield constructed out of animal skin.", MT_LEATHER, 2.00, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
@ -5738,6 +5770,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL);
addflag(lastot->flags, F_OBHP, 18, 18, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
addot(OT_SHIELD, "shield", "A medium-sized metal shield.", MT_METAL, 4.00, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL);
@ -5745,12 +5778,14 @@ void initobjects(void) {
addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 15, NA, NULL);
addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
addot(OT_SHIELDLARGE, "large shield", "A large (if somewhat cumbersome) shield.", MT_METAL, 6.00, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 20, NA, NULL);
addflag(lastot->flags, F_OBHP, 40, 40, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
addot(OT_SHIELDTOWER, "tower shield", "An enormous but very cumbersome shield.", MT_METAL, 11.00, OC_ARMOUR, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL);
@ -5758,6 +5793,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 30, NA, NULL);
addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
// rings
addot(OT_RING_EDUCATION, "ring of education", "Boosts earned XP and Skill points.", MT_METAL, 0.1, OC_RING, SZ_MINI);
@ -5990,6 +6026,7 @@ void initobjects(void) {
addot(OT_TENTACLE, "tentacle", "tentacle object", MT_FLESH, 0, OC_WEAPON, SZ_TINY);
addflag(lastot->flags, F_DAM, DT_BASH, 10, NA, NULL);
addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "slap");
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
@ -7285,6 +7322,9 @@ void initrace(void) {
addflag(lastrace->flags, F_MPMOD, -3, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, "1d6");
addflag(lastrace->flags, F_TAMABLE, 35, NA, NA, NULL);
// for ai:
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_GEM, NA, NA, NULL);
addrace(R_ELF, "elf", 60, '@', C_GREEN, MT_FLESH, RC_HUMANOID, "Elves are slender, graceful beings around human-sized but far nimbler. They have high intelligence and magical affinity, but a lack of physical strength. Elves meditate instead of sleeping, thus maintaining basic awareness.");
@ -8056,7 +8096,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "8d4");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "5d4");
addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
@ -8554,11 +8594,11 @@ void initrace(void) {
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, 60, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 66, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, 66, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "7d4+0");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, 60, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, 66, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, 66, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4+0");
addflag(lastrace->flags, F_EVASION, -5, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
@ -8686,6 +8726,37 @@ void initrace(void) {
addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addrace(R_CRYMIDIA, "crymidia", 10, 'e', C_WHITE, MT_ICE, RC_MAGIC, "A floating crystalline form, a crymidia is formed when a mass of crystal becomes sentient.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "10-20 chunks of ice");
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, "chunk of ice");
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "5d4");
addflag(lastrace->flags, F_LEVITATING, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_LEVITATION, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_LEVITATION, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_S_SUMMONWEAPON, NA, NA, "pw:4;");
addflag(lastrace->flags, F_CANWILL, OT_S_ICECRUST, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_CRYSTALARM, NA, NA, "pw:4;");
addflag(lastrace->flags, F_CANWILL, OT_S_CRYSTALSHIELD, NA, NA, "pw:4;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "shimmers");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_SS_COLD, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_SHIELDS, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_PEGASUS, "pegasus", 130, 'Q', C_GREY, MT_FLESH, RC_MAGIC, "A legendary white, winged horse.");
setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
@ -8906,6 +8977,31 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL);
addrace(R_SKOOB, "skoob", 40, 'n', C_WHITE, MT_ICE, RC_MAGIC, "Your typical snowman right down to the carrot nose, with just a two key differences: it is alive, and it is homocidal.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "carrot");
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, "puddle of water");
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4");
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_S_SNOWBALL, NA, NA, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_SLIDE, NA, NA, "pw:10;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "rubs its hands together");
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHCHILL, 3, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_SS_COLD, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_OOZEGREY, "sizzling slime", 10, 'j', C_GREEN, MT_SLIME, RC_SLIME, "Exactly what it sounds like - a small lump of green ooze. Green, acidic ooze.");
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "puddle of slime");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9007,7 +9103,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL);
addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_WHITE, MT_ICE, RC_MAGIC, "A small magical creature made from freezing ice.");
addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_CYAN, 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");
@ -9544,6 +9640,38 @@ void initrace(void) {
addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 14, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addrace(R_BILCO, "bilco", 25, ';', C_BOLDCYAN, MT_FLESH, RC_ANIMAL, "Bilcos appear to be abnormally large frogs with a strange blue tinge. Seasoned travellers know to beware the bilco's gurgle, which portends them belching out a massive torrent of water.");
setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, 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_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4");
addflag(lastrace->flags, F_HASATTACK, OT_TONGUE, 3, NA, NULL);
addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, SV_SHOUT, NA, "croaks^croaking");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, SV_SHOUT, NA, "croaking^croaking");
addflag(lastrace->flags, F_NOISETEXT, N_SPELLCAST, SV_SHOUT, NA, "gurgles loudly^a loud gurgling");
addflag(lastrace->flags, F_CANWILL, OT_A_JUMP, NA, NA, "stamcost:0;");
addflag(lastrace->flags, F_CANWILL, OT_S_FLOOD, 20, 20, "pw:6;");
addflag(lastrace->flags, F_CANWILL, OT_S_WATERJET, NA, NA, "pw:4;");
addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL);
addflag(lastrace->flags, F_AISPELLTARGETOVERRIDE, OT_S_FLOOD, ST_SELF, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "hop");
addrace(R_CHICKEN, "chicken", 0.5, 'c', C_BROWN, MT_FLESH, RC_ANIMAL, "A common farm-yard chicken.");
setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
@ -9694,10 +9822,11 @@ void initrace(void) {
addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "croaks^croaking");
addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "croaking^croaking");
addflag(lastrace->flags, F_CANWILL, OT_A_THRUST, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_JUMP, NA, NA, "stamcost:0;");
addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL);
@ -10275,6 +10404,38 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL);
addrace(R_WOLFWINTER, "winter wolf", 25, 'd', C_CYAN, MT_FLESH, RC_ANIMAL, "Wolves which have lived in close proximity to the undead sometimes mutate into these frosty beasts. While their claws have become less sharp, they instead deal unnatural cold damage.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, "");
addflag(lastrace->flags, F_ENHANCESMELL, 6, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "5d4+2");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
addflag(lastrace->flags, F_EXTRADAM, DT_COLD, NA, NA, "1d6");
addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL);
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_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, "");
addflag(lastrace->flags, F_HASSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL);
addflag(lastrace->flags, F_MORALE, 11, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_COLDRAY, 10, 10, "pw:2;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "unleashes its icy breath");
addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL);
addrace(R_WORMGLUT, "glutworm", 25, 'W', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Gigantic worms who swallow their prey whole, slowly digesting their still living bodies.");
addbodypart(lastrace, BP_HEAD, NULL);
addbodypart(lastrace, BP_TAIL, NULL);
@ -10738,6 +10899,26 @@ void initrace(void) {
// end dragons
// insects
addrace(R_BLASTBUG, "blastbug", 2, 'x', C_ORANGE, MT_STONE, RC_INSECT, "Blastbugs have somehow evolved the ability to de-stabalise nearby oxygen molecules, resulting in devestation explosions.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4+0");
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "100"); // massively strong to hold stones
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "snorts^a snort");
addflag(lastrace->flags, F_DTIMMUNE, DT_EXPLOSIVE, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSEFLAG, F_EXPLODEONDEATH, NA, 2, "32d2");
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_WANTS, OT_STONE, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_DETONATEDELAY, 20, 20, "pw:1;range:3;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "vibrates");
addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', C_YELLOW, MT_FLESH, RC_ANIMAL, "A harmless, colourful butterfly.");
setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
@ -10870,6 +11051,21 @@ void initrace(void) {
addflag(lastrace->flags, F_TREMORSENSE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addrace(R_FIREBUG, "firebug", 2, 'x', C_RED, MT_FLESH, RC_INSECT, "Constantly burning insects which attack their victims with fire.");
setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4");
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHBURN, 3, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "flares its flames^crackling flames");
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addrace(R_GLOWBUG, "glowbug", 1, 'i', C_WHITE, MT_FLESH, RC_INSECT, "Glowbugs are tiny flying creatures, magically producing light from their bodies.");
setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL);
@ -10984,6 +11180,7 @@ void initrace(void) {
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_HURRICANESTRIKE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_BLINKASS, 3, 3, "pw:1;");
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 2, NA, NULL);
addflag(lastrace->flags, F_VAMPIRIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL);
@ -11117,6 +11314,61 @@ void initrace(void) {
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_SKELETONFIRE, "fire skeleton", 20, 'Z', C_RED, MT_BONE, RC_UNDEAD, "A walking set of flaming bones, imbued with the power of fire. They have all the advantages of normal skeletons but tend to burn victims with their flame rather than use weapons.");
setbodytype(lastrace, BT_HUMANOID);
setbodypartname(lastrace, BP_WEAPON, "right metacarpals");
setbodypartname(lastrace, BP_SECWEAPON, "left metacarpals");
setbodypartname(lastrace, BP_BODY, "ribs");
setbodypartname(lastrace, BP_HEAD, "skull");
setbodypartname(lastrace, BP_SHOULDERS, "scapulas");
setbodypartname(lastrace, BP_HANDS, "carpals");
setbodypartname(lastrace, BP_WAIST, "coccyx");
setbodypartname(lastrace, BP_LEGS, "fibulas");
setbodypartname(lastrace, BP_FEET, "tarsals");
setbodypartname(lastrace, BP_RIGHTFINGER, "right phalange");
setbodypartname(lastrace, BP_LEFTFINGER, "left phalange");
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "5-20 flaming bones");
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4");
addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHBURN, 7, NA, NULL);
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_FALL, NA, NA, "1d3+3");
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);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_WRAITHICE, "ice wraith", 20, 'Z', C_CYAN, MT_ICE, RC_UNDEAD, "Ice wraiths look like frozen humanoid forms, often garbed in threadbare clothing.");
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_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4");
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHCHILL, 7, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "shoddy cloak");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "scheeches^a screech");
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_GHAST, "ghast", 50, 'Z', C_MAGENTA, MT_FLESH, RC_UNDEAD, "A more slender and ghost-like form of ghoul. Ghasts are cunning and deadly, and possess a paralyzing touch.");
setbodytype(lastrace, BT_HUMANOID);
setbodypartname(lastrace, BP_HANDS, "claws");
@ -11752,17 +12004,17 @@ void initskills(void) {
char buf[BUFLEN];
addskilldesc(sk->id, PR_INEPT, "At each skill level, more information about related creatures will be shown.", B_FALSE);
addskilldesc(sk->id, PR_INEPT, "Each level also gives +10% damage and accuracy against related creatures.", B_FALSE);
addskilldesc(sk->id, PR_INEPT, "Each level also gives +1 damage and +2 accuracy against related creatures.", B_FALSE);
snprintf(buf, BUFLEN, "^gYou now know basic information about %s.", rc->pluralname);
snprintf(buf, BUFLEN, "^gYou now know basic information about %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_NOVICE, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou can now determine how much damage %s will deal.", rc->pluralname);
snprintf(buf, BUFLEN, "^gYou can now determine how much damage %s will deal.^n", rc->pluralname);
addskilldesc(sk->id, PR_BEGINNER, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou can now determine how dangerous %s are.", rc->pluralname);
snprintf(buf, BUFLEN, "^gYou can now determine how dangerous %s are.^n", rc->pluralname);
addskilldesc(sk->id, PR_ADEPT, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou can now anticipate how %s will react.", rc->pluralname);
snprintf(buf, BUFLEN, "^gYou can now anticipate how %s will react.^n", rc->pluralname);
addskilldesc(sk->id, PR_SKILLED, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou now know everything there is to know about %s.", rc->pluralname);
snprintf(buf, BUFLEN, "^gYou now know everything there is to know about %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_MASTER, buf, B_TRUE);
}
}

Binary file not shown.

22
defs.h
View File

@ -708,7 +708,9 @@ enum CELLTYPE {
CT_VILLAGEGROUND,
CT_FAKE,
CT_FLOORFLESH,
CT_FLOORCARPET,
CT_FLOORSHOP,
CT_FLOORTILE,
CT_FLOORWOOD,
CT_GRASS,
CT_LOOPCORRIDOR,
@ -900,6 +902,7 @@ enum RACE {
R_BUGBEAR,
R_COCKATRICE,
R_CREEPINGCLAW,
R_CRYMIDIA,
R_DARKMANTLE,
R_EYEBAT,
R_GIANTHILL,
@ -935,6 +938,7 @@ enum RACE {
R_SATYR,
R_SHADOWCAT,
R_SINKMITE,
R_SKOOB,
R_SPRITEFIRE,
R_SPRITEGRAVE,
R_SPRITEICE,
@ -967,6 +971,7 @@ enum RACE {
R_BEAR,
R_BEARCUB,
R_BEARGRIZZLY,
R_BILCO,
R_CHICKEN,
R_DOG,
R_DOGBLINK,
@ -993,8 +998,9 @@ enum RACE {
R_SPIDER,
R_SPIDERFUNNELWEB,
R_SPIDERREDBACK,
R_WOLF,
R_WOLFYOUNG,
R_WOLF,
R_WOLFWINTER,
R_WORMGLUT,
// dragons
R_DRAGONBLUE,
@ -1007,8 +1013,10 @@ enum RACE {
R_DRAGONWHITEY,
R_DRAGONWHITEA,
// insects
R_BLASTBUG,
R_BUTTERFLY,
R_CENTIPEDE,
R_FIREBUG,
R_GLOWBUG,
R_GIANTFLY,
R_GIANTBLOWFLY,
@ -1028,6 +1036,8 @@ enum RACE {
R_GHOST,
R_GHOUL,
R_SKELETON,
R_SKELETONFIRE,
R_WRAITHICE,
R_ZOMBIE,
// special
R_DANCINGWEAPON,
@ -1477,6 +1487,7 @@ enum OBTYPE {
OT_S_ALARM,
OT_S_MANASPIKE,
OT_S_DETONATE,
OT_S_DETONATEDELAY,
OT_S_ENERGYBOLT,
OT_S_ENERGYBLAST,
OT_S_FLASH,
@ -1677,6 +1688,7 @@ enum OBTYPE {
OT_METHANEPUFF,
OT_POISONCLOUD,
OT_POISONPUFF,
OT_VIBCLOUD,
OT_VINE,
OT_WEB,
// armour - multipart
@ -1956,6 +1968,7 @@ enum NOISETYPE {
N_FRUSTRATED,
N_SONICBOLT,
N_WARCRY,
N_SPELLCAST,
};
enum LFSIZE {
@ -2729,6 +2742,9 @@ enum FLAG {
// if v0 != OT_NONE, only use text for spellid v0
// if v2 is 'appendyou' " at xxx" will
// be appended.
F_AISPELLTARGETOVERRIDE, // when casting spellid v0, this lf will
// use v1 (ST_xxx) instead of what the AICASTTOxxx
// flag specifies.
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
F_NODEATHSPEECH, // lf doesn't talk when dying
F_BEHEADED, // use special corpse drop code
@ -3071,6 +3087,8 @@ enum FLAG {
// rest of the map.
F_VAULTRANDOMMAP, // v0=minwidth, v1=minheight. this vault's map is
// v0/1 can be NA.
// OPTIONAL: v2 = floor cell type id
// OPTIONAL: text = wall cell type id (int)
// just a normal random room
F_KEEPMARGIN, // this vault must be at least v0 from e/w of map
// and at least v1 from n/s of map
@ -3166,6 +3184,7 @@ enum LIGHTLEV {
// spell targets
enum SPELLTARGET {
ST_NONE = 0, // dont cast at all. for debugging.
ST_VICTIM, // cast at victim
ST_ADJVICTIM, // cast at victim who is next to us
ST_SELF, // cast at myself
@ -3656,6 +3675,7 @@ typedef struct lifeform_s {
float forgettimer;
struct obpile_s *pack;
struct obpile_s *polypack; // for melded objects when polymorphed
struct flagpile_s *flags;

View File

@ -12,7 +12,7 @@ B = bat
c = cockatricoe
C = celestial / divine ?
d = canine/dog
e = eye
e = eye or floating thing
E = elemental ?
f = feline/cat
F = flora (flowers, plants, etc)
@ -21,7 +21,6 @@ G = large goblin
h = humanoid
H = large humanoid
i = insect
P = gastroPod
j = jelly/ooze/leech
k = kobold
m = mutant
@ -30,6 +29,7 @@ N = necron
o = orc
O = ogre
p = sPirit
P = gastroPod
q = quadraped
Q = large quadraped
r = rodent

56
god.c
View File

@ -616,12 +616,9 @@ int godgiftmaybe(enum RACE rid, int fromtemple) {
}
break;
case 2:
snprintf(obtogive, BUFLEN, "3-5 cursed potions of water");
break;
case 3:
snprintf(obtogive, BUFLEN, "cursed branded weapon");
break;
case 4: // poison your weapon
case 3: // poison your weapon
wep = getweapon(player);
if (wep && canbepoisoned(wep->type->id)) {
applyobmod(wep, findobmod(OM_POISONED));
@ -630,7 +627,7 @@ int godgiftmaybe(enum RACE rid, int fromtemple) {
rollagain = B_TRUE;
}
break;
case 5: // resistant/immune to necrotic
case 4: // resistant/immune to necrotic
if (lfhasflagval(player, F_DTRESIST, DT_NECROTIC, NA, NA, NULL)) {
if (lfhasflagval(player, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL)) {
rollagain = B_TRUE;
@ -643,7 +640,7 @@ int godgiftmaybe(enum RACE rid, int fromtemple) {
f->obfrom = god->race->id;
}
break;
case 6:
case 5: // become a vampire
if (player->race->id == R_VAMPIRE) {
rollagain = B_TRUE;
} else {
@ -651,6 +648,13 @@ int godgiftmaybe(enum RACE rid, int fromtemple) {
setrace(player, R_VAMPIRE, B_TRUE); // ie. don't set origrace!
}
break;
case 6: // necromancy spells
if (!getskill(lf, SK_SS_DEATH)) {
giveskill(lf, SK_SS_DEATH);
} else {
snprintf(obtogive, BUFLEN, "spellbook of necromancy");
}
break;
}
}
break;
@ -793,7 +797,11 @@ void godsay(enum RACE rid, int says, char *format, ...) {
void modpiety(enum RACE rid, int amt) {
lifeform_t *god;
flag_t *f;
god = findgod(rid);
if (godblocked(god->race->id)) return;
f = lfhasflag(god, F_PIETY);
if (!f) return;
f->val[0] += amt;
@ -1013,11 +1021,20 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
dospelleffects(NULL, OT_S_DISPERSAL, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE);
}
} else {
int i,first = B_TRUE;
int redo = B_TRUE;
object_t *possob[MAXPILEOBS];
int npossob,i,first;
while (redo) {
redo = B_FALSE;
switch (rnd(1,2)) {
case 1:
msg("\"Allow me to reveal your surroundings...\"");
dospelleffects(god, OT_S_MAPPING, 5, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
dospelleffects(god, OT_S_REVEALHIDDEN, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
// unlock doors
first = B_TRUE;
for (i = 0; i < player->nlos; i++) {
cell_t *c;
object_t *o;
@ -1034,6 +1051,31 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
}
}
}
break;
case 2: // identify objects
npossob = 0;
for (o = lf->pack->first ; o ; o = o->next) {
if (!isknown(o)) {
possob[npossob++] = o;
}
}
if (npossob) {
char oldname[BUFLEN],newname[BUFLEN];
o = possob[rnd(0,npossob-1)];
getobname(o,oldname,o->amt);
identify(o);
getobname(o,newname,o->amt);
msg("\"%s %s you are carrying %s %s!\"",
(o->amt == 1) ? "That" : "Those",
noprefix(oldname),
(o->amt == 1) ? "is" : "are",
newname);
} else {
redo = B_TRUE;
}
break;
} // end switch
}// end while redo
}
break;
case R_GODMERCY:

36
io.c
View File

@ -6079,19 +6079,14 @@ char *makedesc_ob(object_t *o, char *retbuf) {
col = C_GREY;
}
if (f->val[1] != NA) {
sprintf(buf, "^%dIt requires at least %d %s to use%s.", col, f->val[1], getattrname(f->val[0]),
sprintf(buf, "^%dIt requires at least %d %s to use%s.^n\n", col, f->val[1], getattrname(f->val[0]),
strlen(f->text) ? " effectively" : "");
if (f->val[2] != NA) {
char bbuf[BUFLEN];
sprintf(bbuf, " (bonus at %d)", f->val[2]);
strcat(buf, bbuf);
}
}
if (f->val[2] != NA) {
sprintf(buf, "^nIt can be used more effectively with at least %d %s.\n", f->val[2], getattrname(f->val[0]));
}
strcat(buf, "^n\n");
strncat(retbuf, buf, HUGEBUFLEN);
}
if (f->val[2] != NA) {
sprintf(buf, "^nIt can be used more effectively with at least %d %s^n.\n", f->val[2], getattrname(f->val[0]));
strncat(retbuf, buf, HUGEBUFLEN);
}
if (usable && isweapon(o)) {
if (pctmod > 0) {
@ -7675,6 +7670,11 @@ int dothrow(obpile_t *op, object_t *o) {
// calculate throw range
maxdist = getmaxthrowrange(player, o);
if (maxdist < 1) {
msg("You are not strong enough to throw that.");
return B_TRUE;
}
// ask where to throw it
snprintf(buf2, BUFLEN, "Throw %s where?",buf);
snprintf(subprompt, BUFLEN, "%s->Throw->",buf);
@ -10174,8 +10174,8 @@ void showlfstats(lifeform_t *lf, int showall) {
objecttype_t *ot;
int first;
int i;
float dammod;
int accmod;
int dammod;
//int accmod;
enum BODYPART bp;
enum BODYPART missingbp[MAXBODYPARTS];
int nmissingbp;
@ -10250,7 +10250,7 @@ void showlfstats(lifeform_t *lf, int showall) {
y2 = 2;
dammod = getstrdammod(lf);
accmod = getstatmod(lf, A_AGI);
//accmod = getstatmod(lf, A_AGI);
if (isplayer(lf)) {
getplayername(buf);
@ -10391,11 +10391,11 @@ void showlfstats(lifeform_t *lf, int showall) {
char buf2[BUFLEN];
switch (i) {
case A_STR:
if (dammod > 1) {
snprintf(buf2, BUFLEN, ", +%d%% dmg", (int)((dammod * 100) - 100) );
if (dammod >= 1) {
snprintf(buf2, BUFLEN, ", +%d dmg", dammod);
strcat(buf, buf2);
} else if (dammod < 1) {
snprintf(buf2, BUFLEN, ", -%d%% dmg", (int)(100 - (dammod * 100)) );
} else if (dammod <= -1) {
snprintf(buf2, BUFLEN, ", -%d dmg", abs(dammod));
strcat(buf, buf2);
}
break;

154
lf.c
View File

@ -544,9 +544,11 @@ int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) {
return B_FALSE;
}
if (isswimming(lf) && (getskill(lf, SK_SWIMMING) < PR_EXPERT)) {
if (!isaquatic(lf)) {
reason = E_SWIMMING;
return B_FALSE;
}
}
if (isclimbing(lf)) {
reason = E_CLIMBING;
return B_FALSE;
@ -1678,6 +1680,8 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
}
}
// noise....
makenoise(lf, N_SPELLCAST);
// announce
if (!isplayer(lf) && !fromob) {
@ -2387,6 +2391,8 @@ void die(lifeform_t *lf) {
castspell(lf, OT_S_FLASH, NULL, NULL, lf->cell, NULL, NULL);
}
loseconcentration(lf);
// revert to your original form first.
if (lfhasflag(lf, F_POLYMORPHED)) {
if (lfhasflag(lf, F_ORIGRACE)) {
@ -2644,6 +2650,12 @@ void die(lifeform_t *lf) {
if (copyflag(corpse->flags, lf->flags, F_REVIVETIMER)) {
killflagsofid(corpse->flags, F_OBHPDRAIN);
}
// special case
if (lf->race->id == R_BLASTBUG) {
flag_t *hpflag;
hpflag = hasflag(corpse->flags, F_OBHP);
if (hpflag) hpflag->val[0] = rnd(4,5);
}
// corpse of a player pet?
if (ispetof(lf, player)) {
@ -3474,10 +3486,14 @@ int eat(lifeform_t *lf, object_t *o) {
// blink!
dospelleffects(lf, OT_S_BLINK, 1, lf, NULL, NULL, B_UNCURSED, NULL, B_TRUE);
stopeating = B_TRUE;
} else if (hasflagval(o->flags, F_CORPSEOF, R_BLASTBUG, NA, NA, NULL)) {
dospelleffects(lf, OT_S_DETONATE, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
stopeating = B_TRUE;
}
// eating your pet is very bad!
if (isplayer(lf) && hasflagval(o->flags, F_PETOF, player->id, NA, NA, NULL)) {
angergodmaybe(R_GODPURITY, 150, GA_EAT);
@ -4365,10 +4381,13 @@ int flee(lifeform_t *lf) {
flag_t *retflag[MAXCANDIDATES];
int nretflags;
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
real_getlfname(lf, lfname, B_FALSE, B_FALSE);
if (isdead(lf)) return B_FALSE;
// are we fleeing?
getflags(lf->flags, retflag, &nretflags, F_FLEEFROM, F_NONE);
@ -4397,7 +4416,7 @@ int flee(lifeform_t *lf) {
// player let something flee?
if (isplayer(thisone)) {
pleasegodmaybe(R_GODMERCY, 5);
angergodmaybe(R_GODDEATH, 25, GA_MERCY);
angergodmaybe(R_GODDEATH, 15, GA_MERCY);
}
killflag(f);
} else {
@ -5513,8 +5532,8 @@ int getavgdam(lifeform_t *lf, int forxp) {
dammod = getstrdammod(lf);
// apply damage mod for strength
if (!hasflag(w->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
mindam = (int)((float)mindam * dammod);
maxdam = (int)((float)maxdam * dammod);
mindam += dammod;
maxdam += dammod;
}
if (mindam < 0) mindam = 0;
@ -9841,12 +9860,19 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
if (hasbp(lf, bp2)) {
object_t *o[2];
char buf[BUFLEN];
enum BODYPART fingerbp;
int i;
// drop anyting in that hand
o[0] = getequippedob(lf->pack, bp2);
if (bp2 == BP_WEAPON) o[1] = getequippedob(lf->pack, BP_RIGHTFINGER);
else o[1] = getequippedob(lf->pack, BP_LEFTFINGER);
if (bp2 == BP_WEAPON) {
o[1] = getequippedob(lf->pack, BP_RIGHTFINGER);
fingerbp = BP_RIGHTFINGER;
} else {
o[1] = getequippedob(lf->pack, BP_LEFTFINGER);
fingerbp = BP_LEFTFINGER;
}
addflag(lf->flags, F_NOBODYPART, bp2, B_FROMINJURY, NA, NULL);
addflag(lf->flags, F_NOBODYPART, fingerbp, B_FROMINJURY, NA, NULL);
inj = IJ_HANDMISSING;
sprintf(buf, "%s is destroyed^cannot use this hand", getbodypartname(lf, bp2));
desc = strdup(buf);
@ -10720,9 +10746,14 @@ void killlf(lifeform_t *lf) {
while (lf->pack->first) {
killob(lf->pack->first);
}
// kill object pile
free(lf->pack);
lf->pack = NULL;
// kill any remaining obs
while (lf->polypack->first) {
killob(lf->polypack->first);
}
free(lf->polypack);
lf->polypack = NULL;
// kill flags
killflagpile(lf->flags);
@ -11269,6 +11300,7 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
a->created = B_FALSE;
a->pack = addobpile(a, NOLOC, NOOB);
a->polypack = addobpile(a, NOLOC, NOOB);
a->turnsskipped = 0;
@ -11786,7 +11818,7 @@ void applylfdammod(int *dam, lifeform_t *lf, object_t *wep) {
enum SKILLLEVEL slev;
// modify for strength
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
*dam = (int)((float)*dam * getstrdammod(lf));
*dam = *dam + getstrdammod(lf);
}
// strength scaling on weapon
@ -12862,8 +12894,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
// cold: dam*10 chance of shattering potions, or damaging other things.
for (o = lf->pack->first ; o ; o = nexto) {
nexto = o->next;
//if (isvulnto(o->flags, DT_COLD) && pctchance(amt*10)) {
if (isvulnto(o->flags, DT_COLD, B_FALSE)) {
if (isvulnto(o->flags, DT_COLD, B_FALSE) && pctchance(amt*10)) {
int newdam;
// object takes 1/4 of damage
newdam = pctof(25, amt);
@ -15317,7 +15348,9 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
race_t *newrace;
char buf[BUFLEN];
flag_t *retflag[MAXCANDIDATES];
race_t *origrace = NULL;
int nretflags;
int reverting = B_FALSE;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
newrace = findrace(rid);
@ -15332,20 +15365,23 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
loseconcentration(lf);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (frompolymorph && (gamemode == GM_GAMESTARTED) && lf->race) {
race_t *origrace = NULL;
// remove 'become a ghost' flag
killflagsofid(lf->flags, F_RISEASGHOST);
// were we already polymorphed?
f = lfhasflag(lf, F_ORIGRACE);
if (f) {
origrace = findrace(f->val[0]);
}
// announce
if (origrace && (newrace == origrace)) {
reverting = B_TRUE;
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (frompolymorph && (gamemode == GM_GAMESTARTED) && lf->race) {
// remove 'become a ghost' flag
killflagsofid(lf->flags, F_RISEASGHOST);
// announce
if (reverting) {
// reverting to original form....
if (!isdead(lf)) {
if (isplayer(lf)) {
@ -15370,12 +15406,6 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
killflagsofid(lf->flags, F_ORIGRACE);
killflagsofid(lf->flags, F_POLYMORPHED);
// restore stats
for (i = 0; i < MAXATTS; i++) {
lf->att[i] = lf->origatt[i];
lf->baseatt[i] = lf->origatt[i];
if (isplayer(lf)) statdirty = B_TRUE;
}
} else {
if (isplayer(lf)) {
msg("^wYou transform into %s %s!", isvowel(newrace->name[0]) ? "an" : "a", newrace->name);
@ -15450,11 +15480,27 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// generate stats
if (reverting) {
// restore stats - note that your "base" attrib score
// is set to your original one here.
for (i = 0; i < MAXATTS; i++) {
lf->att[i] = lf->origatt[i];
lf->baseatt[i] = lf->origatt[i];
}
if (isplayer(lf)) statdirty = B_TRUE;
} else {
// remember original atts
for (i = 0; i < MAXATTS; i++) {
lf->origatt[i] = lf->att[i];
}
// generate new stats
for (i = 0; i < MAXATTS; i++) {
rollstat(lf, i);
lf->baseatt[i] = lf->att[i];
}
}
if (!retainhp) {
// generate hp/maxhp from hit dice
@ -15488,6 +15534,8 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
lf->born = B_TRUE;
setlosdirty(lf);
// check whether:
// new race can equip things (F_NOBODYPART xx)
// new race can hold objects (F_NOPACK xx)
@ -15500,6 +15548,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// no pack?
if (lfhasflag(lf, F_NOPACK)) {
if (reverting) {
// drop everything
if (countobs(lf->pack, B_FALSE)) {
if (isplayer(lf)) {
@ -15514,6 +15563,22 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
moveob(o, lf->cell->obpile, o->amt);
}
} else {
// meld
if (countobs(lf->pack, B_FALSE)) {
if (isplayer(lf)) {
msg("Your possessions meld into your new form!");
} else if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s%s possessions meld into its new form!",buf, getpossessive(buf));
}
}
for (o = lf->pack->first ; o ; o = nexto) {
nexto = o->next;
moveob(o, lf->polypack, o->amt);
}
}
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
@ -15521,6 +15586,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
if (!hasbp(lf, bp)) {
o = getequippedob(lf->pack, bp);
if (o) {
if (reverting) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
// drop it!
@ -15532,6 +15598,19 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
noprefix(obname));
}
moveob(o, lf->cell->obpile, o->amt);
} else {
char obname[BUFLEN];
getobname(o, obname, o->amt);
// drop it!
if (isplayer(lf)) {
msg("Your %s melds into your new form!",noprefix(obname));
} else if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s%s %s melds into its new form!",buf, getpossessive(buf),
noprefix(obname));
}
moveob(o, lf->polypack, o->amt);
}
}
}
}
@ -15541,6 +15620,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
nexto = o->next;
if (!canpickup(lf, o, o->amt)) {
if (reverting) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
// drop it!
@ -15552,6 +15632,18 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
noprefix(obname));
}
moveob(o, lf->cell->obpile, o->amt);
} else {
char obname[BUFLEN];
getobname(o, obname, o->amt);
if (isplayer(lf)) {
msg("Your %s melds into your new form!",noprefix(obname));
} else if (cansee(player, lf)) {
getlfname(lf, buf);
msg("%s%s %s melds into its new form!",buf, getpossessive(buf),
noprefix(obname));
}
moveob(o, lf->polypack, o->amt);
}
}
}
@ -15566,6 +15658,16 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} // end if gamestarted
if (reverting) {
// restore objects
while (lf->polypack->first) {
moveob(lf->polypack->first, lf->pack, lf->polypack->first->amt);
}
// in case something which affects our vision came out of ->polypack
setlosdirty(lf);
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
}
@ -19013,6 +19115,7 @@ int wear(lifeform_t *lf, object_t *o) {
if (isplayer(lf)) msg("You have nowhere to wear that!");
return B_TRUE;
}
if (isplayer(lf)) {
ch = getchoice(&prompt);
if (ch == '-') {
@ -19020,6 +19123,9 @@ int wear(lifeform_t *lf, object_t *o) {
if (isplayer(lf)) msg("Cancelled.");
return B_TRUE;
} else bp = *((enum BODYPART *)prompt.result);
} else {
bp = *((enum BODYPART *)prompt.choice[rnd(0,prompt.nchoices - 1)].data);
}
possbp[0] = bp;
nparts = 1;

38
map.c
View File

@ -1212,6 +1212,14 @@ int damagecell(cell_t *c, int amt, enum DAMTYPE damtype) {
if (getshardobname(cellmat, what)) {
fragments(c, what, 3, 3);
}
} else {
switch (cellmat) {
case MT_STONE:
addob(c->obpile, "50-100 stones");
break;
default:
break;
}
}
}
return B_FALSE;
@ -5822,19 +5830,29 @@ int getslipperyness(cell_t *c, object_t **slipob) {
object_t *o,*bestob = NULL;
int bestslip = 0;
int totalslip = 0;
int addition = 0;
if (slipob) *slipob = NULL;
switch (c->type->id) {
case CT_FLOORTILE: addition = 2; break;
case CT_FLOORCARPET: addition = -2; break;
default: addition = 0; break;
}
for (o = c->obpile->first ; o ; o = o->next) {
int thisslip;
sumflags(o->flags, F_SLIPPERY, &thisslip, NULL, NULL);
thisslip += addition;
limit(&thisslip, 0, NA);
if (thisslip > 0) {
if (thisslip > bestslip) {
bestob = o;
bestslip = thisslip;
}
}
thisslip *= o->amt;
totalslip += thisslip;
}
}
totalslip *= 2;
@ -6009,28 +6027,32 @@ void initmap(void) {
addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE);
// cell types - solid
addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0, 100);
addcelltype(CT_WALLDIRT, "dirt wall", UNI_SHADEDARK, C_BROWN, B_SOLID, B_OPAQUE, MT_STONE, 0, 50);
addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0, 50);
addcelltype(CT_WALLFLESH, "flesh wall", UNI_SOLID, C_RED, B_SOLID, B_OPAQUE, MT_FLESH, 0, 50);
addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0, 25);
addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0, 200);
addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0, 50);
addcelltype(CT_WALLDIRT, "dirt wall", UNI_SHADEDARK, C_BROWN, B_SOLID, B_OPAQUE, MT_STONE, 0, 25);
addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0, 40);
addcelltype(CT_WALLFLESH, "flesh wall", UNI_SOLID, C_RED, B_SOLID, B_OPAQUE, MT_FLESH, 0, 30);
addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0, 20);
addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0, 75);
// cell types - non-solid
addcelltype(CT_FAKE, "fake cell", '.', C_GREEN, B_EMPTY, B_TRANS, MT_STONE, 0, -1);
addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0, -1);
addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0, -1);
addcelltype(CT_FLOORCARPET, "carpetted floor", '.', C_YELLOW, B_EMPTY, B_TRANS, MT_CLOTH, 0, -1);
addcelltype(CT_FLOORWOOD, "wood floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0, -1);
addcelltype(CT_FLOORFLESH, "flesh floor", '.', C_RED, B_EMPTY, B_TRANS, MT_FLESH, 0, -1);
addcelltype(CT_FLOORSHOP, "shop floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0, -1);
addcelltype(CT_FLOORTILE, "tiled floor", '.', C_WHITE, B_EMPTY, B_TRANS, MT_METAL, 0, -1);
addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT, 0, -1);
addcelltype(CT_DIRT, "dirt", '.', C_BROWN, B_EMPTY, B_TRANS, MT_STONE, 0, -1);
addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -1, -1);
addcelltype(CT_VLOWFLOOR, "very low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -2, -1);
// region types
// maxdepth stairs stair major? depthmod
// perlev dir
addregiontype(RG_WORLDMAP, "The Surface", B_FALSE, H_FOREST, 10, 0, D_NONE, B_TRUE, 0);
addregiontype(RG_MAINDUNGEON, "The Main Dungeon", B_FALSE, H_DUNGEON, 25, 3, D_DOWN, B_TRUE, 0);
addregiontype(RG_CAVE, "The Goblin Caves", B_TRUE, H_CAVE, 5, 1, D_DOWN, B_TRUE, 5);
addregiontype(RG_CAVE, "The Goblin Caves", B_TRUE, H_CAVE, 5, 1, D_DOWN, B_TRUE, 2);
addregiontype(RG_HEAVEN, "The Realm of Gods", B_FALSE, H_HEAVEN, 1, 0, D_NONE, B_FALSE, 0);
addregiontype(RG_PIT, "A Pit", B_FALSE, H_PIT, 1, 1, D_DOWN, B_FALSE, 0);
addregiontype(RG_SEWER, "A Sewer", B_FALSE, H_SEWER, 1, 0, D_NONE, B_FALSE, 2);

4
move.c
View File

@ -2076,7 +2076,9 @@ int closedoor(lifeform_t *lf, object_t *o) {
f = hasflag(o->flags, F_DOOR);
addflag(o->flags, F_IMPASSABLE, f->val[0], f->val[1], f->val[2], f->text);
addflag(o->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
if (hasflag(o->type->flags, F_BLOCKSVIEW)) {
copyflag(o->flags, o->type->flags, F_BLOCKSVIEW);
}
if (lf) {
// stop sprinting

View File

@ -2516,13 +2516,6 @@ int canseeob(lifeform_t *lf, object_t *o) {
return B_FALSE;
}
}
if (isblind(player) || (o->pile->where && !haslos(player, o->pile->where)) ) {
if (hasflag(o->flags, F_NOFEEL)) {
return B_FALSE;
}
}
f = hasflag(o->flags, F_TRAIL);
if (f) {
if (f->val[2] == S_SIGHT) {
@ -2572,6 +2565,15 @@ int canseeob(lifeform_t *lf, object_t *o) {
}
}
if (o->pile->where && (o->pile->where->map == lf->cell->map)) {
if (isblind(lf) || (!haslos(lf, o->pile->where)) ) {
if (hasflag(o->flags, F_NOFEEL)) {
return B_FALSE;
}
}
}
return B_TRUE;
}
@ -3403,6 +3405,21 @@ recipe_t *findrecipefor(enum OBTYPE result) {
return NULL;
}
int fountain_will_dryup(object_t *o) {
if (hasflagval(o->flags, F_LINKOB, OT_POT_EXPERIENCE, NA, NA, NULL) ||
onein(ONEIN_FOUNTAINDRYUP)) {
cell_t *loc;
loc = getoblocation(o);
if (haslos(player, loc)) {
char fname[BUFLEN];
getobname(o, fname, o->amt);
msg("%s dries up.", fname);
}
return B_TRUE;
}
return B_FALSE;
}
void fragments(cell_t *centre, char *what, int speed, int howfar) {
cell_t *c,*dst;
int n,dir;
@ -4384,7 +4401,9 @@ enum DEPTH getobdepth(object_t *o, lifeform_t *lf) {
char *getobdesc(object_t *o, char *buf) {
int blind = B_FALSE;
int known = B_FALSE;
if (gamemode == GM_GAMESTARTED) {
// can't see the object ?
if (o->pile->owner == player) {
if (!haslos(player, player->cell) || isblind(player)) {
if (!hasflag(o->flags, F_FEELTEXT)) {
@ -4393,7 +4412,15 @@ char *getobdesc(object_t *o, char *buf) {
}
}
}
if (isknown(o) && !blind) {
if (isknown(o)) {
known = B_TRUE;
} else {
if (o->pile->parentob && hasflag(o->pile->parentob->flags, F_SHOP)) {
known = B_TRUE;
}
}
if (known && !blind) {
if (o->type->id == OT_CORPSE) {
flag_t *f;
f = hasflag(o->flags, F_CORPSEOF);
@ -7958,12 +7985,13 @@ void obdie(object_t *o) {
if (f->val[2] == B_IFACTIVATED) {
if (isactivated(o)) {
explodeob(o, f, f->val[1]);
return;
}
} else {
explodeob(o, f, f->val[1]);
}
return;
}
}
if (hasflag(o->flags, F_CONTAINER)) {
@ -8920,7 +8948,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
getobname(newob, newobname, newob->amt);
msgnocap("%c - %s.",newob->letter, newobname);
}
// kill the ground object?
switch (oo->type->id) {
case OT_SPLASHWATER:
case OT_BLOODSPLASH:
@ -8930,20 +8957,13 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
removeob(oo, 1);
break;
case OT_FOUNTAIN:
if (hasflagval(oo->flags, F_LINKOB, OT_POT_EXPERIENCE, NA, NA, NULL) ||
onein(ONEIN_FOUNTAINDRYUP)) {
cell_t *loc;
loc = getoblocation(oo);
if (haslos(player, loc)) {
char fname[BUFLEN];
getobname(oo, fname, oo->amt);
msg("%s dries up.", obname);
}
if (fountain_will_dryup(oo)) {
removeob(oo, oo->amt);
}
break;
default:
break;
}
} else {
msg("That doesn't seem like a very good idea.");
@ -9403,7 +9423,6 @@ int pour(lifeform_t *lf, object_t *o) {
// god effects
if (isplayer(lf)) {
pleasegodmaybe(R_GODPURITY, 3);
angergodmaybe(R_GODDEATH, 15, GA_HERESY);
}
} else if ((o->type->id == OT_POT_WATER) && (o->blessed == B_CURSED)) { // unholy water
if (isplayer(lf)) {
@ -9416,7 +9435,6 @@ int pour(lifeform_t *lf, object_t *o) {
if (!isknown(o)) makeknown(o->type->id);
// god effects
if (isplayer(lf)) {
pleasegodmaybe(R_GODDEATH, 3);
angergodmaybe(R_GODPURITY, 25, GA_HERESY);
}
} else if (o->type->id == OT_POT_INVULN) {
@ -9648,13 +9666,10 @@ void quaff(lifeform_t *lf, object_t *o) {
}
// fountains sometimes dry up
if ((o->type->id == OT_FOUNTAIN) && onein(ONEIN_FOUNTAINDRYUP)) {
cell_t *loc;
if (o->type->id == OT_FOUNTAIN) {
if (fountain_will_dryup(o)) {
// dry up (ie. remove DONTKILL property)
drinkflag->val[2] = NA;
loc = getoblocation(o);
if (haslos(player, loc)) {
msg("%s dries up.", obname);
}
}
@ -9877,6 +9892,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
break;
case OT_POT_FURY:
lf->stamina = getmaxstamina(lf);
abilityeffects(lf, OT_A_RAGE, lf->cell, lf, NULL);
break;
case OT_POT_GASEOUSFORM:
@ -10547,6 +10563,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
removeob(o, 1);
} else if (o->type->id == OT_SCR_PERMENANCE) {
int ndone = 0;
enum ATTRIB a;
flag_t *f;
// makes certain flags permenant
for (f = lf->flags->first ; f ; f = f->next) {
@ -10555,6 +10572,17 @@ int readsomething(lifeform_t *lf, object_t *o) {
ndone++;
}
}
// make enhanced/reduced attributes permenant
for (a = 0; a < MAXATTS; a++) {
int innate,actual;
innate = lf->att[a];
actual = getattr(lf, a);
if (actual != innate) {
lf->att[a] = actual;
ndone++;
if (isplayer(lf)) statdirty = B_TRUE;
}
}
if (isplayer(lf)) {
if (ndone) {
@ -11929,7 +11957,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
glyph_t *gl;
gl = getglyph(o);
anim(where, srcloc, gl->ch, gl->colour);
msg("%s is reflected away from %s!", obname, targetname);
msg("%s %s reflected away from %s!", obname, (o->amt == 1) ? "is" : "are", targetname);
}
// adjust target
where = srcloc;
@ -12031,7 +12059,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
if (check_for_block(thrower, target, getthrowdam(o) + speed, DT_PROJECTILE, difficulty, attackname)) {
announcedmiss = B_TRUE;
youhit = B_FALSE;
missiledam += ((speed*2)+1);
missiledam += ((speed*2)+rnd(1,4));
}
}
@ -12218,7 +12246,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
wepeffects(o->flags, target->cell, hasflag(o->flags, F_DAM), dam);
missiledam += ((speed*2)+1);
missiledam += ((speed*2)+rnd(1,4));
if (willtangle) {
missiledam = 0; // don't damage the misisle

View File

@ -63,6 +63,7 @@ obmod_t *findobmod(enum OBMOD id);
objecttype_t *findot(enum OBTYPE id);
objecttype_t *findotn(char *name); // find objecttype by name
recipe_t *findrecipefor(enum OBTYPE result);
int fountain_will_dryup(object_t *o);
void fragments(cell_t *centre, char *what, int speed, int howfar);
void genhiddennames(void);
enum LFSIZE getarmoursize(object_t *o);

41
save.c
View File

@ -277,6 +277,34 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
if (db) dblog("----> done (id=%ld)",thisid);
}
// now repeat the above for polypack...
obcount = 0;
obid = 9998; // for testing
rv = fscanf(f, "polyob:%ld\n",&obid);
while (obid != -1) {
if (db) dblog("--> Load ob id %d into polypack list...",obid);
l->polypack->oblist[obcount] = obid;
obcount++;
fscanf(f, "polyob:%ld\n",&obid);
}
// terminate with -1s!
for (i = obcount ; i < MAXPILEOBS; i++) {
l->polypack->oblist[i] = -1;
}
if (db) dblog("--> Finished polypack oblist. Found %d objects.",obcount);
// now load object defs for this lf's pack!
fscanf(f, "polyobdefs\n");
for (i = 0; i < obcount; i++) {
long thisid;
if (db) dblog("--> Creating polypack ob #%d for lf.",i);
//if (db) dblog("-----> ob %d/%d...\n",i+1,obcount);
if (loadob(f, l->polypack, &thisid)) {
dblog("Error - can't create object %d/%d!\n",i+1,obcount);
exit(1);
}
if (db) dblog("----> done (id=%ld)",thisid);
}
// is this the player?
if (l->controller == C_PLAYER) {
player = l;
@ -857,6 +885,19 @@ int savelf(FILE *f, lifeform_t *l) {
saveob(f, o);
}
// lifeform polypack objects
obcount = 0;
for (o = l->polypack->first ; o ; o = o->next) {
fprintf(f, "polyob:%ld\n",o->id);
obcount++;
}
fprintf(f, "polyob:-1\n");
fprintf(f, "polyobdefs\n");
// now save our polypack object definitions
for (o = l->polypack->first ; o ; o = o->next) {
saveob(f, o);
}
return B_FALSE;
}

56
spell.c
View File

@ -2317,7 +2317,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) {
msg("You try to trip %s, but fail.",targetname);
} else if (cansee(player, user)) {
msg("%s tries to trip %s, but fail.",username, targetname);
msg("%s tries to trip %s, but fails.",username, targetname);
}
}
} else if (abilid == OT_A_TUMBLE) {
@ -4828,7 +4828,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("%s forms %s %s%s %s!", obname, getbodypartequipname(bp[i]),
castername, getpossessive(castername), getbodypartname(target, bp[i]));
}
wear(target, o);
// don't use "wear" because we don't want it being announced.
addflag(o->flags, F_EQUIPPED, bp[i], -1, -1, NULL);
// set its values
f = hasflag(o->flags, F_OBHP);
if (f) {
@ -4861,7 +4862,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
o = addob(target->pack, "ice crystal shield");
if (o) {
if (canwear(target, o, BP_NONE)) {
if (canwear(target, o, BP_SECWEAPON)) {
flag_t *f;
enum LFSIZE sz;
if (power <= 2) {
@ -4878,7 +4879,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("A %s shield of shimmering ice forms in %s%s hand!", getsizetext(sz), castername,
getpossessive(castername));
}
wear(target, o);
// don't use "wear" because we don't want it being announced.
addflag(o->flags, F_EQUIPPED, BP_SECWEAPON, -1, -1, NULL);
// set its values
f = hasflag(o->flags, F_OBHP);
if (f) {
@ -5244,11 +5246,17 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} // end if isplayer
} else if (spellid == OT_S_DETONATE) {
// don't need line of fire!
explodecells(targcell, 20, B_TRUE, NULL, power / 4, DT_ORTH, B_TRUE);
explodecells(targcell, 20+(power*2), B_TRUE, NULL, power / 4, DT_ORTH, B_TRUE);
if (haslos(player, targcell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (spellid == OT_S_DETONATEDELAY) {
addobfast(targcell->obpile, OT_VIBCLOUD);
if (haslos(player, targcell)) {
msg("The air nearby begins to vibrate violently..."); more();
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (spellid == OT_S_EQANDOP) {
flag_t *f;
f = addtempflag(caster->flags, F_REFLECTION, B_TRUE, NA, NA, NULL, FROMSPELL);
@ -6468,7 +6476,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// affect equipped objects
for (o = target->pack->first ; o ; o = nexto) {
nexto = o->next;
// destroy metal items on the ground
if (ismetal(o->material->id)) {
int dodam = B_FALSE;
if (isequippedon(o, BP_WEAPON) || isequippedon(o, BP_SECWEAPON)) {
@ -6491,7 +6498,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
noprefix(obname), OBS1(o));
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
takedamage(o, rnd(1,4), DT_HEAT);
takedamage(o, rnd(6,12), DT_HEAT);
}
}
}
@ -6515,7 +6522,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// affect objects on ground
for (o = targcell->obpile->first ; o ; o = nexto) {
nexto = o->next;
// destroy metal items on the ground
// damage metal items on the ground
if (ismetal(o->material->id)) {
if (haslos(player, targcell)) {
char obname[BUFLEN];
@ -6524,7 +6531,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE;
donesomething = B_FALSE;
}
takedamage(o, rnd(1,4), DT_HEAT);
takedamage(o, rnd(6,12), DT_HEAT);
}
}
}
@ -8592,9 +8599,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE;
}
amttolose = power*2;
// only announce if the target will have some stamina left.
// if they drop to 0, modstamina will handle the announce.
if (getstamina(target) >= amttolose) {
if (isplayer(target)) {
msg("You suddenly feel very lethargic!");
} else if (cansee(player, target)) {
@ -8602,7 +8606,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
getlfname(target, targname);
msg("%s looks very lethargic!", targname);
}
}
modstamina(target, -amttolose);
} else if (spellid == OT_S_REPELINSECTS) {
// just announce
@ -9080,7 +9083,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
if (targcell->lf) {
losehp(targcell->lf, rnd(1,6), DT_FIRE, caster, "a spark");
losehp(targcell->lf, rnd(2,2), DT_FIRE, caster, "a spark");
} else {
for (o = targcell->obpile->first ; o ; o = nexto) {
nexto = o->next;
@ -9923,7 +9926,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// set its damage value
f = hasflag(o->flags, F_DAM);
if (f) {
f->val[1] = 2+(power*2);
f->val[1] = 2+power;
}
addflag(o->flags, F_CREATEDBYSPELL, spellid, NA, NA, NULL);
} else {
@ -10054,6 +10057,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char lfname[BUFLEN];
cell_t *retcell[MAXRETCELLS];
int nretcell,i;
int dam;
// animation
//anim(caster->cell, targcell, '}', C_BLUE);
if (isplayer(caster) || cansee(player, caster)) {
@ -10062,30 +10066,37 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
dam = roll("2d6");
calcbresnham(caster->cell->map, caster->cell->x, caster->cell->y, targcell->x, targcell->y, retcell, &nretcell);
for (i = 1; i < nretcell; i++) {
target = haslf(retcell[i]);
if (target) {
int dir,amt, i;
int dir,amt, n;
object_t *arm[MAXBODYPARTS];
int narm = 0;
int dam;
getlfname(target, lfname);
// hit
if (cansee(player, target)) {
msg("%s %s hit by a jet of water!",lfname, is(target));
}
// does less damage the further you are away.
if (dam > 0) dam--;
// water damage will generally be turn to zero unless people are specifically
// vulnerable to water, so do bashing damage too.
losehp(target, roll("3d4"), DT_WATER, caster, "a high-pressure jet of water");
losehp(target, roll("3d4"), DT_BASH, caster, "a high-pressure jet of water");
losehp(target, dam, DT_WATER, caster, "a high-pressure jet of water");
losehp(target, dam, DT_BASH, caster, "a high-pressure jet of water");
// 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);
// rust
getallouterarmour(target, arm, &narm);
for (i = 0; i < narm; i++) {
takedamage(arm[i], R_TRUSTY, DT_WATER);
for (n = 0; n < narm; n++) {
takedamage(arm[n], R_TRUSTY, DT_WATER);
}
// add water object
addob(retcell[i]->obpile, "large puddle of water");
@ -11160,8 +11171,11 @@ int getstamcost(lifeform_t *lf, enum OBTYPE oid) {
flag_t *f;
f = lfhasflagval(lf, F_CANWILL, oid, NA, NA, NULL);
if (f) {
int newcost;
// override stamina cost?
texttospellopts(f->text, "stamcost:", &stamcost, NULL);
if (texttospellopts(f->text, "stamcost:", &newcost, NULL)) {
stamcost = newcost;
}
}
if (stamcost == -1) {
objecttype_t *ot;

8
text.c
View File

@ -99,7 +99,7 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
// modify victimname if required
//if (helpless && !isbehind(lf, victim)) {
if (!isplayer(victim) && ishelplessvictim(victim, lf, &helpless)) {
if (victim && !isplayer(victim) && ishelplessvictim(victim, lf, &helpless)) {
char *vn;
// strip "the" from "the xxx"
vn = strdup(victimname);
@ -1914,9 +1914,11 @@ void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *r
}
*/
void texttospellopts(char *text, ... ) {
// returns # opts filled in
int texttospellopts(char *text, ... ) {
char *p;
va_list args;
int nfilled = 0;
char *validname[] = {
"pw:",
"dam:",
@ -1990,6 +1992,7 @@ void texttospellopts(char *text, ... ) {
} else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, valfull);
}
nfilled++;
}
}
}
@ -1999,6 +2002,7 @@ void texttospellopts(char *text, ... ) {
if (wantname) writeto = va_arg(args, void *);
}
va_end(args);
return nfilled;
}
char *you(lifeform_t *lf) {

2
text.h
View File

@ -60,7 +60,7 @@ char *strends(char *a, char *suffix);
char *strstarts(char *a, char *prefix);
int strpixmatch(char *haystack, char *needle);
int texttodice(char *text, int *ndice, int *nsides, int *bonus);
void texttospellopts(char *text, ... );
int texttospellopts(char *text, ... );
//void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range, char *racestr);
char *you(lifeform_t *lf);
char *you_l(lifeform_t *lf);

View File

@ -9,6 +9,7 @@
@end
@legend
.:cell:carpetted floor
#:cell:rock wall
b:ob:wooden bed
t:ob:wooden table

View File

@ -13,6 +13,7 @@ entertext:You enter a dining room.
autodoors:75
autopop
! tables & chairs
fill(1,1,-2,-2) cell:tiled floor
scatter(1,1,-2,-2) ob:wooden table:20%
scatter(1,1,-2,-2) ob:wooden footstool:20%
scatter(1,1,-2,-2) ob:random food:1-2