- [+] add more vrare vaults to reduce likelihood of cockatrice lair!

- [+] bazaar
    - [+] money vault hsould be vrare
    - [+] so should traproom
- [+] rename giant rat to "dire rat"
- [+] don't show anything other than object description and throwing
      for unknown tech
- [+] shouldn't be able to rest in a tent if it's not known!
- [+] eyebat corpse increase maxmp?
- [+] blessed missiles should nearly always hit undead
* [+] too easy to dodge thrown missiles?
- [+] spell and wand of culinary abundance
- [+] if a carnivorous animal kills you:  "Eaten by a xxx"
* [+] bug: stairsperlev is only ever used in making DUNGEONS. 
      generecise this ??
- [+] safetorest - should ignore monsters feigning death
- [+] broken nose should reduce smell range
- [+] fresh and stale bread should be interchangable in cooking
- [+] make scroll of permenance act on you, not your objects
- [+] tweak object rarity yet agian...
- [+] bug: hole in roof above player start pos is immediately destroyed.
- [+] change pickaxe to be like resting
    - [+] wait first, then if not interrupted, do the dig.
    - [+] add cell->hp, celltype->hp. around 100.
    - [+] f_digging, x, y, digperturn
    - [+] interrupt() will stop this.
    - [+] each turn, lower hp of cell by 1.
- [+] make wlaking bakwards take less time based on athletics skill!!!
    - [+] at adept, takes no extra time?
- [+] better racial display
    - [+] ? for extra info.
        - [+] hitdice
        - [+] general attribs (str etc)
        - [+] don't show description until you press '?'
        - [+] addbonustext(flagpile, f_BONDESC, "asdffas") - to avoid
              index issues
        - [+] remove VULNS from "effects" unless temporary
            - [+] isresistantto() etc need to have "int onlytemp"
        - [+] remove VULNS from manual BONTEXT flags
        - [+] CRASH IN DTVULN CODE!!
- [+] limit '?r' display ??
    - [+] what to show
        - [+] show races you have encountered
        - [+] show races you know about through Lore (adept level)
        - [+] show playable races?????
    - [+] structs
        - [+] race->encountered
        - [+] need to save this.
- [+] make EFFECTS only show TEMPORARY effects or ones which don't come
      from race?
- [+] automate bondesc/pendesc based on flags!
    - [+] vulnarabilities / resist / immun
    - [+] vision range!! (visrangemod)
    - [+] size? restricted armour.
    - [+] stayinroom
    - [+] f_humanoid (can use weapons)
    - [+] tamable
    - [+] seeindark
    - [+] caneatraw
    - [+] enhancesmell
    - [+] caneatraw
    - [+] vegeatrian
    - [+] cernivore
    - [+] fastmetab
    - [+] startskill
    - [+] tremorsense
    - [+] silentmove
    - [+] deaf
    - [+] flying / levitating
    - [+] awareness
    - [+] nocturnal / diurnal
    - [+] heavyblow
    - [+] packattack
    - [+] dodges
    - [+] autocreateob
    - [+] MPMOD
    - [+] HPMOD
    - [+] MEDITATES
    - [+] PHOOTMEM
    - [+] canwill "Spells: xx, x, x, x"
- [+] spells:
    - [+] animate stone - "power" walls turn into stone golems
        - [+] implement spell
        - [+] golem
            - [+] r_golemstone
            - [+] knockback attack
            - [+] high str
            - [+] fists 
            - [+] corpsetype and iunsummonob = boulder
- [+] spell power modification - subtract spell level.
- [+] when i go down a drain, make sure the new map links to THE DRAIN
      I WENT DOWN. not some otehr one.
- [+] some monsters shouldn't sleep! add new flag: f_nosleep
- [+] make spanner help disarm traps!
This commit is contained in:
Rob Pearce 2011-12-03 22:33:37 +00:00
parent c27ad12c49
commit d5b1e40f98
22 changed files with 1488 additions and 915 deletions

5
ai.c
View File

@ -794,7 +794,6 @@ int ai_healing(lifeform_t *lf) {
if ((lf->race->id == R_STIRGE) || (lf->race->id == R_LEECH)) { if ((lf->race->id == R_STIRGE) || (lf->race->id == R_LEECH)) {
if (ispeaceful(lf)) { if (ispeaceful(lf)) {
int sleepval = 18; int sleepval = 18;
if (modcounter(lf->flags, 1) >= sleepval) { if (modcounter(lf->flags, 1) >= sleepval) {
// we say that this ISNT on purpose, because otherwise // we say that this ISNT on purpose, because otherwise
// we'll wake up as soon as we're healed. in this case // we'll wake up as soon as we're healed. in this case
@ -833,7 +832,7 @@ int ai_healing(lifeform_t *lf) {
if (lf->hp < (lf->maxhp/2)) { if (lf->hp < (lf->maxhp/2)) {
if (!useitemwithflag(lf, F_AIHEALITEM)) { if (!useitemwithflag(lf, F_AIHEALITEM)) {
return B_TRUE; return B_TRUE;
} else { } else if (cansleep(lf)) {
// don't have or can't use our healing items // don't have or can't use our healing items
// no enemies in sight? // no enemies in sight?
if (safetorest(lf)) { if (safetorest(lf)) {
@ -1978,7 +1977,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if ((ot->id == OT_S_DISPERSAL) && (lf->race->raceclass->id == RC_GOD)) { if ((ot->id == OT_S_DISPERSAL) && (lf->race->raceclass->id == RC_GOD)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
if ((ot->id == OT_S_DRAINLIFE) && isimmuneto(victim->flags, DT_NECROTIC)) { if ((ot->id == OT_S_DRAINLIFE) && isimmuneto(victim->flags, DT_NECROTIC, B_FALSE)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} }
if (ot->id == OT_A_FLIP) { if (ot->id == OT_A_FLIP) {

View File

@ -852,7 +852,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
if (i == 0) { if (i == 0) {
if (lfhasflag(lf, F_HOLYAURA) && isvulnto(victim->flags, DT_HOLY)) { if (lfhasflag(lf, F_HOLYAURA) && isvulnto(victim->flags, DT_HOLY, B_FALSE)) {
damtype[i] = DT_HOLY; damtype[i] = DT_HOLY;
} }
// blocked by defender's shield? // blocked by defender's shield?
@ -1021,7 +1021,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (f) { if (f) {
int diff; int diff;
diff = f->val[2]; diff = f->val[2];
if (isimmuneto(victim->flags, DT_COLD) || skillcheck(victim, SC_RESISTMAG, diff, 0)) { if (isimmuneto(victim->flags, DT_COLD, B_FALSE) || skillcheck(victim, SC_RESISTMAG, diff, 0)) {
if (isplayer(victim)) { if (isplayer(victim)) {
msg("You feel mildly chilly."); msg("You feel mildly chilly.");
} }
@ -2270,10 +2270,10 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) {
draintype = DR_FROMWEP; draintype = DR_FROMWEP;
} }
if (draintype && !isimmuneto(victim->flags, DT_NECROTIC)) { if (draintype && !isimmuneto(victim->flags, DT_NECROTIC, B_FALSE)) {
int hpgain; int hpgain;
// drain life! // drain life!
if (isresistantto(victim->flags, DT_NECROTIC)) { if (isresistantto(victim->flags, DT_NECROTIC, B_FALSE)) {
hpgain = dam; hpgain = dam;
} else { } else {
hpgain = (dam/2); hpgain = (dam/2);

156
data.c
View File

@ -31,6 +31,18 @@ extern char *technoun[];
extern objecttype_t *lastot; extern objecttype_t *lastot;
void addbonustext(flagpile_t *fp, enum FLAG fid, char *text) {
int idx = -1;
flag_t *f;
// find last index
for (f = fp->first ; f; f = f->next) {
if (f->id == fid) {
if (f->val[0] > idx) idx = f->val[0];
}
}
addflag(fp, fid, idx+1, NA, NA, text);
}
command_t *addcommand(enum COMMAND id, char ch, char *desc) { command_t *addcommand(enum COMMAND id, char ch, char *desc) {
command_t *a; command_t *a;
@ -1123,7 +1135,7 @@ void initobjects(void) {
addoc(OC_TRAP, "Trap", "Fiendish traps.", '^', C_GREY, RR_RARE); addoc(OC_TRAP, "Trap", "Fiendish traps.", '^', C_GREY, RR_RARE);
addocnoun(lastobjectclass, "trap"); addocnoun(lastobjectclass, "trap");
addoc(OC_MONEY, "Money", "The standard currency of Nexus.", '$', C_GREY, RR_UNCOMMON); addoc(OC_MONEY, "Money", "The standard currency of Nexus.", '$', C_GREY, RR_UNCOMMON);
addoc(OC_SCROLL, "Scrolls", "An arcane roll of parchment, inscribed with many magical glyphs.", '?', C_GREY, RR_UNCOMMON); addoc(OC_SCROLL, "Scrolls", "An arcane roll of parchment, inscribed with many magical glyphs.", '?', C_GREY, RR_COMMON);
addocnoun(lastobjectclass, "scroll"); addocnoun(lastobjectclass, "scroll");
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
@ -1142,7 +1154,7 @@ void initobjects(void) {
addflag(lastobjectclass->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_RNDCHARGES, 1, 8, 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_UNCOMMON); addoc(OC_POTION, "Potions", "A strange concoction contained within a small flask.", '!', C_GREY, RR_COMMON);
addocnoun(lastobjectclass, "potion"); addocnoun(lastobjectclass, "potion");
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
@ -1171,7 +1183,7 @@ void initobjects(void) {
addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_MASTERWORK, 17, NA, NULL); addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_MASTERWORK, 17, NA, NULL);
addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_SHODDY, 34, NA, NULL); addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_SHODDY, 34, NA, NULL);
addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_BLOODSTAINED, 17, NA, NULL); addflag(lastobjectclass->flags, F_CANHAVEOBMOD, OM_BLOODSTAINED, 17, NA, NULL);
addoc(OC_MISSILE, "Missiles/Ammunition", "An instrument used for the purpose of causing harm or death.", ';', C_GREY, RR_COMMON); addoc(OC_MISSILE, "Missiles/Ammunition", "An instrument used for the purpose of causing harm or death.", ';', C_GREY, RR_UNCOMMON);
addocnoun(lastobjectclass, "missile"); addocnoun(lastobjectclass, "missile");
addocnoun(lastobjectclass, "ammo"); addocnoun(lastobjectclass, "ammo");
addocnoun(lastobjectclass, "ammunition"); addocnoun(lastobjectclass, "ammunition");
@ -3255,10 +3267,9 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addot(OT_S_ANIMATESTATUE, "animate statue", "Temporarily transforms a statue into living flesh, under control of the caster. Also stops stoning.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_ANIMATESTATUE, "animate statue", "Temporarily brings a statue to life, under control of the caster. Also stops stoning.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell only affects stone which is in the form of a living creature."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell only affects stone which is in the form of a living creature.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT|TT_PLAYER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT|TT_PLAYER, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL); addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
@ -3274,6 +3285,12 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addot(OT_S_QUICKENSTONE, "quicken stone", "Crafts nearby stone into powerful stone primalities.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many creatures will be created.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 8, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
// l6 // l6
addot(OT_S_PETRIFY, "petrify", "Causes a living creature to turn into stone.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PETRIFY, "petrify", "Causes a living creature to turn into stone.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability.");
@ -3317,11 +3334,18 @@ void initobjects(void) {
addflag(lastot->flags, F_ONGOING, 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_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
// l2 // 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.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_NONE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l3
addot(OT_S_CREATEMONSTER, "create monster", "Summons a (probably hostile) monster to a nearby location.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_CREATEMONSTER, "create monster", "Summons a (probably hostile) monster to a nearby location.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V you can control where the monster appears."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V you can control where the monster appears.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power VII you can control the type of monster created."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power VII you can control the type of monster created.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l5 // l5
@ -3627,6 +3651,10 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
// wands // wands
addot(OT_WAND_CREATEFOOD, "wand of culinary abundance", "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, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_CREATEFOOD, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL);
addot(OT_WAND_KNOCK, "wand of opening", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND, SZ_SMALL); addot(OT_WAND_KNOCK, "wand of opening", "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_RARITY, H_DUNGEON, 80, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL); addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL);
@ -3817,6 +3845,7 @@ void initobjects(void) {
addot(OT_PICKAXE, "pickaxe", "A heavy tool for breaking rock.", MT_METAL, 8, OC_TOOLS, SZ_MEDIUM); addot(OT_PICKAXE, "pickaxe", "A heavy tool for breaking rock.", MT_METAL, 8, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_HELPSDIG, 10, NA, NA, NULL);
addot(OT_ROPE, "rope", "A long length of strong rope.", MT_CLOTH, 5, OC_TOOLS, SZ_MEDIUM); addot(OT_ROPE, "rope", "A long length of strong rope.", MT_CLOTH, 5, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
@ -6121,6 +6150,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDDIR, B_TRUE, NA, NA, "Use your spanner in which direction"); addflag(lastot->flags, F_OPERNEEDDIR, B_TRUE, NA, NA, "Use your spanner in which direction");
addflag(lastot->flags, F_HELPSDISARM, 5, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL);
addot(OT_SHILLELAGH, "shillelagh", "An small cudgel with a strap, lightweight yet surprisingly effective. Irish in origin.", MT_WOOD, 2, OC_WEAPON, SZ_MEDIUM); addot(OT_SHILLELAGH, "shillelagh", "An small cudgel with a strap, lightweight yet surprisingly effective. Irish in origin.", MT_WOOD, 2, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
@ -6432,18 +6462,13 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_WIS, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_RANDOM, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CHA, AT_RANDOM, NA, NULL);
// bonuses // bonuses
addflag(lastrace->flags, F_BONDESC, 0, NA, NA, "Unarmed claw attack (damage rating 4)"); addbonustext(lastrace->flags, F_BONDESC, "Unarmed claw attack (damage rating 4)");
addflag(lastrace->flags, F_BONDESC, 1, NA, NA, "Can fly at will");
addflag(lastrace->flags, F_BONDESC, 2, NA, NA, "+1 vision range");
addflag(lastrace->flags, F_BONDESC, 3, NA, NA, "Starts with one rank of Evasion.");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, "pw:1;"); addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, "pw:1;");
addflag(lastrace->flags, F_VISRANGEMOD, 1, NA, NA, NULL); addflag(lastrace->flags, F_VISRANGEMOD, 1, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_EVASION, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_EVASION, PR_NOVICE, NA, NULL);
// penalties // penalties
addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Low hit points."); addbonustext(lastrace->flags, F_PENDESC, "Low hit points.");
addflag(lastrace->flags, F_PENDESC, 1, NA, NA, "Low Strength and Fitness.");
addflag(lastrace->flags, F_PENDESC, 2, NA, NA, "Vulnerable to Fire and Electricity.");
addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_ELECTRIC, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_ELECTRIC, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+3"); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+3");
@ -6480,16 +6505,11 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VLOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VLOW, NA, NULL);
// bonuses // bonuses
addflag(lastrace->flags, F_BONDESC, 0, NA, NA, "Computerised brain provides automatic analysis."); addbonustext(lastrace->flags, F_BONDESC, "Computerised brain provides automatic analysis.");
addflag(lastrace->flags, F_BONDESC, 1, NA, NA, "Starts with one rank of Tech Usage.");
addflag(lastrace->flags, F_BONDESC, 2, NA, NA, "Above average Strength, Intelligence and Fitness.");
addflag(lastrace->flags, F_EXTRAINFO, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_EXTRAINFO, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_TECHUSAGE, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_TECHUSAGE, PR_ADEPT, NA, NULL);
// penalties // penalties
addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Cannot use magic."); addbonustext(lastrace->flags, F_PENDESC, "Cannot use magic.");
addflag(lastrace->flags, F_PENDESC, 1, NA, NA, "Vulnerable to Cold, Water and Electricity.");
addflag(lastrace->flags, F_PENDESC, 2, NA, NA, "Low Agility and Wisdom.");
addflag(lastrace->flags, F_PENDESC, 3, NA, NA, "Very low Charisma.");
addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_WATER, NA, NA, "2d6"); addflag(lastrace->flags, F_DTVULN, DT_WATER, NA, NA, "2d6");
addflag(lastrace->flags, F_DTVULN, DT_ELECTRIC, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_ELECTRIC, NA, NA, NULL);
@ -6548,13 +6568,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HATESRACEWITHFLAG, F_CANINE, NA, NA, NULL); addflag(lastrace->flags, F_HATESRACEWITHFLAG, F_CANINE, NA, NA, NULL);
addflag(lastrace->flags, F_HATESRACEWITHFLAG, F_AVIAN, NA, NA, NULL); addflag(lastrace->flags, F_HATESRACEWITHFLAG, F_AVIAN, NA, NA, NULL);
// bonuses // bonuses
addflag(lastrace->flags, F_BONDESC, 0, NA, NA, "Above average Agility and Charisma."); addbonustext(lastrace->flags, F_BONDESC, "Unarmed claw attack (damage rating 3)");
addflag(lastrace->flags, F_BONDESC, 1, NA, NA, "Unarmed claw attack (damage rating 3)");
addflag(lastrace->flags, F_BONDESC, 2, NA, NA, "Starts with one rank of Climbing and Listen.");
addflag(lastrace->flags, F_BONDESC, 3, NA, NA, "Can Jump at will.");
addflag(lastrace->flags, F_BONDESC, 4, NA, NA, "Enhanced balance prevents slips and falls.");
addflag(lastrace->flags, F_BONDESC, 5, NA, NA, "Enhanced sense of smell (range 2)");
addflag(lastrace->flags, F_BONDESC, 6, NA, NA, "Darkvision (range 2)");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_NOVICE, NA, NULL);
@ -6564,12 +6578,9 @@ void initrace(void) {
addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
// penalties // penalties
addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Below average Strength, low Wisdom, and slightly low Hit Points."); addbonustext(lastrace->flags, F_PENDESC, "Slightly low Hit Points.");
addflag(lastrace->flags, F_PENDESC, 1, NA, NA, "Carnivorous (only eats meat)."); addbonustext(lastrace->flags, F_PENDESC, "Can never learn Swimming.");
addflag(lastrace->flags, F_PENDESC, 2, NA, NA, "Fast metabolism."); addbonustext(lastrace->flags, F_PENDESC, "Enters a bezerk rage upon sight of avians or canines.");
addflag(lastrace->flags, F_PENDESC, 3, NA, NA, "Vulnerable to Magic, Water and Sonic damage.");
addflag(lastrace->flags, F_PENDESC, 4, NA, NA, "Can never learn Swimming.");
addflag(lastrace->flags, F_PENDESC, 5, NA, NA, "Enters a bezerk rage upon sight of avians or canines.");
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FASTMETAB, 2, NA, NA, NULL); addflag(lastrace->flags, F_FASTMETAB, 2, NA, NA, NULL);
@ -6602,16 +6613,10 @@ void initrace(void) {
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL);
// bonuses // bonuses
addflag(lastrace->flags, F_BONDESC, 0, NA, NA, "High Fitness.");
addflag(lastrace->flags, F_BONDESC, 1, NA, NA, "Above average Strength.");
addflag(lastrace->flags, F_BONDESC, 2, NA, NA, "Darkvision (range: 3)");
addflag(lastrace->flags, F_BONDESC, 3, NA, NA, "Starts with one rank of Cartography and Metalwork.");
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_METALWORK, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_METALWORK, PR_NOVICE, NA, NULL);
// penalties // penalties
addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Below average Agility, Intelligence and Charisma.");
addflag(lastrace->flags, F_PENDESC, 1, NA, NA, "Penalty to Mana.");
addflag(lastrace->flags, F_MPMOD, -3, NA, NA, NULL); addflag(lastrace->flags, F_MPMOD, -3, NA, NA, NULL);
addflag(lastrace->flags, F_TAMABLE, 35, NA, NA, NULL); addflag(lastrace->flags, F_TAMABLE, 35, NA, NA, NULL);
@ -6647,19 +6652,13 @@ void initrace(void) {
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL);
// bonuses // bonuses
addflag(lastrace->flags, F_BONDESC, 0, NA, NA, "Above average Agility, Intelligence and Charisma.");
addflag(lastrace->flags, F_BONDESC, 1, NA, NA, "Darkvision (range: 2)");
addflag(lastrace->flags, F_BONDESC, 2, NA, NA, "Meditates to retain awareness while resting.");
addflag(lastrace->flags, F_BONDESC, 3, NA, NA, "Extra Mana points.");
addflag(lastrace->flags, F_BONDESC, 4, NA, NA, "Starts with one rank of Ranged Weapons and Stealth.");
addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL);
addflag(lastrace->flags, F_MEDITATES, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MEDITATES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MPMOD, 3, NA, NA, NULL); addflag(lastrace->flags, F_MPMOD, 3, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_RANGED, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_RANGED, PR_NOVICE, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_STEALTH, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_STEALTH, PR_NOVICE, NA, NULL);
// penalties // penalties
addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Below average Strength and Fitness."); addbonustext(lastrace->flags, F_PENDESC, "Slightly below average Hit Points.");
addflag(lastrace->flags, F_PENDESC, 1, NA, NA, "Slightly below average Hit Points.");
addflag(lastrace->flags, F_TAMABLE, 25, NA, NA, NULL); addflag(lastrace->flags, F_TAMABLE, 25, NA, NA, NULL);
addrace(R_MAMMOAN, "mammoan", 150, '@', C_GREY, MT_LEATHER, RC_HUMANOID, "Mammoans are huge, elephant-like humanoids. Their have great senses of hearing and smell, a photographic memory, and leather skin which greatly lessens damage. On the other hand they vision is poor, their movement slow, and their digestive system cannot cope with meat."); addrace(R_MAMMOAN, "mammoan", 150, '@', C_GREY, MT_LEATHER, RC_HUMANOID, "Mammoans are huge, elephant-like humanoids. Their have great senses of hearing and smell, a photographic memory, and leather skin which greatly lessens damage. On the other hand they vision is poor, their movement slow, and their digestive system cannot cope with meat.");
@ -6690,20 +6689,12 @@ void initrace(void) {
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL);
// bonuses // bonuses
addflag(lastrace->flags, F_BONDESC, 0, NA, NA, "High Strength."); addbonustext(lastrace->flags, F_BONDESC, "Leather skin reduces damage.");
addflag(lastrace->flags, F_BONDESC, 1, NA, NA, "Leather skin reduces damage.");
addflag(lastrace->flags, F_BONDESC, 2, NA, NA, "Photographic memory.");
addflag(lastrace->flags, F_BONDESC, 3, NA, NA, "Enhanced sense of smell (range 3)");
addflag(lastrace->flags, F_BONDESC, 4, NA, NA, "Starts with one rank of Listen.");
addflag(lastrace->flags, F_PHOTOMEM, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_PHOTOMEM, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_LISTEN, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_LISTEN, PR_NOVICE, NA, NULL);
// penalties // penalties
addflag(lastrace->flags, F_PENDESC, 0, NA, NA, "Very low Agility and Charisma."); addbonustext(lastrace->flags, F_PENDESC, "Can never learn Athletics.");
addflag(lastrace->flags, F_PENDESC, 1, NA, NA, "-2 vision range.");
addflag(lastrace->flags, F_PENDESC, 2, NA, NA, "Vulnerable to Sonic damage.");
addflag(lastrace->flags, F_PENDESC, 3, NA, NA, "Vegeterian (will not eat meat)");
addflag(lastrace->flags, F_PENDESC, 4, NA, NA, "Can never learn Athletics.");
addflag(lastrace->flags, F_VISRANGEMOD, -2, NA, NA, NULL); addflag(lastrace->flags, F_VISRANGEMOD, -2, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_SONIC, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_SONIC, NA, NA, NULL);
addflag(lastrace->flags, F_VEGETARIAN, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_VEGETARIAN, B_TRUE, NA, NA, NULL);
@ -7065,6 +7056,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_BUGBEAR, "bugbear", 120, 'G', C_BROWN, MT_FLESH, RC_HUMANOID, "A huge goblinoid creature, similar to a hobgoblin but larger again, with a temperament to match."); addrace(R_BUGBEAR, "bugbear", 120, 'G', C_BROWN, MT_FLESH, RC_HUMANOID, "A huge goblinoid creature, similar to a hobgoblin but larger again, with a temperament to match.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
@ -7135,6 +7127,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;"); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;");
addflag(lastrace->flags, F_CASTCHANCE, 70, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 70, NA, NA, NULL);
addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_DARKMANTLE, "darklurk", 70, 'U', C_BLUE, MT_FLESH, RC_MAGIC, "A floating squid-like creature, rarely seen due to its ability to cloak itself in a magical darkness. They use their huge tentacles to grab then crush their unsuspecting prey."); addrace(R_DARKMANTLE, "darklurk", 70, 'U', C_BLUE, MT_FLESH, RC_MAGIC, "A floating squid-like creature, rarely seen due to its ability to cloak itself in a magical darkness. They use their huge tentacles to grab then crush their unsuspecting prey.");
addbodypart(lastrace, BP_BODY, NULL); addbodypart(lastrace, BP_BODY, NULL);
@ -7168,6 +7161,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addrace(R_EYEBAT, "eyebat", 5, 'e', C_BLUE, MT_FLESH, RC_MAGIC, "A smaller cousin to the beholder, an eyebat is a single oversized eyeball suspended between bat-like wings."); addrace(R_EYEBAT, "eyebat", 5, 'e', C_BLUE, MT_FLESH, RC_MAGIC, "A smaller cousin to the beholder, an eyebat is a single oversized eyeball suspended between bat-like wings.");
addbodypart(lastrace, BP_BODY, NULL); addbodypart(lastrace, BP_BODY, NULL);
@ -7574,6 +7568,30 @@ void initrace(void) {
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL);
addrace(R_GOLEMSTONE, "stone primality", 200, 'H', C_GREY, MT_STONE, RC_HUMANOID, "A living mass of stone, animated by powerful magic.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_EXHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_EXHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_EXLOW, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "10d4");
addflag(lastrace->flags, F_ARMOURRATING, 14, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, -50, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_VERYSLOW, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 16, NA, NULL);
addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "boulder");
addflag(lastrace->flags, F_UNSUMMONOB, NA, NA, NA, "boulder");
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID, "A larger, stronger, smarter and more menacing form of a goblin."); 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); setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
@ -7988,6 +8006,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_XPMULTIPLY, 2, NA, NA, NULL); addflag(lastrace->flags, F_XPMULTIPLY, 2, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_SATYR, "satyr", 80, 'h', C_GREEN, MT_FLESH, RC_HUMANOID, "A goat-like humanoid equipped with a set of magical panpipes."); addrace(R_SATYR, "satyr", 80, 'h', C_GREEN, MT_FLESH, RC_HUMANOID, "A goat-like humanoid equipped with a set of magical panpipes.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
@ -8064,6 +8083,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOFLEE, 5, NA, NA, NULL); addflag(lastrace->flags, F_NOFLEE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE, RC_MAGIC, "A small magical creature surrounded by crackling flames."); addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE, RC_MAGIC, "A small magical creature surrounded by crackling flames.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
@ -8092,6 +8112,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, 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_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_WHITE, MT_ICE, RC_MAGIC, "A small magical creature surrounded by freezing ice."); addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_WHITE, MT_ICE, RC_MAGIC, "A small magical creature surrounded by freezing ice.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
@ -8120,6 +8141,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, 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_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_TROLL, "troll", 100, 't', C_GREEN, MT_FLESH, RC_HUMANOID, "A savage, hairy green monster. Trolls are extremely muscular, move abnormally quickly and regenerate."); addrace(R_TROLL, "troll", 100, 't', C_GREEN, MT_FLESH, RC_HUMANOID, "A savage, hairy green monster. Trolls are extremely muscular, move abnormally quickly and regenerate.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
@ -8225,6 +8247,7 @@ void initrace(void) {
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL);
addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_PIRANHAKING, "king piranha", 1, ';', C_GREEN, MT_FLESH, RC_AQUATIC, "A larger version of a standard piranha. King piranhas can leap through the air."); addrace(R_PIRANHAKING, "king piranha", 1, ';', C_GREEN, MT_FLESH, RC_AQUATIC, "A larger version of a standard piranha. King piranhas can leap through the air.");
setbodytype(lastrace, BT_FISH); setbodytype(lastrace, BT_FISH);
addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL);
@ -8242,6 +8265,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 6, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 6, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;"); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;");
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_EELELEC, "electric eel", 120, ';', C_CYAN, MT_FLESH, RC_AQUATIC, "A sliippery eel charged with electricity."); addrace(R_EELELEC, "electric eel", 120, ';', C_CYAN, MT_FLESH, RC_AQUATIC, "A sliippery eel charged with electricity.");
setbodytype(lastrace, BT_FISH); setbodytype(lastrace, BT_FISH);
addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL);
@ -8258,6 +8282,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HASATTACK, OT_ZAPPER, 6, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_ZAPPER, 6, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_ELECTRIC, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_ELECTRIC, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_EELGIANT, "giant eel", 150, ';', C_BLUE, MT_FLESH, RC_AQUATIC, "A very long, slippery eel. They tend to catch and crush their prey."); addrace(R_EELGIANT, "giant eel", 150, ';', C_BLUE, MT_FLESH, RC_AQUATIC, "A very long, slippery eel. They tend to catch and crush their prey.");
setbodytype(lastrace, BT_FISH); setbodytype(lastrace, BT_FISH);
addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL);
@ -8274,6 +8299,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d6;"); addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d6;");
addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
// plants // plants
addrace(R_CACTUS, "cactus", 30, 'F', C_YELLOW, MT_PLANT, RC_PLANT, "A wide upright plant coated with sharp spines. Said to sprout delicious fruit."); addrace(R_CACTUS, "cactus", 30, 'F', C_YELLOW, MT_PLANT, RC_PLANT, "A wide upright plant coated with sharp spines. Said to sprout delicious fruit.");
addbodypart(lastrace, BP_BODY, "stalk"); addbodypart(lastrace, BP_BODY, "stalk");
@ -8843,7 +8869,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RETALIATE, 1, 4, DT_PIERCE, "sharp spines"); addflag(lastrace->flags, F_RETALIATE, 1, 4, DT_PIERCE, "sharp spines");
addflag(lastrace->flags, F_CORPSEFLAG, F_SHARP, 1, 4, NULL); addflag(lastrace->flags, F_CORPSEFLAG, F_SHARP, 1, 4, NULL);
addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL);
addrace(R_RAT, "giant rat", 3, 'r', C_BROWN, MT_FLESH, RC_ANIMAL, "A rodent of unusual size."); addrace(R_RAT, "dire rat", 3, 'r', C_BROWN, MT_FLESH, RC_ANIMAL, "A rodent of unusual size.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9706,14 +9732,14 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+1"); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+1");
addflag(lastrace->flags, F_ENHANCESMELL, 2, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 2, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 1, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "buzzes angrily^an angry buzzing"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "buzzes angrily^an angry buzzing");
addflag(lastrace->flags, F_NOISETEXT, N_FLY, 2, NA, "^buzzing"); addflag(lastrace->flags, F_NOISETEXT, N_FLY, 2, NA, "^buzzing");
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, 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, 3, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SUCKBLOOD, NA, NA, "dam:1d4;"); addflag(lastrace->flags, F_CANWILL, OT_A_SUCKBLOOD, NA, NA, "dam:1d1;");
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
@ -10055,6 +10081,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
// special: fully heal if our origrace is a vampire, and we are resting over a coffin // special: fully heal if our origrace is a vampire, and we are resting over a coffin
addrace(R_DANCINGWEAPON, "dancing weapon", 0, ')', C_GREY, MT_METAL, RC_OTHER, "A magically animated weapon."); addrace(R_DANCINGWEAPON, "dancing weapon", 0, ')', C_GREY, MT_METAL, RC_OTHER, "A magically animated weapon.");
@ -10073,6 +10100,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_FLOATINGDISC, "floating disc", 0, '_', C_BOLDGREEN, MT_METAL, RC_OTHER, "A magically created disc of energy which floats in the air."); addrace(R_FLOATINGDISC, "floating disc", 0, '_', C_BOLDGREEN, MT_METAL, RC_OTHER, "A magically created disc of energy which floats in the air.");
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
@ -10090,11 +10118,15 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
// now do final steps in race initialisation: // now do final steps in race initialisation:
// - add flags based on raceclass, etc // - add flags based on raceclass, etc
// - fill in missing alignments // - fill in missing alignments
for (r = firstrace ; r ; r = r->next) { for (r = firstrace ; r ; r = r->next) {
if (hasflag(r->flags, F_PLAYABLE)) {
r->known = B_TRUE;
}
if (r->raceclass->id == RC_AQUATIC) { if (r->raceclass->id == RC_AQUATIC) {
addflag(r->flags, F_HASSKILL, SK_SWIMMING, PR_MASTER, NA, NULL); addflag(r->flags, F_HASSKILL, SK_SWIMMING, PR_MASTER, NA, NULL);
addflag(r->flags, F_AQUATIC, B_TRUE, NA, NA, NULL); addflag(r->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
@ -10104,6 +10136,7 @@ void initrace(void) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_MATVULN, MT_SILVER, 200, NA, NULL); addflag(r->flags, F_MATVULN, MT_SILVER, 200, NA, NULL);
addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_GOD) { } else if (r->raceclass->id == RC_GOD) {
addflag(r->flags, F_PIETY, 100, NA, NA, NULL); addflag(r->flags, F_PIETY, 100, NA, NA, NULL);
addflag(r->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(r->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
@ -10115,6 +10148,7 @@ void initrace(void) {
addflag(r->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); addflag(r->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL);
addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL); addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL);
addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL); addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL);
addflag(r->flags, F_MEDITATES, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_MAGIC) { } else if (r->raceclass->id == RC_MAGIC) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_PLANT) { } else if (r->raceclass->id == RC_PLANT) {
@ -10125,8 +10159,9 @@ void initrace(void) {
addflag(r->flags, F_DTVULN, DT_DECAY, NA, NA, NULL); addflag(r->flags, F_DTVULN, DT_DECAY, NA, NA, NULL);
addflag(r->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL); addflag(r->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL);
addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_SLIME) { } else if (r->raceclass->id == RC_SLIME) {
addflag(lastrace->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_UNDEAD) { } else if (r->raceclass->id == RC_UNDEAD) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
@ -10138,6 +10173,7 @@ void initrace(void) {
addflag(r->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(r->flags, F_DTVULN, DT_HOLY, NA, NA, NULL);
addflag(r->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL); addflag(r->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
} }
// fill in missins alignments // fill in missins alignments

1
data.h
View File

@ -1,5 +1,6 @@
#include "defs.h" #include "defs.h"
void addbonustext(flagpile_t *fp, enum FLAG fid, char *text);
command_t *addcommand(enum COMMAND id, char c, char *desc); command_t *addcommand(enum COMMAND id, char c, char *desc);
void initcommands(void); void initcommands(void);
void initjobs(void); void initjobs(void);

Binary file not shown.

43
defs.h
View File

@ -864,6 +864,7 @@ enum RACE {
R_GOBLINWAR, R_GOBLINWAR,
R_GOBLINSHOOTER, R_GOBLINSHOOTER,
R_GOBLINHEXER, R_GOBLINHEXER,
R_GOLEMSTONE,
R_HOBGOBLIN, R_HOBGOBLIN,
R_HOBGOBLINWAR, R_HOBGOBLINWAR,
R_KOBOLD, R_KOBOLD,
@ -1328,6 +1329,7 @@ enum OBTYPE {
OT_S_PETRIFY, OT_S_PETRIFY,
OT_S_POLYMORPH, OT_S_POLYMORPH,
OT_S_POLYMORPHRND, OT_S_POLYMORPHRND,
OT_S_QUICKENSTONE,
// nature / enviromancy // nature / enviromancy
OT_S_BARKSKIN, OT_S_BARKSKIN,
OT_S_CALLLIGHTNING, OT_S_CALLLIGHTNING,
@ -1364,6 +1366,7 @@ enum OBTYPE {
OT_S_WARPWOOD, OT_S_WARPWOOD,
OT_S_WATERJET, OT_S_WATERJET,
// -- summoning // -- summoning
OT_S_CREATEFOOD,
OT_S_FLOATINGDISC, OT_S_FLOATINGDISC,
OT_S_GLYPHWARDING, OT_S_GLYPHWARDING,
OT_S_CLEARLEVEL, OT_S_CLEARLEVEL,
@ -1441,6 +1444,7 @@ enum OBTYPE {
// otherwise 'shouts a blood-curdling war cry' // otherwise 'shouts a blood-curdling war cry'
// wands // wands
OT_WAND_COLD, OT_WAND_COLD,
OT_WAND_CREATEFOOD,
OT_WAND_DETONATION, OT_WAND_DETONATION,
OT_WAND_DIGGING, OT_WAND_DIGGING,
OT_WAND_DISPERSAL, OT_WAND_DISPERSAL,
@ -2035,8 +2039,22 @@ enum FLAG {
F_CHARGELOWMSG, // text = msg when charges are nearly out F_CHARGELOWMSG, // text = msg when charges are nearly out
F_CHARGEOUTMSG, // text = msg when charges are gone F_CHARGEOUTMSG, // text = msg when charges are gone
F_HELPSCLIMB, // object gives v0 bonus to sc_climb checks. F_HELPSCLIMB, // object gives v0 bonus to sc_climb checks.
F_HELPSDIG, // object can dig. does v0 dam to cells.
F_HELPSDISARM, // object gives v0 bonus to disarm trap checks.
F_HELPSREST, // makes you heal mp/hp faster when using 'R'
// reduces skillcheck difficulty by v0.
// optional v1 = how many less turns between
// skillchecks. should not go more than
// DEFAULTRESTHEALTIME.
// technology flags // technology flags
F_TECHLEVEL, // v0 is a PR_xxx enum for tech usage skill F_TECHLEVEL, // v0 is a PR_xxx enum for tech usage skill
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_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.
F_REFILLWITH, // pour obj id val0 onto this to refill its charges
// what can you do with this object? // what can you do with this object?
F_TAINTED, // will give food poisoning if you eat/drink it F_TAINTED, // will give food poisoning if you eat/drink it
F_PREPARED, // raw meat has been prepared using cooking skill F_PREPARED, // raw meat has been prepared using cooking skill
@ -2200,19 +2218,6 @@ enum FLAG {
F_BALANCE, // heals target if their maxhp < your maxhp F_BALANCE, // heals target if their maxhp < your maxhp
F_MERCIFUL, // puts to sleep instead of killing. F_MERCIFUL, // puts to sleep instead of killing.
F_REVENGE, // causes damage based on your hp F_REVENGE, // causes damage based on your hp
F_HELPSREST, // makes you heal mp/hp faster when using 'R'
// reduces skillcheck difficulty by v0.
// optional v1 = how many less turns between
// skillchecks. should not go more than
// DEFAULTRESTHEALTIME.
// tech flags
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_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.
F_REFILLWITH, // pour obj id val0 onto this to refill its charges
// //
F_POWDER, // this item is a powder F_POWDER, // this item is a powder
// ob appearance flags // ob appearance flags
@ -2385,8 +2390,9 @@ enum FLAG {
// (for ghosts) // (for ghosts)
F_NOCORPSE, // monster's body crumbles to dust after death F_NOCORPSE, // monster's body crumbles to dust after death
F_NOCTURNAL, // monster sleeps during the day F_NOCTURNAL, // monster sleeps during the day
F_NOSKILL, // lifeform CANNOT ever learn skill v0
F_DIURNAL, // monster sleeps at night F_DIURNAL, // monster sleeps at night
F_NOSLEEP, // monster doesn't sleep
F_NOSKILL, // lifeform CANNOT ever learn skill v0
F_LFSUFFIX, // text = suffix. eg. "skeleton" F_LFSUFFIX, // text = suffix. eg. "skeleton"
F_VISRANGE, // how far you can see (in the light) F_VISRANGE, // how far you can see (in the light)
F_VISRANGEMOD, // modifications to visrange F_VISRANGEMOD, // modifications to visrange
@ -2517,6 +2523,7 @@ enum FLAG {
// if v2 is 'appendyou' " at xxx" will // if v2 is 'appendyou' " at xxx" will
// be appended. // be appended.
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies 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 F_BEHEADED, // use special corpse drop code
F_MOVESPEED, // override default move speed F_MOVESPEED, // override default move speed
F_ACTIONSPEED, // override default action speed F_ACTIONSPEED, // override default action speed
@ -2548,6 +2555,8 @@ enum FLAG {
F_NAME, // text = lf's name F_NAME, // text = lf's name
F_XPMOD, // add/subtract this much from calculated xpval F_XPMOD, // add/subtract this much from calculated xpval
F_BLOODOB, // text = type of object to drop for blood F_BLOODOB, // text = type of object to drop for blood
F_UNSUMMONOB, // text = type of object to drop when this creature
// uis unsummoned.
F_DIESPLATTER, // this lf will splatter objcets of type 'text' F_DIESPLATTER, // this lf will splatter objcets of type 'text'
// when it dies. // when it dies.
// v0 = max distance to splatter (or UNLIMITED) // v0 = max distance to splatter (or UNLIMITED)
@ -2740,7 +2749,6 @@ enum FLAG {
// v0 or lower. // v0 or lower.
F_DODGES, // you dodge missed attacks F_DODGES, // you dodge missed attacks
F_NOTIME, // this lf's actions don't take time F_NOTIME, // this lf's actions don't take time
F_PERCEPTION, // v0 = 0-20. perception level.
// skills // skills
F_HASSKILL, // lf has skill v0 at level v1 F_HASSKILL, // lf has skill v0 at level v1
F_PRACTICINGSKILL, // lf is pract skill v0 F_PRACTICINGSKILL, // lf is pract skill v0
@ -2758,6 +2766,8 @@ enum FLAG {
// we can do it. // we can do it.
F_INTERRUPTED, // somethign interrupted our rest. stop! F_INTERRUPTED, // somethign interrupted our rest. stop!
F_EATING, // lf is eating obid v0 F_EATING, // lf is eating obid v0
F_DIGGING, // v0/v1 = cell where lf is digging.
// v2 is how much to dig per turn.
F_TRAINING, // are we training? cleared on any action other than rest. F_TRAINING, // are we training? cleared on any action other than rest.
// v0 = current training amount // v0 = current training amount
// v1 = training target. // v1 = training target.
@ -3268,6 +3278,7 @@ typedef struct cell_s {
habitat_t *habitat; habitat_t *habitat;
int origlittimer; int origlittimer;
int littimer; int littimer;
int hp;
char *writing; char *writing;
int writinglifetime; int writinglifetime;
@ -3295,6 +3306,7 @@ typedef struct celltype_s {
int solid; // can you walk through it? int solid; // can you walk through it?
int transparent; // can you see through it? int transparent; // can you see through it?
int floorheight; // 0 is default. <0 is low. int floorheight; // 0 is default. <0 is low.
int hp; // hit points left. <0 = invulnerable
struct material_s *material; struct material_s *material;
struct flagpile_s *flags; struct flagpile_s *flags;
@ -3323,6 +3335,7 @@ typedef struct race_s {
struct flagpile_s *flags; struct flagpile_s *flags;
struct bodypart_s bodypart[MAXBODYPARTS]; struct bodypart_s bodypart[MAXBODYPARTS];
int nbodyparts; int nbodyparts;
int known;
// speed modifiers // speed modifiers
// hit dice // hit dice

31
flag.c
View File

@ -72,7 +72,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
} }
// impossible flags // impossible flags
if ((id == F_POISONED) && isimmuneto(fp, DT_POISON)) return NULL; if ((id == F_POISONED) && isimmuneto(fp, DT_POISON, B_FALSE)) return NULL;
if ((id == F_VEGETARIAN) && hasflag(fp, F_CARNIVORE)) return NULL; if ((id == F_VEGETARIAN) && hasflag(fp, F_CARNIVORE)) return NULL;
if ((id == F_PARTVEGETARIAN) && hasflag(fp, F_CARNIVORE)) return NULL; if ((id == F_PARTVEGETARIAN) && hasflag(fp, F_CARNIVORE)) return NULL;
if ((id == F_CARNIVORE) && (hasflag(fp, F_VEGETARIAN) || hasflag(fp, F_PARTVEGETARIAN)) ) return NULL; if ((id == F_CARNIVORE) && (hasflag(fp, F_VEGETARIAN) || hasflag(fp, F_PARTVEGETARIAN)) ) return NULL;
@ -348,6 +348,35 @@ flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) {
return fp; return fp;
} }
int canbemadepermenant(enum FLAG id) {
switch (id) {
case F_BLIND:
case F_BREATHWATER:
case F_CAFFEINATED:
case F_DEAF:
case F_DETECTAURAS:
case F_DETECTOBS:
case F_DETECTMETAL:
case F_DISEASEIMMUNE:
case F_DRUNK:
case F_ENHANCESEARCH:
case F_ENHANCESMELL:
case F_EXTRAINFO:
case F_EXTRALUCK:
case F_FLYING:
case F_PHOTOMEM:
case F_REFLECTION:
case F_SEEINDARK:
case F_SEEINVIS:
case F_STABILITY:
case F_STENCH:
case F_TREMORSENSE:
return B_TRUE;
default: break;
}
return B_FALSE;
}
void changeflagtext(flag_t *f, char *newtext) { void changeflagtext(flag_t *f, char *newtext) {
free(f->text); free(f->text);
if (newtext) { if (newtext) {

1
flag.h
View File

@ -8,6 +8,7 @@ flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@n
flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text, int timeleft); flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text, int timeleft);
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text, int lifetime, int known, long obfromid); flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text, int lifetime, int known, long obfromid);
flagpile_t *addflagpile(lifeform_t *owner, object_t *o); flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
int canbemadepermenant(enum FLAG id);
void changeflagtext(flag_t *f, char *newtext); void changeflagtext(flag_t *f, char *newtext);
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id); void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);

444
io.c
View File

@ -64,6 +64,7 @@ extern int nretobs;
extern FILE *logfile; extern FILE *logfile;
extern enum OBCLASS sortorder[]; extern enum OBCLASS sortorder[];
extern objectclass_t *objectclass;
extern knowledge_t *knowledge; extern knowledge_t *knowledge;
extern objecttype_t *objecttype; extern objecttype_t *objecttype;
extern command_t *firstcommand; extern command_t *firstcommand;
@ -3416,6 +3417,7 @@ void describeob(object_t *o) {
void describerace(enum RACE rid) { void describerace(enum RACE rid) {
char buf[BUFLEN]; char buf[BUFLEN];
char *buf2; char *buf2;
int x,y;
race_t *r; race_t *r;
cls(); cls();
r = findrace(rid); r = findrace(rid);
@ -3430,8 +3432,10 @@ void describerace(enum RACE rid) {
wmove(mainwin, 2, 0); wmove(mainwin, 2, 0);
buf2 = malloc(HUGEBUFLEN * sizeof(char)); buf2 = malloc(HUGEBUFLEN * sizeof(char));
makedesc_race(rid, buf2, B_FALSE); makedesc_race(rid, buf2, B_TRUE);
textwithcol(mainwin, buf2); //textwithcol(mainwin, buf2);
getyx(mainwin,y,x);
wrapprint(mainwin, &y, &x, "%s", buf2);
free(buf2); free(buf2);
wrefresh(mainwin); wrefresh(mainwin);
@ -4554,6 +4558,8 @@ char *makedesc_ob(object_t *o, char *retbuf) {
} }
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, "\n", HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, "\n", HUGEBUFLEN);
}
f = hasflag(o->flags, F_THROWMISSILE); f = hasflag(o->flags, F_THROWMISSILE);
if (f) { if (f) {
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) { if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) {
@ -4565,7 +4571,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
} }
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, "\n", HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, "\n", HUGEBUFLEN);
} }
}
if ((f = hasflag(o->flags, F_IMPASSABLE)) != NULL) { if ((f = hasflag(o->flags, F_IMPASSABLE)) != NULL) {
if ((f->val[0] == SZ_MIN) && (f->val[1] == SZ_MAX)) { if ((f->val[0] == SZ_MIN) && (f->val[1] == SZ_MAX)) {
@ -4596,7 +4601,8 @@ char *makedesc_ob(object_t *o, char *retbuf) {
} }
} }
// unknown items?
if (isknown(o)) {
// weapons? // weapons?
if (isfirearm(o)) { if (isfirearm(o)) {
flag_t *ff, *ff2; flag_t *ff, *ff2;
@ -5036,6 +5042,16 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, "It can be used to assist in climbing.\n"); sprintf(buf, "It can be used to assist in climbing.\n");
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
} }
f = hasflag(o->flags, F_HELPSDISARM);
if (f) {
sprintf(buf, "It gives a +%d%% bonus when disarming traps.\n", f->val[0] * 5);
strncat(retbuf, buf, HUGEBUFLEN);
}
f = hasflag(o->flags, F_HELPSREST);
if (f) {
sprintf(buf, "It provides a %d%% bonus to health regeneration when resting.", f->val[0] * 5);
strncat(retbuf, buf, HUGEBUFLEN);
}
// skip line // skip line
@ -5054,7 +5070,7 @@ char *makedesc_ob(object_t *o, char *retbuf) {
int first = B_TRUE; int first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) { for (i = 0; i < MAXDAMTYPE; i++) {
if (basedamagetype(i) != i) continue; if (basedamagetype(i) != i) continue;
f = isimmuneto(o->flags, i); f = isimmuneto(o->flags, i, B_FALSE);
if (f) { if (f) {
char buf2[BUFLEN]; char buf2[BUFLEN];
if (first) { if (first) {
@ -5081,7 +5097,7 @@ char *makedesc_ob(object_t *o, char *retbuf) {
int first = B_TRUE; int first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) { for (i = 0; i < MAXDAMTYPE; i++) {
if (basedamagetype(i) != i) continue; if (basedamagetype(i) != i) continue;
f = isresistantto(o->flags, i); f = isresistantto(o->flags, i, B_FALSE);
if (f) { if (f) {
char buf2[BUFLEN]; char buf2[BUFLEN];
if (first) { if (first) {
@ -5108,7 +5124,7 @@ char *makedesc_ob(object_t *o, char *retbuf) {
int first = B_TRUE; int first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) { for (i = 0; i < MAXDAMTYPE; i++) {
if (basedamagetype(i) != i) continue; if (basedamagetype(i) != i) continue;
f = isvulnto(o->flags, i); f = isvulnto(o->flags, i, B_FALSE);
if (f) { if (f) {
char buf2[BUFLEN]; char buf2[BUFLEN];
if (first) { if (first) {
@ -5126,7 +5142,10 @@ char *makedesc_ob(object_t *o, char *retbuf) {
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
} }
} }
} // end if isknown
// skip line
strncat(retbuf, "\n", HUGEBUFLEN);
for (f = o->flags->first ; f ; f = f->next) { for (f = o->flags->first ; f ; f = f->next) {
if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) { if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
@ -5136,9 +5155,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
} }
// skip line
strncat(retbuf, "\n", HUGEBUFLEN);
// physical properties // physical properties
f = hasflag(o->flags, F_ONFIRE); f = hasflag(o->flags, F_ONFIRE);
if (f) { if (f) {
@ -5155,7 +5171,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, "It is rusty.\n"); sprintf(buf, "It is rusty.\n");
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
} }
f = hasflag(o->flags, F_WATERPROOF); f = hasflag(o->flags, F_WATERPROOF);
if (f) { if (f) {
sprintf(buf, "It is waterproof.\n"); sprintf(buf, "It is waterproof.\n");
@ -5173,13 +5188,12 @@ char *makedesc_ob(object_t *o, char *retbuf) {
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
} }
// other weapon properties...
f = hasflag(o->flags, F_NEEDSSPACE); f = hasflag(o->flags, F_NEEDSSPACE);
if (f) { if (f && f->known) {
sprintf(buf, "It is ineffective in confined spaces due to its length.\n"); sprintf(buf, "It is ineffective in confined spaces due to its length.\n");
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
} }
// show special properties where known
f = hasflag(o->flags, F_ARMOURPIERCE); f = hasflag(o->flags, F_ARMOURPIERCE);
if (f && f->known) { if (f && f->known) {
sprintf(buf, "Armour will not reduce %s damage.\n",(o->amt == 1) ? "its" : "their"); sprintf(buf, "Armour will not reduce %s damage.\n",(o->amt == 1) ? "its" : "their");
@ -5679,29 +5693,66 @@ char *makedesc_ob(object_t *o, char *retbuf) {
return retbuf; return retbuf;
} }
char *makedesc_race(enum RACE rid, char *retbuf, int showbonpen) { char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
race_t *r; race_t *r;
char buf[HUGEBUFLEN]; char buf[HUGEBUFLEN];
flag_t *retflag[MAXCANDIDATES],*f; flag_t *retflag[MAXCANDIDATES],*f;
int nretflags,i; int nretflags,i;
flagpile_t *doneflags;
doneflags = addflagpile(NULL, NULL);
strcpy(retbuf, ""); strcpy(retbuf, "");
r = findrace(rid); r = findrace(rid);
if (showextra) {
int a;
int curidx,donesomething;
char bonheading[BUFLEN],penheading[BUFLEN];
sprintf(bonheading, "^%dStrengths^n:\n", C_WHITE);
sprintf(penheading, "^%dWeaknesses^n:\n", C_WHITE);
// stats
snprintf(buf, HUGEBUFLEN, "HD: %-3d ", gethitdicerace(r));
strncat(retbuf, buf, HUGEBUFLEN);
for (a = 0; a < MAXATTS; a++) {
char ch[BUFLENTINY];
int col;
f = hasflagval(r->flags, F_STARTATT, a, NA, NA, NULL);
if (f) {
switch (f->val[1]) {
case AT_RANDOM: sprintf(ch, "?"); col = C_GREY; break;
case AT_EXLOW: sprintf(ch, "%-4s", "xxxx"); col = C_MAGENTA; break;
case AT_VLOW: sprintf(ch, "%-4s", "xxx"); col = C_RED; break;
case AT_LOW: sprintf(ch, "%-4s", "xx"); col = C_RED; break;
case AT_LTAVERAGE: sprintf(ch, "%-4s", "x"); col = C_RED; break;
case AT_AVERAGE: sprintf(ch, "%-4s", "-"); col = C_GREY; break;
case AT_GTAVERAGE: sprintf(ch, "%-4s", "+"); col = C_GREEN; break;
case AT_HIGH: sprintf(ch, "%-4s", "++"); col = C_GREEN; break;
case AT_VHIGH: sprintf(ch, "%-4s", "+++"); col = C_GREEN; break;
case AT_EXHIGH: sprintf(ch, "%-4s", "++++"); col = C_BOLDBLUE; break;
}
} else {
sprintf(ch, "%-4s", "?");
col = C_GREY;
}
sprintf(buf, "^n%s:^%d%s ^n", getattrabbrev(a), col, ch);
strncat(retbuf, buf, HUGEBUFLEN);
}
strncat(retbuf, "\n\n", HUGEBUFLEN);
snprintf(buf, HUGEBUFLEN, "%s\n\n", r->desc); snprintf(buf, HUGEBUFLEN, "%s\n\n", r->desc);
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
if (showbonpen) { //////////////////////////////////////////////
int curidx,donesomething;
// bonuses // bonuses
//////////////////////////////////////////////
strncat(retbuf, bonheading, HUGEBUFLEN);
// manually specified bonuses
getflags(r->flags, retflag, &nretflags, F_BONDESC, F_NONE); getflags(r->flags, retflag, &nretflags, F_BONDESC, F_NONE);
if (nretflags) {
snprintf(buf, HUGEBUFLEN, "^%dBonuses^n:\n", C_WHITE);
strncat(retbuf, buf, HUGEBUFLEN);
donesomething = B_TRUE;
curidx = 0; curidx = 0;
if (nretflags) {
donesomething = B_TRUE;
while (donesomething) { while (donesomething) {
donesomething = B_FALSE; donesomething = B_FALSE;
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
@ -5715,17 +5766,153 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showbonpen) {
} }
} }
} }
} else {
snprintf(buf, HUGEBUFLEN, "^%dBonuses^n:\n@None.\n", C_WHITE);
strncat(retbuf, buf, HUGEBUFLEN);
} }
// auto bonuses from flags
for (f = r->flags->first ; f ; f = f->next) {
char *p;
objecttype_t *ot;
int power;
strcpy(buf, "");
switch (f->id) {
case F_AUTOCREATEOB:
p = makeplural(f->text);
sprintf(buf, "Automatically creates %s around itself.", p);
free(p);
break;
case F_AQUATIC: strcpy(buf, "Moves normally through water"); break;
case F_AWARENESS: strcpy(buf, "Can see in all directions."); break;
case F_CANEATRAW: strcpy(buf, "Can safely digest raw meat."); break;
case F_CANWILL:
ot = findot(f->val[0]);
sprintf(buf, "%s: %s", (ot->obclass->id == OC_ABILITY) ? "Ability" : "Spell",
ot->name);
texttospellopts(f->text, "pw:", &power, NULL);
if (power) {
strcat(buf, " (power ");
strcat(buf, roman(power));
strcat(buf, ")");
}
break;
case F_DODGES: strcpy(buf, "Can dodge attacks into adjacent locations"); break;
case F_DTIMMUNE:
if (!hasflag(doneflags, F_DTIMMUNE)) {
if (f->val[0] == DT_ALL) {
sprintf(buf, "Immune to %s.", getdamname(DT_ALL));
} else {
char buf2[BUFLEN];
int first = B_TRUE,n;
strcpy(buf, "");
for (n = 0; n < MAXDAMTYPE; n++) {
if (basedamagetype(n) != n) continue;
if (isimmuneto(r->flags, n, B_FALSE)) {
if (first) {
sprintf(buf2, "Immune to: %s", getdamname(n));
first = B_FALSE;
} else {
sprintf(buf2, ", %s", getdamname(n));
}
strcat(buf, buf2);
}
}
}
addflag(doneflags, F_DTIMMUNE, B_TRUE, NA, NA, NULL);
}
break;
case F_DTRESIST:
if (!hasflag(doneflags, F_DTRESIST)) {
if (f->val[0] == DT_ALL) {
sprintf(buf, "Resistant to %s.", getdamname(DT_ALL));
} else {
char buf2[BUFLEN];
int first = B_TRUE,n;
strcpy(buf, "");
for (n = 0; n < MAXDAMTYPE; n++) {
if (basedamagetype(n) != n) continue;
if (isimmuneto(r->flags, n, B_FALSE)) {
if (first) {
sprintf(buf2, "Resistant to: %s", getdamname(n));
first = B_FALSE;
} else {
sprintf(buf2, ", %s", getdamname(n));
}
strcat(buf, buf2);
}
}
}
addflag(doneflags, F_DTRESIST, B_TRUE, NA, NA, NULL);
}
break;
case F_DTVULN:
if (!hasflag(doneflags, F_DTVULN)) {
if (f->val[0] == DT_ALL) {
sprintf(buf, "Vulnerable to %s.", getdamname(DT_ALL));
} else {
char buf2[BUFLEN];
int first = B_TRUE,n;
strcpy(buf, "");
for (n = 0; n < MAXDAMTYPE; n++) {
if (basedamagetype(n) != n) continue;
if (isimmuneto(r->flags, n, B_FALSE)) {
if (first) {
sprintf(buf2, "Vulnerable to: %s", getdamname(n));
first = B_FALSE;
} else {
sprintf(buf2, ", %s", getdamname(n));
}
strcat(buf, buf2);
}
}
}
addflag(doneflags, F_DTVULN, B_TRUE, NA, NA, NULL);
}
break;
case F_ENHANCESMELL: sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break;
case F_FLYING: sprintf(buf, "Can fly at will"); break;
case F_HEAVYBLOW: sprintf(buf, "Attacks will knock enemies backwards"); break;
case F_HUMANOID: sprintf(buf, "Can use weapons and armour."); break;
case F_LEVITATING: sprintf(buf, "Can levitate at will"); break;
case F_MEDITATES: sprintf(buf, "Meditates to retain awareness while sleeping."); break;
case F_MPMOD: if (f->val[0] > 0) sprintf(buf, "+%d Mana", f->val[0]); break;
case F_NOSLEEP: sprintf(buf, "Does not sleep"); break;
case F_PACKATTACK: sprintf(buf, "Deals extra damage when in a pack."); break;
case F_PHALANX: sprintf(buf, "Gains extra defence when in a pack."); break;
case F_PHOTOMEM: sprintf(buf, "Photographic memory"); break;
case F_QUICKBITE: sprintf(buf, "Can bite wounded enemies for extra damage"); break;
case F_REGENERATES: sprintf(buf, "Automatically regenerates health."); break;
case F_RESISTMAG: sprintf(buf, "Magic-resistant"); break;
case F_SEEINDARK: sprintf(buf, "Darkvision (range %d)", f->val[0]); break;
case F_SEEINVIS: sprintf(buf, "Can see invisible things"); break;
case F_SILENTMOVE: sprintf(buf, "Moves silently"); break;
case F_STABILITY: sprintf(buf, "Will not fall on slippery ground."); break;
case F_STARTSKILL: sprintf(buf, "%s %s", getskillname(f->val[0]), getskilllevelname(f->val[1])); break;
case F_STENCH: sprintf(buf, "Emits a foul odour which affects others"); break;
case F_TREMORSENSE: sprintf(buf, "Can sense vibrations (range %d)", f->val[0]); break;
case F_VISRANGEMOD: if (f->val[0] > 0) sprintf(buf, "Enhanced vision range (+%d)", f->val[0]); break;
default:
break;
}
if (strlen(buf)) {
strncat(retbuf, "@- ", HUGEBUFLEN);
strcat(buf, "\n");
strncat(retbuf, buf, HUGEBUFLEN);
curidx++;
}
}
if (curidx == 0) {
strncat(retbuf, "^n@None.\n", HUGEBUFLEN);
}
//////////////////////////////////////////////
// penalties
//////////////////////////////////////////////
strncat(retbuf, penheading, HUGEBUFLEN);
// manually specified penalties
curidx = 0;
getflags(r->flags, retflag, &nretflags, F_PENDESC, F_NONE); getflags(r->flags, retflag, &nretflags, F_PENDESC, F_NONE);
if (nretflags) { if (nretflags) {
snprintf(buf, HUGEBUFLEN, "^%dPenalties^n:\n", C_WHITE);
strncat(retbuf, buf, HUGEBUFLEN);
donesomething = B_TRUE; donesomething = B_TRUE;
curidx = 0;
while (donesomething) { while (donesomething) {
donesomething = B_FALSE; donesomething = B_FALSE;
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
@ -5739,15 +5926,57 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showbonpen) {
} }
} }
} }
} else { }
snprintf(buf, HUGEBUFLEN, "^%dPenalties^n:\n@None.\n", C_WHITE);
// auto penalties from flags
for (f = r->flags->first ; f ; f = f->next) {
material_t *mt;
strcpy(buf, "");
switch (f->id) {
case F_CARNIVORE: sprintf(buf, "Will only eat meat."); break;
case F_DEAF: sprintf(buf, "Deaf"); break;
case F_DIURNAL: sprintf(buf, "Sleeps at night."); break;
case F_FASTMETAB: sprintf(buf, "Fast metabolism (needs to eat often)"); break;
case F_MATVULN:
mt = findmaterial(f->val[0]);
sprintf(buf, "Takes %d%% damage from weapons made of %s.", retflag[i]->val[1], mt->name);
break;
case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "-%d Mana", f->val[0]); break;
case F_NEEDSWATER: sprintf(buf, "Will suffocate without water"); break;
case F_NOCTURNAL: sprintf(buf, "Sleeps during the day."); break;
case F_NOPACK: sprintf(buf, "Cannot carry objects."); break;
case F_SIZE:
if (hasflag(r->flags, F_HUMANOID) && (f->val[0] != SZ_HUMAN)) {
sprintf(buf, "Only specially sized armour will fit.");
}
break;
case F_STAYINROOM:
sprintf(buf, "Will not leave its home territory."); break;
break;
case F_TAMABLE:
sprintf(buf, "Susceptible to bribery."); break;
break;
case F_VEGETARIAN: sprintf(buf, "Will not eat meat."); break;
case F_VISRANGEMOD: if (f->val[0] < 0) sprintf(buf, "Reduced vision range (%d)", f->val[0]); break;
case F_PARTVEGETARIAN: sprintf(buf, "Will only eat meat when hungry."); break;
default:
break;
}
if (strlen(buf)) {
strncat(retbuf, "@- ", HUGEBUFLEN);
strcat(buf, "\n");
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
} curidx++;
while (donesomething) {
donesomething = B_FALSE;
} }
} }
if (curidx == 0) {
strncat(retbuf, "^n@None.\n", HUGEBUFLEN);
}
}
free(doneflags);
return retbuf; return retbuf;
} }
@ -6475,8 +6704,10 @@ void dohelp(char helpmode) {
initprompt(&prompt, "Describe which race (ESC when done)?"); initprompt(&prompt, "Describe which race (ESC when done)?");
for (r = firstrace ; r ; r = r->next) { for (r = firstrace ; r ; r = r->next) {
if (r->known) {
addchoice(&prompt, 'a', r->name, NULL, r, r->desc); addchoice(&prompt, 'a', r->name, NULL, r, r->desc);
} }
}
addchoice(&prompt, '\0', "(done)", NULL, NULL, NULL); addchoice(&prompt, '\0', "(done)", NULL, NULL, NULL);
prompt.maycancel = B_TRUE; prompt.maycancel = B_TRUE;
ch = getchoicestr(&prompt, B_FALSE, B_TRUE); ch = getchoicestr(&prompt, B_FALSE, B_TRUE);
@ -6484,7 +6715,7 @@ void dohelp(char helpmode) {
done = B_TRUE; done = B_TRUE;
} else { } else {
r = (race_t *)prompt.result; r = (race_t *)prompt.result;
describerace(r->id); if (r) describerace(r->id);
} }
} else if (helpmode == 's') { } else if (helpmode == 's') {
skill_t *sk; skill_t *sk;
@ -6502,7 +6733,8 @@ void dohelp(char helpmode) {
done = B_TRUE; done = B_TRUE;
} else { } else {
sk = (skill_t *)prompt.result; sk = (skill_t *)prompt.result;
describeskill(sk->id, PR_INEPT); if (sk) describeskill(sk->id, PR_INEPT);
else done = B_TRUE;
} }
} else if (helpmode == 'g') { } else if (helpmode == 'g') {
lifeform_t *god; lifeform_t *god;
@ -7262,6 +7494,21 @@ int drop(object_t *o, int count) {
return B_FALSE; return B_FALSE;
} }
void dumpoc(void) {
enum RARITY rr;
objectclass_t *oc;
dblog("BEGIN OBJECTCLASS DUMP");
for (rr = RR_FREQUENT; rr <= RR_VERYRARE; rr++ ){
dblog(" %s", getrarityname(rr));
for (oc = objectclass ; oc ; oc = oc->next) {
if (oc->rarity == rr) {
dblog(" %s", oc->name);
}
}
}
dblog("END OBJECTCLASS DUMP");
}
void dumpspells(void) { void dumpspells(void) {
objecttype_t *ot; objecttype_t *ot;
enum SPELLSCHOOL ss; enum SPELLSCHOOL ss;
@ -10302,8 +10549,6 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
// show racial effects // show racial effects
if (hasjob(lf, J_PIRATE)) { if (hasjob(lf, J_PIRATE)) {
mvwprintw(mainwin, y, 0, "%s can hold %s liquor well.", you(lf), isplayer(lf) ? "Your" : "its"); mvwprintw(mainwin, y, 0, "%s can hold %s liquor well.", you(lf), isplayer(lf) ? "Your" : "its");
@ -10327,25 +10572,18 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
} }
// traits based on the monster's racial characteristics
// these are fairly common knowledge - ie if you ask around most // we DONT show traits based on the monster's racial characteristics
// people would know this. // here. leave that to makedesc_race.
//
// This display is only for effects specific to this INDIVIDUAL lifeform.
if (showall || (lorelev >= PR_NOVICE)) { if (showall || (lorelev >= PR_NOVICE)) {
if (lfhasflag(lf, F_AQUATIC)) {
mvwprintw(mainwin, y, 0, "%s %s aquatic, and move normally through water.", you(lf), is(lf));
y++;
}
if (isdeaf(lf)) { if (isdeaf(lf)) {
mvwprintw(mainwin, y, 0, "%s %s deaf.", you(lf), is(lf)); mvwprintw(mainwin, y, 0, "%s %s deaf.", you(lf), is(lf));
y++; y++;
} }
f = lfhasknownflag(lf, F_NOPACK);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s cannot carry objects.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_ENHANCESMELL); f = lfhasknownflag(lf, F_ENHANCESMELL);
if (f) { if (f && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s %s an enhanced sense of smell.", you(lf), isplayer(lf) ? "have" : "has"); mvwprintw(mainwin, y, 0, "%s %s an enhanced sense of smell.", you(lf), isplayer(lf) ? "have" : "has");
y++; y++;
} }
@ -10355,43 +10593,12 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
f = lfhasknownflag(lf, F_PACKATTACK);
if (f && (f->known)) {
snprintf(buf, BUFLEN,"%s deal%s extra damage when in a pack.", you(lf), isplayer(lf) ? "" : "s");
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_PHALANX);
if (f && (f->known)) {
snprintf(buf, BUFLEN,"%s gain%s %d extra armour rating when in a %s pack.", you(lf), isplayer(lf) ? "" : "s",
f->val[0], f->text);
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasknownflag(lf, F_HEAVYBLOW); f = lfhasknownflag(lf, F_HEAVYBLOW);
if (f) { if (f && (f->lifetime != FROMRACE)) {
snprintf(buf, BUFLEN,"%s%s attacks knock enemies back.", you(lf), getpossessive(you(lf))); snprintf(buf, BUFLEN,"%s%s attacks knock enemies back.", you(lf), getpossessive(you(lf)));
mvwprintw(mainwin, y, 0, buf); mvwprintw(mainwin, y, 0, buf);
y++; y++;
} }
f = lfhasknownflag(lf, F_QUICKBITE);
if (f && (f->known)) {
snprintf(buf, BUFLEN,"%s can bite wounded enemies for extra damage.", you(lf));
mvwprintw(mainwin, y, 0, buf);
y++;
}
f = lfhasflag(lf, F_MEDITATES);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s retain awareness via 'sleeping' through meditation.", you(lf));
y++;
}
f = lfhasflag(lf, F_NEEDSWATER);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s will suffocate without water.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_REGENERATES); f = lfhasknownflag(lf, F_REGENERATES);
if (f) { if (f) {
char regenspeed[BUFLEN]; char regenspeed[BUFLEN];
@ -10427,27 +10634,27 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
f = lfhasknownflag(lf, F_TREMORSENSE); f = lfhasknownflag(lf, F_TREMORSENSE);
if (f) { if (f && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s can 'see' by sensing vibrations around %s.", you(lf), you(lf)); mvwprintw(mainwin, y, 0, "%s can 'see' by sensing vibrations around %s.", you(lf), you(lf));
y++; y++;
} }
f = lfhasflag(lf, F_STENCH); f = lfhasflag(lf, F_STENCH);
if (f && (f->known)) { if (f && (f->known) && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s smell%s terrible.", you(lf), isplayer(lf) ? "" : "s"); mvwprintw(mainwin, y, 0, "%s smell%s terrible.", you(lf), isplayer(lf) ? "" : "s");
y++; y++;
} }
f = lfhasknownflag(lf, F_SEEINDARK); f = lfhasknownflag(lf, F_SEEINDARK);
if (f) { if (f && (f->known) && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s can see in the dark.", you(lf)); mvwprintw(mainwin, y, 0, "%s can see in the dark.", you(lf));
y++; y++;
} }
f = lfhasknownflag(lf, F_SEEINVIS); f = lfhasknownflag(lf, F_SEEINVIS);
if (f) { if (f && (f->known) && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s can see invisible things.", you(lf)); mvwprintw(mainwin, y, 0, "%s can see invisible things.", you(lf));
y++; y++;
} }
f = lfhasknownflag(lf, F_XRAYVIS); f = lfhasknownflag(lf, F_XRAYVIS);
if (f) { if (f && (f->known) && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s can see through walls.", you(lf)); mvwprintw(mainwin, y, 0, "%s can see through walls.", you(lf));
y++; y++;
} }
@ -10462,17 +10669,6 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
} }
// material vulnerbilities
getflags(lf->flags, retflag, &nretflags, F_MATVULN, F_NONE);
for (i = 0; i < nretflags; i++) {
material_t *mt;
mt = findmaterial(retflag[i]->val[0]);
sprintf(buf, "%s take%s %d%% damage from weapons made of %s.", you(lf),
isplayer(lf) ? "" : "s", retflag[i]->val[1], mt->name);
mvwprintw(mainwin, y, 0, "%s", buf); y++;
}
} }
// traits based on the monster's bevaviour. // traits based on the monster's bevaviour.
@ -10482,12 +10678,6 @@ void showlfstats(lifeform_t *lf, int showall) {
if (!isplayer(lf)) { if (!isplayer(lf)) {
int morale; int morale;
char moralebuf[BUFLEN]; char moralebuf[BUFLEN];
if (lfhasflag(lf, F_NOCTURNAL)) {
mvwprintw(mainwin, y, 0, "It normally sleeps during the day."); y++;
}
if (lfhasflag(lf, F_DIURNAL)) {
mvwprintw(mainwin, y, 0, "It normally sleeps during the night."); y++;
}
morale = getmorale(lf); morale = getmorale(lf);
if (morale >= 30) { if (morale >= 30) {
strcpy(moralebuf, "fearless"); strcpy(moralebuf, "fearless");
@ -10505,21 +10695,6 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "It looks %s.", moralebuf); y++; mvwprintw(mainwin, y, 0, "It looks %s.", moralebuf); y++;
} }
// eating habits
if (lfhasflag(lf, F_CARNIVORE)) {
mvwprintw(mainwin, y, 0, "%s %s a carnivore (only eats meat).", you(lf), is(lf));
y++;
} else if (lfhasflag(lf, F_PARTVEGETARIAN)) {
mvwprintw(mainwin, y, 0, "%s %s a vegetarian (will only eat meat when hungry).", you(lf), is(lf));
y++;
} else if (lfhasflag(lf, F_VEGETARIAN)) {
mvwprintw(mainwin, y, 0, "%s %s a vegetarian (will not eat meat).", you(lf), is(lf));
y++;
}
if (lfhasflag(lf, F_CANEATRAW)) {
mvwprintw(mainwin, y, 0, "%s can digest raw meat.", you(lf));
y++;
}
// damage desistances/vulnerabilities // damage desistances/vulnerabilities
// resistances // resistances
@ -10531,7 +10706,7 @@ void showlfstats(lifeform_t *lf, int showall) {
first = B_TRUE; first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) { for (i = 0; i < MAXDAMTYPE; i++) {
if (basedamagetype(i) != i) continue; if (basedamagetype(i) != i) continue;
f = isresistantto(lf->flags, i); f = isresistantto(lf->flags, i, B_TRUE);
if (f) { if (f) {
if (first) { if (first) {
snprintf(buf2, BUFLEN, "%s %s resistant to: %s", you(lf), is(lf),getdamnamenoun(i)); snprintf(buf2, BUFLEN, "%s %s resistant to: %s", you(lf), is(lf),getdamnamenoun(i));
@ -10565,7 +10740,7 @@ void showlfstats(lifeform_t *lf, int showall) {
first = B_TRUE; first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) { for (i = 0; i < MAXDAMTYPE; i++) {
if (basedamagetype(i) != i) continue; if (basedamagetype(i) != i) continue;
f = isimmuneto(lf->flags, i); f = isimmuneto(lf->flags, i, B_TRUE);
if (f) { if (f) {
if (first) { if (first) {
snprintf(buf2, BUFLEN, "%s %s immune to: %s", you(lf), is(lf), getdamname(i)); snprintf(buf2, BUFLEN, "%s %s immune to: %s", you(lf), is(lf), getdamname(i));
@ -10591,7 +10766,7 @@ void showlfstats(lifeform_t *lf, int showall) {
first = B_TRUE; first = B_TRUE;
for (i = 0; i < MAXDAMTYPE; i++) { for (i = 0; i < MAXDAMTYPE; i++) {
if (basedamagetype(i) != i) continue; if (basedamagetype(i) != i) continue;
f = isvulnto(lf->flags, i); f = isvulnto(lf->flags, i, B_TRUE);
if (f) { if (f) {
if (first) { if (first) {
snprintf(buf2, BUFLEN, "%s %s vulnerable to: %s", you(lf), is(lf), getdamnamenoun(i)); snprintf(buf2, BUFLEN, "%s %s vulnerable to: %s", you(lf), is(lf), getdamnamenoun(i));
@ -10651,19 +10826,6 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
} }
// other
f = lfhasflag(lf, F_SILENTMOVE);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s move%s silently.", you(lf), isplayer(lf) ? "" : "s");
y++;
}
f = lfhasflag(lf, F_STABILITY);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s will not fall on slippery ground.", you(lf));
y++;
}
} }
// show intrinsics // show intrinsics
@ -10682,7 +10844,8 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s identity is obscured.", your(lf)); mvwprintw(mainwin, y, 0, "%s identity is obscured.", your(lf));
y++; y++;
} }
if (lfhasknownflag(lf, F_AWARENESS)) { f = lfhasknownflag(lf, F_AWARENESS);
if (f && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s can see things which are behind %s.", you(lf), you(lf)); mvwprintw(mainwin, y, 0, "%s can see things which are behind %s.", you(lf), you(lf));
y++; y++;
} }
@ -10908,11 +11071,6 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "Gravity is lessened around %s, preventing fall damage and increasing flight speed.", you_l(lf)); mvwprintw(mainwin, y, 0, "Gravity is lessened around %s, preventing fall damage and increasing flight speed.", you_l(lf));
y++; y++;
} }
f = lfhasknownflag(lf, F_DODGES);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s can dodge attacks.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_INVULNERABLE); f = lfhasknownflag(lf, F_INVULNERABLE);
if (f && (f->known)) { if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s protected from all physical harm.", you(lf), is(lf)); mvwprintw(mainwin, y, 0, "%s %s protected from all physical harm.", you(lf), is(lf));
@ -10939,7 +11097,7 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
f = lfhasflag(lf, F_PHOTOMEM); f = lfhasflag(lf, F_PHOTOMEM);
if (f && (f->known)) { if (f && (f->known) && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s do not forget your surroundings.", you(lf)); mvwprintw(mainwin, y, 0, "%s do not forget your surroundings.", you(lf));
y++; y++;
} }
@ -10971,7 +11129,7 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
f = lfhasflag(lf, F_STENCH); f = lfhasflag(lf, F_STENCH);
if (f && (f->known)) { if (f && (f->known) && (f->lifetime != FROMRACE)) {
mvwprintw(mainwin, y, 0, "%s %s emitting a foul stench, nauseating those nearby.", you(lf), is(lf)); mvwprintw(mainwin, y, 0, "%s %s emitting a foul stench, nauseating those nearby.", you(lf), is(lf));
y++; y++;
} }

3
io.h
View File

@ -82,6 +82,7 @@ void drawmsg(void);
void drawscreen(void); void drawscreen(void);
void drawstatus(void); void drawstatus(void);
int drop(object_t *o, int count); int drop(object_t *o, int count);
void dumpoc(void);
void dumpspells(void); void dumpspells(void);
void dumpweps(void); void dumpweps(void);
void forceredraw(void); void forceredraw(void);
@ -100,7 +101,7 @@ int keycodetokey(int keycode, int escseqok);
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints); void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints);
char *makedesc_god(lifeform_t *god, char *retbuf); char *makedesc_god(lifeform_t *god, char *retbuf);
char *makedesc_ob(object_t *o, char *retbuf); char *makedesc_ob(object_t *o, char *retbuf);
char *makedesc_race(enum RACE rid, char *retbuf, int showbonpen); char *makedesc_race(enum RACE rid, char *retbuf, int showextra);
char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite); char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite);
char *makedesc_spell(objecttype_t *ot, char *retbuf); char *makedesc_spell(objecttype_t *ot, char *retbuf);
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard,int mpcutoff); void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard,int mpcutoff);

238
lf.c
View File

@ -1130,11 +1130,7 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) {
} }
int cansleep(lifeform_t *lf) { int cansleep(lifeform_t *lf) {
enum RACECLASS rc; if (lfhasflag(lf, F_NOSLEEP)) {
rc = getraceclass(lf);
if (rc == RC_PLANT) {
return B_FALSE;
} else if (rc == RC_UNDEAD) {
return B_FALSE; return B_FALSE;
} }
return B_TRUE; return B_TRUE;
@ -1406,12 +1402,19 @@ int cantalk(lifeform_t *lf) {
case RC_DRAGON: case RC_DRAGON:
case RC_GOD: case RC_GOD:
case RC_HUMANOID: case RC_HUMANOID:
return B_TRUE; // these ones can talk
break;
default: default:
return B_FALSE;
break; break;
} }
// too dumb?
if (getattr(lf, A_IQ) <= AT_VLOW) {
return B_FALSE; return B_FALSE;
} }
return B_TRUE;
}
int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell, object_t *fromob, int *seen) { int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell, object_t *fromob, int *seen) {
int rv; int rv;
@ -1909,7 +1912,7 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
} }
if (!isdead(lf)) { if (!isdead(lf)) {
f = isvulnto(lf->flags, DT_WATER); f = isvulnto(lf->flags, DT_WATER, B_FALSE);
if (f) { if (f) {
int dam; int dam;
if (strlen(f->text)) { if (strlen(f->text)) {
@ -1979,6 +1982,61 @@ int confuse(lifeform_t *lf, int howlong) {
return B_FALSE; return B_FALSE;
} }
int continuedigging(lifeform_t *lf) {
cell_t *c;
flag_t *f = NULL;
int digpower;
int stopnow = B_FALSE;
if (!hasfreeaction(lf)) {
stopnow = B_TRUE;
}
f = hasflag(lf->flags, F_DIGGING);
if (!f) {
stopnow = B_TRUE;
}
if (!stopnow) {
c = getcellat(lf->cell->map, f->val[0], f->val[1]);
if (!c) {
stopnow = B_TRUE;
}
}
if (stopnow) {
if (f) killflag(f);
return B_TRUE;
}
digpower = f->val[2];
c->hp -= digpower;
if (c->hp <= 0) {
if (isplayer(lf)) {
msg("You finish digging through %s %s.",needan(c->type->name) ? "an" : "a", c->type->name);
needredraw = B_TRUE;
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s finishes digging through %s %s.",lfname,needan(c->type->name) ? "an" : "a", c->type->name);
needredraw = B_TRUE;
}
// replace wall
setcelltype(c, c->map->habitat->emptycelltype);
// stop digging
killflag(f);
} else {
if (isplayer(lf)) {
msg("You dig into %s %s.",needan(c->type->name) ? "an" : "a", c->type->name);
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s digs into %s %s.",lfname,needan(c->type->name) ? "an" : "a", c->type->name);
}
}
return B_FALSE;
}
int countinnateattacks(lifeform_t *lf) { int countinnateattacks(lifeform_t *lf) {
int count = 0,i; int count = 0,i;
flag_t *f; flag_t *f;
@ -2277,8 +2335,8 @@ void die(lifeform_t *lf) {
} }
} }
} else { } else {
// intelligent monsters will say something // intelligent monsters will say something
if (!hasflag(lf->flags, F_NODEATHSPEECH)) {
if (ispetof(lf, player)) { if (ispetof(lf, player)) {
if (cantalk(lf) && canhear(player, lf->cell, 4)) { if (cantalk(lf) && canhear(player, lf->cell, 4)) {
sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL); sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL);
@ -2293,6 +2351,7 @@ void die(lifeform_t *lf) {
sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL); sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL);
} }
} }
}
if (!hasflag(lf->flags, F_NODEATHANNOUNCE)) { if (!hasflag(lf->flags, F_NODEATHANNOUNCE)) {
if (cansee(player, lf)) { if (cansee(player, lf)) {
@ -2612,27 +2671,31 @@ void dumpxp(void) {
int digcell(lifeform_t *lf, cell_t *c, object_t *o) { int digcell(lifeform_t *lf, cell_t *c, object_t *o) {
char obname[BUFLEN]; char obname[BUFLEN];
flag_t *f;
int digpower = 1;
getobname(o, obname, 1); getobname(o, obname, 1);
f = hasflag(o->flags, F_HELPSDIG);
if (f) {
digpower = f->val[0];
}
if (!c) { if (!c) {
return B_TRUE; return B_TRUE;
} }
if (c->type->solid) { if (c->type->solid) {
if (isdiggable(c)) { if (isdiggable(c)) {
// replace wall // start digging!
setcelltype(c, c->map->habitat->emptycelltype); addflag(lf->flags, F_DIGGING, c->x, c->y, digpower, NULL);
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You dig through the wall."); msg("You start digging into %s %s.", needan(c->type->name) ? "an" : "a", c->type->name);
needredraw = B_TRUE; needredraw = B_TRUE;
} else if (cansee(player, lf)) { } else if (cansee(player, lf)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
getlfname(lf, lfname); getlfname(lf, lfname);
msg("%s digs through a wall.",lfname); msg("%s starts digging into %s %s.", lfname, needan(c->type->name) ? "an" : "a", c->type->name);
needredraw = B_TRUE; needredraw = B_TRUE;
} }
//drawscreen(); taketime(lf, getactspeed(lf));
// takes extra time
taketime(lf, getactspeed(lf)*9);
} else { } else {
// fail // fail
if (isplayer(lf)) { if (isplayer(lf)) {
@ -2655,7 +2718,7 @@ int digcell(lifeform_t *lf, cell_t *c, object_t *o) {
if (door) { if (door) {
// TODO: metal doors are immune to CHOP damage // TODO: metal doors are immune to CHOP damage
if (!isimmuneto(door->flags, DT_CHOP)) { if (!isimmuneto(door->flags, DT_CHOP, B_FALSE)) {
taketime(lf, getactspeed(lf)); taketime(lf, getactspeed(lf));
removeob(door, door->amt); removeob(door, door->amt);
if (isplayer(lf)) { if (isplayer(lf)) {
@ -3111,7 +3174,7 @@ int eat(lifeform_t *lf, object_t *o) {
} }
if (isrotting(o)) { if (isrotting(o)) {
if (!isimmuneto(lf->flags, DT_POISON)) { if (!isimmuneto(lf->flags, DT_POISON, B_FALSE)) {
char dambuf[BUFLEN]; char dambuf[BUFLEN];
// lose hp // lose hp
if (isplayer(lf)) { if (isplayer(lf)) {
@ -3140,6 +3203,14 @@ int eat(lifeform_t *lf, object_t *o) {
// think "eye of newt" // think "eye of newt"
gainmp(lf, 2); gainmp(lf, 2);
} }
if (hasflagval(o->flags, F_CORPSEOF, R_EYEBAT, NA, NA, NULL)) {
lf->maxmp++;
if (isplayer(lf)) {
statdirty = B_TRUE;
drawstatus();
msg("You feel slightly more magically attuned.");
}
}
// special case for bananas // special case for bananas
if (o->type->id == OT_BANANA) { if (o->type->id == OT_BANANA) {
@ -4200,12 +4271,12 @@ void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose) {
} }
int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong) { int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong) {
if (isimmuneto(freezee->flags, DT_COLD)) { if (isimmuneto(freezee->flags, DT_COLD, B_FALSE)) {
if (isplayer(freezee)) { if (isplayer(freezee)) {
msg("You feel a slight chill."); msg("You feel a slight chill.");
} }
return B_TRUE; return B_TRUE;
} else if (isresistantto(freezee->flags, DT_COLD)) { } else if (isresistantto(freezee->flags, DT_COLD, B_FALSE)) {
char buf[BUFLEN]; char buf[BUFLEN];
if (isplayer(freezee)) { if (isplayer(freezee)) {
msg("^bYou feel freezing cold!"); msg("^bYou feel freezing cold!");
@ -6258,6 +6329,20 @@ char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer) {
return getlfconditionname(cond); return getlfconditionname(cond);
} }
int getsmellrange(lifeform_t *lf) {
flag_t *f;
int range = 0;
f = lfhasflag(lf, F_ENHANCESMELL);
if (f) {
range = f->val[0];
// adjust for injuries
if (lfhasflagval(lf, F_INJURY, IJ_NOSEBROKEN, NA, NA, NULL)) {
range /= 2;
}
}
return range;
}
glyph_t *getlfglyph(lifeform_t *lf) { glyph_t *getlfglyph(lifeform_t *lf) {
flag_t *f; flag_t *f;
@ -7302,6 +7387,7 @@ object_t *getrestob(lifeform_t *lf) {
} }
for (o = lf->cell->obpile->first ; o ; o = o->next) { for (o = lf->cell->obpile->first ; o ; o = o->next) {
if (isknown(o)) {
f = hasflag(o->flags, F_HELPSREST); f = hasflag(o->flags, F_HELPSREST);
if (f && !isarmour(o)) { if (f && !isarmour(o)) {
if (!bestob || (f->val[0] > bestval)) { if (!bestob || (f->val[0] > bestval)) {
@ -7310,9 +7396,11 @@ object_t *getrestob(lifeform_t *lf) {
} }
} }
} }
}
for (o = lf->pack->first; o ; o = o->next) { for (o = lf->pack->first; o ; o = o->next) {
if (isknown(o)) {
f = hasflag(o->flags, F_HELPSREST); f = hasflag(o->flags, F_HELPSREST);
if (f) { if (f) {
int valid = B_TRUE; int valid = B_TRUE;
@ -7328,6 +7416,7 @@ object_t *getrestob(lifeform_t *lf) {
} }
} }
} }
}
return bestob; return bestob;
} }
@ -8244,6 +8333,15 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
// special effects based on skill level // special effects based on skill level
if (isplayer(lf) && isloreskill(id) && (f->val[1] == PR_ADEPT)) {
race_t *r;
// at adept lore skill, you can look up this kind of race in '?r'
for (r = firstrace ; r ; r = r->next) {
if (r->raceclass->skill == id) r->known = B_TRUE;
}
}
if (id == SK_ATHLETICS) { if (id == SK_ATHLETICS) {
if (f->val[1] == PR_ADEPT) { if (f->val[1] == PR_ADEPT) {
newf = addflag(lf->flags, F_CANWILL, OT_A_TUMBLE, NA, NA, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_TUMBLE, NA, NA, NULL);
@ -8720,6 +8818,7 @@ flag_t *hasbleedinginjury(lifeform_t *lf, enum BODYPART bp) {
int hasfreeaction(lifeform_t *lf) { int hasfreeaction(lifeform_t *lf) {
if (isimmobile(lf)) return B_FALSE; if (isimmobile(lf)) return B_FALSE;
if (lfhasflag(lf, F_CASTINGSPELL)) return B_FALSE; if (lfhasflag(lf, F_CASTINGSPELL)) return B_FALSE;
if (lfhasflag(lf, F_DIGGING)) return B_FALSE;
if (lfhasflag(lf, F_EATING)) return B_FALSE; if (lfhasflag(lf, F_EATING)) return B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) return B_FALSE; if (lfhasflag(lf, F_ASLEEP)) return B_FALSE;
return B_TRUE; return B_TRUE;
@ -8844,7 +8943,7 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
break; break;
case 4: case 4:
inj = IJ_NOSEBROKEN; inj = IJ_NOSEBROKEN;
desc = strdup("nose is broken^charisma penalty"); desc = strdup("nose is broken^charisma penalty,reduced smell sense");
break; break;
} }
break; break;
@ -9113,7 +9212,7 @@ int lfcanbestoned(lifeform_t *lf) {
if (lfhasflag(lf, F_NONCORPOREAL)) { if (lfhasflag(lf, F_NONCORPOREAL)) {
return B_FALSE; return B_FALSE;
} }
if (isimmuneto(lf->flags, DT_PETRIFY)) { if (isimmuneto(lf->flags, DT_PETRIFY, B_FALSE)) {
return B_FALSE; return B_FALSE;
} }
if (isdead(lf)) { if (isdead(lf)) {
@ -9973,13 +10072,21 @@ int isgenius(lifeform_t *lf) {
return B_FALSE; return B_FALSE;
} }
flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt) { flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp) {
flag_t *f; flag_t *f;
dt = basedamagetype(dt); dt = basedamagetype(dt);
f = hasflagval(fp, F_DTIMMUNE, dt, NA, NA, NULL); f = hasflagval(fp, F_DTIMMUNE, dt, NA, NA, NULL);
if (f) return f; if (f) {
if (!onlytemp || (f->lifetime != FROMRACE)) {
return f;
}
}
f = hasflagval(fp, F_DTIMMUNE, DT_ALL, NA, NA, NULL); f = hasflagval(fp, F_DTIMMUNE, DT_ALL, NA, NA, NULL);
if (f) return f; if (f) {
if (!onlytemp || (f->lifetime != FROMRACE)) {
return f;
}
}
return NULL; return NULL;
} }
@ -10178,13 +10285,21 @@ int isprone(lifeform_t *lf) {
return B_FALSE; return B_FALSE;
} }
flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt) { flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp) {
flag_t *f; flag_t *f;
dt = basedamagetype(dt); dt = basedamagetype(dt);
f = hasflagval(fp, F_DTRESIST, dt, NA, NA, NULL); f = hasflagval(fp, F_DTRESIST, dt, NA, NA, NULL);
if (f) return f; if (f) {
if (!onlytemp || (f->lifetime != FROMRACE)) {
return f;
}
}
f = hasflagval(fp, F_DTRESIST, DT_ALL, NA, NA, NULL); f = hasflagval(fp, F_DTRESIST, DT_ALL, NA, NA, NULL);
if (f) return f; if (f) {
if (!onlytemp || (f->lifetime != FROMRACE)) {
return f;
}
}
if (dt == DT_FIRE) { if (dt == DT_FIRE) {
f = hasflag(fp, F_WET); f = hasflag(fp, F_WET);
if (f) return f; if (f) return f;
@ -10431,6 +10546,7 @@ race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcol
a->weight = weight; a->weight = weight;
a->glyph.ch = glyph; a->glyph.ch = glyph;
a->glyph.colour = glyphcolour; a->glyph.colour = glyphcolour;
a->known = B_FALSE;
a->nbodyparts = 0; a->nbodyparts = 0;
@ -10597,7 +10713,7 @@ void adjustspeedforwater(lifeform_t *lf, int *speed) {
void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) { void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) {
flag_t *f; flag_t *f;
if (isimmuneto(lf->flags, damtype)) { if (isimmuneto(lf->flags, damtype, B_FALSE)) {
*amt = 0; *amt = 0;
return; return;
} }
@ -10608,7 +10724,7 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) {
} }
// water normally doesn't hurt. // water normally doesn't hurt.
if ((damtype == DT_WATER) && !isvulnto(lf->flags, damtype)) { if ((damtype == DT_WATER) && !isvulnto(lf->flags, damtype, B_FALSE)) {
*amt = 0; *amt = 0;
return; return;
} }
@ -10645,10 +10761,10 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) {
*amt = 0; *amt = 0;
} }
if (isresistantto(lf->flags, damtype)) { if (isresistantto(lf->flags, damtype, B_FALSE)) {
(*amt) /= 2; (*amt) /= 2;
} }
f = isvulnto(lf->flags, damtype); f = isvulnto(lf->flags, damtype, B_FALSE);
if (f) { if (f) {
if ((*amt == 0) && strlen(f->text)) { if ((*amt == 0) && strlen(f->text)) {
int ndice,nsides,bonus; int ndice,nsides,bonus;
@ -11166,14 +11282,22 @@ int isundead(lifeform_t *lf) {
return B_FALSE; return B_FALSE;
} }
flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt) { flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp) {
flag_t *f; flag_t *f;
dt = basedamagetype(dt); dt = basedamagetype(dt);
f = hasflagval(fp, F_DTVULN, dt, NA, NA, NULL); f = hasflagval(fp, F_DTVULN, dt, NA, NA, NULL);
if (f) return f; if (f) {
if (!onlytemp || (f->lifetime != FROMRACE)) {
return f;
}
}
f = hasflagval(fp, F_DTVULN, DT_ALL, NA, NA, NULL); f = hasflagval(fp, F_DTVULN, DT_ALL, NA, NA, NULL);
if (f) return f; if (f) {
if (!onlytemp || (f->lifetime != FROMRACE)) {
return f;
}
}
return NULL; return NULL;
} }
@ -11629,6 +11753,13 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
postbleed = B_TRUE; postbleed = B_TRUE;
} }
//////////////////////////////////////////
// Figure out death text for tombstone.
// eg. Killed by something
// Impaled by something.
// etc
//////////////////////////////////////////
// replace 'the' at start of damsrc with 'a' // replace 'the' at start of damsrc with 'a'
if (strstr(damsrc, "the ") == damsrc) { if (strstr(damsrc, "the ") == damsrc) {
snprintf(buf, BUFLEN, "a %s", (damsrc+4)); snprintf(buf, BUFLEN, "a %s", (damsrc+4));
@ -11659,6 +11790,9 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
setlastdam(lf, buf); setlastdam(lf, buf);
if (fromlf && lfhasflag(fromlf, F_CARNIVORE)) {
setkillverb(lf, "Eaten");
} else {
switch (damtype) { switch (damtype) {
case DT_ACID: setkillverb(lf, "Dissolved"); break; case DT_ACID: setkillverb(lf, "Dissolved"); break;
case DT_COLD: setkillverb(lf, "Frozen"); break; case DT_COLD: setkillverb(lf, "Frozen"); break;
@ -11672,6 +11806,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
case DT_EXPLOSIVE: setkillverb(lf, "Vaporised"); break; case DT_EXPLOSIVE: setkillverb(lf, "Vaporised"); break;
default: break; default: break;
} }
}
// special case // special case
if (lf->race->id == R_DREAMFUNGUS) { if (lf->race->id == R_DREAMFUNGUS) {
@ -11735,7 +11870,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
// fire: dam*10 chance of burning each object which is vulnerable to fire // fire: dam*10 chance of burning each object which is vulnerable to fire
for (o = lf->pack->first ; o ; o = nexto) { for (o = lf->pack->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
if (isvulnto(o->flags, DT_FIRE) && pctchance(amt*10)) { if (isvulnto(o->flags, DT_FIRE, B_FALSE) && pctchance(amt*10)) {
int newdam; int newdam;
nburnt++; nburnt++;
if (nburnt >= (amt/5)) break; if (nburnt >= (amt/5)) break;
@ -11751,7 +11886,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
for (o = lf->pack->first ; o ; o = nexto) { for (o = lf->pack->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
//if (isvulnto(o->flags, DT_COLD) && pctchance(amt*10)) { //if (isvulnto(o->flags, DT_COLD) && pctchance(amt*10)) {
if (isvulnto(o->flags, DT_COLD)) { if (isvulnto(o->flags, DT_COLD, B_FALSE)) {
int newdam; int newdam;
// object takes 1/4 of damage // object takes 1/4 of damage
newdam = pctof(25, amt); newdam = pctof(25, amt);
@ -13399,7 +13534,7 @@ int safetorest(lifeform_t *lf) {
reason = E_OK; reason = E_OK;
for (l = lf->cell->map->lf ; l ; l = l->next) { for (l = lf->cell->map->lf ; l ; l = l->next) {
if ((l != lf) && areenemies(lf, l) && !lfhasflag(l, F_HARMLESS)) { if ((l != lf) && areenemies(lf, l) && !lfhasflag(l, F_HARMLESS) && !lfhasflag(l, F_FEIGNINGDEATH)) {
int monsternearby = B_FALSE; int monsternearby = B_FALSE;
if (isplayer(lf)) { if (isplayer(lf)) {
@ -14105,6 +14240,7 @@ void interrupt(lifeform_t *lf) {
stopresting(lf); stopresting(lf);
stoprunning(lf); stoprunning(lf);
killflagsofid(lf->flags, F_AUTOCMD); killflagsofid(lf->flags, F_AUTOCMD);
killflagsofid(lf->flags, F_DIGGING);
} }
int setlfmaterial(lifeform_t *lf, enum MATERIAL id, int wantannounce) { int setlfmaterial(lifeform_t *lf, enum MATERIAL id, int wantannounce) {
@ -14348,8 +14484,8 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
} }
} else if (ct == SC_DODGE) { } else if (ct == SC_DODGE) {
if (attrib) { if (attrib) {
// ie. -5 to 5 // ie. -2 to 2
othermod += (getstatmod(lf, A_AGI) / 10); othermod += (getstatmod(lf, A_AGI) / 20);
} }
} else if (ct == SC_SLIP) { } else if (ct == SC_SLIP) {
if (lfhasflagval(lf, F_INJURY, IJ_LEGBROKEN, NA, NA, NULL)) { if (lfhasflagval(lf, F_INJURY, IJ_LEGBROKEN, NA, NA, NULL)) {
@ -14404,11 +14540,11 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
} }
} else if (ct == SC_POISON) { } else if (ct == SC_POISON) {
// auto pass if we are immune // auto pass if we are immune
if (isimmuneto(lf->flags, DT_POISON)) { if (isimmuneto(lf->flags, DT_POISON, B_FALSE)) {
othermod += (diff*2); othermod += (diff*2);
} else if (isresistantto(lf->flags, DT_POISON)) { } else if (isresistantto(lf->flags, DT_POISON, B_FALSE)) {
othermod += 5; othermod += 5;
} else if (isvulnto(lf->flags, DT_POISON)) { } else if (isvulnto(lf->flags, DT_POISON, B_FALSE)) {
othermod -= 10; othermod -= 10;
} }
} else if (ct == SC_SEARCH) { } else if (ct == SC_SEARCH) {
@ -15335,7 +15471,7 @@ void startlfturn(lifeform_t *lf) {
} }
f = hasflag(o->flags, F_CAUSESCOUGH); f = hasflag(o->flags, F_CAUSESCOUGH);
if (f && !isimmuneto(lf->flags, DT_POISONGAS)) { if (f && !isimmuneto(lf->flags, DT_POISONGAS, B_FALSE)) {
char obname[BUFLEN]; char obname[BUFLEN];
getobname(o, obname, o->amt); getobname(o, obname, o->amt);
if (!skillcheck(lf, SC_CON, f->val[0] * o->amt, 0)) { if (!skillcheck(lf, SC_CON, f->val[0] * o->amt, 0)) {
@ -16256,6 +16392,7 @@ void turntoface(lifeform_t *lf, cell_t *dstcell) {
void unsummon(lifeform_t *lf, int vanishobs) { void unsummon(lifeform_t *lf, int vanishobs) {
lifeform_t *creator = NULL; lifeform_t *creator = NULL;
flag_t *f; flag_t *f;
char unsummonob[BUFLEN];
f = hasflag(lf->flags, F_SUMMONEDBY); f = hasflag(lf->flags, F_SUMMONEDBY);
if (f) { if (f) {
creator = findlf(NULL, f->val[0]); creator = findlf(NULL, f->val[0]);
@ -16286,8 +16423,16 @@ void unsummon(lifeform_t *lf, int vanishobs) {
lf->hp = 0; lf->hp = 0;
addflag(lf->flags, F_DEAD, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_DEAD, B_TRUE, NA, NA, NULL);
addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
addflag(lf->flags, F_NODEATHSPEECH, B_TRUE, NA, NA, NULL);
addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addob(lf->cell->obpile, "puff of smoke");
f = lfhasflag(lf, F_UNSUMMONOB);
if (f) {
strcpy(unsummonob, f->text);
} else {
strcpy(unsummonob, "puff of smoke");
}
addob(lf->cell->obpile, unsummonob);
} }
int unweild(lifeform_t *lf, object_t *o) { int unweild(lifeform_t *lf, object_t *o) {
@ -16835,6 +16980,11 @@ int validateraces(void) {
printf("ERROR in race '%s' - has NOISETEXT but no volume.\n", r->name); printf("ERROR in race '%s' - has NOISETEXT but no volume.\n", r->name);
goterror = B_TRUE; goterror = B_TRUE;
} }
} else if (f->id == F_NOSLEEP) {
if (hasflag(r->flags, F_NOCTURNAL) || hasflag(r->flags, F_DIURNAL) || hasflag(r->flags, F_STARTASLEEPPCT)) {
printf("ERROR in race '%s' - has both NOSSLEEP and nocturnal/diurnal/startasleeppct.\n", r->name);
goterror = B_TRUE;
}
} else if (f->id == F_NOSMELL) { } else if (f->id == F_NOSMELL) {
if (hasflag(r->flags, F_ENHANCESMELL)) { if (hasflag(r->flags, F_ENHANCESMELL)) {
printf("ERROR in race '%s' - has both NOSMELL and ENHANCESMELL.\n", r->name); printf("ERROR in race '%s' - has both NOSMELL and ENHANCESMELL.\n", r->name);

8
lf.h
View File

@ -65,6 +65,7 @@ int check_rest_ok(lifeform_t *lf);
//void checkxp(enum RACE rid); //void checkxp(enum RACE rid);
float comparelfs(lifeform_t *lf1, lifeform_t *lf2); float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
int confuse(lifeform_t *lf, int howlong); int confuse(lifeform_t *lf, int howlong);
int continuedigging(lifeform_t *lf);
int countinnateattacks(lifeform_t *lf); int countinnateattacks(lifeform_t *lf);
int countnearbyallies(lifeform_t *lf); int countnearbyallies(lifeform_t *lf);
int countnearbyhurtallies(lifeform_t *lf); int countnearbyhurtallies(lifeform_t *lf);
@ -171,6 +172,7 @@ object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp);
int getowing(lifeform_t *buyer, int shopid, int *retnitems); int getowing(lifeform_t *buyer, int shopid, int *retnitems);
enum LFCONDITION getseenlfconditioncutoff(lifeform_t *lf); enum LFCONDITION getseenlfconditioncutoff(lifeform_t *lf);
char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer); char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer);
int getsmellrange(lifeform_t *lf);
glyph_t *getlfglyph(lifeform_t *lf); glyph_t *getlfglyph(lifeform_t *lf);
enum MATERIAL getlfmaterial(lifeform_t *lf); enum MATERIAL getlfmaterial(lifeform_t *lf);
enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid); enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid);
@ -286,7 +288,7 @@ int isgenius(lifeform_t *lf);
int isgod(lifeform_t *lf); int isgod(lifeform_t *lf);
int ishirable(lifeform_t *lf); int ishirable(lifeform_t *lf);
int isimmobile(lifeform_t *lf); int isimmobile(lifeform_t *lf);
flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt); flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp);
int isinbattle(lifeform_t *lf); int isinbattle(lifeform_t *lf);
int isingunrange(lifeform_t *lf, cell_t *where); int isingunrange(lifeform_t *lf, cell_t *where);
int isloreskill(enum SKILL skid); int isloreskill(enum SKILL skid);
@ -301,7 +303,7 @@ flag_t *ispoisoned(lifeform_t *lf);
flag_t *ispoisonedwith(lifeform_t *lf, enum POISONTYPE pt); flag_t *ispoisonedwith(lifeform_t *lf, enum POISONTYPE pt);
int ispolymorphed(lifeform_t *lf); int ispolymorphed(lifeform_t *lf);
int isprone(lifeform_t *lf); int isprone(lifeform_t *lf);
flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt); flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp);
flag_t *isresting(lifeform_t *lf); flag_t *isresting(lifeform_t *lf);
int issleepingtimefor(lifeform_t *lf); int issleepingtimefor(lifeform_t *lf);
object_t *isstuck(lifeform_t *lf); object_t *isstuck(lifeform_t *lf);
@ -309,7 +311,7 @@ int issmellablelf(lifeform_t *lf);
int isswimming(lifeform_t *lf); int isswimming(lifeform_t *lf);
int isunconscious(lifeform_t *lf); int isunconscious(lifeform_t *lf);
int isundead(lifeform_t *lf); int isundead(lifeform_t *lf);
flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt); flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp);
int isweaponskill(enum SKILL skid); int isweaponskill(enum SKILL skid);
enum FLAG iswoozy(lifeform_t *lf); enum FLAG iswoozy(lifeform_t *lf);
void killjob(job_t *job); void killjob(job_t *job);

37
map.c
View File

@ -177,7 +177,7 @@ map_t *addmap(void) {
// when monsters are made during level generation, autogen will be true. otherwise false; // when monsters are made during level generation, autogen will be true. otherwise false;
// if "rid" RR_NONE, paste racename to get the race. // if "rid" RR_NONE, parse racename to get the race.
// otherwise just use the given race. // otherwise just use the given race.
lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int amt, int autogen, int *nadded) { lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int amt, int autogen, int *nadded) {
lifeform_t *lf = NULL; lifeform_t *lf = NULL;
@ -3173,7 +3173,7 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
// have to force these stairs to go back to a different region. // have to force these stairs to go back to a different region.
f = hasflag(o->flags, F_CLIMBABLE); f = hasflag(o->flags, F_CLIMBABLE);
f->val[1] = map->region->parentregion->id; f->val[1] = map->region->parentregion->id;
linkstairs(o, NULL); linkstairs(o, entryob);
} }
@ -5069,22 +5069,22 @@ void initmap(void) {
addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE); addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE);
// cell types - solid // cell types - solid
addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0); addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0, 100);
addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0); addcelltype(CT_ROOMWALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0, 100);
addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0); addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0, 50);
addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0); addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0, 150);
addcelltype(CT_ROOMWALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0); addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0, 200);
// cell types - non-solid // cell types - non-solid
addcelltype(CT_FAKE, "fake cell", '.', C_GREEN, B_EMPTY, B_TRANS, MT_STONE, 0); 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); 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); addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0, -1);
addcelltype(CT_FLOORWOOD, "wood floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0); addcelltype(CT_FLOORWOOD, "wood floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0, -1);
addcelltype(CT_FLOORSHOP, "shop floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0); addcelltype(CT_FLOORSHOP, "shop floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0, -1);
addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0); addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0, -1);
addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT, 0); 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); 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); 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); addcelltype(CT_VLOWFLOOR, "very low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -2, -1);
// region types // region types
addregiontype(RG_WORLDMAP, "World map", H_FOREST, 10, 0, D_NONE, B_TRUE); addregiontype(RG_WORLDMAP, "World map", H_FOREST, 10, 0, D_NONE, B_TRUE);
@ -5523,7 +5523,7 @@ object_t *linkportal(object_t *srcportal, int wantdepth) {
} }
// link the staircase 'o' to a free one in adjacent maps. // link the staircase 'o' to a free one in adjacent maps.
// o2 is options. if not probided, we will try to find // o2 is optional. if not probided, we will try to find
// something to link to ourself. // something to link to ourself.
// returns TRUE if it failed because othermap doesn't exist. // returns TRUE if it failed because othermap doesn't exist.
int linkstairs(object_t *o, object_t *o2) { int linkstairs(object_t *o, object_t *o2) {
@ -5922,6 +5922,7 @@ void setcelltype(cell_t *cell, enum CELLTYPE id) {
assert(cell); assert(cell);
cell->type = findcelltype(id); cell->type = findcelltype(id);
assert(cell->type); assert(cell->type);
cell->hp = cell->type->hp;
if (cell->type->solid) { if (cell->type->solid) {
assert(!cell->obpile->first); assert(!cell->obpile->first);
} }

17
move.c
View File

@ -242,7 +242,7 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
} }
f = hasflag(o->flags, F_WALKDAM); f = hasflag(o->flags, F_WALKDAM);
if (f) { if (f) {
if ((f->val[0] != DT_WATER) || isvulnto(lf->flags, DT_WATER)) { if ((f->val[0] != DT_WATER) || isvulnto(lf->flags, DT_WATER, B_FALSE)) {
// are we immune to this? // are we immune to this?
if (!lfhasflagval(lf, F_DTIMMUNE, f->val[0], NA, NA, NULL)) { if (!lfhasflagval(lf, F_DTIMMUNE, f->val[0], NA, NA, NULL)) {
if (error) { if (error) {
@ -1386,6 +1386,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
//} //}
} }
dointerrupt = B_TRUE; dointerrupt = B_TRUE;
// mark the observed race as known.
lf->race->known = B_TRUE;
} }
} else if (isplayer(lf)) { } else if (isplayer(lf)) {
if (areallies(lf, l)) { if (areallies(lf, l)) {
@ -2627,8 +2629,17 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
// strafing sideways/backwards takes longer // strafing sideways/backwards takes longer
if (strafe && !lfhasflag(lf, F_AWARENESS)) { if (strafe && !lfhasflag(lf, F_AWARENESS)) {
switch (reldir) { switch (reldir) {
case RD_SIDEWAYS: howlong = pctof(125, howlong); break; //case RD_SIDEWAYS: howlong = pctof(125, howlong); break;
case RD_BACKWARDS: howlong = pctof(150, howlong); break; case RD_SIDEWAYS: break;
case RD_BACKWARDS:
switch (getskill(lf, SK_ATHLETICS)) {
case PR_INEPT: howlong = pctof(150, howlong); break;
case PR_NOVICE:
case PR_BEGINNER:
howlong = pctof(125, howlong); break;
default: break;
}
break;
case RD_FORWARDS: case RD_FORWARDS:
if (hasactivespell(lf, OT_S_TAILWIND)) { if (hasactivespell(lf, OT_S_TAILWIND)) {
// faster // faster

19
nexus.c
View File

@ -276,7 +276,7 @@ int main(int argc, char **argv) {
// this is the hole which you fell down to get here. // this is the hole which you fell down to get here.
addobfast(where->obpile, OT_HOLEINROOF); addobfast(where->obpile, OT_HOLEINROOF);
// kill any objects which were already there, or which fell down the hole // kill any objects which were already there, or which fell down the hole
killallobs(where->obpile); killallobsexcept(where->obpile, OT_HOLEINROOF, OT_NONE);
// now add the player // now add the player
real_addlf(where, startrace->id, 1, C_PLAYER); // this will assign 'player' real_addlf(where, startrace->id, 1, C_PLAYER); // this will assign 'player'
@ -540,7 +540,7 @@ int main(int argc, char **argv) {
return B_FALSE; return B_FALSE;
} }
celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight) { celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp) {
celltype_t *a; celltype_t *a;
// add to the end of the list // add to the end of the list
@ -567,6 +567,7 @@ celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, in
a->transparent = transparent; a->transparent = transparent;
a->material = findmaterial(mat); a->material = findmaterial(mat);
a->floorheight = floorheight; a->floorheight = floorheight;
a->hp = hp;
a->flags = addflagpile(NULL, NULL); a->flags = addflagpile(NULL, NULL);
@ -798,6 +799,19 @@ void donextturn(map_t *map) {
} }
} }
// digging?
if (donormalmove) {
f = lfhasflag(who, F_DIGGING);
if (f) {
if (isplayer(who) && checkforkey()) {
msg("Stopped digging.");
killflag(f);
} else {
if (!continuedigging(who)) donormalmove = B_FALSE;
}
}
}
// eating? // eating?
if (donormalmove) { if (donormalmove) {
f = lfhasflag(who, F_EATING); f = lfhasflag(who, F_EATING);
@ -841,7 +855,6 @@ void donextturn(map_t *map) {
} }
} }
if (donormalmove) { if (donormalmove) {
// paralyzed etc? // paralyzed etc?
if (isimmobile(who)) { if (isimmobile(who)) {

View File

@ -1,6 +1,6 @@
#include "defs.h" #include "defs.h"
celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight); celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp);
warning_t *addwarning(char *text); warning_t *addwarning(char *text);
void checkdeath(void); void checkdeath(void);
void checkendgame(void); void checkendgame(void);

120
objects.c
View File

@ -1487,7 +1487,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
switch (wantom[n]->id) { switch (wantom[n]->id) {
case OM_FLAMING: // flaming weapons are immune to fire case OM_FLAMING: // flaming weapons are immune to fire
if (o->type->obclass->id == OC_WEAPON) { if (o->type->obclass->id == OC_WEAPON) {
if (!isimmuneto(o->flags, DT_FIRE)) { if (!isimmuneto(o->flags, DT_FIRE, B_FALSE)) {
addflag(o->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); addflag(o->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
} }
} }
@ -2034,17 +2034,17 @@ void adjustdamob(object_t *o, int *dam, enum DAMTYPE damtype) {
} }
// immune? // immune?
if (isimmuneto(o->flags, damtype)) { if (isimmuneto(o->flags, damtype, B_FALSE)) {
*dam = 0; *dam = 0;
return; return;
} }
if (isresistantto(o->flags, damtype)) { if (isresistantto(o->flags, damtype, B_FALSE)) {
// no resistances etc if rusty... // no resistances etc if rusty...
if (!hasflag(o->flags, F_RUSTED)) { if (!hasflag(o->flags, F_RUSTED)) {
*dam /= 2; *dam /= 2;
} }
} }
if (isvulnto(o->flags, damtype)) { if (isvulnto(o->flags, damtype, B_FALSE)) {
*dam *= 2; *dam *= 2;
} }
@ -2055,7 +2055,7 @@ void adjustdamob(object_t *o, int *dam, enum DAMTYPE damtype) {
} }
if (damtype == DT_WATER) { if (damtype == DT_WATER) {
if (!isvulnto(o->flags, damtype)) { if (!isvulnto(o->flags, damtype, B_FALSE)) {
*dam = 0; *dam = 0;
return; return;
} }
@ -2326,10 +2326,13 @@ int canbepoisoned(enum OBTYPE oid) {
int canseeob(lifeform_t *lf, object_t *o) { int canseeob(lifeform_t *lf, object_t *o) {
flag_t *f; flag_t *f;
cell_t *obloc;
if (gamemode != GM_GAMESTARTED) { if (gamemode != GM_GAMESTARTED) {
return B_TRUE; return B_TRUE;
} }
obloc = getoblocation(o);
if (hasflag(o->flags, F_SECRET) && isplayer(lf)) { if (hasflag(o->flags, F_SECRET) && isplayer(lf)) {
// can't see // can't see
return B_FALSE; return B_FALSE;
@ -2369,6 +2372,7 @@ int canseeob(lifeform_t *lf, object_t *o) {
return B_FALSE; return B_FALSE;
} }
} else { } else {
int smellrange;
// ie. SCENT // ie. SCENT
// special case: if lf is the player's pet, they can always "smell" the player // special case: if lf is the player's pet, they can always "smell" the player
@ -2379,8 +2383,10 @@ int canseeob(lifeform_t *lf, object_t *o) {
} }
} }
smellrange = getsmellrange(lf);
// can't smell your own race... // can't smell your own race...
if ((f->val[0] != lf->race->id) && lfhasflag(lf, F_ENHANCESMELL)) { if ((f->val[0] != lf->race->id) && smellrange && (getcelldist(lf->cell, obloc) <= smellrange)) {
return B_TRUE; return B_TRUE;
} else { } else {
return B_FALSE; return B_FALSE;
@ -6197,7 +6203,7 @@ int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown) {
if (!onlyifknown || (iqb >= AT_AVERAGE)) { if (!onlyifknown || (iqb >= AT_AVERAGE)) {
if (hasflag(o->flags, F_SHARP)) { if (hasflag(o->flags, F_SHARP)) {
if (!getequippedob(lf->pack, BP_HANDS) && !isimmuneto(lf->flags, DT_SLASH)) { if (!getequippedob(lf->pack, BP_HANDS) && !isimmuneto(lf->flags, DT_SLASH, B_FALSE)) {
return B_TRUE; return B_TRUE;
} }
} }
@ -6205,7 +6211,7 @@ int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown) {
if (!onlyifknown || (iqb >= IQ_ANIMAL)) { if (!onlyifknown || (iqb >= IQ_ANIMAL)) {
if (hasflag(o->flags, F_ONFIRE)) { if (hasflag(o->flags, F_ONFIRE)) {
if (!isimmuneto(lf->flags, DT_FIRE)) { if (!isimmuneto(lf->flags, DT_FIRE, B_FALSE)) {
return B_TRUE; return B_TRUE;
} }
} }
@ -6611,6 +6617,38 @@ void killallobs(obpile_t *op) {
} }
} }
// returns number of obs killed.
// terminate args with OT_NONE
int killallobsexcept(obpile_t *op, ...) {
va_list args;
enum OBTYPE exception[MAXCANDIDATES],thisob;
int nexceptions = 0,i,nkilled = 0;
object_t *o,*nexto;
va_start(args, op);
thisob = va_arg(args, enum OBTYPE);
while (thisob != OT_NONE) {
exception[nexceptions++] = thisob;
thisob = va_arg(args, enum OBTYPE);
}
va_end(args);
for (o = op->first ; o; o = nexto) {
int killthis = B_TRUE;
nexto = o->next;
for (i = 0;i < nexceptions; i++) {
if (o->type->id == exception[i]) {
killthis = B_FALSE;
break;
}
}
if (killthis) {
killob(o);
nkilled++;
}
}
return nkilled;
}
void killmaterial(material_t *m) { void killmaterial(material_t *m) {
material_t *nextone, *lastone; material_t *nextone, *lastone;
@ -9125,10 +9163,10 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
// how long for? // how long for?
i = geteffecttime(15,25,potblessed); i = geteffecttime(15,25,potblessed);
if (!isimmuneto(lf->flags, DT_FIRE)) { if (!isimmuneto(lf->flags, DT_FIRE, B_FALSE)) {
addtempflag(lf->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL, i); addtempflag(lf->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL, i);
} }
if (!isimmuneto(lf->flags, DT_COLD)) { if (!isimmuneto(lf->flags, DT_COLD, B_FALSE)) {
addtempflag(lf->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL, i); addtempflag(lf->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL, i);
} }
break; break;
@ -9821,19 +9859,21 @@ int readsomething(lifeform_t *lf, object_t *o) {
// removeob one of the object // removeob one of the object
removeob(o, 1); removeob(o, 1);
} else if (o->type->id == OT_SCR_PERMENANCE) { } else if (o->type->id == OT_SCR_PERMENANCE) {
if (isplayer(lf)) { int ndone = 0;
targob = askobject(lf->pack, "Target which object", NULL, '\0', AO_NONE); flag_t *f;
// makes certain flags permenant
for (f = lf->flags->first ; f ; f = f->next) {
if ((f->lifetime > 0) && canbemadepermenant(f->id)) {
f->lifetime = PERMENANT;
ndone++;
}
} }
if (targob) {
flag_t *f;
for (f = targob->flags->first ; f ; f = f->next) {
f->lifetime = PERMENANT;
}
if (isplayer(lf)) { if (isplayer(lf)) {
char obname[BUFLEN]; if (ndone) {
getobname(targob, obname, targob->amt); msg("You are surrounded by a stabilising aura.");
msg("Your %s emit%s a blinding burst of power!",noprefix(obname), (targob->amt == 1) ? "s" : ""); } else {
nothinghappens();
} }
} }
@ -11179,6 +11219,12 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
// roll for hit // roll for hit
youhit = B_FALSE; youhit = B_FALSE;
myroll = rnd(1,100); myroll = rnd(1,100);
// blessed projectile vs undead? 20% bonus.
if (isblessed(o) && isundead(target)) {
myroll -= 20;
}
// metal projectile versus magnetic shield? // metal projectile versus magnetic shield?
if (target && lfhasflag(target, F_MAGSHIELD) && ismetal(o->material->id)) { if (target && lfhasflag(target, F_MAGSHIELD) && ismetal(o->material->id)) {
// announce // announce
@ -11237,9 +11283,11 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
} }
} }
// saving throws // saving throws
if (youhit && !willcatch && !isprone(target)) { if (youhit && !willcatch && !isprone(target)) {
// undead can't dodge blessed missiles
if (isblessed(o) && isundead(target)) {
} else {
// can the victim see where the object came from? // can the victim see where the object came from?
if (haslos(target, srcloc)) { if (haslos(target, srcloc)) {
int catchmod,dodgemod; int catchmod,dodgemod;
@ -11262,15 +11310,15 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
catchmod = -6; catchmod = -6;
dodgemod = 2; dodgemod = 2;
} }
// first check to see if you can catch it. this is hard! // first check to see if you can catch it. this should be very hard!
if (!lfhasflag(target, F_NOPACK) && hasbp(target, BP_HANDS) && if (!lfhasflag(target, F_NOPACK) && hasbp(target, BP_HANDS) &&
lfhasflag(target, F_HUMANOID) && lfhasflag(target, F_HUMANOID) &&
canpickup(target, o, o->amt) && canpickup(target, o, o->amt) &&
!willburden(target, o, o->amt) && !willburden(target, o, o->amt) &&
!isimmobile(target) && !isimmobile(target) &&
skillcheck(target, SC_DEX, 30 + (speed*5), catchmod)) { skillcheck(target, SC_DEX, 27 + (speed*5), catchmod)) {
willcatch = B_TRUE; willcatch = B_TRUE;
} else if (!lfhasflag(target, F_CASTINGSPELL) && skillcheck(target, SC_DODGE, 14+(speed*2), dodgemod)) { } else if (hasfreeaction(target) && skillcheck(target, SC_DODGE, 27+(speed*2), dodgemod)) {
// then check if we dodge it... // then check if we dodge it...
if (db) dblog("target passed dodge check."); if (db) dblog("target passed dodge check.");
@ -11286,6 +11334,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
} }
} }
} }
}
// doesn't matter wheter you hit or not... // doesn't matter wheter you hit or not...
if (isundead(target) && isblessed(o)) { if (isundead(target) && isblessed(o)) {
@ -11299,7 +11348,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (youhit && lfhasflag(target, F_NONCORPOREAL)) { if (youhit && lfhasflag(target, F_NONCORPOREAL)) {
if (isvulnto(target->flags, DT_HOLY) && isblessed(o)) { if (isvulnto(target->flags, DT_HOLY, B_FALSE) && isblessed(o)) {
} else { } else {
youhit = B_FALSE; youhit = B_FALSE;
willcatch = B_FALSE; willcatch = B_FALSE;
@ -12622,15 +12671,26 @@ int getingredients(obpile_t *op, recipe_t *rec, object_t **retob, int *retcount,
object_t *poss[MAXPILEOBS]; object_t *poss[MAXPILEOBS];
int nposs = 0; int nposs = 0;
for (o = op->first ; o ; o = o->next) { for (o = op->first ; o ; o = o->next) {
if ((o->type->id == rec->ingredient[i]) && (o->amt >= rec->count[i])) { int obmatches = B_FALSE;
int valid = B_TRUE; if (o->type->id == rec->ingredient[i]) {
// special case - chicken soup must use chicken meat obmatches = B_TRUE;
} else if ((rec->ingredient[i] == OT_BREADSTALE) && (o->type->id == OT_BREADFRESH)) {
obmatches = B_TRUE;
} else if ((rec->ingredient[i] == OT_BREADFRESH) && (o->type->id == OT_BREADSTALE)) {
obmatches = B_TRUE;
}
if (obmatches) {
// chicken soup must have chicken
if ((rec->result == OT_POT_SOUPCHICKEN) && (rec->ingredient[i] == OT_ROASTMEAT)) { if ((rec->result == OT_POT_SOUPCHICKEN) && (rec->ingredient[i] == OT_ROASTMEAT)) {
if (!hasflagval(o->flags, F_CORPSEOF, R_CHICKEN, NA, NA, NULL)) { if (!hasflagval(o->flags, F_CORPSEOF, R_CHICKEN, NA, NA, NULL)) {
valid = B_FALSE; obmatches = B_FALSE;
} }
} }
if (valid) poss[nposs++] = o; }
if (obmatches && (o->amt >= rec->count[i])) {
poss[nposs++] = o;
} }
} }

View File

@ -202,6 +202,7 @@ int istriedot(objecttype_t *ot);
int isweapon(object_t *o); int isweapon(object_t *o);
int iswearable(object_t *o); int iswearable(object_t *o);
void killallobs(obpile_t *op); void killallobs(obpile_t *op);
int killallobsexcept(obpile_t *op, ...);
void killmaterial(material_t *m); void killmaterial(material_t *m);
void killob(object_t *o); void killob(object_t *o);
void killobpile(obpile_t *o); void killobpile(obpile_t *o);

20
save.c
View File

@ -21,6 +21,7 @@ extern long curtime;
extern lifeform_t *player; extern lifeform_t *player;
extern map_t *firstmap; extern map_t *firstmap;
extern race_t *firstrace;
extern knowledge_t *knowledge; extern knowledge_t *knowledge;
extern region_t *firstregion,*lastregion; extern region_t *firstregion,*lastregion;
extern regionoutline_t *firstregionoutline,*lastregionoutline; extern regionoutline_t *firstregionoutline,*lastregionoutline;
@ -140,11 +141,21 @@ int loadknowledge(FILE *f) {
} }
int loadvars(FILE *f) { int loadvars(FILE *f) {
int id;
int db = B_FALSE; int db = B_FALSE;
race_t *r;
if (db) dblog("--> Loading knowledge...\n"); if (db) dblog("--> Loading knowledge...\n");
fscanf(f, "startvars\n"); fscanf(f, "startvars\n");
fscanf(f, "curtime:%ld\n",&curtime); fscanf(f, "curtime:%ld\n",&curtime);
fscanf(f, "endvars\n"); fscanf(f, "endvars\n");
fscanf(f, "startknownraces\n");
fscanf(f, "%d\n", &id);
while (id != -1) {
r = findrace(id);
r->known = B_TRUE;
fscanf(f, "%d\n", &id);
}
fscanf(f, "endknownraces\n");
return B_FALSE; return B_FALSE;
} }
@ -731,10 +742,19 @@ int loadsavegame(void) {
int savevars(FILE *f) { int savevars(FILE *f) {
int db = B_FALSE; int db = B_FALSE;
race_t *r;
if (db) dblog("--> Saving knowledge...\n"); if (db) dblog("--> Saving knowledge...\n");
fprintf(f, "startvars\n"); fprintf(f, "startvars\n");
fprintf(f, "curtime:%ld\n",curtime); fprintf(f, "curtime:%ld\n",curtime);
fprintf(f, "endvars\n"); fprintf(f, "endvars\n");
fprintf(f, "startknownraces\n");
for (r = firstrace ; r ; r = r->next) {
if (r->known) {
fprintf(f, "%d\n",r->id);
}
}
fprintf(f, "-1\n");
fprintf(f, "endknownraces\n");
return B_FALSE; return B_FALSE;
} }

131
spell.c
View File

@ -745,6 +745,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
object_t *o,*trapob = NULL; object_t *o,*trapob = NULL;
flag_t *trapflag = NULL; flag_t *trapflag = NULL;
char buf[BUFLEN]; char buf[BUFLEN];
int bonus = 0;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You can't disable traps while swimming!"); if (isplayer(user)) msg("You can't disable traps while swimming!");
@ -807,8 +808,17 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
movelf(user, targcell); movelf(user, targcell);
} }
// have any objects which will help?
bonus = 0;
for (o = user->pack->first ; o ; o = o->next) {
f = hasflag(o->flags, F_HELPSDISARM);
if (f && (f->val[0] > bonus)) {
bonus = f->val[0];
}
}
// try to disarm it // try to disarm it
if (skillcheck(user, SC_DISARM, trapflag->val[0], 0)) { if (skillcheck(user, SC_DISARM, trapflag->val[0], bonus)) {
if (trapflag->id == F_TRAP) { if (trapflag->id == F_TRAP) {
// ie. trapped cell // ie. trapped cell
getobname(trapob, buf, 1); getobname(trapob, buf, 1);
@ -3566,7 +3576,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char damstring[BUFLEN]; char damstring[BUFLEN];
char realcname[BUFLEN]; char realcname[BUFLEN];
getlfname(c->lf,buf); getlfname(c->lf,buf);
if (!isimmuneto(c->lf->flags, DT_FIRE)) { if (!isimmuneto(c->lf->flags, DT_FIRE, B_FALSE)) {
msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s"); msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s");
} }
real_getlfname(caster, realcname, B_FALSE); real_getlfname(caster, realcname, B_FALSE);
@ -4040,14 +4050,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
dam = rnd(1,exposedlimbs); dam = rnd(1,exposedlimbs);
if (isplayer(target)) { if (isplayer(target)) {
if (isimmuneto(target->flags, DT_COLD)) { if (isimmuneto(target->flags, DT_COLD, B_FALSE)) {
msg("You feel mildly chilly."); msg("You feel mildly chilly.");
} else { } else {
msg("You feel cold!"); msg("You feel cold!");
} }
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player, target)) { } else if (cansee(player, target)) {
if (isimmuneto(target->flags, DT_COLD)) { if (isimmuneto(target->flags, DT_COLD, B_FALSE)) {
msg("%s doesn't seem to mind the cold.", lfname); msg("%s doesn't seem to mind the cold.", lfname);
} else { } else {
msg("%s looks cold!", lfname); msg("%s looks cold!", lfname);
@ -4057,7 +4067,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// target takes magical damage // target takes magical damage
// always hit // always hit
if (!isimmuneto(target->flags, DT_COLD)) { if (!isimmuneto(target->flags, DT_COLD, B_FALSE)) {
losehp(target, dam, DT_COLD, caster, "a chill spell"); losehp(target, dam, DT_COLD, caster, "a chill spell");
} }
} else if (spellid == OT_S_COLDBURST) { } else if (spellid == OT_S_COLDBURST) {
@ -4168,6 +4178,36 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
killflag(f); killflag(f);
} }
} else if (spellid == OT_S_CREATEFOOD) {
objecttype_t *ot;
object_t *o;
char obname[BUFLEN];
int i,amt;
if (!targcell || targcell->type->solid) {
fizzle(caster);
return B_TRUE;
}
for (i = 0; i < power; i++) {
ot = getrandomobofclass(OC_FOOD, NA, NA);
o = addobfast(targcell->obpile, ot->id);
if (i == 0) {
getobname(o, obname, o->amt);
amt = o->amt;
}
}
if (haslos(player, targcell)) {
if (power >= 8) {
msg("A grand feast appears!");
} else if (power >= 5) {
msg("A hearty meal appears!");
} else if (power >= 2) {
msg("Some light refreshments appear!");
} else { // ie. power == 1
msg("%s appear%s!", obname, (amt == 1) ? "s" : "");
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else if (spellid == OT_S_CREATEMONSTER) { } else if (spellid == OT_S_CREATEMONSTER) {
lifeform_t *newlf; lifeform_t *newlf;
race_t *r = NULL; race_t *r = NULL;
@ -4252,17 +4292,17 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
needredraw = B_TRUE; needredraw = B_TRUE;
ch = askchar("Teleport to the new vault", "yn","y", B_TRUE, B_FALSE); ch = askchar("Teleport to the new vault", "yn","y", B_TRUE, B_FALSE);
if (ch == 'y') { if (ch == 'y') {
int x,y; int ntries = 0;
// find it c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1);
for (y = vy; y < vy+vh; y++) { if (!c || !cellwalkable(caster, c, NULL)) {
for (x = vy; x < vx + vw; x++) { if (++ntries >= 10) {
c = getcellat(caster->cell->map, x, y); msg("Oops, couldn't find a free space.");
if (c && cellwalkable(caster, c, NULL)) {
teleportto(caster, c, B_TRUE);
return B_FALSE; return B_FALSE;
} }
c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1);
} }
} teleportto(caster, c, B_TRUE);
return B_FALSE;
} }
} }
@ -4837,12 +4877,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE; return B_FALSE;
} }
if (!isimmuneto(target->flags, DT_NECROTIC)) { if (!isimmuneto(target->flags, DT_NECROTIC, B_FALSE)) {
// animation (opposite dir) // animation (opposite dir)
anim(targcell, caster->cell, '%', C_MAGENTA); anim(targcell, caster->cell, '%', C_MAGENTA);
} }
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
if (isimmuneto(target->flags, DT_NECROTIC)) { if (isimmuneto(target->flags, DT_NECROTIC, B_FALSE)) {
msg("%s suck%s death from %s!",castername,isplayer(caster) ? "" : "s", lfname); msg("%s suck%s death from %s!",castername,isplayer(caster) ? "" : "s", lfname);
} else { } else {
msg("%s suck%s life from %s!",castername,isplayer(caster) ? "" : "s", lfname); msg("%s suck%s life from %s!",castername,isplayer(caster) ? "" : "s", lfname);
@ -4855,7 +4895,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (target) { if (target) {
int amt; int amt;
if (isimmuneto(target->flags, DT_NECROTIC)) { if (isimmuneto(target->flags, DT_NECROTIC, B_FALSE)) {
// target gains hp // target gains hp
amt = rnd(1,6) + power; amt = rnd(1,6) + power;
gainhp(target, amt); gainhp(target, amt);
@ -5574,14 +5614,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
dam = rolldie(exposedlimbs, 3); dam = rolldie(exposedlimbs, 3);
if (isplayer(target)) { if (isplayer(target)) {
if (isimmuneto(target->flags, DT_COLD)) { if (isimmuneto(target->flags, DT_COLD, B_FALSE)) {
msg("You feel mildly chilly."); msg("You feel mildly chilly.");
} else { } else {
msg("You feel extremely cold!"); msg("You feel extremely cold!");
} }
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player, target)) { } else if (cansee(player, target)) {
if (isimmuneto(target->flags, DT_COLD)) { if (isimmuneto(target->flags, DT_COLD, B_FALSE)) {
msg("%s looks mildly chilly.", lfname); msg("%s looks mildly chilly.", lfname);
} else { } else {
msg("%s looks extremely cold!", lfname); msg("%s looks extremely cold!", lfname);
@ -5591,7 +5631,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// target takes magical damage // target takes magical damage
// always hit // always hit
if (!isimmuneto(target->flags, DT_COLD)) { if (!isimmuneto(target->flags, DT_COLD, B_FALSE)) {
losehp(target, dam, DT_COLD, caster, "a frostbite spell"); losehp(target, dam, DT_COLD, caster, "a frostbite spell");
} }
} else if (spellid == OT_S_GASEOUSFORM) { } else if (spellid == OT_S_GASEOUSFORM) {
@ -5850,7 +5890,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
target = targcell->lf; target = targcell->lf;
if (target) { if (target) {
if (ismetal(target->race->material->id)) { if (ismetal(target->race->material->id)) {
if (!isimmuneto(target->flags, DT_HEAT)) { if (!isimmuneto(target->flags, DT_HEAT, B_FALSE)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("Your suffer massive burns!"); msg("Your suffer massive burns!");
} else if (cansee(player, target)) { } else if (cansee(player, target)) {
@ -5895,7 +5935,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
if (nburn && !isimmuneto(target->flags, DT_FIRE)) { if (nburn && !isimmuneto(target->flags, DT_FIRE, B_FALSE)) {
int i; int i;
losehp(target, rnd(nburn,4), DT_HEAT, caster, "red-hot metal"); losehp(target, rnd(nburn,4), DT_HEAT, caster, "red-hot metal");
if (isplayer(target)) { if (isplayer(target)) {
@ -6126,7 +6166,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
for (l = caster->cell->map->lf ; l ; l = l->next) { for (l = caster->cell->map->lf ; l ; l = l->next) {
if (l != caster) { if (l != caster) {
if (isimmuneto(l->flags, DT_NECROTIC) || if (isimmuneto(l->flags, DT_NECROTIC, B_FALSE) ||
spellresisted(l, caster, spellid, power, seenbyplayer, B_FALSE)) { spellresisted(l, caster, spellid, power, seenbyplayer, B_FALSE)) {
if (isplayer(l)) { if (isplayer(l)) {
msg("Luckily, the evil doesn't seem to harm you."); msg("Luckily, the evil doesn't seem to harm you.");
@ -6143,7 +6183,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// now hit the caster! // now hit the caster!
if (isimmuneto(caster->flags, DT_NECROTIC) || spellresisted(caster, caster, spellid, power, seenbyplayer, B_FALSE)) { if (isimmuneto(caster->flags, DT_NECROTIC, B_FALSE) || spellresisted(caster, caster, spellid, power, seenbyplayer, B_FALSE)) {
if (isplayer(caster)) { if (isplayer(caster)) {
msg("Luckily, the evil doesn't seem to harm you."); msg("Luckily, the evil doesn't seem to harm you.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -6534,7 +6574,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (cansee(player, target)) { if (cansee(player, target)) {
msg("A glob of venom hits %s.",lfname); msg("A glob of venom hits %s.",lfname);
} }
if (!isimmuneto(target->flags, DT_POISON)) { if (!isimmuneto(target->flags, DT_POISON, B_FALSE)) {
poison(target, power*3, P_VENOM, (power/4)+1, "a glob of venom"); poison(target, power*3, P_VENOM, (power/4)+1, "a glob of venom");
} }
} }
@ -7823,6 +7863,43 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!ndone) { if (!ndone) {
fizzle(caster); fizzle(caster);
} }
} else if (spellid == OT_S_QUICKENSTONE) {
int howmany,i,n,sel,nposs = 0,nseen = 0;
cell_t *c,*poss[MAXCANDIDATES];
howmany = (power / 2) + 1;
// get a list of all stone cells near caster
for (i = DC_N; i <= DC_NW; i++) {
c = getcellindir(caster->cell, i);
if (c && c->type->solid && (c->type->material->id == MT_STONE)) {
poss[nposs++] = c;
}
}
limit(&howmany, NA, nposs);
if (!howmany) {
fizzle(caster);
return B_TRUE;
}
// now change them
for (i = 0; i < howmany; i++) {
lifeform_t *lf;
// pick a random one
sel = rnd(0,nposs-1);
c = poss[sel];
// turn it into a golem
setcelltype(c, c->map->habitat->emptycelltype);
lf = summonmonster(caster, c, R_GOLEMSTONE, NULL, 30, B_TRUE);
if (haslos(player, c)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
nseen++;
}
// remove it from the list
for (n = sel ; n < (nposs-1); n++) {
poss[n] = poss[n+1];
}
nposs--;
}
// set dirty line of sight for caster, as walls have vanished
caster->losdirty = B_TRUE;
} else if (spellid == OT_S_LESSENPOISON) { } else if (spellid == OT_S_LESSENPOISON) {
flag_t *f; flag_t *f;
int ndone = 0; int ndone = 0;
@ -10097,7 +10174,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
// HOW POWERFUL IS THIS SPELL? // HOW POWERFUL IS THIS SPELL?
//////////////////////////////////// ////////////////////////////////////
if (isplayer(lf)) { if (isplayer(lf)) {
power = 1; // base power of 1. power = 1;
// plus your hitdice/3 // plus your hitdice/3
power += (gethitdice(lf)/3); power += (gethitdice(lf)/3);
@ -10114,8 +10191,8 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
power += (getstatmod(lf, A_IQ) / 50); power += (getstatmod(lf, A_IQ) / 50);
} }
// plus your school skill // plus any extra school levels
power += schoolskill; power += (schoolskill - spelllev);
} else { } else {
// for monsters, just based on hitdice: // for monsters, just based on hitdice:
power = gethitdice(lf); power = gethitdice(lf);

View File

@ -17,6 +17,6 @@ scatter(1,1,-2,-2) ob:corpse:1-5
! chance of great items... ! chance of great items...
scatter(1,1,-2,-2) ob:great armour:1:30 scatter(1,1,-2,-2) ob:great armour:1:30
scatter(1,1,-2,-2) ob:great weapon:1:30 scatter(1,1,-2,-2) ob:great weapon:1:30
rarity:uncommon rarity:vrare
@end @end

View File

@ -17,7 +17,7 @@ $:ob:25-200 gold
@flags @flags
goesin:dungeon goesin:dungeon
mayrotate mayrotate
rarity:uncommon rarity:vrare
! don't link to rest of map. ie this can be in the middle of nowhere. ! don't link to rest of map. ie this can be in the middle of nowhere.
nolink nolink
@end @end