- [+] vault:pub

- [+] has lots of recruitable people
- [+] plants, magic creatures, etc shoudl have infinite staina
- [+] severed fingers/heads are no longer considered "corpses".
- [+] new kind of bed: pile of straw
- [+] closed shops now work properly.
- [+] stench skillcheck (in makenauseated) - announce this differenlty
      to 'nothing happen's
- [+] monsters won't turn to face sounds when fleeing.
- [+] increase accuracy for spear, but reduce accuracy when adjacent 
- [+] why didn't cyborg warrior start with bullwhip equiped??
    - [+] isbetterwepthan() should take EXTRADAM flag into account
- [+] monster starting skill levels should depend on iq
- [+] no sprinting with injured legs
- [+] more restructions when stunned:
    - [+] no throwing
    - [+] no operating
    - [+] no firearms
- [+] tombstone text:   Eaten by a snow troll's halberd
- [+] bug: ekrub gained MASSIVE piety when i sacrificed a  soldier ant
      corpse! reduced.
- [+] learning certain lore skills should please gods
- [+] repairing should take a lot longer. ie. shoudlbn't be able to do
      it during a fight.
    - [+] workhelpobs (spanner/needle) should have F_HELPSREPAIR,
          v0=material, v1=howmuch
    - [+] continuerepairing() should only fix <skill + helpsrepair> hp
          per turn.
    - [+] announce helpsrepair in obdesc
- [+] coldroom vault:
    - [+] ice floor
    - [+] ice walls
    - [+] ice pillar
    - [+] frozen corpses
- [+] new job: gladiator
    - [+] sword
    - [+] shield
    - [+] high shield skill
    - [+] high evasion skill
    - [+] limited armour skill
    - [+] net
    - [+] war cry fairly early on
- [+] gust of wind and airblast should drop flying creatures
    - [+] fall_from_air().
    - [+] trigger then when wind-based effects hit.
    - [+] chance of falling depends on size.
- [+] if you polymorph a monster, it should NOT turn back to its
      original form!
- [+] criticals dont seem to be happening any more... fixed
- [+] when picking first askcoords target lf, pick the closest
- [+] sakcs etc should contain rarer objects.
- [+] intelligent ai: if exhausted and in battle, and faster than
      opponent, flee.???
- [+] easy way to fix reachability:
    - [+] is there a solid cell which is: 
        - [+]  adjacent to both a filled and an unfilled area?
        - [+] not a fixed vault wall?
    - [+] if so, just clear it.
- [+] genericise getrandomrace flags
- [+] some containers should have mini/tiny monsters inside!
    - [+] f_hashidinglf, v0=rid
    - [+] if you loot it, monster jumps out
        - [+] ...and gets a free hit!
    - [+] perception lets you see the container moving (only if it
          weighs less than what is inside it)
- [+] genericise getrandomcell() with conditionsets.
    * [+] condset_t
    - [+] then replace all getrandomadjcell() calls...
    - [+] remove getrandomroomcells
    - [+] then remove WE_xxx
This commit is contained in:
Rob Pearce 2012-11-13 05:04:30 +00:00
parent 64412035bb
commit 98ba363e8a
23 changed files with 1592 additions and 460 deletions

29
ai.c
View File

@ -23,9 +23,10 @@ extern int playerhasmoved;
int wantdb = B_TRUE;
void addignorecell(lifeform_t *lf, cell_t *c) {
if (!c) return;
int howmany = 0;
if (!c || !lf) return;
// TEST: just have one ignorecell at once.
killflagsofid(lf->flags, F_IGNORECELL);
howmany = killflagsofid(lf->flags, F_IGNORECELL);
addtempflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL, 10);
//if (c && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
// addtempflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL, 10);
@ -509,8 +510,6 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
return OT_NONE;
}
if (missingspellcastob(lf)) {
if (db) dblog(".oO { Cannot cast spell, I don't have my spellcast object }");
return OT_NONE;
@ -739,6 +738,12 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
object_t *o;
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
if (lfhasflag(lf, F_STUNNED)) {
if (db) dblog(".oO { no ranged attack because i am stunned }");
if (ra) *ra = RA_NONE;
return NULL;
}
if (lfhasflag(lf, F_RAGE)) {
if (db) dblog(".oO { no ranged attack because i am enraged }");
if (ra) *ra = RA_NONE;
@ -762,7 +767,7 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
}
o = getfirearm(lf);
if (o && getammo(o)) {
if (o && getammo(o) && canshoot(lf, NULL)) {
if (db) {
char gunname[BUFLEN];
getobname(o, gunname, o->amt);
@ -780,8 +785,7 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
} else {
o = aigetwand(lf, F_AICASTTOATTACK);
}
if (o) {
if (o && canoperate(lf, o, NULL)) {
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name);
if (ra) *ra = RA_WAND;
@ -791,7 +795,7 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
}
// can we attack by throwing something?
if (hasbp(lf, BP_HANDS)) {
if (hasbp(lf, BP_HANDS) && !lfhasflag(lf, F_STUNNED)) {
o = getbestthrowmissile(lf, target);
if (o) {
if (db) dblog(".oO { will throw %s at my target }", o->type->name);
@ -1093,7 +1097,7 @@ object_t *aigetwand(lifeform_t *lf, enum FLAG purpose) {
// wand with charges left?
if ((o->type->obclass->id == OC_WAND) && (getcharges(o) > 0)) {
// do we know how to use it?
if (hasflag(o->flags, purpose)) {
if (canoperate(lf, o, NULL) && hasflag(o->flags, purpose)) {
// TODO: if castatself, check whether we actually need to (ie. healing, invis, etc)
poss[nposs] = o;
nposs++;
@ -1871,7 +1875,7 @@ int ai_premovement(lifeform_t *lf) {
if (lfproduceslight(lf, NULL) && (lf->cell->map->illumination != IL_FULLLIT)) {
object_t *lamp;
lamp = hasobwithflagval(lf->pack, F_ACTIVATECONFER, F_PRODUCESLIGHT, NA, NA, NULL);
if (lamp && !isactivated(lamp)) {
if (lamp && !isactivated(lamp) && canoperate(lf, lamp, NULL)) {
if (db) dblog(".oO { it's dark and i have an inactive light source (%s) }", lamp->type->name);
if (!operate(lf, lamp, NULL)) {
if (db) dblog(".oO { successfully turned it on. }");
@ -3491,10 +3495,13 @@ int lookforobs(lifeform_t *lf) {
}
if (cancast(lf, OT_A_SNATCH, NULL) && haslofknown(lf->cell, c, LOF_NEED, NULL) &&
(getcelldist(lf->cell, c) == 1)) {
// only snatch those things which we can carry
if (canpickup(lf, o, 1)) {
if (!useability(lf, OT_A_SNATCH, NULL, c)) {
success = B_TRUE;
}
}
}
if (success) {
// got the object. now try to eat it if possible.
object_t *oo;
@ -3646,7 +3653,7 @@ int useitemwithflag(lifeform_t *lf, enum FLAG whichflag) {
if (!readsomething(lf, o)) {
return B_FALSE;
}
} else if ((o->type->obclass->id == OC_WAND) && getcharges(o)) {
} else if ((o->type->obclass->id == OC_WAND) && getcharges(o) && canoperate(lf, o, NULL)) {
// if wand, use it on ourself
if (!operate(lf, o, lf->cell)) {
return B_FALSE;

View File

@ -2979,6 +2979,15 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
int gothit = B_FALSE;
enum SKILLLEVEL lorelev = PR_INEPT;
flag_t *f;
int db = B_FALSE;
char lfname[BUFLEN];
char vicname[BUFLEN];
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
real_getlfname(lf, lfname, NULL, B_SHOWALL, B_CURRACE);
real_getlfname(victim, vicname, NULL, B_SHOWALL, B_CURRACE);
if (db) dblog("%s: rolling to hit %s", lfname, vicname);
// default
if (critical) *critical = 0;
@ -2987,6 +2996,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
// anticipate action spell?
if (lfhasflagval(victim, F_ANTICIPATE, lf->id, NA, NA, NULL)) {
if (db) dblog("%s: victim has anticipate action - MISS.", lfname);
return B_FALSE;
}
@ -3001,9 +3011,11 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
killflag(f);
}
gothit = B_TRUE;
if (db) dblog("%s: we have truestrike - HIT.", lfname);
} else if (critical && *critical) {
// forced critical?
// critical already set = forced critical
gothit = B_TRUE;
if (db) dblog("%s: pre-determined critical - HIT.", lfname);
} else {
int myroll;
int reachpenalty = 0;
@ -3011,29 +3023,46 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
baseacc = getlfaccuracy(lf, wep);
acc = baseacc;
if (db) dblog("%s: base accuracy: %d", lfname, baseacc);
// size difference (penalty for attacking smaller ones)
modifyforsize(&acc, lf, victim, -5, M_VAL);
if (db) dblog("%s: modified for victim size -> %d", lfname, acc);
// easier to hit victims who are prone.
if (isprone(victim)) {
acc += 30;
if (db) dblog("%s: +30 for prone victim -> %d", lfname, acc);
}
if (lfhasflag(lf, F_AIMEDSTRIKE)) {
acc -= 20;
if (db) dblog("%s: -20 for aimed strike -> %d", lfname, acc);
}
// easier to hit things which have grabbed you
if (lfhasflagval(lf, F_GRABBEDBY, victim->id, NA, NA, NULL)) {
acc += 30;
if (db) dblog("%s: +30 as victim is holding us -> %d", lfname, acc);
}
// MUCH easier to hit things which you have grabbed
if (lfhasflagval(lf, F_GRABBING, victim->id, NA, NA, NULL)) {
acc += 50;
if (db) dblog("%s: +50 as we are holding victim -> %d", lfname, acc);
}
if (wep && (getcelldist(lf->cell, victim->cell) <= 1)) {
f = hasflag(wep->flags, F_ADJACCMOD);
if (f) {
acc += f->val[0];
if (db) dblog("%s: %s%d for weapon adjacency modifier -> %d", lfname,
(f->val[0] < 0) ? "" : "+", f->val[0], acc);
}
}
if (!canreach(lf, victim, &reachpenalty)) {
acc -= (10*reachpenalty);
if (db) dblog("%s: -%d reach penalty -> %d", lfname, (10*reachpenalty), acc);
}
// modify for defender's evasion
@ -3044,15 +3073,28 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
}
acc -= ev;
if (db) dblog("%s: minus victim's evaion (%d) -> %d", lfname, ev, acc);
// modify if we can't see the victim
if (!cansee(lf, victim)) acc -= 30;
if (!cansee(lf, victim)) {
acc -= 30;
if (db) dblog("%s: -30 for not being able to see victim -> %d", lfname, acc);
}
// metal weapon versus magnetic shield?
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) acc -= 45;
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
acc -= 45;
if (db) dblog("%s: -45 for metal weapon vs magshield -> %d", lfname, acc);
}
// victim immobile or asleep?
if (isimmobile(victim) || lfhasflag(victim, F_EATING)) acc += 50;
if (isimmobile(victim) || lfhasflag(victim, F_EATING)) {
acc += 50;
if (db) dblog("%s: +50 for immobile victim -> %d", lfname, acc);
}
// modify for lore level
if (lorelev != PR_INEPT) acc += (lorelev*10);
if (lorelev != PR_INEPT) {
acc += (lorelev*10);
if (db) dblog("%s: +%d for knowledge about victim's race -> %d", lfname, lorelev*10, acc);
}
// modify for attacking while climbing
if (isclimbing(lf) && !lfhasflag(lf, F_SPIDERCLIMB)) {
@ -3066,10 +3108,15 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
default:
case PR_MASTER: break;
}
if (db) dblog("%s: modified for attacking while climbing -> %d", lfname, acc);
}
limit(&acc, 0, 100);
if (db) dblog("%s: FINAL ACCURACY: %d%%", lfname, acc);
if (db) {
msg("%s vs. %s - %d%% hit chance", lfname, vicname, acc);
}
//if (aidb) dblog(".oO { my modified chance to hit is %d %% }", acc);
myroll = rnd(1,100);
if (myroll <= acc) {
@ -3083,9 +3130,9 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
// critical chance
if (critical && gothit) {
int critpossible = B_TRUE;
if (lf && !lfhasflag(lf, F_NOGIVECRITS)) {
if (lf && lfhasflag(lf, F_NOGIVECRITS)) {
critpossible = B_FALSE;
} else if (victim && !lfhasflag(victim, F_NOTAKECRITS)) {
} else if (victim && lfhasflag(victim, F_NOTAKECRITS)) {
critpossible = B_FALSE;
}
if (critpossible) {
@ -3112,11 +3159,17 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical,
if (isexhausted(lf) || (baseacc <= 60) || !getweaponskill(lf, wep)) {
int nfailed = 0, i;
int nrolls = 1;
int newacc;
if (getskill(lf, SK_COMBAT) >= PR_BEGINNER) {
newacc = pctof(150, baseacc);
} else {
newacc = baseacc;
}
// chance to fumble
// if you miss, make more attack rolls. if you fail
// all of them, you fumble..
for (i = 0; i < nrolls; i++) {
if (!pctchance(acc)) nfailed++;
if (!pctchance(newacc)) nfailed++;
}
if (nfailed >= nrolls) {
*fumble = B_TRUE;

148
data.c
View File

@ -1,5 +1,6 @@
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "data.h"
@ -27,6 +28,7 @@ extern obmod_t *firstobmod,*lastobmod;
extern material_t *material,*lastmaterial;
extern lifeform_t *player;
extern plural_t *firstplural,*lastplural;
extern int totalraces;
extern hiddennamewithcol_t colour[];
extern char *bookadjective[];
@ -40,6 +42,9 @@ extern char *amuletnoun[];
extern objecttype_t *lastot;
extern condset_t ccwalkable;
void addbonustext(flagpile_t *fp, enum FLAG fid, char *text) {
int idx = -1;
flag_t *f;
@ -283,7 +288,7 @@ void initjobs(void) {
}
addflag(lastjob->flags, F_NOSCORE, B_TRUE, NA, NA, NULL);
addjob(J_ADVENTURER, "Adventurer", "Adventurers are a versatile jack-of-all-trades type job. They can learn all skills, and already have basic Cartography and Lore skills. They also start the game with three healing potions. Recommended for beginners.", JC_FIGHTERTHIEF);
addjob(J_ADVENTURER, "Adventurer", "Adventurers are a versatile jack-of-all-trades type job. They can learn all skills, and already have basic Cartography and Lore skills. They also start the game with three healing potions. Recommended for beginners.", JC_GENERAL);
// stat mods
addflag(lastjob->flags, F_ALIGNMENT, AL_NONE, NA, NA, "gne"); // ie. select
// initial objects
@ -493,7 +498,7 @@ void initjobs(void) {
f = addflag(lastjob->flags, F_RNDSPELLSCHOOL, SS_NATURE, 1, 6, NULL); addcondition(f, FC_IFMONSTER, 100);
///////////////////////////////////////
addjob(J_MONK, "Monk", "A life of strict self-discipline from an early age makes Monks masters of unarmed combat. This discipline extends to their minds, sometimes allowing them to develop powerful psionic abilities over time. On the downside, they are useless with most weapons and are strict vegetarians.", JC_FIGHTERMAGE);
addjob(J_MONK, "Monk", "A life of strict self-discipline from an early age makes Monks masters of unarmed combat. This discipline extends to their minds, sometimes allowing them to develop powerful psionic abilities over time. On the downside, they are useless with most weapons and are strict vegetarians.", JC_FIGHTERSPEC);
// stats
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 20, NA, NULL);
@ -654,7 +659,7 @@ void initjobs(void) {
// abilities
addflag(lastjob->flags, F_OBESE, B_TRUE, NA, NA, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addjob(J_NINJA, "Ninja", "A dark warrior-assassin dedicated to the art of ninjutsu. Ninjas are skilled with exotic weapons, and gain special martial arts abilities at higher levels.", JC_FIGHTER);
addjob(J_NINJA, "Ninja", "A dark warrior-assassin dedicated to the art of ninjutsu. Ninjas are skilled with exotic weapons, and gain special martial arts abilities at higher levels.", JC_FIGHTERSPEC);
// stats
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 5, NA, NULL);
@ -859,7 +864,7 @@ void initjobs(void) {
// abilities
addflag(lastjob->flags, F_MPDICE, 1, NA, NA, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addjob(J_ASSASSIN, "Assassin", "Rogues of a darker dispoistion sometimes become Assassins, famed for their skill at taking lives. Assassins have less ability in lockpicking or thievery than regular rogues, prefering to tackle their enemies head on.", JC_THIEF);
addjob(J_ASSASSIN, "Assassin", "Rogues of a darker dispoistion sometimes become Assassins, famed for their skill at taking lives. Assassins have less ability in lockpicking or thievery than regular rogues, prefering to tackle their enemies head on.", JC_FIGHTERTHIEF);
// stats
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 15, NA, NULL);
@ -1016,6 +1021,49 @@ void initjobs(void) {
addflag(lastjob->flags, F_LEVABIL, 10, OT_A_HURRICANESTRIKE, NA, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addjob(J_GLADIATOR, "Gladiator", "A slave-warrior whose life revolves around arena combat. Even when not in battle, gladiators maintain their fitness through a constant exercise regime. They do not tend to wear body armour, instead relying on their finely-honed senses for survival, along with their evasion and shield skills.", JC_FIGHTER);
// stats
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 15, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_IQ, 0, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_CON, 20, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_CHA, 20, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_WIS, 0, NA, NULL);
addflag(lastjob->flags, F_ALIGNMENT, AL_NONE, NA, NA, "gne");
// initial objects
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "gladius");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "apsis");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "throwing net");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of sandals");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "30-40 gold dollars");
// initial skills
addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_COMBAT, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_EVASION, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SHIELDS, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LISTEN, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SEWING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_METALWORK, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_THROWING, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TWOWEAPON, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_BEGINNER, NA, NULL);
// learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_ARMOUR, PR_NOVICE, NA, NULL); // limited
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, PR_BEGINNER, NA, NULL); // limited
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_ARMOUR, PR_NOVICE, NA, NULL); // limit
addflag(lastjob->flags, F_CANLEARN, SK_LORE_LANGUAGE, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SWIMMING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_MPDICE, 1, -1, NA, NULL);
addflag(lastjob->flags, F_LEVABIL, 4, OT_A_WARCRY, NA, NULL);
//addflag(lastjob->flags, F_MAXHPMOD, 120, NA, NA, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addjob(J_BATTLEMAGE, "Battlemage", "Unlike other warriors Battlemages are minimally skilled in magic, but at the expense of the regular warrior abilities.", JC_FIGHTERMAGE);
// stats
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 10, NA, NULL);
@ -1143,7 +1191,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_LEVABIL, 5, OT_S_DISRUPTUNDEAD, NA, NULL);
addflag(lastjob->flags, F_LEVABIL, 7, OT_S_EXORCISE, NA, "pw:1;");
addjob(J_SCOURGE, "Scourge", "Scourges have dedicated their life to ridding the world of magic. Strict training has granted them an innate immunity to magic, but this immunity also extends to beneficial effects.", JC_FIGHTER);
addjob(J_SCOURGE, "Scourge", "Scourges have dedicated their life to ridding the world of magic. Strict training has granted them an innate immunity to magic, but this immunity also extends to beneficial effects.", JC_FIGHTERSPEC);
// stats
addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 10, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 10, NA, NULL);
@ -1627,7 +1675,6 @@ void initobjects(void) {
flag_t *f;
int i,n;
// init poison types
addpoisontype(P_MIGRAINE, "a migraine", "Sick", "have developed", "", OT_NONE, 0, 0, PS_DISEASE,20);
addpoisontype(P_COLD, "hypothermia", "Sick", "are sick with", "^bYOU cough#S violently.", OT_NONE, 1, 25, PS_DISEASE, 30);
@ -3363,7 +3410,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 90, NA, "");
addflag(lastot->flags, F_ISMEAT, B_TRUE, 80, NA, "");
addot(OT_MUSHROOMSHI, "shiitake mushroom", "A large brown mushroom.", MT_FOOD, 0.2, OC_FOOD, SZ_TINY);
addot(OT_MUSHROOMSHI, "shiitake mushroom", "A large brown mushroom.", MT_FOOD, 0.05, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 30, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, NULL);
@ -3372,7 +3419,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_ANTNEST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, "");
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "mushroom");
addot(OT_MUSHROOMTOAD, "toadstool", "A poisonous variety of mushroom.", MT_FOOD, 0.2, OC_FOOD, SZ_TINY);
addot(OT_MUSHROOMTOAD, "toadstool", "A poisonous variety of mushroom.", MT_FOOD, 0.05, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, NULL);
addflag(lastot->flags, F_TAINTED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_COMMON, NULL);
@ -3385,7 +3432,7 @@ void initobjects(void) {
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "mushroom");
addot(OT_MUSHROOMGREY, "greycap", "A strange mushroom with a greyish-white tip.", MT_FOOD, 0.2, OC_FOOD, SZ_TINY);
addot(OT_MUSHROOMGREY, "greycap", "A strange mushroom with a greyish-white tip.", MT_FOOD, 0.05, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, NULL);
addflag(lastot->flags, F_TAINTED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_UNCOMMON, NULL);
@ -3396,7 +3443,7 @@ void initobjects(void) {
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "mushroom");
addot(OT_MUSHROOMSTUFFED, "stuffed mushroom", "A large brown mushroom stuffed with breadcrumbs. This healthy food slightly increases your maximum hit points..", MT_FOOD, 0.2, OC_FOOD, SZ_TINY);
addot(OT_MUSHROOMSTUFFED, "stuffed mushroom", "A large brown mushroom stuffed with breadcrumbs. This healthy food slightly increases your maximum hit points..", MT_FOOD, 0.1, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 30, NA, "");
addot(OT_NUT, "peanut", "A species in the legume family.", MT_FOOD, 0.1, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL);
@ -3465,7 +3512,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL); // will be overridden
addflag(lastot->flags, F_ISMEAT, B_TRUE, 80, NA, "");
addot(OT_HEAD, "head", "xxx", MT_FLESH, 1, OC_CORPSE, SZ_SMALL);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL); // will be overridden
//addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL); // will be overridden
addflag(lastot->flags, F_ISMEAT, B_TRUE, 80, NA, "");
addot(OT_FLESHCHUNK, "chunk of flesh", "A chunk of flesh from something.", MT_FLESH, 1, OC_FOOD, SZ_SMALL);
addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL);
@ -3739,7 +3786,7 @@ void initobjects(void) {
addot(OT_SCR_MAPPING, "scroll of sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, 4, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_COMMON, NULL);
/*
addot(OT_SCR_MINDSCAN, "scroll of mind scan", "Allows you to view the world through another creature's eyes.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
@ -5823,6 +5870,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, '^', NA, NULL);
addflag(lastot->flags, F_SHARP, 2, 5, NA, NULL);
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_PIERCE, FALLTHRU, "1d4");
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
addflag(lastot->flags, F_VALUE, 20, NA, NA, NULL);
@ -5948,6 +5996,7 @@ void initobjects(void) {
addflag(lastot->flags, F_STARTOBRND, 30, NA, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 10, NA, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_SACKLARGE, VT_OB, NA, NULL);
addflag(lastot->flags, F_CANHAVELFINSIDE, 5, 5, 50, NULL);
addot(OT_SACKLARGE, "large sack", "A large cloth sack.", MT_CLOTH, 1, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
@ -5964,6 +6013,7 @@ void initobjects(void) {
addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_SACKHUGE, VT_OB, NA, NULL);
addflag(lastot->flags, F_SHRINKSTO, OT_SACK, VT_OB, NA, NULL);
addflag(lastot->flags, F_CANHAVELFINSIDE, 5, 5, 50, NULL);
addot(OT_SACKHUGE, "huge sack", "An enormous cloth sack.", MT_CLOTH, 1, OC_TOOLS, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
@ -5983,6 +6033,7 @@ void initobjects(void) {
addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL);
addflag(lastot->flags, F_SHRINKSTO, OT_SACKLARGE, VT_OB, NA, NULL);
addflag(lastot->flags, F_CANHAVELFINSIDE, 5, 5, 50, NULL);
addot(OT_BAGOFHOLDING, "bag of holding", "A magical sack which causes items placed inside it to become weightless.", MT_CLOTH, 0.5, OC_TOOLS, SZ_SMALL);
@ -6965,6 +7016,15 @@ void initobjects(void) {
addflag(lastot->flags, F_GROWSTO, OT_DOORWOOD, VT_OB, NA, NULL);
addflag(lastot->flags, F_SHRINKSTO, OT_WOODENTABLE, VT_OB, NA, NULL);
addot(OT_BEDSTRAW, "pile of straw", "A large pile of straw. Looks like it would be mildly more comfortable to sleep on than the floor.", MT_PLANT, 10, OC_FURNITURE, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '_', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 15, 0, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_TREE, VT_OB, NA, NULL);
addflag(lastot->flags, F_SHRINKSTO, OT_SHRUB, VT_OB, NA, NULL);
addot(OT_BOOKSHELF, "bookshelf", "A set of wooden shelves, sized for book storage.", MT_WOOD, 150, OC_FURNITURE, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_GLYPH, C_BROWN, '\\', NA, NULL);
@ -7914,7 +7974,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 5, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_WOODENTABLE, VT_OB, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_APSIS, VT_OB, NA, NULL);
// similar to a buckler, but repairable, lighter, and less durable
addot(OT_SHIELDHIDE, "hide shield", "A small shield constructed out of animal skin.", MT_LEATHER, 2.00, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
@ -7925,6 +7985,17 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 18, 18, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_CORPSE, VT_OB, NA, NULL);
//
addot(OT_APSIS, "apsis", "A sturdy, bowl-shaped leather shield. Slightly more durable than a buckler.", MT_LEATHER, 4.00, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CANBLOCK, DT_ALL, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SHIELDPENALTY, 10, NA, NULL);
addflag(lastot->flags, F_OBHP, 25, 25, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
addflag(lastot->flags, F_GROWSTO, OT_ARMOURLEATHER, VT_OB, NA, NULL);
addot(OT_SHIELD, "shield", "A medium-sized metal shield.", MT_METAL, 4.00, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL);
@ -8475,6 +8546,8 @@ void initobjects(void) {
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 25, NA, NULL);
addflag(lastot->flags, F_MISSILEALWAYSDIES, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREPAIR, MT_LEATHER, 2, 15, NULL);
addflag(lastot->flags, F_HELPSREPAIR, MT_CLOTH, 3, 15, NULL);
addot(OT_NET, "throwing net", "A grid of strong cords, weighted at the edges. Made for throwing over a target.", MT_CLOTH, 2, OC_MISSILE, SZ_MEDIUM);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
@ -9067,7 +9140,8 @@ void initobjects(void) {
addflag(lastot->flags, F_DAM, DT_PIERCE, 11, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, "butt bash");
addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
addflag(lastot->flags, F_ADJACCMOD, -15, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_AGI, 65, 80, "10");
addflag(lastot->flags, F_CRITCHANCE, 1, NA, NA, NULL);
@ -9090,7 +9164,8 @@ void initobjects(void) {
addflag(lastot->flags, F_DAM, DT_PIERCE, 11, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, "butt bash");
addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_ADJACCMOD, -10, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 45, 65, "1");
addflag(lastot->flags, F_ATTREQ, A_AGI, 65, 80, "5");
@ -9110,7 +9185,8 @@ void initobjects(void) {
addflag(lastot->flags, F_DAM, DT_PIERCE, 10, NA, NULL);
addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, "butt bash");
addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 65, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); // less when adjacent
addflag(lastot->flags, F_ADJACCMOD, -10, NA, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
@ -9334,6 +9410,7 @@ void initobjects(void) {
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_HELPSDISARM, 5, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREPAIR, MT_METAL, 2, 15, 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);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
@ -10370,7 +10447,7 @@ void initrace(void) {
noarmouron(lastrace, BP_EARS);
addflag(lastrace->flags, F_PLAYABLE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_AVERAGE, NA, NULL);
@ -10401,7 +10478,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTSKILL, SK_LISTEN, PR_NOVICE, NA, NULL);
// penalties
addbonustext(lastrace->flags, F_PENDESC, "Can never learn Athletics.");
addflag(lastrace->flags, F_VISRANGEMOD, -2, NA, NA, NULL);
addflag(lastrace->flags, F_VISRANGEMOD, -3, 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_NOSKILL, SK_ATHLETICS, NA, NA, NULL);
@ -11032,7 +11109,7 @@ void initrace(void) {
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking plants");
addflag(lastrace->flags, F_HATESRACECLASS, RC_DRAGON, NA, NA, NULL);
// sacrifices
addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, RC_ANIMAL, 10, "Writhing vines sprout up and drag OB underground.");
addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, RC_ANIMAL, 5, "Writhing vines sprout up and drag OB underground.");
addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, RC_DRAGON, 25, "Writhing vines sprout up and tear OB to pieces!");
addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_FOOD, NA, 3, "Writhing vines sprout up and drag OB underground.");
addflag(lastrace->flags, F_SACRIFICEOBCLASS, OC_FLORA, NA, 2, "OB transforms into a beautiful butterfly!");
@ -11720,7 +11797,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HITDICE, 7, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
//addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
addflag(lastrace->flags, F_NATURALFLIGHT, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_MOVESPEED, SP_VERYSLOW, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLSPEED, SP_VERYSLOW, NA, NA, NULL);
@ -11837,7 +11914,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
@ -11879,7 +11956,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 2, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 20, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_NATURALFLIGHT, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL);
@ -12214,7 +12291,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 9, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
//addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
@ -12338,7 +12415,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL);
@ -12385,7 +12462,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL);
@ -12460,7 +12537,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 6, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL);
@ -12532,7 +12609,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 3, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
addflag(lastrace->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
@ -12566,7 +12643,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 7, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 20, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
@ -12644,7 +12721,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 8, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 8, NA, NULL);
@ -12689,7 +12766,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HITDICE, 7, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
//addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 10, NA, NULL);
@ -12812,7 +12889,6 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL);
@ -12952,7 +13028,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_NATURALFLIGHT, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL);
@ -17685,7 +17761,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 1, NA, 4, NULL);
addflag(lastrace->flags, F_TR, 1, NA, NA, NULL);
addflag(lastrace->flags, F_FLIGHTEVASION, 50, NA, NA, NULL);
addflag(lastrace->flags, F_FLIGHTEVASION, 15, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_ZAPPER, 1, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_FLASH, 15, 15, "pw:4;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "pulses");
@ -18885,6 +18961,7 @@ void initrace(void) {
// now do final steps in race initialisation:
// - add flags based on raceclass, etc
// - fill in missing alignments
totalraces = 0;
for (r = firstrace ; r ; r = r->next) {
if (hasflag(r->flags, F_PLAYABLE)) {
r->known = B_TRUE;
@ -19000,6 +19077,7 @@ void initrace(void) {
if (!hasflag(r->flags, F_ALIGNMENT)) {
addflag(r->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
}
totalraces++;
}
}
@ -19080,6 +19158,7 @@ void initskills(void) {
addskilldesc(SK_COMBAT, PR_NOVICE, "Unskilled weapon penalties are greatly reduced.", B_FALSE);
addskillabil(SK_COMBAT, PR_NOVICE, OT_A_STRIKETOKO, NA, NULL, B_TRUE);
addskilldesc(SK_COMBAT, PR_BEGINNER, "Eliminates penalties for being prone or nauseated.", B_FALSE);
addskilldesc(SK_COMBAT, PR_BEGINNER, "Reduced chance of fumbling attacks.", B_FALSE);
addskilldesc(SK_COMBAT, PR_ADEPT, "Eliminates penalties when fighting unseen enemies.", B_FALSE);
addskillabil(SK_COMBAT, PR_ADEPT, OT_A_DISARMLF, NA, NULL, B_TRUE);
addskillabil(SK_COMBAT, PR_SKILLED, OT_A_FLIP, NA, NULL, B_TRUE);
@ -19214,7 +19293,8 @@ void initskills(void) {
addskilldesc(SK_TECHUSAGE, PR_EXPERT, "^gYou can now recognise level 5 Tech.^n", B_TRUE);
addskilldesc(SK_TECHUSAGE, PR_MASTER, "^gYou can now recognise level 6 Tech.^n", B_TRUE);
addskill(SK_THIEVERY, "Thievery", "Your ability to pick pockets and steal items.", 50);
addskilldesc(SK_THIEVERY, PR_NOVICE, "^gYou gain the 'steal' ability, usable on enemies or in shops.^n", B_FALSE);
//addskilldesc(SK_THIEVERY, PR_NOVICE, "^gYou gain the 'steal' ability, usable on enemies or in shops.^n", B_FALSE);
addskillabil(SK_THIEVERY, PR_NOVICE, OT_A_STEAL, NA, NULL, B_TRUE);
addskilldesc(SK_THIEVERY, PR_BEGINNER, "^gYour accuracy penalty when stealing is reduced.^n", B_TRUE);
addskilldesc(SK_THIEVERY, PR_ADEPT, "^gYou can now choose which items to steal.^n", B_TRUE);
addskilldesc(SK_THIEVERY, PR_SKILLED, "^gYou can now steal heavy items.", B_TRUE);

Binary file not shown.

View File

@ -12,6 +12,7 @@
.:cell:carpetted floor
#:cell:SOLID
b:ob:wooden bed
b:mon:sleeping humanoid:75
t:ob:wooden table
a:ob:armour rack
c:ob:candelabrum

55
defs.h
View File

@ -73,6 +73,7 @@
#define UNI_TREE 0x2042
// getrandomemptycell() params
/*
#define WE_NONE 0
#define WE_WALKABLE 1
#define WE_EMPTY 2
@ -80,6 +81,7 @@
#define WE_NOTWALL 4
#define WE_NOLF 5
#define WE_SOLID 6
*/
// Booleans
#define B_FALSE (0)
@ -367,6 +369,31 @@
#define MAXDIR_MAP 15
enum CELLCONDITION {
CC_NONE, //
// CELLS
CC_CELLTYPE, // arg is celltype id
CC_DANGEROUSFOR, // arg is lf id
CC_EMPTY, // no arg
CC_OKFORPORTAL, // no arg
CC_OKFORSTAIRS, // no arg
CC_HASLF, // no arg
CC_HASMATERIAL, // arg is material id
CC_HASOBTYPE, // arg is ob id
CC_HASROOMID, // arg is room id
CC_IMPASSABLE, // no arg
CC_ISROOM, // arg is ob id
CC_SOLID, // no arg
CC_WALKABLE, // no arg
CC_WALKABLEFOR, // arg is lfid
// RACES
CC_HASFLAG, // arg is flagid
CC_HASCORPSE, // no arg
CC_HASSIZE, // arg is enum lfsize
};
enum GODBONUS {
GB_DTRESIST, // resist damtype 'arg'
GB_DTIMMUNE, // immune to damtype 'arg'
@ -893,6 +920,7 @@ enum CELLTYPE {
CT_WALLDIRT,
CT_WALLFLESH,
CT_WALLGLASS,
CT_WALLICE,
CT_WALLMETAL,
CT_WALLTREE,
CT_WALLWOOD,
@ -1347,6 +1375,7 @@ enum JOB {
J_ALLOMANCER,
J_WARRIOR,
J_BATTLEMAGE,
J_GLADIATOR,
J_PALADIN,
J_SCOURGE,
J_CHEF,
@ -1380,6 +1409,7 @@ enum JOBCATEGORY {
JC_NONE,
JC_FIGHTER,
JC_FIGHTERRANGED,
JC_FIGHTERSPEC,
JC_MAGE,
JC_THIEF,
JC_FIGHTERMAGE,
@ -2085,6 +2115,7 @@ enum OBTYPE {
// furniture
OT_ARMOURRACK,
OT_BED,
OT_BEDSTRAW,
OT_BOOKSHELF,
OT_CANDELABRUM,
OT_COFFIN,
@ -2214,6 +2245,7 @@ enum OBTYPE {
OT_EYEPATCH,
OT_SUNGLASSES,
// armour - shields
OT_APSIS,
OT_BUCKLER,
OT_SHIELD,
OT_SHIELDHIDE,
@ -2822,9 +2854,12 @@ enum FLAG {
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_HELPSREPAIR, // object gives v1 bonus to repairing obejcts
// made of material v0. Also decreases the
// damage cutoff by v2.
F_HELPSREST, // makes you heal mp/hp faster when using 'R'
// reduces skillcheck difficulty by v0.
// optional v1 = how many less turns between
// optional v1 = how many fewer turns between
// skillchecks. should not go more than
// DEFAULTRESTHEALTIME.
F_DONTSHOWDEST, // don't show destination of this stair
@ -2872,6 +2907,11 @@ enum FLAG {
// vulnerable to, the object's material will be
// automatically changed to the first listed.
// CANBEDIFFMAT.
F_CANHAVELFINSIDE, // this object might start with a monster
// hiding inside it.
// v0 = base pct chance
// v1 = extra pct chance every 5 levels
// v2 = max chance
F_CANBETRAPPED, // this object might start with a trap
// v0 = base pct chance
// v1 = extra pct chance every 5 levels
@ -3039,6 +3079,7 @@ enum FLAG {
// if V1/V2 are set, then F_RESTRICTMOVEMENT
// v1->v0, v2->v1 is added to this object after it hits.
F_ACCURACY, // 100 - val0 = modify to tohit% (ie. higher is better)
F_ADJACCMOD, // +v0% tohit adjacent enemies
F_UNARMEDWEP, // this is not a real weapon, ie. claws, teeth etc
F_ARMOURIGNORE, // armour has no effect
F_ARMOURPIERCE, // goes through armour. armour can't reduce the
@ -3087,6 +3128,8 @@ enum FLAG {
F_LINKOB, // val0 = linked object id
F_LINKRACE, // val0 = linked race id
F_LINKGOD, // val0 = linked god race id
// container flags
F_LFINSIDE, // lf of race v0 is inside.
// scroll flags
F_LINKSPELL, // val0 = spell this scroll will cast when read
// v1 = spell power (optional)
@ -3882,6 +3925,7 @@ enum FLAG {
// on objects:
// creatures standing on it gain f_nauseated = v1
F_STUNNED, // cannot attack or cast spells
// or use firearms, or throw, or operate stuff
F_TREMORSENSE, // doesn't need eyes to see, can see in dark with v0
F_PRODUCESLIGHT, // produces light of val0 radius.
// (but not for obs in pack)
@ -4147,10 +4191,12 @@ enum ERROR {
E_WEARINGSOMETHINGELSE,
E_NOUNARMEDATTACK,
E_NOTEQUIPPED,
E_EQUIPPED,
E_NOPICKUP,
E_STUCK,
E_MONSTERNEARBY,
E_NOEFFECT,
E_RESISTED,
E_FAILED,
E_WRONGCELLTYPE,
E_OBINWAY,
@ -4193,6 +4239,7 @@ enum ERROR {
E_LOWWIS,
E_WONT,
E_OFFMAP,
E_RAGE,
E_STUNNED,
// charm failure reasons
// LOWIQ
@ -4289,6 +4336,12 @@ enum COMMAND {
CMD_EXCHANGE,
};
typedef struct condset_s {
enum CELLCONDITION cond[MAXCANDIDATES];
int arg[MAXCANDIDATES];
int val[MAXCANDIDATES];
int nconds;
} condset_t;
typedef struct behaviour_s {
enum BEHAVIOUR id;

81
flag.c
View File

@ -58,12 +58,13 @@ flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int lifetime, int known, long obfromid) {
lifeform_t *lf;
flag_t *f;
flag_t *f = NULL;
//map_t *redolight = NULL;
int redrawscreenatend = B_FALSE;
int redrawstatatend = B_FALSE;
int i;
int rv;
enum { NONE, FIRST, FIRST2, MIDDLE, LAST } fml = NONE;
//checkflagpile(fp);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
@ -150,7 +151,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
////////////////////////////////
if (fp->first == NULL) {
fp->first = malloc(sizeof(flag_t));
fp->first = (flag_t *)calloc(1, sizeof(flag_t));
f = fp->first;
f->prev = NULL;
@ -158,6 +159,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
fp->last = f;
f->next = NULL;
fml = FIRST;
} else {
flag_t *ff;
// we will keep flags sorted.
@ -166,35 +168,58 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
while (ff && (ff->id < id)) {
ff = ff->next;
}
if (ff) {
// start or middle of list
// insert BEFORE this one
flag_t *newone = NULL;
flag_t *prev;
prev = ff->prev;
// allocate new flag
newone = (flag_t *)calloc(1, sizeof(flag_t));
assert(newone != NULL);
// link to previous element
if (prev) {
prev->next = malloc(sizeof(flag_t));
f = prev->next;
flag_t *origpn;
//f = (flag_t *)malloc(sizeof(flag_t)); assert(f);
//prev->next = f;
origpn = prev->next;
prev->next = newone;
assert(prev->next != origpn);
assert(prev->next != ff);
//f = prev->next;
f = newone;
fml = MIDDLE;
} else {
// first one
fp->first = malloc(sizeof(flag_t));
f = fp->first;
//fp->first = (flag_t *)calloc(1, sizeof(flag_t));
fp->first = newone;
assert(fp->first != NULL);
//f = fp->first;
f = newone;
fml = FIRST2;
}
assert(prev != f);
f->prev = prev;
// link to next element
assert(ff != f);
f->next = ff;
ff->prev = f;
} else {
// last one. insert at end of list.
f = fp->last;
f->next = malloc(sizeof(flag_t)); /// <- died here!
f->next = (flag_t *)malloc(sizeof(flag_t)); /// <- died here!
f->next->prev = f;
f = f->next;
fp->last = f;
f->next = NULL;
fml = LAST;
}
/*
// go to end of list
@ -205,6 +230,8 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
*/
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
assert(f->prev != f);
assert(f->next != f);
// fill in props
f->id = id;
@ -979,10 +1006,12 @@ int istransitoryflag(flag_t *f) {
}
// returns true if we did something
// returns # flags killed
int killflagsofid(flagpile_t *fp, enum FLAG fid) {
flag_t *f,*nextf;
int donesomething = B_FALSE;
flag_t *f;
//,*nextf;
int ndone = 0;
/*
for (f = fp->first ; f ; f = nextf) {
nextf = f->next;
@ -994,7 +1023,14 @@ int killflagsofid(flagpile_t *fp, enum FLAG fid) {
donesomething = B_TRUE;
}
}
return donesomething;
*/
f = hasflag(fp, fid);
while (f) {
killflag(f);
ndone++;
f = hasflag(fp, fid);
}
return ndone;
}
// returns # flags removed if we did something
@ -1034,9 +1070,14 @@ void killflag(flag_t *f) {
int redostat = B_FALSE;
int redoscreen = B_FALSE;
int i,dopleasegod[MAXGODS];
flagpile_t *newflags = NULL;
//checkflagpile(f->pile);
// remember the pile so that we can re-index
pile = f->pile;
fid = f->id;
for (i = 0; i < ngodlfs; i++) {
@ -1099,7 +1140,8 @@ void killflag(flag_t *f) {
// once you recover from fleeing from something,
// you don't find it scary for a little while.
if (!lfhasflagval(lf, F_NOFLEEFROM, f->val[0], NA, NA, NULL)) {
addtempflag(lf->flags, F_NOFLEEFROM, f->val[0], NA, NA, NULL, 10);
if (!newflags) newflags = addflagpile(NULL, NULL);
addtempflag(newflags, F_NOFLEEFROM, f->val[0], NA, NA, NULL, 10);
}
} else if (f->id == F_RAGE) {
if (!isdead(lf)) {
@ -1114,8 +1156,9 @@ void killflag(flag_t *f) {
// announce
if (announceflagloss(lf, f)) {
if (flagcausesinterrupt(f, GL_LOSS)) {
addflag(lf->flags, F_INTERRUPTED, B_TRUE, NA, NA, NULL);
if (flagcausesinterrupt(f, GL_LOSS) && !hasflag(lf->flags, F_INTERRUPTED)) {
if (!newflags) newflags = addflagpile(NULL, NULL);
addflag(newflags, F_INTERRUPTED, B_TRUE, NA, NA, NULL);
}
/*
// don't include flags which interrupt will kill!
@ -1159,9 +1202,6 @@ void killflag(flag_t *f) {
// now we are actually removing the flag.
/////////////////////////////////////////////
// remember the pile so that we can re-index
pile = f->pile;
// free mem
if (f->text) {
free(f->text);
@ -1249,6 +1289,11 @@ void killflag(flag_t *f) {
}
}
//checkflagpile(pile);
// NOW add the new flags.
if (newflags) {
copyflags(pile, newflags, NA);
killflagpile(newflags);
}
}
void killflagpile(flagpile_t *fp) {

18
god.c
View File

@ -31,6 +31,8 @@ extern skill_t *firstskill, *lastskill;
extern objecttype_t *objecttype;
extern lifeform_t *player;
extern condset_t ccwalkable;
lifeform_t *godlf[MAXGODS];
int ngodlfs = 0;
@ -520,6 +522,7 @@ void askforworship(enum RACE rid) {
lifeform_t *god;
char yn;
if (lfhasflag(player, F_NOPRAY)) return;
// make sure the player knows about it!
killtransitoryflags(player->flags, F_BLIND);
@ -686,7 +689,7 @@ void dooffer(void) {
// special effect sacrificing flora to ekrub makes it turn into a
// butterfly
if ((god->race->id == R_GODNATURE) && (o->type->obclass->id == OC_FLORA)) {
newcell = getrandomadjcell(player->cell, B_FALSE, B_NOEXPAND);
newcell = getrandomadjcell(player->cell, &ccwalkable, B_NOEXPAND);
}
if (haslos(player, player->cell)) {
@ -1041,13 +1044,16 @@ lifeform_t *godappears(enum RACE rid, cell_t *where) {
real_getlfname(god, godname, NULL, B_NOSHOWALL, B_REALRACE);
strcpy(killedname, "");
if (!where) {
condset_t cs;
// somewhere next to the player.
where = real_getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, player, MT_NOTHING);
where = real_getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, player);
if (!where) {
where = real_getrandomadjcell(player->cell, WE_NOTWALL, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, player, MT_NOTHING);
initcond(&cs); addcond(&cs, CC_IMPASSABLE, B_FALSE, NA);
where = real_getrandomadjcell(player->cell, &cs, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, player);
}
if (!where) {
where = real_getrandomadjcell(player->cell, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, player, MT_NOTHING);
initcond(&cs); addcond(&cs, CC_IMPASSABLE, B_FALSE, NA);
where = real_getrandomadjcell(player->cell, &cs, B_ALLOWEXPAND, LOF_DONTNEED, NULL, player);
}
}
@ -2196,7 +2202,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
break;
case R_GODPURITY:
msg("\"Witness the holy radiance of purity!\"");
c = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND);
if (c) {
dospelleffects(god, OT_S_LIGHT, 10, NULL, NULL, c, B_BLESSED, NULL, B_TRUE, NULL);
}
@ -2324,7 +2330,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
who->hp = 0;
} else if (n != OT_NONE) {
if (n == OT_S_HECTASSERVANT) {
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND);
if (c) {
castspell(god, n, player, NULL, c, NULL, NULL);
}

51
io.c
View File

@ -81,6 +81,8 @@ extern job_t *firstjob;
extern enum GAMEMODE gamemode;
extern long curtime;
extern condset_t ccwalkable;
char msgbuf[HUGEBUFLEN];
char lastmsgbuf[HUGEBUFLEN];
char prevmsg[HUGEBUFLEN];
@ -667,9 +669,23 @@ cell_t *real_askcoords(char *prompt, char *subprompt, int targettype, lifeform_t
}
if ((curtarget == -1) && ntargets) {
int closest = -1,i;
// set to the closest one.
//curtarget = ntargets;
for (i = 0; i < ntargets; i++) {
if (closest == -1) {
closest = i;
} else if (getcelldist(srclf->cell, target[i]) <
getcelldist(srclf->cell, target[closest])) {
closest = i;
}
}
if (closest != -1) {
curtarget = closest;
} else {
curtarget = 0;
}
}
// start prompting
if (curtarget == -1) {
@ -4567,7 +4583,7 @@ void docomms(lifeform_t *lf) {
break;
}
// find adjacent cell
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND);
if (c) {
aigoto(lf, c, MR_OTHER, NULL, DEF_AIFOLLOWTIME);
}
@ -6592,6 +6608,13 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, "It gives a +%d%% bonus when disarming traps.\n", f->val[0] * 5);
strncat(retbuf, buf, HUGEBUFLEN);
}
getflags(o->flags, retflag, &nretflags, F_HELPSREPAIR, F_NONE);
for (i = 0; i < nretflags; i++) {
material_t *m;
m = findmaterial(retflag[i]->val[0]);
sprintf(buf, "It provides a +%d bonus whenrepairing %s objects.", retflag[i]->val[1], m->name);
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);
@ -8722,9 +8745,10 @@ void dofinaloblist(obpile_t *op) {
}
void dofire(void) {
if (shoot(player)) {
enum ERROR why;
if (!canshoot(player, &why)) {
// why not?
switch (reason) {
switch (why) {
case E_NOTEQUIPPED:
msg("You have no firearm equipped!");
break;
@ -8738,7 +8762,10 @@ void dofire(void) {
msg("You cannot fire for some reason!");
break;
}
return;
}
shoot(player);
}
void dohelp(char helpmode) {
@ -9132,7 +9159,6 @@ int dotakeoff(obpile_t *op) {
// returns B_TRUE on failure.
int dothrow(obpile_t *op, object_t *o) {
char buf[BUFLEN],buf2[BUFLEN];
flag_t *f;
if (!hasbp(player, BP_HANDS)) {
msg("You have no hands to throw with!");
@ -9147,22 +9173,23 @@ int dothrow(obpile_t *op, object_t *o) {
int maxdist;
char subprompt[BUFLEN],oidbuf[BUFLENSMALL];
cell_t *where;
enum ERROR why;
getobname(o, buf, 1);
f = hasflag(o->flags, F_EQUIPPED);
if (f && (f->val[0] != BP_WEAPON)) {
msg("You'll need to take it off first.");
if (!canthrow(player, o, &why)) {
switch (why) {
case E_EQUIPPED: msg("You'll need to take it off first."); break;
case E_RAGE: msg("You are too enraged to throw anything!"); break;
case E_STUNNED: msg("You cannot throw anything while stunned."); break;
case E_LOWSTR: msg("You are not strong enough to throw that."); break;
default: msg("For some reason, you can't throw that."); break;
}
return B_TRUE;
}
// calculate throw range
maxdist = getmaxthrowrange(player, o);
if (maxdist < 1) {
msg("You are not strong enough to throw that.");
return B_TRUE;
}
// ask where to throw it
snprintf(buf2, BUFLEN, "Throw %s where?",buf);
snprintf(subprompt, BUFLEN, "%s->Throw->",buf);

541
lf.c

File diff suppressed because it is too large Load Diff

17
lf.h
View File

@ -56,6 +56,7 @@ int canhear(lifeform_t *lf, cell_t *c, int volume, int *numwalls);
int canlearn(lifeform_t *lf, enum SKILL skid);
int canmakerecipe(lifeform_t *lf, recipe_t *rec);
int canopendoors(lifeform_t *lf);
int canoperate(lifeform_t *lf, object_t *o, enum ERROR *why);
int canpickup(lifeform_t *lf, object_t *o, int amt);
int canpolymorphto(enum RACE rid);
int canpush(lifeform_t *lf, object_t *o, int dir);
@ -64,7 +65,9 @@ int canreach(lifeform_t *lf, lifeform_t *victim, int *reachpenalty);
int canreachbp(lifeform_t *lf, lifeform_t *victim, enum BODYPART bp);
int cansee(lifeform_t *viewer, lifeform_t *viewee);
int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos);
int canshoot(lifeform_t *lf, enum ERROR *why);
int cansleep(lifeform_t *lf);
int canthrow(lifeform_t *lf, object_t *o, enum ERROR *why);
int canuseweapons(lifeform_t *lf);
int canwear(lifeform_t *lf, object_t *o, enum BODYPART where);
int canweild(lifeform_t *lf, object_t *o);
@ -112,6 +115,7 @@ object_t *eyesshaded(lifeform_t *lf);
int fall(lifeform_t *lf, lifeform_t *fromlf, int announce);
int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong);
int fall_from_air(lifeform_t *lf);
int real_fall_from_air(lifeform_t *lf, enum LFSIZE leqsize);
void fightback(lifeform_t *lf, lifeform_t *attacker);
behaviour_t *findbehaviour(enum BEHAVIOUR bid);
job_t *findjob(enum JOB jobid);
@ -121,7 +125,7 @@ lifeform_t *findlfunique(enum RACE rid);
cell_t *findnearbylifeob(cell_t *src, int maxdist, flag_t *lifeobflag, object_t **retlifeob);
poisontype_t *findpoisontype(enum POISONTYPE id);
race_t *findrace(enum RACE id);
race_t *findracebyname(char *name);
race_t *findracebyname(char *name, condset_t *cs);
raceclass_t *findraceclass(enum RACECLASS id);
//lifeform_t *findshopkeeper(map_t *m, int roomid);
skill_t *findskill(enum SKILL id);
@ -163,6 +167,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, /*@null@*/cha
int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset);
int getavgdam(lifeform_t *lf, int forxp);
enum CASTTYPE getcasttype(lifeform_t *lf, enum OBTYPE sid);
int getdistspotmod(lifeform_t *lf, cell_t *c);
int getdrunkattrmod(lifeform_t *lf, enum ATTRIB att, int drunkamt);
int getengineeringwallmod(lifeform_t *lf);
float getequippedweight(lifeform_t *lf);
@ -268,9 +273,10 @@ enum BODYPART getrandomcorebp(lifeform_t *lf, lifeform_t *attacker);
race_t *getrandomcorpserace(cell_t *c);
job_t *getrandomjob(int onlyplayerjobs);
int getrandommonlevel(race_t *r, map_t *m);
race_t *getrandomrace(cell_t *c, int forcedepth);
race_t *getrandomrace(cell_t *c, int forcedepth, condset_t *cs);
race_t *getrandomraceofsize(enum LFSIZE wantsize);
race_t *getrandomracewithflag(enum FLAG fid);
race_t *getreallyrandomrace(enum RACECLASS wantrc);
race_t *getreallyrandomrace(enum RACECLASS wantrc, condset_t *cs);
enum SKILL getrandomskill(void);
object_t *getrestob(lifeform_t *lf);
enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id);
@ -311,6 +317,7 @@ flag_t *hasbleedinginjury(lifeform_t *lf, enum BODYPART bp);
int hasfreeaction(lifeform_t *lf);
int real_hasfreeaction(lifeform_t *lf, enum FLAG exception);
int hashealableinjuries(lifeform_t *lf);
flag_t *hasinjuredbp(lifeform_t *lf, enum BODYPART bp);
job_t *hasjob(lifeform_t *lf, enum JOB job);
int hasjobcat(lifeform_t *lf, enum JOBCATEGORY jcid);
flag_t *hasname(lifeform_t *lf);
@ -414,7 +421,7 @@ void magicwoods_warn(lifeform_t *who);
void makefriendly(lifeform_t *lf, int howlong);
void makeheard(lifeform_t *listener, lifeform_t *noisemaker, int showglyph, char *noisetext, int howlong);
int makelearnable(lifeform_t *lf, enum SKILL skid);
int makenauseated(lifeform_t *lf, int amt, int howlong);
int makenauseated(lifeform_t *lf, int amt, int howlong, enum ERROR *why);
void makenoise(lifeform_t *lf, enum NOISETYPE nid);
void makepeaceful(lifeform_t *lf, lifeform_t *causedby);
lifeform_t *makezombie(object_t *o);
@ -450,6 +457,8 @@ void precalclos(lifeform_t *lf);
void preparecorpse(lifeform_t *lf, object_t *corpse);
int push(lifeform_t *lf, object_t *o, int dir);
int racecantalk(enum RACE rid);
int racemeetscondition(race_t *r, enum CELLCONDITION cond, int arg, int val);
int racemeets(enum RACE rid, condset_t *cs);
int readytotrain(lifeform_t *lf);
int recruit(lifeform_t *lf);
void refreshlevelabilities(lifeform_t *lf);

389
map.c
View File

@ -53,6 +53,10 @@ extern int notime;
extern long curtime;
extern condset_t ccwalkable;
extern condset_t ccwalkableroom;
extern condset_t ccroom;
cell_t *addcell(map_t *m, int x, int y) {
cell_t *cell;
@ -133,7 +137,7 @@ void addhomeobs(lifeform_t *lf, int dolevelobs) {
cell_t *c;
o = addob(homeobloc->obpile, f->text);
if (o && (homeobloc == lf->cell) && isimpassableob(o, lf, SZ_ANY)) {
c = real_getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
c = real_getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
if (c) {
homeobloc = c; // future obs will go here too.
moveob(o, homeobloc->obpile, o->amt);
@ -160,9 +164,11 @@ void addhomeobs(lifeform_t *lf, int dolevelobs) {
for (i = 0; i < amt; i++) {
object_t *o = NULL;
cell_t *c;
//condset_t cs;
if (range == NA) { // ie. anywhere on level
// pick new EMPTY random spot. try rooms first.
c = getrandomroomcell(lf->cell->map, ANYROOM, WE_WALKABLE);
//c = getrandomroomcell(lf->cell->map, ANYROOM, WE_WALKABLE);
c = getcell_cond(lf->cell->map, &ccwalkableroom);
if (!c) {
// if no rooms, get any walkable cell.
c = getrandomcell(lf->cell->map);
@ -266,18 +272,19 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
if (rid != R_SPECIFIED) {
if (rid == R_RANDOM) {
r = getrandomrace(c, NA);
r = getrandomrace(c, NA, NULL);
} else {
r = findrace(rid);
}
} else {
condset_t cs;
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
rid = parserace(racename, wantflags, &wantjob, &wantbehaviour);
rid = parserace(racename, wantflags, &cs, &wantjob, &wantbehaviour);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (rid == R_RANDOM) {
r = getrandomrace(c, NA);
r = getrandomrace(c, NA, &cs);
} else {
r = findrace(rid);
}
@ -454,7 +461,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
lifeform_t *newlf;
// find an adjacent cell to one of the newly added monsters,
// starting with the first one
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, NULL, MT_NOTHING);
adjcell = real_getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
// did we find one?
if (!adjcell) break;
@ -503,11 +510,12 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
lifeform_t *newlf;
enum RACE newrid;
race_t *newr;
condset_t cs;
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, NULL, MT_NOTHING);
adjcell = real_getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
if (!adjcell) break;
newrid = parserace(f->text, NULL, NULL, NULL);
newrid = parserace(f->text, NULL, &cs, NULL, NULL);
newr = findrace(newrid);
if (!newr) break;
@ -1290,6 +1298,7 @@ int adjcellokforreachability(cell_t *c, int srcroomid, int dir, int wantfilled)
return B_FALSE;
}
/*
int cellmatchescondition(cell_t *c, int wecond) {
int ok = B_FALSE;
if (wecond == WE_EMPTY) {
@ -1322,6 +1331,154 @@ int cellmatchescondition(cell_t *c, int wecond) {
}
return ok;
}
*/
int cellmeetscondition(cell_t *c, enum CELLCONDITION cond, int arg, int value) {
int ok = B_FALSE,vok = B_FALSE;
object_t *o;
lifeform_t *lf;
assert(c);
switch (cond) {
case CC_CELLTYPE:
if (value && (c->type->id == arg)) {
ok = B_TRUE;
} else if (!value && (c->type->id != arg)) {
ok = B_TRUE;
}
break;
case CC_DANGEROUSFOR:
lf = findlf(NULL, arg);
if (value == B_TRUE) {
if (celldangerous(lf, c, B_FALSE, NULL)) {
ok = B_TRUE;
}
} else {
if (!celldangerous(lf, c, B_FALSE, NULL)) {
ok = B_TRUE;
}
}
break;
case CC_EMPTY:
if (value && isempty(c)) {
ok = B_TRUE;
} else if (!value && !isempty(c)) {
ok = B_TRUE;
}
break;
case CC_OKFORPORTAL:
if (value == B_TRUE) {
if (cellwalkable(NULL, c, NULL) && !hasenterableobject(c) && !hasobwithflag(c->obpile, F_DOOR)) {
ok = B_TRUE;
}
} else {
if (!cellwalkable(NULL, c, NULL) || hasenterableobject(c) || hasobwithflag(c->obpile, F_DOOR)) {
ok = B_TRUE;
}
}
break;
case CC_OKFORSTAIRS:
if (getcellvault(c) && hasflag(c->room->vault->flags, F_NOSTAIRS)) {
vok = B_FALSE;
} else {
vok = B_TRUE;
}
if (value == B_TRUE) {
if (vok && cellwalkable(NULL, c, NULL) && !hasenterableobject(c) && !hasobwithflag(c->obpile, F_DOOR) ) {
ok = B_TRUE;
}
} else {
if (!vok || !cellwalkable(NULL, c, NULL) || hasenterableobject(c) || hasobwithflag(c->obpile, F_DOOR)) {
ok = B_TRUE;
}
}
break;
case CC_HASLF:
if (value && c->lf) {
ok = B_TRUE;
} else if (!value && !c->lf) {
ok = B_TRUE;
}
break;
case CC_HASMATERIAL:
if (value && (c->type->material->id == arg)) {
ok = B_TRUE;
} else if (!value && (c->type->material->id != arg)) {
ok = B_TRUE;
}
break;
case CC_HASOBTYPE:
o = hasob(c->obpile, arg);
if ((o && value) || (!o && !value)) {
ok = B_TRUE;
}
break;
case CC_HASROOMID:
if (value && isroom(c) && (getroomid(c) == arg)) {
ok = B_TRUE;
} else if (!value && (!isroom(c) || (getroomid(c) != arg)) ) {
ok = B_TRUE;
}
break;
case CC_IMPASSABLE:
if (value) {
if (c->type->solid || hasobwithflag(c->obpile, F_IMPASSABLE)) {
ok = B_TRUE;
}
} else {
if (!c->type->solid && !hasobwithflag(c->obpile, F_IMPASSABLE)) {
ok = B_TRUE;
}
}
break;
case CC_ISROOM:
if (value) {
if (isroom(c)) ok = B_TRUE;
} else {
if (!isroom(c)) ok = B_TRUE;
}
break;
case CC_SOLID:
if (value) {
if (issolid(c)) ok = B_TRUE;
} else {
if (!issolid(c)) ok = B_TRUE;
}
break;
case CC_WALKABLE:
if (value == B_TRUE) {
if (cellwalkable(NULL, c, NULL)) {
ok = B_TRUE;
}
} else {
if (!cellwalkable(NULL, c, NULL)) ok = B_TRUE;
}
break;
case CC_WALKABLEFOR:
lf = findlf(NULL, arg);
if (value == B_TRUE) {
if (cellwalkable(lf, c, NULL)) {
ok = B_TRUE;
}
} else {
if (!cellwalkable(lf, c, NULL)) ok = B_TRUE;
}
break;
case CC_NONE: ok = B_TRUE; break;
default: break;
}
return ok;
}
int cellmeets(cell_t *c, condset_t *cs) {
int i;
if (!cs) return B_TRUE;
for (i = 0; i < cs->nconds; i++ ){
if (!cellmeetscondition(c, cs->cond[i], cs->arg[i], cs->val[i])) {
return B_FALSE;
}
}
return B_TRUE;
}
// returns B_TRUE, B_FALSE or B_MAYBE
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom) {
@ -1377,7 +1534,6 @@ int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir,
// kill everything in the given cell (lifeforms && objects)
// but DONT remove the cell itself.
void clearcell(cell_t *c) {
if (c->lf && !isplayer(c->lf)) {
killlf(c->lf);
}
@ -2167,15 +2323,25 @@ int fix_reachability(map_t *m) {
}
// try to fix unreachable areas.
if (nunreach) {
int nadded = 0,nportals = 0;
int idx,ntries = 0,maxtries = 5;
int nadded = 0,nportals = 0, ndoors = 0;
cell_t *ucell;
ucell = unreachcell[0];
if (db) dblog(" attempting to fix unreachable area at %d,%d.",
ucell->x, ucell->y);
// first: try to link up the two areas.
ndoors = fix_unreach_via_doors(m);
if (!ndoors) {
int idx,firstidx = -1,ntries = 0;
//,maxtries = 5;
// pick one of the unreachable cells
while (ntries < maxtries) {
idx = rnd(0,nunreach-1);
//while (ntries < maxtries) {
while (idx != firstidx) {
if (firstidx == -1) firstidx = idx;
ucell = unreachcell[idx];
// try to link it back to a filled cell.
if (db) dblog(" attempting to fix unreachable area at %d,%d.",
if (db) dblog(" looking for fixes at %d,%d...",
ucell->x, ucell->y);
if (!linkexit(ucell, B_TRUE, &nadded)) {
@ -2185,8 +2351,12 @@ int fix_reachability(map_t *m) {
} else {
if (db) dblog("failed, trying new cell.");
ntries++;
// loop around to start
if (++idx == nunreach) idx = 0;
}
}
}
/*
if (ntries >= maxtries) {
cell_t *rcell;
int ptries = 0;
@ -2204,9 +2374,10 @@ int fix_reachability(map_t *m) {
}
}
}
*/
if (nadded || nportals) {
if (db) dblog(" fixed unreachable area by adding %d cells and %d portals.", nadded,nportals);
if (ndoors || nadded || nportals) {
if (db) dblog(" fixed unreachable area by adding %d doors, %d cells, %d portals.", ndoors, nadded,nportals);
} else {
// didn't add anything - fail!
if (db) dblog(" fix_reachability failed.");
@ -2219,11 +2390,52 @@ int fix_reachability(map_t *m) {
nfixed++;
}
}
if (db) dblog(" fix_reachability complete. fixed %d unreachable areas.", nfixed);
if (nfixed) {
if (db) dblog(" fix_reachability complete. found and fixed %d unreachable areas.", nfixed);
} else {
if (db) dblog(" fix_reachability complete. no unreachable areas found.");
}
return B_FALSE;
}
// returns # doors added
int fix_unreach_via_doors(map_t *m) {
int i,dir;
cell_t *c,*adjcell;
for (i = 0; i < m->w*m->h; i++) {
c = m->cell[i];
if (issolid(c) && !cellisfixedvaultwall(c)) {
int gotreach = B_FALSE,gotunreach = B_FALSE;
// is there an adjacent reachable cell?
for (dir = DC_N; dir <= DC_NW; dir++) {
adjcell = getcellindir(c, dir);
if (adjcell && !issolid(adjcell) && adjcell->filled) {
gotreach = B_TRUE;
break;
}
}
// is there an adjacent unreachable cell?
for (dir = DC_N; dir <= DC_NW; dir++) {
adjcell = getcellindir(c, dir);
if (adjcell && !issolid(adjcell) && !adjcell->filled) {
gotunreach = B_TRUE;
break;
}
}
if (gotreach && gotunreach) {
// this cell links reachable and unreachable areas.
setcelltype(c, getmapempty(m));
makedoor(c, 0);
setcellreason(c, "making door to link seperated areas");
dblog(" successfully fixed by creating a door.");
return 1;
}
}
}
return 0;
}
void floodfill(cell_t *startcell) {
int d;
object_t *o;
@ -2311,6 +2523,31 @@ int getbranchlinks(regionthing_t **thing, int *nthings, ...) {
return *nthings;
}
cell_t *getcell_cond(map_t *map, condset_t *cs ) {
cell_t **poss,*c;
int nposs = 0,i;
poss = calloc(map->w * map->h, sizeof(cell_t *));
// get a list of all possible cells
nposs = 0;
for (i = 0; i < map->w*map->h; i++) {
c = map->cell[i];
if (cellmeets(c, cs)) {
poss[nposs++] = c;
}
}
if (nposs) {
c = poss[rnd(0,nposs-1)];
} else {
c = NULL;
}
free(poss);
return c;
}
cell_t *getcellat(map_t *map, int x, int y) {
if (!isonmap(map, x, y)) return NULL;
return map->cell[y*map->w + x];
@ -3744,7 +3981,11 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
if (db) dblog("--> Will add %d pillars",numpillars);
for (n = 0; n < numpillars;n++ ) {
//dblog("----> Adding pillar %d/%d",n+1,numpillars);
c = getrandomroomcell(map, i, WE_EMPTY);
condset_t cs;
initcondv(&cs, CC_HASROOMID, B_TRUE, i,
CC_EMPTY, B_TRUE, NA, CC_NONE);
//c = getrandomroomcell(map, i, WE_EMPTY);
c = getcell_cond(map, &cs);
if (c && !countobs(c->obpile, B_TRUE)) {
setcelltype(c, solidcell);
@ -3768,7 +4009,8 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
int nmonsters = 0;
done = B_FALSE;
while (!done) {
c = getrandomroomcell(map, i, WE_WALKABLE);
//c = getrandomroomcell(map, i, WE_WALKABLE);
c = getcell_cond(map, &ccwalkable);
// if nothing there
if (c) {
int obchance;
@ -4390,16 +4632,18 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
break;
case RT_OBJECT:
if (db) dblog(" adding forced regionthing object: %s", thing[i]->what);
c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
//c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
c = getcell_cond(map, &ccwalkableroom);
if (!c) c = getrandomcell(map);
c = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
c = real_getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
addob(c->obpile, thing[i]->what);
break;
case RT_LF:
if (db) dblog(" adding forced regionthing lifeform: %s", thing[i]->what);
c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
//c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
c = getcell_cond(map, &ccwalkableroom);
if (!c) c = getrandomcell(map);
c = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
c = real_getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
addmonster(c, R_SPECIFIED, thing[i]->what, B_FALSE, thing[i]->value, B_TRUE, NULL);
break;
case RT_BRANCHLINK:
@ -4442,6 +4686,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
unmakemap(map);
continue;
}
//
} // end while failed)
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
@ -4628,7 +4873,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
nstairslinked++;
} else {
if (db) {
dblog(" FAILED to link stairs: '%s'",o->type->name);
dblog(" couldn't link stairs: '%s' (probably no lower level yet)",o->type->name);
}
}
@ -4940,7 +5185,8 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
c = NULL;
// infinite loop here.
while (!c || (countadjwalls(c) == 0) || getcellwaterdepth(c, NULL)) {
c = getrandomroomcell(map, ANYROOM, WE_NONE);
//c = getrandomroomcell(map, ANYROOM, WE_NONE);
c = getcell_cond(map, &ccroom);
assert(c);
}
//////////
@ -5643,6 +5889,7 @@ int linkexits(map_t *m, int roomid) {
int minx = -1, miny = -1, maxx = -1, maxy = -1;
int roomidx = -1;
vault_t *v;
condset_t cs;
// figure out room coords
for (i = 0; i < m->nrooms; i++) {
@ -5658,7 +5905,9 @@ int linkexits(map_t *m, int roomid) {
assert(roomidx != -1);
// does this roomid actually exist??
c = getrandomroomcell(m, roomid, WE_NONE);
//c = getrandomroomcell(m, roomid, WE_NONE);
initcondv(&cs, CC_HASROOMID, B_TRUE, roomid, CC_NONE);
c = getcell_cond(m, &cs);
if (!c) return B_FALSE;
v = getcellvault(c);
@ -5794,8 +6043,12 @@ void createmastervaults(map_t *map, int depth, map_t *parentmap, int exitdir, ob
// place chests
for (i = 0; i < map->nrooms; i++) {
int nchests;
condset_t cs;
nchests = rnd(1,5);
c = getrandomroomcell(map, i, WE_WALKABLE);
initcondv(&cs, CC_HASROOMID, B_TRUE, i,
CC_WALKABLE, B_TRUE, NA, CC_NONE);
//c = getrandomroomcell(map, i, WE_WALKABLE);
c = getcell_cond(map, &cs);
if (c) {
addob(c->obpile, "random container");
}
@ -6337,6 +6590,13 @@ void finalisemap(map_t *map, object_t *entryob, int exitdir) {
int nupstairsneeded = 0,ndownstairsneeded = 0;
cell_t *c;
object_t *o,*nexto;
condset_t okforstairs;
initcondv(&okforstairs, CC_EMPTY, B_TRUE, NA,
CC_OKFORSTAIRS, B_TRUE, NA,
CC_ISROOM, B_TRUE, NA,
CC_NONE);
// make sure this map has sufficient up/down staircases as defined by its
// region type.
//
@ -6371,7 +6631,8 @@ void finalisemap(map_t *map, object_t *entryob, int exitdir) {
// first dungeon level. just one exit stairs
c = NULL;
while (!c || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
//c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
c = getcell_cond(map, &okforstairs);
}
o = addobfast(c->obpile, upstairtype);
if (entryob) {
@ -6399,12 +6660,21 @@ void finalisemap(map_t *map, object_t *entryob, int exitdir) {
for (i = 0; i < nupstairsneeded; i++) {
c = NULL;
while (!c || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
//c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
c = getcell_cond(map, &okforstairs);
/*
while (!c || (getcellvault(c) && hasflag(c->room->vault->flags, F_NOSTAIRS))) {
// ANY cell at all, doesn't have to be a room.
c = getrandomcell(map);
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
if (!cellwalkable(NULL, c, NULL)) {
trytokillobs(c->obpile);
}
// still not walkable? find something nearby.
if (!cellwalkable(NULL, c, NULL)) {
c = getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND);
}
}
*/
trytokillobs(c->obpile);
}
o = addobfast(c->obpile, upstairtype);
@ -6429,12 +6699,8 @@ void finalisemap(map_t *map, object_t *entryob, int exitdir) {
for (i = 0; i < ndownstairsneeded; i++) {
c = NULL;
while (!c || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
while (!c || (getcellvault(c) && hasflag(c->room->vault->flags, F_NOSTAIRS))) {
// ANY cell at all, doesn't have to be a room.
c = getrandomcell(map);
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
}
//c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
c = getcell_cond(map, &okforstairs);
trytokillobs(c->obpile);
}
o = addobfast(c->obpile, downstairtype);
@ -7219,12 +7485,11 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) {
}
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) {
return real_getrandomadjcell(c, wantempty, allowexpand, LOF_NEED, NULL, NULL, NULL, MT_NOTHING);
cell_t *getrandomadjcell(cell_t *c, condset_t *cs, int allowexpand) {
return real_getrandomadjcell(c, cs, allowexpand, LOF_NEED, NULL, NULL);
}
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob, cell_t *dontwantcell, lifeform_t *preferlos, enum MATERIAL wantmat) {
cell_t *real_getrandomadjcell(cell_t *c, condset_t *cs, int allowexpand, enum LOFTYPE needlof, cell_t *dontwantcell, lifeform_t *preferlos) {
int radius = 1;
int x,y;
cell_t *poss[MAXCANDIDATES];
@ -7247,13 +7512,13 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
(new != c) &&
(getcelldist(c,new) == radius) &&
(new != dontwantcell) && gotlof) {
enum OBTYPE *badoid;
int ok = B_FALSE;
numwithlof++;
ok = cellmatchescondition(new, wantempty);
ok = cellmeets(new, cs);
// obs we dont want?
/*
if (dontwantob) {
for (badoid = dontwantob; (*badoid != OT_NONE) ; badoid++) {
if (hasob(new->obpile, *badoid)) {
@ -7262,11 +7527,14 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
}
}
}
*/
/*
if (wantmat != MT_NOTHING) {
if (new->type->material->id != wantmat) {
ok = B_FALSE;
}
}
*/
if (ok) {
if (preferlos && haslos(preferlos, new)) {
@ -7288,6 +7556,8 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
if (numwithlof) {
// increment radius
radius++;
// more than map width? fail.
if (radius >= MAXOF(MAX_MAPH,MAX_MAPW)) return NULL;
} else {
if (preferlos) {
// start again without preferlos
@ -7328,6 +7598,7 @@ cell_t *getrandomcell(map_t *map) {
return cell;
}
cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id) {
cell_t *cell;
cell = getrandomcell(map);
@ -7337,6 +7608,8 @@ cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id) {
return cell;
}
int compassdir(int orthdir) {
switch (orthdir) {
case D_N:
@ -7374,6 +7647,7 @@ int getrandomdirexcept(int dirtype, int exception) {
return dir;
}
/*
cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty) {
int npossible = 0;
int selidx;
@ -7417,6 +7691,7 @@ cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty) {
free(poss);
return c;
}
*/
// popuplates retcell[] with all cells from room
void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells) {
@ -7697,6 +7972,7 @@ void initmap(void) {
addcelltype(CT_WALLDWOOD, "wyrmwood wall", UNI_SOLID, C_BROWN, NA, B_SOLID, B_OPAQUE, MT_DRAGONWOOD, 0, 100, 0, B_NOABSORB);
addcelltype(CT_WALLFLESH, "flesh wall", UNI_SOLID, C_RED, NA, B_SOLID, B_OPAQUE, MT_FLESH, 0, 25, 0, B_NOABSORB);
addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, NA, B_SOLID, B_TRANS, MT_GLASS, 0, 20, 0, B_NOABSORB);
addcelltype(CT_WALLICE, "ice wall", UNI_SHADEDARK, C_CYAN, NA, B_SOLID, B_TRANS, MT_ICE, 0, 30, 0, B_NOABSORB);
//addcelltype(CT_WALLTREE, "dense bushland", UNI_SHADEDARK, C_GREEN, B_SOLID, B_OPAQUE, MT_PLANT, 0, 100);
addcelltype(CT_WALLTREE, "dense bushland", UNI_TREELOTS, C_GREEN, NA, B_SOLID, B_OPAQUE, MT_PLANT, 0, 100, 0, B_NOABSORB);
addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, NA, B_SOLID, B_OPAQUE, MT_METAL, 0, 75, 0, B_NOABSORB);
@ -8304,10 +8580,14 @@ int linkholes(map_t *map) {
// make a link to it in this map, as close as possible to same pos
c2 = getcellat(map, x, y);
if (c2->lf || hasobid(c2->obpile, ot->id)) {
condset_t cs;
// this will automatically avoid lifeforms since we're using
// we_walkable rather than we_notwall. this saves problems
// with someine coming up underneath you!
c2 = real_getrandomadjcell(c2, WE_NOLF, B_ALLOWEXPAND, LOF_DONTNEED, &ot->id, NULL, NULL, MT_NOTHING);
initcondv(&cs, CC_HASLF, B_FALSE, NA,
CC_HASOBTYPE, B_FALSE, ot->id,
CC_NONE);
c2 = real_getrandomadjcell(c2, &cs, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
}
// clear out the cell if required
if (c2->type->solid) {
@ -8720,10 +9000,14 @@ void mapentereffects(map_t *m) {
// chosen cell is not near stairs
if (dowandering) {
int monchance;
condset_t cs;
monchance = getmapdifficulty(m)*5;
for (i = 0; i < m->nrooms; i++) {
if (pctchance(monchance)) {
c = getrandomroomcell(m, m->room[i].id, WE_WALKABLE);
initcondv(&cs, CC_HASROOMID, B_TRUE, m->room[i].id,
CC_WALKABLE, B_TRUE, NA, CC_NONE);
//c = getrandomroomcell(m, m->room[i].id, WE_WALKABLE);
c = getcell_cond(m, &cs);
if (c && !hasobflagwithin(c, F_STAIRS, 15, DT_COMPASS)) {
addmonster(c, R_RANDOM, NULL, B_TRUE, 1, B_TRUE, NULL);
}
@ -8785,7 +9069,7 @@ int orthdir(int compassdir) {
return D_NONE;
}
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour) {
enum RACE parserace(char *name, flagpile_t *wantflags, condset_t *cs, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour) {
int donesomething;
char *p,*suff;
job_t *j;
@ -8794,6 +9078,9 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum B
char *namestart;
behaviour_t *b;
assert(cs);
initcond(cs);
// get params
donesomething = B_TRUE;
@ -8821,6 +9108,11 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum B
if (wantflags) addflag(wantflags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
donesomething = B_TRUE;
}
if (strstarts(p, "hirable ")) {
p += strlen("hirable ");
addcond(cs, CC_HASFLAG, B_TRUE, F_PLAYABLE);
donesomething = B_TRUE;
}
if (wantbehaviour && (*wantbehaviour != BH_NONE)) {
} else {
// try removing prefixes for behaviours
@ -8937,24 +9229,26 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum B
race_t *baser,*r;
// ie. "random xxx_baseraceid_xxx"
p += strlen("random ");
baser = findracebyname(p);
baser = findracebyname(p, NULL);
if (baser) {
enum RACE poss[MAXCANDIDATES];
int nposs = 0;
// find all races with this baseid
for (r = firstrace ; r ; r = r->next) {
if (r->baseid == baser->id) {
if (racemeets(r->id, cs)) {
poss[nposs++] = r->id;
if (nposs == MAXCANDIDATES) break;
}
}
}
if (nposs) {
return poss[rnd(0,nposs-1)];
}
}
} else {
race_t *r;
r = findracebyname(p);
r = findracebyname(p, cs);
if (r) {
return r->id;
}
@ -9384,6 +9678,7 @@ int validateregionthing(regionthing_t *thing) {
int goterrors = B_FALSE;
object_t *o;
enum RACE rid;
condset_t cs;
createfakes(&fakemap, &fakecell);
switch (thing->whatkind) {
case RT_HABITAT:
@ -9393,7 +9688,7 @@ int validateregionthing(regionthing_t *thing) {
}
break;
case RT_LF:
rid = parserace(thing->what, NULL, NULL, NULL);
rid = parserace(thing->what, NULL, &cs, NULL, NULL);
if (rid == R_NONE) {
dblog("Invalid lifeform '%s' specified in regionthing.", thing->what);
goterrors = B_TRUE;

15
map.h
View File

@ -16,7 +16,9 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
void breakwall(cell_t *c, char *why, ...);
int cellhaslos(cell_t *c1, cell_t *dest);
int cellisfixedvaultwall(cell_t *c);
int cellmatchescondition(cell_t *c, int wecond);
//int cellmatchescondition(cell_t *c, int wecond);
int cellmeetscondition(cell_t *c, enum CELLCONDITION cond, int arg, int value);
int cellmeets(cell_t *c, condset_t *cs);
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom);
void clearcell(cell_t *c);
void clearcell_exceptflags(cell_t *c, ...);
@ -33,9 +35,10 @@ int doelementspread(cell_t *c);
int dodoorfill(cell_t *c);
void doorfill_r(cell_t *startcell, cell_t *c, int *nfilled);
int fix_reachability(map_t *m);
int fix_unreachable_cell(cell_t *badcell);
int fix_unreach_via_doors(map_t *m);
void floodfill(cell_t *startcell);
int getbranchlinks(regionthing_t **thing, int *nthings, ...);
cell_t *getcell_cond(map_t *map, condset_t *cs );
cell_t *getcellat(map_t *map, int x, int y);
int getcellclimbdifficulty(cell_t *c);
int getcellclimbdifficultyavg(cell_t *c);
@ -135,13 +138,13 @@ cell_t *getclosestroomcell(lifeform_t *lf, int roomid);
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
int getobchance(int habitat);
int getthingchance(int habitat);
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob, cell_t *dontwantcell, lifeform_t *preferlos, enum MATERIAL wantmat);
cell_t *getrandomadjcell(cell_t *c, condset_t *cs, int allowexpand);
cell_t *real_getrandomadjcell(cell_t *c, condset_t *cs, int allowexpand, enum LOFTYPE needlof, cell_t *dontwantcell, lifeform_t *preferlos);
cell_t *getrandomcell(map_t *map);
cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id);
int getrandomdir(int dirtype);
int getrandomdirexcept(int dirtype, int exception);
cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty);
//cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty);
void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells);
int getslipperyness(cell_t *c, object_t **slipob);
cell_t *getstairdestination(object_t *o, int *madenewmap);
@ -191,7 +194,7 @@ void mapentereffects(map_t *m);
void modillumination(map_t *m, int dir);
void moveobtoclearcell(object_t *o);
int orthdir(int compassdir);
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour);
enum RACE parserace(char *name, flagpile_t *wantflags, condset_t *cs, enum JOB *wantjob, enum BEHAVIOUR *wantbehaviour);
int remove_deadends(map_t *m, int howmuch);
int remove_baddoors(map_t *m);
void selectcelltypes(map_t *map);

8
move.c
View File

@ -31,6 +31,8 @@ extern int noredraw;
extern long curtime;
extern condset_t ccwalkable;
extern WINDOW *gamewin, *msgwin;
int canandwillmove(lifeform_t *lf, int dir, enum ERROR *error) {
@ -1723,7 +1725,7 @@ int movelfsoutofway(cell_t *newcell) {
if (newcell->lf) {
cell_t *c;
// if they are, find somewhere to move them.
c = getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(newcell, &ccwalkable, B_ALLOWEXPAND);
if (c) {
// move them there
movelf(newcell->lf, c, B_FALSE);
@ -2794,7 +2796,7 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) {
// can't teleport on top of something else
if (c->lf) {
// go somewhere nearby
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND);
if (!c) {
if (isplayer(lf)) {
msg("You feel a wrenching sensation.");
@ -3588,7 +3590,7 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
if (onpurpose) {
for (n = 0; n < nadjallies; n++) {
cell_t *c;
c = getrandomadjcell(dst, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(dst, &ccwalkable, B_ALLOWEXPAND);
if (c) {
if (!initiatemove(adjally[n], NULL, B_TRUE, NULL)) {
movelf(adjally[n], c, B_FALSE);

76
nexus.c
View File

@ -46,6 +46,11 @@ knowledge_t *knowledge = NULL, *lastknowledge = NULL;
hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
npcname_t *npcname;
int numnpcnames;
int totalraces = 0;
condset_t ccwalkable;
condset_t ccwalkableroom;
condset_t ccroom;
extern lifeform_t *godlf[];
extern int ngodlfs;
@ -411,15 +416,25 @@ int main(int argc, char **argv) {
race_t *r;
lifeform_t *pet;
enum OBTYPE avoidob = OT_WATERDEEP;
condset_t cs,cs2;
initcondv(&cs, CC_WALKABLE, B_TRUE, NA,
CC_HASOBTYPE, B_FALSE, avoidob,
CC_NONE
);
initcondv(&cs2, CC_SOLID, B_TRUE, NA,
CC_HASOBTYPE, B_FALSE, avoidob,
CC_NONE
);
f = retflag[i];
r = findracebyname(f->text);
r = findracebyname(f->text, NULL);
assert(r);
// create pet, in view of player if possible.
c = real_getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, &avoidob, NULL, player, MT_NOTHING);
c = real_getrandomadjcell(player->cell, &cs, B_ALLOWEXPAND, LOF_NEED, NULL, player);
if (!c) {
c = real_getrandomadjcell(player->cell, WE_SOLID, B_NOEXPAND, LOF_DONTNEED, &avoidob, NULL, player, MT_NOTHING);
// if no valid spaces, try to make one.
c = real_getrandomadjcell(player->cell, &cs2, B_NOEXPAND, LOF_DONTNEED, NULL, player);
assert(c);
setcelltype(c, getmapempty(player->cell->map));
}
@ -737,6 +752,15 @@ celltype_t *addcelltype(int id, char *name, int glyph, int colour, int altcol, i
return a;
}
int addcond(condset_t *cs, enum CELLCONDITION cond, int val, int arg) {
cs->cond[cs->nconds] = cond;
cs->arg[cs->nconds] = arg;
cs->val[cs->nconds] = val;
(cs->nconds)++;
return cs->nconds;
}
warning_t *addwarning(char *text, int lifetime) {
warning_t *a;
@ -982,7 +1006,7 @@ void donextturn(map_t *map) {
if (isplayer(who)) {
msg("You feel a change coming over your body!");
}
r = findracebyname(changerace);
r = findracebyname(changerace, NULL);
//polymorphto(who, r->id, rnd(mintime,maxtime));
polymorphto(who, r->id, PERMENANT);
donormalmove = B_FALSE;
@ -1446,6 +1470,17 @@ int init(void) {
// random numbers
srand(time(NULL));
// preset conditions
initcondv(&ccwalkable, CC_WALKABLE, B_TRUE, NA,
CC_NONE);
initcondv(&ccroom, CC_ISROOM, B_TRUE, NA,
CC_NONE);
initcondv(&ccwalkableroom, CC_WALKABLE, B_TRUE, NA,
CC_ISROOM, B_TRUE, NA,
CC_NONE);
// precalc sin/cos
for (i = 0; i < 360; i++) {
double rads;
@ -1503,6 +1538,29 @@ int init(void) {
return B_FALSE;
}
void initcond(condset_t *cs) {
cs->nconds = 0;
}
void initcondv(condset_t *cs, ...) {
enum CELLCONDITION condition;
va_list args;
int value,arg;
va_start(args, cs);
cs->nconds = 0;
condition = va_arg(args, enum CELLCONDITION);
while (condition != CC_NONE) {
value = va_arg(args, int);
assert((value == B_TRUE) || (value == B_FALSE));
arg = va_arg(args, int);
addcond(cs, condition, value, arg);
condition = va_arg(args, enum CELLCONDITION);
}
va_end(args);
}
void inctime(long nunits) {
curtime += (nunits*(TIMECONST));
// don't let it get higher than 23:59
@ -2220,9 +2278,15 @@ void timeeffectsworld(map_t *map, int updategametime) {
// midnight
if (h == 0) {
cell_t *c;
condset_t cs;
initcondv(&cs, CC_WALKABLE, B_TRUE, NA,
CC_ISROOM, B_TRUE, NA,
CC_NONE
);
// lunar gate appears in a random spot on the player's level
c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
//c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
//c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
c = getcell_cond(map, &cs);
if (c) {
o = addobfast(c->obpile, OT_LUNARGATE);
if (o) {

View File

@ -1,6 +1,7 @@
#include "defs.h"
celltype_t *addcelltype(int id, char *name, int glyph, int colour, int altcol, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp, int volumemod, int absobent);
int addcond(condset_t *cs, enum CELLCONDITION cond, int arg, int val);
warning_t *addwarning(char *text, int lifetime);
void checkdeath(void);
void checkendgame(void);
@ -20,6 +21,8 @@ enum COLOUR getpctcol(float num, float max);
char getpctletter(float num, float max);
void getrarityrange(int depth, int *min, int *max, int range, int oodok);
int init(void);
void initcond(condset_t *cs);
void initcondv(condset_t *cs, ...);
void inctime(long nunits);
void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels);
void initbresnham(int x1, int y1, int x2, int y2, int *xinc1, int *yinc1, int *dinc1, int *xinc2, int *yinc2, int *dinc2, int *numpixels, int *d);

173
objects.c
View File

@ -61,6 +61,8 @@ extern int statdirty;
extern int obdb;
extern condset_t ccwalkable;
extern condset_t ccwalkableroom;
char letorder[MAXPILEOBS] = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
@ -738,7 +740,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
p += strlen("linkrace:");
// read next
p = readuntil(racename, p, ' ');
linkrace = findracebyname(racename);
linkrace = findracebyname(racename, NULL);
donesomething = B_TRUE;
// condition flags
} else if (strstarts(p, "battered ")) {
@ -917,7 +919,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
p2 += 6;
p2 = readuntil(racename, p2, ' ');
corpserace = findracebyname(racename);
corpserace = findracebyname(racename, NULL);
ot = findot(OT_ROASTMEAT);
} else if (strstr(p, "water fountain")) {
wantfountaintype = OT_POT_WATER;
@ -938,7 +940,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
len = p2 - p;
snprintf(racename, len, "%s",p);
corpserace = findracebyname(racename);
corpserace = findracebyname(racename, NULL);
ot = findot(OT_CORPSE);
} else if (strstr(p, "map to ")) {
branch_t *rt;
@ -968,7 +970,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
// now at start of name
snprintf(racename, BUFLEN, "%s",p2);
corpserace = findracebyname(racename);
corpserace = findracebyname(racename, NULL);
ot = findot(OT_STATUE);
} else if (strstr(p, " head")) {
int len;
@ -977,7 +979,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
len = p2 - p + 1;
snprintf(racename, len, "%s",p);
corpserace = findracebyname(racename);
corpserace = findracebyname(racename, NULL);
ot = findot(OT_HEAD);
} else if (strstarts(p, "portal to lv")) {
char *pp;
@ -995,10 +997,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
targetmap = addmap();
createmap(targetmap, dlev, c->map->region, NULL, D_NONE, NULL);
}
targetcell = getrandomroomcell(targetmap, ANYROOM, WE_WALKABLE);
//targetcell = getrandomroomcell(targetmap, ANYROOM, WE_WALKABLE);
targetcell = getcell_cond(targetmap, &ccwalkableroom);
if (!targetcell) targetcell = getrandomcell(targetmap);
while (!cellwalkable(NULL, targetcell, NULL)) {
targetcell = getrandomadjcell(targetcell, WE_WALKABLE, B_ALLOWEXPAND);
targetcell = getrandomadjcell(targetcell, &ccwalkable, B_ALLOWEXPAND);
}
} else {
// ie. adding to dummy cell
@ -2186,6 +2190,25 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
traptype = getrandomtrapforob(o);
addflag(o->flags, F_TRAPPED, traptype, NA, NA, NULL);
}
// monster hiding inside?
f = hasflag(o->flags, F_CANHAVELFINSIDE);
if (f) {
enum LFSIZE maxsize;
maxsize = getobsize(o);
if (maxsize != SZ_MINI) {
int hidingchance;
hidingchance = f->val[0] + (f->val[1] * (obloc->map->depth/5));
limit(&hidingchance, f->val[0], f->val[2]);
if (pctchance(hidingchance)) {
race_t *r;
r = getrandomraceofsize(maxsize-1);
if (r) {
addflag(o->flags, F_LFINSIDE, r->id, NA, NA, NULL);
}
}
}
}
}
if (o->pile->where) {
@ -4127,7 +4150,6 @@ int getobaccuracy(object_t *wep, lifeform_t *weilder, int forthrow) {
}
}
if (wep) {
// blessed weapons have better base accuracy
if (wep->blessed == B_BLESSED) acc += 10;
@ -5304,6 +5326,18 @@ char *getshopobname(object_t *o, char *buf, int count) {
return getobnametrue(o, buf, o->amt);
}
enum SKILL getskilltorepair(object_t *o) {
switch (o->material->id) {
case MT_CLOTH:
case MT_LEATHER:
return SK_SEWING;
case MT_METAL:
return SK_METALWORK;
default: break;
}
return SK_NONE;
}
char *getobname(object_t *o, char *buf, int count) {
return real_getobname(o, buf, count, B_PREMODS, B_CONDITION, B_BLINDADJUST, B_BLESSINGS, B_USED, B_NOSHOWALL);
}
@ -7320,7 +7354,8 @@ int isblessknown(object_t *o) {
int iscorpse(object_t *o) {
if (o->type->obclass->id == OC_CORPSE) {
//if (o->type->obclass->id == OC_CORPSE) {
if (o->type->id == OT_CORPSE) {
return B_TRUE;
}
return B_FALSE;
@ -8219,7 +8254,7 @@ lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level) {
flag_t *f;
lifeform_t *newlf;
where = getrandomadjcell(lf->cell, WE_EMPTY, B_NOEXPAND);
where = getrandomadjcell(lf->cell, &ccwalkable, B_NOEXPAND);
if (!where) return NULL;
newlf = addlf(where, R_DANCINGWEAPON, level);
@ -8542,12 +8577,23 @@ void makewet(object_t *o, int amt) {
void modifybetterwepdam(object_t *o, lifeform_t *owner, int *dam) {
flag_t *f;
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0,i;
if (hasflag(o->flags, F_HASBRAND)) {
*dam *= 3;
}
if (hasflag(o->flags, F_ONFIRE)) {
*dam += 8;
}
getflags(o->flags, retflag, &nretflags, F_EXTRADAM, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->val[2] == NA) {
*dam += real_roll(f->text, B_TRUE);
} else {
*dam += f->val[2];
}
}
// prefer weapons "...of xxxslaying" which match our targets
if (owner) {
f = hasflag(o->flags, F_RACESLAY);
@ -9392,6 +9438,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
flag_t *f;
int willid = B_FALSE;
int wastech = B_FALSE;
enum ERROR why;
if (!lfhasflag(lf, F_HUMANOID) || !hasbp(lf, BP_HANDS)) {
if (!hasflag(o->flags, F_OPERWITHOUTHANDS)) {
@ -9403,6 +9450,18 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
}
if (!canoperate(lf, o, &why)) {
if (isplayer(lf)) {
switch (why) {
case E_NOHANDS: msg("You lack the manual dexterity to operate this."); break;
case E_RAGE: msg("You are too enraged to operate anything!"); break;
case E_STUNNED: msg("You cannot operate anything while stunned."); break;
default: msg("For some reason, you can't operate this."); break;
}
return B_TRUE;
}
}
if (lfhasflag(lf, F_RAGE)) {
if (isplayer(lf)) {
msg("You are too enraged to operate anything!");
@ -9677,6 +9736,40 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
msg("The %s seems to be locked.", noprefix(obname));
return B_TRUE;
}
// monster inside?
f = hasflag(o->flags, F_LFINSIDE);
if (f) {
char theob[BUFLEN];
cell_t *where;
lifeform_t *mon = NULL;
if (o->pile->owner) {
char ownername[BUFLEN];
getlfname(o->pile->owner,ownername);
sprintf(theob, "%s%s %s",ownername,getpossessive(ownername),
noprefix(obname));
} else {
sprintf(theob, "the %s", noprefix(obname));
}
where = getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND);
if (where) {
mon = addmonster(where, f->val[0], NULL, B_TRUE, 1, B_FALSE, NULL);
}
if (mon) {
char monname[BUFLEN];
getlfnamea(mon, monname);
msg("^w%s leaps out of %s!", monname, theob);
// it gets a free attack
if (isadjacent(mon->cell, player->cell)) {
attackcell(mon, player->cell, B_TRUE);
}
} else {
msg("^vSomething swipes at you as you open %s!", theob);
}
} else {
snprintf(buf, BUFLEN, "Looting %s. Will you:",obname);
initprompt(&prompt, buf);
if (countobs(lf->pack, B_FALSE)) {
@ -9715,6 +9808,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
return B_FALSE;
}
}
}
} else if (hasflag(o->flags, F_OPERONOFF)) { // operating toggles on/off
if (isactivated(o)) {
turnoff(lf, o);
@ -9805,7 +9899,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
switch (rnd(0,22)) {
case 0: // butterflies around user
willid = B_TRUE;
where = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
where = getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND);
addmonster(where, R_BUTTERFLY, NULL, B_FALSE, rnd(10,20), B_FALSE, NULL);
if (haslos(player, where)) {
msg("A swarm of butterflies appears!");
@ -10158,7 +10252,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
r = poss[rnd(0,nposs-1)];
sprintf(wname, "%s warrior", r->name);
c = real_getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, lf, MT_NOTHING);
c = real_getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, lf);
if (c) {
summonmonster(lf, c, R_SPECIFIED, wname, rnd(50,90), B_TRUE);
}
@ -10300,7 +10394,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
}
// summon treant
c = real_getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL, lf, MT_NOTHING);
c = real_getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, lf);
if (c) {
summonmonster(lf, c, R_TREANT, NULL, rnd(50,90), B_TRUE);
}
@ -10338,7 +10432,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
where = lf->cell;
if (!moveob(oo, where->obpile, ALL) ){
// try somewhere nearby
where = getrandomadjcell(where, WE_WALKABLE, B_NOEXPAND);
where = getrandomadjcell(where, &ccwalkable, B_NOEXPAND);
if (where) {
moveob(oo, where->obpile, ALL);
}
@ -14509,6 +14603,8 @@ void timeeffectsob(object_t *o) {
char sgname[BUFLEN];
cell_t *newc;
int canseeloc = B_FALSE;
condset_t cs;
initcondv(&cs, CC_IMPASSABLE, B_FALSE, NA, CC_NONE);
if (haslos(player, location) && canseeob(player, sg)) {
getobname(sg, sgname, sg->amt);
@ -14518,7 +14614,7 @@ void timeeffectsob(object_t *o) {
}
// object gets thrown away
newc = getrandomadjcell(location, WE_NOTWALL, B_ALLOWEXPAND);
newc = getrandomadjcell(location, &cs, B_ALLOWEXPAND);
if (newc) {
//flag_t *inv;
object_t *newob = NULL;
@ -14694,8 +14790,9 @@ void timeeffectsob(object_t *o) {
// check each flag for this object...
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_EXPLODEONDEATH, F_MATCONVERT, F_HOT, F_KNOCKAWAY, F_OBHPDRAIN, F_ONFIRE,
F_RECHARGE, F_REVIVETIMER, F_WALKDAM, F_WET, F_NONE);
getflags(o->flags, retflag, &nretflags, F_ACTIVATED, F_EDIBLE, F_EXPLODEONDEATH, F_MATCONVERT,
F_HOT, F_KNOCKAWAY, F_LFINSIDE, F_OBHPDRAIN, F_ONFIRE, F_RECHARGE, F_REVIVETIMER,
F_WALKDAM, F_WET, F_NONE);
for (i = 0; i < nretflags; i++) {
object_t *oo,*nextoo;
f = retflag[i];
@ -14945,7 +15042,7 @@ void timeeffectsob(object_t *o) {
cell_t *lfloc = NULL;
if (obloc) {
if (obloc->lf) {
lfloc = getrandomadjcell(obloc, WE_WALKABLE, B_NOEXPAND);
lfloc = getrandomadjcell(obloc, &ccwalkable, B_NOEXPAND);
} else {
lfloc = obloc;
}
@ -14973,12 +15070,27 @@ void timeeffectsob(object_t *o) {
} else if ((f->val[1] - f->val[0]) <= 10) {
if (haslos(player, obloc)) {
// pass a perception chekc to see it moving...
if (skillcheck(player, SC_SEARCH, 100, 0)) {
if (skillcheck(player, SC_SEARCH, 100 + getdistspotmod(player, obloc), 0)) {
msg("%s twitches.", obname);
}
}
}
}
// lf hiding inside?
if (f->id == F_LFINSIDE) {
cell_t *obloc = NULL;
obloc = getoblocation(o);
if (haslos(player, obloc) && (o->pile->owner == player)) {
// pass a perception chekc to see it moving...
if (skillcheck(player, SC_SEARCH, 100 + getdistspotmod(player, obloc), 0)) {
if (o->pile->owner == player) {
msg("%s moves slightly.", obname);
} else {
msg("Your %s moves slightly.", noprefix(obname));
}
}
}
}
// damaging objects here will damage other objects
if (f->id == F_WALKDAM) {
@ -15328,7 +15440,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
if (lf) {
if (avoided) {
escapeto = getrandomadjcell(lf->cell, WE_WALKABLE, B_NOEXPAND);
escapeto = getrandomadjcell(lf->cell, &ccwalkable, B_NOEXPAND);
if (!escapeto) avoided = B_FALSE;
}
@ -15403,7 +15515,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
dospelleffects(NULL, OT_S_FLAMEPILLAR, 3, NULL, NULL, c, B_UNCURSED, NULL, B_TRUE, NULL);
if (lf && avoided) {
cell_t *escapeto = NULL;
escapeto = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND);
escapeto = getrandomadjcell(c, &ccwalkable, B_NOEXPAND);
if (escapeto) {
if (isplayer(lf)) {
msg("You leap out of the way!");
@ -15432,7 +15544,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
} else if (oid == OT_TRAPSUMMON) {
cell_t *cc;
// can't be dodged
cc = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
cc = getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND);
if (cc) {
summonmonster(NULL, cc, R_SPECIFIED, "random", PERMENANT, B_FALSE);
}
@ -15456,18 +15568,21 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
// kill all objcts in the pile, as long as it doesn't contain
// anything important like stairs.
//
// returns FALSE if we cleared objects, or didn't need to.
// returns FALSE if we cleared all objects, or didn't need to.
// returns TRUE if there were objects which we couldn't clear
int trytokillobs(obpile_t *op) {
object_t *o, *nexto;
int failed = B_FALSE;
// objects here? destroy them if we can.
if (countobs(op, B_TRUE)) {
if (hasobwithflag(op, F_IMPORTANT)) {
return B_TRUE;
for (o = op->first ; o ; o = nexto) {
nexto = o->next;
if (hasflag(o->flags, F_IMPORTANT)) {
failed = B_TRUE;
continue;
}
killallobs(op);
return B_FALSE;
killob(o);
}
return B_FALSE;
return failed;
}
void turnoff(lifeform_t *lf, object_t *o) {

View File

@ -136,6 +136,7 @@ cell_t *getobpilelocation(obpile_t *op);
char *getobname(object_t *o, char *buf, int count);
char *getshardobname(enum MATERIAL mid, char *buf);
char *getshopobname(object_t *o, char *buf, int count);
enum SKILL getskilltorepair(object_t *o);
char *getobnametrue(object_t *o, char *buf, int count);
char *getobnametruebase(object_t *o, char *buf, int count);
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int wanttried, int showall);

View File

@ -177,6 +177,7 @@ void shop(lifeform_t *lf, object_t *vm) {
if (!timeisbetween(h, f->val[0], f->val[1])) {
sayphrase(NULL, f->val[2], SV_TALK, hoursto12(f->val[0]), NULL, player);
}
return;
}
if (lfhasflag(lf, F_STENCH)) {

180
spell.c
View File

@ -49,6 +49,9 @@ extern enum ERROR reason;
extern int needredraw, statdirty;
extern condset_t ccwalkable;
extern condset_t ccwalkableroom;
// return value of FALSE means that stamina costs should be charged.
// TRUE is a cancellation - don't change stamina
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target, flag_t *cwflag) {
@ -1657,7 +1660,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
getlfname(victim,victimname);
// move them out of the way
c = getrandomadjcell(victim->cell, WE_EMPTY, B_NOEXPAND);
c = getrandomadjcell(victim->cell, &ccwalkable, B_NOEXPAND);
// nowhere to move? move to where the lf jumped from!
if (c) {
movelf(victim, c, B_FALSE);
@ -2143,6 +2146,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) msg("You can't sprint with a crushed windpipe.");
return B_TRUE;
}
if (hasinjuredbp(user, BP_LEGS)) {
if (isplayer(user)) msg("You can't sprint with injured legs.");
return B_TRUE;
}
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You can't sprint while swimming!");
@ -2395,6 +2402,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
cell_t *c,*entry;
flag_t *lflinkflag;
int x,y;
condset_t cs;
lflinkflag = hasflag(user->flags, F_MAPLINK);
@ -2415,10 +2423,17 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
}
// find a random empty cell here
entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
//entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
initcondv(&cs, CC_ISROOM, B_TRUE, NA,
CC_WALKABLEFOR, B_TRUE, target->id, CC_NONE);
entry = getcell_cond(newmap, &cs);
/*
while (!cellwalkable(target, entry, NULL)) {
entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
//entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
entry = getcell_cond(newmap, &ccwalkableroom);
}
*/
// link the map to this lf
if (!lflinkflag) {
@ -4201,6 +4216,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
targcell = nextc;
target = targcell->lf;
knockback(target, dir, power, caster, 0, B_TRUE);
real_fall_from_air(targcell->lf, SZ_HUMAN + (power/4));
} else if (firstobcell) {
// objects
for (o = firstobcell->obpile->first ;o ; o = nexto) {
@ -5241,7 +5257,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else if (spellid == OT_S_CLONE) {
// duplicate the caster
targcell = getrandomadjcell(caster->cell, WE_WALKABLE, B_NOEXPAND);
targcell = getrandomadjcell(caster->cell, &ccwalkable, B_NOEXPAND);
if (!targcell) {
if (isplayer(caster)) fizzle(caster);
return B_TRUE;
@ -5650,7 +5666,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else {
// get random adjacent cell
targcell = getrandomadjcell(caster->cell, WE_EMPTY, B_ALLOWEXPAND);
targcell = getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND);
}
}
@ -5665,7 +5681,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// ask what kind of monster
askstring("Create what kind of monster", '?', buf, BUFLEN, NULL);
} else {
r = getreallyrandomrace(RC_ANY);
r = getreallyrandomrace(RC_ANY, NULL);
snprintf(buf, BUFLEN, "%s", r->name);
}
@ -5720,15 +5736,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
needredraw = B_TRUE;
ch = askchar("Teleport to the new vault", "yn","y", B_TRUE, B_FALSE);
if (ch == 'y') {
int ntries = 0;
c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1, WE_WALKABLE);
if (!c || !cellwalkable(caster, c, NULL)) {
if (++ntries >= 10) {
condset_t cs;
initcondv(&cs, CC_WALKABLEFOR, B_TRUE, caster->id,
CC_HASROOMID, B_TRUE, caster->cell->map->nrooms-1,
CC_NONE);
//c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1, WE_WALKABLE);
c = getcell_cond(caster->cell->map, &cs);
if (!c) {
msg("Oops, couldn't find a free space.");
return B_FALSE;
}
c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1, WE_WALKABLE);
}
teleportto(caster, c, B_TRUE);
return B_FALSE;
}
@ -6821,7 +6838,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FLOATINGDISC) {
lifeform_t *newlf;
// get random adjacent cell
targcell = getrandomadjcell(caster->cell, WE_EMPTY, B_ALLOWEXPAND);
targcell = getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND);
if (!targcell) {
fizzle(caster);
return B_TRUE;
@ -6847,19 +6864,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *o;
o = addob(targcell->obpile, "water");
if (o) {
enum OBTYPE badoid[2];
enum OBTYPE badoid;
int i,amt;
int depth;
condset_t cs;
depth = DP_SHOULDERS + power;
//amt = ((power+1) * (power+1)) - 1;
//amt = power;
amt = power*2;
badoid[0] = OT_WATERDEEP;
badoid[1] = OT_NONE;
badoid = OT_WATERDEEP;
for (i = 0; i < amt; i++) {
cell_t *c;
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_WALLSTOP, badoid, NULL, NULL, MT_NOTHING);
initcondv(&cs, CC_SOLID, B_FALSE, NA,
CC_HASOBTYPE, B_FALSE, badoid,
CC_NONE);
c = real_getrandomadjcell(targcell, &cs, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
if (c) {
object_t *water;
water = addob(c->obpile, "water");
@ -7987,6 +8009,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_HOLDPORTAL) {
object_t *o,*oo;
cell_t *c;
condset_t cs;
o = hasobwithflag(targcell->obpile, F_DOOR);
if (!o) {
@ -7995,9 +8018,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
// move any objects which are in the way (but not lfs)
initcondv(&cs, CC_SOLID, B_FALSE, NA,
CC_NONE);
for (oo = targcell->obpile->first ; oo ; oo = oo->next) {
if ((oo != o) && (getmaterialstate(oo->material->id) == MS_SOLID)) {
c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND);
c = getrandomadjcell(targcell, &cs, B_ALLOWEXPAND);
if (c) moveob(oo, c->obpile, ALL);
}
}
@ -8162,7 +8187,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// knock lfs away
if (targcell->lf) {
cell_t *c;
c = getrandomadjcell(targcell, WE_WALKABLE, B_NOEXPAND);
c = getrandomadjcell(targcell, &ccwalkable, B_NOEXPAND);
if (c) {
knockback(targcell->lf, getdirtowards(targcell, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, 100+(power*10), B_TRUE);
} else {
@ -8527,7 +8552,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
job_t *j;
object_t *o;
// create a mirror image
targcell = real_getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL, NULL, caster, MT_NOTHING);
targcell = real_getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
if (!targcell) break;
lf = clonelf(caster, targcell);
if (!lf) break;
@ -9072,7 +9097,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
if (dstcell && !cellwalkable(caster, dstcell, NULL)) {
dstcell = real_getrandomadjcell(dstcell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
dstcell = real_getrandomadjcell(dstcell, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
}
if (dstcell) {
@ -9111,19 +9136,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
m = heaven;
}
if (m) {
int ntries = 0;
condset_t cs;
// find random free cell in map
//targcell = getrandomcell(m);
targcell = getrandomroomcell(m, ANYROOM, WE_WALKABLE);
while (!cellwalkable(target, targcell, NULL) || celldangerous(target, targcell, B_FALSE, NULL)) {
//targcell = getrandomcell(m);
targcell = getrandomroomcell(m, ANYROOM, WE_WALKABLE);
ntries++;
if (ntries >= 5) {
//targcell = getrandomroomcell(m, ANYROOM, WE_WALKABLE);
initcondv(&cs, CC_ISROOM, B_TRUE, NA,
CC_WALKABLEFOR, B_TRUE, target->id,
CC_DANGEROUSFOR, B_FALSE, target->id,
CC_NONE);
targcell = getcell_cond(m, &ccwalkableroom);
if (!targcell) {
fizzle(caster);
return B_TRUE;
}
}
teleportto(target, targcell, B_TRUE);
} else {
fizzle(caster);
@ -9197,7 +9222,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
if (!cellwalkable(caster, targcell, NULL)) {
targcell = real_getrandomadjcell(targcell, WE_WALKABLE, B_NOEXPAND, LOF_DONTNEED, NULL, NULL, NULL, MT_NOTHING);
targcell = real_getrandomadjcell(targcell, &ccwalkable, B_NOEXPAND, LOF_DONTNEED, NULL, NULL);
if (!targcell) {
fizzle(caster);
return B_FALSE;
@ -9597,7 +9622,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *srcportal,*dstportal;
// find adjacent cell for portal
srccell = real_getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL, NULL, caster, MT_NOTHING);
srccell = real_getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
if (!srccell) {
fizzle(caster);
return B_TRUE;
@ -9661,7 +9686,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
// find cell next to caster
newcell = getrandomadjcell(targcell, WE_WALKABLE, B_NOEXPAND);
newcell = getrandomadjcell(targcell, &ccwalkable, B_NOEXPAND);
if (!newcell) {
newcell = targcell;
}
@ -10228,9 +10253,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (i = 0; i < nblowobs; i++) {
char obname[BUFLEN];
cell_t *c;
condset_t cs;
initcondv(&cs, CC_SOLID, B_FALSE, NA, CC_NONE);
getobname(blowob[i], obname, 1);
c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND);
c = getrandomadjcell(targcell, &cs, B_ALLOWEXPAND);
if (c && ((rnd(1,100)-power) <= 33)) {
// move it
fireat(NULL, blowob[i], 1, c, 4, NULL);
@ -10238,6 +10265,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
if (target) {
if (!real_fall_from_air(target, SZ_SMALL + (power/4))) {
int pen = 0;
// easyish save to avoid falling
switch (getlfsize(target)) {
@ -10256,6 +10284,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fall(target, NULL, B_TRUE);
}
}
}
needredraw = B_TRUE;
} else if (spellid == OT_S_MIST) {
object_t *o;
@ -10478,7 +10507,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
//if ((caster == target) && getforcedspellrace(caster, spellid, buf)) {
if (getforcedspellrace(target, spellid, buf, NULL)) {
r = findracebyname(buf);
r = findracebyname(buf, NULL);
} else {
if (spellid == OT_S_POLYMORPH) {
int dorandom = B_FALSE;
@ -10499,7 +10528,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
snprintf(buf2, BUFLEN, "What will you transform %s into", targname);
askstring(buf2, '?', buf, BUFLEN, NULL);
}
r = findracebyname(buf);
r = findracebyname(buf, NULL);
} else {
// TODO: select based on player damage, etc
dorandom = B_TRUE;
@ -10507,7 +10536,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else { // random
if (isplayer(target) && lfhasflag(target, F_CONTROL)) {
askstring("What will you become", '?', buf, BUFLEN, NULL);
r = findracebyname(buf);
r = findracebyname(buf, NULL);
// make sure race is valid:
if (r && !canpolymorphto(r->id)) r = NULL;
@ -10529,7 +10558,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
forcedepth = gettr(target)*2;
r = target->race;
while ((r == target->race) || !canpolymorphto(r->id)) {
r = getrandomrace(NULL, forcedepth);
r = getrandomrace(NULL, forcedepth, NULL);
}
}
} else if (spellid == OT_S_SHAPESHIFT) {
@ -10601,6 +10630,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
howlong = PERMENANT;
}
polymorphto(target, r->id, howlong);
if (isplayer(caster) && !isplayer(target) && !lfhasflag(target, F_UNIQUE)) {
// permenant
killflagsofid(target->flags, F_POLYMORPHED);
killflagsofid(target->flags, F_ORIGRACE);
}
// if someone cast the spell at themself and it's controlled, they can change back at will.
if (target == caster) {
@ -11642,7 +11676,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// ask for a target cell
if (targcell) {
object_t *o,*oo;
enum OBTYPE badoid[2];
int i;
oo = hasob(targcell->obpile, OT_BOULDER);
@ -11674,15 +11707,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (targcell->type->id != CT_DIRT) setcelltype(targcell, CT_DIRT);
o = addob(targcell->obpile, "pool of mud");
if (o) {
condset_t cs;
initcondv(&cs, CC_SOLID, B_FALSE, NA,
CC_HASOBTYPE, B_FALSE, OT_MUDPOOL,
CC_HASMATERIAL, B_TRUE, MT_STONE,
CC_NONE);
ndone++;
powerleft--;
if (haslos(player, targcell)) seenground = B_TRUE;
// do the rest
badoid[0] = OT_MUDPOOL;
badoid[1] = OT_NONE;
for (i = 0; i < powerleft; i++) {
cell_t *c;
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, badoid, NULL, NULL, MT_STONE);
c = real_getrandomadjcell(targcell, &cs, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
if (c) {
if (targcell->type->id != CT_DIRT) setcelltype(targcell, CT_DIRT);
o = addob(c->obpile, "pool of mud");
@ -11857,6 +11893,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
real_fireat(caster, o, 1, targcell, 6, NULL, B_FALSE, OT_S_SPIKEVOLLEY, NULL);
} else if (spellid == OT_S_STENCH) {
int howlong;
enum ERROR why;
target = targcell->lf;
if (!target) {
@ -11880,8 +11917,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(target) || haslos(player, target->cell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if (makenauseated(target, power, howlong)) {
if (isplayer(caster)) nothinghappens();
if (makenauseated(target, power, howlong, &why)) {
// if 'why' was 'resisted', then makenauseated()
// will ahve already announced the failure.
if (isplayer(caster) && (why != E_RESISTED)) {
char buf[BUFLEN];
getlfname(target, buf);
msg("%s seems unaffected.", buf);
}
// failed
return B_TRUE;
}
@ -11932,7 +11975,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char lfname[BUFLEN];
getobname(o, obname, o->amt);
getlfname(c->lf, lfname);
newcell = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND);
newcell = getrandomadjcell(c, &ccwalkable, B_NOEXPAND);
if (newcell) {
lifeform_t *snake;
// add a snake there.
@ -11977,7 +12020,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// add to current cell or new one?
if (c->lf) { // ie. if a previous object made a snake here
newcell = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND);
newcell = getrandomadjcell(c, &ccwalkable, B_NOEXPAND);
} else {
newcell = c;
}
@ -12209,7 +12252,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// next to a random monster
for (lf = target->cell->map->lf ; lf ; lf = lf->next) {
if (areenemies(lf, target)) {
c = getrandomadjcell(lf->cell, WE_WALKABLE, B_NOEXPAND);
c = getrandomadjcell(lf->cell, &ccwalkable, B_NOEXPAND);
if (c) break;
}
}
@ -12346,7 +12389,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// ok, but you'll die!
} else if (!cellwalkable(caster, c, NULL)) {
// go somewhere nearby...
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(c, &ccwalkable, B_ALLOWEXPAND);
if (!c) {
fizzle(caster);
return B_TRUE;
@ -12374,7 +12417,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (nallies) {
int i;
for (i = 0; i < nallies; i++) {
c = getrandomadjcell(targcell, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(targcell, &ccwalkable, B_ALLOWEXPAND);
if (c) {
teleportto(ally[i], c, B_TRUE);
}
@ -12661,7 +12704,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// override with forced race?
if (caster && getforcedspellrace(caster, spellid, racename, &tempcount)) {
race_t *r;
r = findracebyname(racename);
r = findracebyname(racename, NULL);
if (r) {
wantrace = r->id;
wantrc = RC_ANY;
@ -13185,7 +13228,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (i == 0) {
c = targcell;
} else {
c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND);
condset_t cs;
initcondv(&cs, CC_SOLID, B_FALSE, NA, CC_NONE);
c = getrandomadjcell(targcell, &cs, B_ALLOWEXPAND);
}
if (c) {
if (c->lf && (c->lf->race->baseid != R_SPIDER)) {
@ -13447,7 +13492,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
job_t *j;
char *p,lfname[BUFLEN];
// summon a human
c = getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND);
c = getrandomadjcell(caster->cell, &ccwalkable, B_ALLOWEXPAND);
j = getrandomjob(B_TRUE);
lf = addlf(c, R_HUMAN, target->level);
givejob(lf, j->id);
@ -13556,7 +13601,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (strlen(buf)) {
if (appearonground) {
cell_t *where;
where = real_getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, target, MT_NOTHING);
where = real_getrandomadjcell(target->cell, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED, NULL, target);
if (!where) {
where = target->cell;
}
@ -13637,7 +13682,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (hasflag(o->flags, F_IMPASSABLE)) {
cell_t *newloc;
// if so, don't put it where the player is!
newloc = real_getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL, target, MT_NOTHING);
newloc = real_getrandomadjcell(target->cell, &ccwalkable, B_ALLOWEXPAND, LOF_DONTNEED,
NULL, target);
o = relinkob(o, newloc->obpile);
}
if (o) {
@ -14511,7 +14557,7 @@ char *getspelldesc(enum OBTYPE spellid, int power, char *buf) {
// returns the number of materials/cutoffs which were appended.
int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repairablemats, int *cutoffpct, int *nmats) {
enum SKILLLEVEL slev;
int cutoff,nworkable = 0;
int cutoff,cutoffmod = 0,nworkable = 0;
object_t *helpob = NULL;
// note: we DONT initialise nmats to zero.
@ -14527,11 +14573,13 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair
default: cutoff = 100; break;
}
if (skid == SK_METALWORK) {
helpob = getworkhelpob(lf->pack, MT_METAL);
helpob = getworkhelpob(lf->pack, MT_METAL, NULL, &cutoffmod);
} else if (skid == SK_SEWING) {
helpob = getworkhelpob(lf->pack, MT_CLOTH);
helpob = getworkhelpob(lf->pack, MT_CLOTH, NULL, &cutoffmod);
}
if (helpob) {
cutoff -= cutoffmod;
}
if (helpob) cutoff -= 15;
limit(&cutoff, 0, NA);
@ -14558,12 +14606,18 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair
}
// returns an object from 'op' which will help with work on the given material
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat) {
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat, int *howmuch, int *cutoffmod) {
object_t *helpob = NULL;
if ((mat == MT_LEATHER) || (mat == MT_CLOTH)) {
helpob = hasob(op, OT_NEEDLE);
} else if (mat == MT_METAL) {
helpob = hasob(op, OT_SPANNER);
if (howmuch) *howmuch = 0;
if (cutoffmod) *cutoffmod = 0;
helpob = hasobwithflagval(op, F_HELPSREPAIR, mat, NA, NA, NULL);
if (helpob) {
flag_t *f;
f = hasflagval(helpob->flags, F_HELPSREPAIR, mat, NA, NA, NULL);
if (f) {
if (howmuch) *howmuch = f->val[1];
if (cutoffmod) *cutoffmod = f->val[2];
}
}
return helpob;
}
@ -14964,7 +15018,7 @@ int summonlfs(lifeform_t *caster, cell_t *where, enum RACE wantrace, enum RACECL
for (i = 0; i < howmany; i++) {
// get random adjacent cell
// (prefer cells in sight of caster)
c = real_getrandomadjcell(where, WE_EMPTY, B_ALLOWEXPAND, LOF_NEED, NULL, NULL, caster, MT_NOTHING);
c = real_getrandomadjcell(where, &ccwalkable, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
if (!c) {
return ncreated;
}

View File

@ -33,7 +33,7 @@ int getspellrange(lifeform_t *lf, enum OBTYPE spellid, int power, int *minrange)
int getstamcost(lifeform_t *lf, enum OBTYPE oid);
char *getspelldesc(enum OBTYPE spellid, int power, char *buf);
int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repairablemats, int *cutoffpct, int *nmats);
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat);
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat, int *howmuch, int *cutoffmod);
void pullobto(object_t *o, lifeform_t *lf);
int schoolappearsinbooks(enum SPELLSCHOOL ss);
void spellcloud(cell_t *srcloc, int radius, int dirtype, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext, int aimedateyes, object_t *fromob, int includecentre);

5
text.c
View File

@ -1240,6 +1240,8 @@ char *getjobcatname(enum JOBCATEGORY jc) {
return "Fighter/Thief";
case JC_FIGHTERRANGED:
return "Ranged Fighter";
case JC_FIGHTERSPEC:
return "Specialist Fighter";
case JC_MAGE:
return "Mage";
case JC_THIEF:
@ -2500,8 +2502,9 @@ char *strrep(char *text, char *oldtok, char *newtok, int *rv) {
// returns TRUE if any replacements made
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv) {
char *temp;
char *found = strstr(in, oldtok);
char *found;
int idx;
found = strstr(in, oldtok);
if(!found) {
*out = realloc(*out, strlen(in) + 1); // oooooooo crashing in realloc
strcpy(*out, in);

15
vault.c
View File

@ -1162,7 +1162,7 @@ int handleline(vault_t *v, char *line) {
addflag(v->flags, F_VAULTBOX, thingtype, pct, B_FALSE, buf);
ok = B_TRUE;
} else {
dblog("invalid box() definition: '%s'", line);
dblog("thingok() failed in box definition: '%s'", line);
}
} else if (strstarts(line, "fill(")) { // fill region
@ -1213,7 +1213,8 @@ int handleline(vault_t *v, char *line) {
addflag(v->flags, F_VAULTBOX, thingtype, pct, B_TRUE, buf);
ok = B_TRUE;
} else {
dblog("invalid box() definition: '%s'", line);
dblog("thingok failed in fill() definition: '%s'", line);
dblog("failed thingname: '%s'", thingname);
}
} else if (strstarts(line, "scatter(")) { // fill region
// scatter(x,y,x2,y2) type:what:howmany[:pct]
@ -1631,6 +1632,11 @@ vault_t *loadvault(char *dir, char *filename) {
while (!feof(f)) {
// strip newline
line[strlen(line)-1] = '\0';
// strip trailing spaces
while (line[strlen(line)-1] == ' ') {
line[strlen(line)-1] = '\0';
}
// handle it
if (handleline(v, line)) {
goterrors = B_TRUE;
@ -1752,7 +1758,7 @@ int real_vaultthingok(enum VAULTTHING vt, char *what, int *hasfire) {
if (streq(what, "random")) {
return B_TRUE;
} else {
r = findracebyname(what);
r = findracebyname(what, NULL);
if (r) {
if (r->material->id == MT_FIRE) {
*hasfire = B_TRUE;
@ -1760,7 +1766,8 @@ int real_vaultthingok(enum VAULTTHING vt, char *what, int *hasfire) {
return B_TRUE;
} else {
enum RACE rid;
rid = parserace(what, NULL, NULL, NULL);
condset_t cs;
rid = parserace(what, NULL, &cs, NULL, NULL);
if (rid) {
if (hasfire) {
r = findrace(rid);