- [+] BUG: arrows shouldn't be able to trigger arrow traps!!!

- [+] king piranhas shouldn't leap out of the water!
- [+] don't catch thrown missiles if it will burden us
- [+] in @@, show "accuracy" as a seperate line, not with your weapon.
- [+] higher chance of learning psionics on level up.
- [+] fix up monster hp - too easy to kill most things in one hit with
      dam = 4-12, 2 attacks (ie. l6 monk)
    - [+] dump out all mosnters sorted by hit dice (show avg hp)
    - [+] fix them up
- [+] vault->entertext - ie "you enter a dining room"
- [+] make random monster generation go by hitdice AND rarity rr_. 
      IGNORE rarity value.
    - [+] start with hd = level.  sometimes incrase
    - [+] remove all rarity values from monsters
- [+] disorient might need to be higher level than stun
- [+] make psionic spell mp cost be level, rather than level^2?
- [+] ai bug:
    - [+] .oO { looking for a target . }
          .oO { found an enemy target - lfid 256 (human) ! }
          .oO { default - moving randomly }
- [+] reduce cost for higher levle spells agian.
- [+] prevent player from eating an ice sheid!
- [+] bug when eating from the floor with multiple food items there
- [+] assassin's blink spell - teleport behind and facing someone.
      medium level translocation.
- [+] make "chunk of roast meat" be "chunk of roast goblin meat"
    - [+] and base nutrition on corpse type
- [+] highlevel sixth sense should let you turn to face it
* [+] add prompt text to msg hist:
- [+] sixth sense should only pick up hostile monsters
- [+] need a good reason that wizards can't wear armour.
    - [+] if isplayer(), failure chance depends on any arm/shield
          penalties
- [+] show f_impassable in describeob()
- [+] no walking backwards/sideways if you're stuck in a web/vine. can
      only turn.
- [+] objects for protection:
    - [+] eyeglasses (+vision)
    - [+] safety goggles
- [+] ERROR - stairs link to existing map 0('the surface(0,0) (id #0)',
      depth 1), but it has no free stairs.
    - [+] when we restart map regeneration, must first REMOVE
          referenecs to this map!!!
    - [+] implemented.
- [+] fixed bug with sleep interruption
- [+] You attack the helpless the dwarf monk!  You flatten the dwarf
      monk!
      The dwarf monk loses consciousness.   damage's robe protects it.
- [+] add stamina cost to other abilities
- [+] add descriptions to lore skills
- [+] make athletics skill give you more stamina?
* [+] monstesr stopping fleeing when they can't see player
This commit is contained in:
Rob Pearce 2011-09-27 18:56:58 +00:00
parent 2db53bca61
commit 5cb8b05817
26 changed files with 922 additions and 448 deletions

21
ai.c
View File

@ -37,21 +37,27 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
}
if (!canattack(lf)) {
dblog(".oO { canattack() is false }");
return B_FALSE;
}
// mindless?
/*
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) == IQ_MINDLESS) {
if (!isundead(lf)) {
if (!isundead(lf) && (lf->race->raceclass->id != RC_PLANT)) {
dblog(".oO { i am mindless and not undead }");
return B_TRUE;
}
}
*/
// already targetting this lf?
f = lfhasflagval(lf, F_TARGETLF, victim->id, NA, NA, NULL);
if (f) {
dblog(".oO { i am already targetting this lf }");
if ((f->lifetime > 0) && (f->lifetime < timelimit)) {
f->lifetime = timelimit;
dblog(".oO { (flag lifetime updated) }");
}
return B_TRUE;
}
@ -62,7 +68,7 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
penalty = (getcelldist(lf->cell, victim->cell)-1);
if (penalty < 0) penalty = 0;
penalty *= 3;
if (!skillcheckvs(lf, SC_WILL, -penalty, victim, SC_WILL, 0)) {
if (!skillcheckvs(lf, SC_WILL, -penalty, victim, SC_WILL, 5)) {
dblog(".oO { attempted target fooled me with feign death. ignoring. }");
return B_TRUE;
}
@ -1426,6 +1432,7 @@ void aiturn(lifeform_t *lf) {
if (aiattack(lf, newtarget, DEF_AIFOLLOWTIME)) {
// failed for some reason. maybe target was feigning
// death?
if (db) dblog(".oO { setting a new target via aiattack failed! }");
} else {
// then move towards them...
if (db) dblog(".oO { moving towards my new target (%d,%d) -> (%d,%d) }", lf->cell->x, lf->cell->y,
@ -1790,8 +1797,8 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
}
}
if ((ot->id == OT_A_SWOOP) || (ot->id == OT_A_CHARGE)) {
flag_t *willflag;
flag_t *srflag;
cell_t *adjcell;
flag_t *willflag, *srflag;
int srange = 5;
willflag = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
@ -1805,8 +1812,10 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
srange = srflag->val[0];
}
if (!haslof(lf->cell, victim->cell, LOF_NEED,NULL)) {
adjcell = get_closest_adjcell(lf->cell, victim->cell);
if (!adjcell || celldangerous(lf, adjcell, B_TRUE, NULL)) { // don't charge into dangerous cells
specificcheckok = B_FALSE;
} else if (!haslof(lf->cell, victim->cell, LOF_NEED,NULL)) {
specificcheckok = B_FALSE;
} else if (isimmobile(lf)) {
specificcheckok = B_FALSE;

View File

@ -1454,6 +1454,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum
if (isplayer(victim)) {
msg("Your %s protects you.", noprefix(obname));
} else if (cansee(player, victim)) {
getlfname(victim, victimname);
msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname));
}
} else {
@ -1483,6 +1484,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum
if (isplayer(victim)) {
msg("Your %s protects you.", noprefix(obname));
} else if (cansee(player, victim)) {
getlfname(victim, victimname);
msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname));
}
}
@ -1496,6 +1498,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum
if (isplayer(victim)) {
msg("Your %s protects you.", noprefix(obname));
} else if (cansee(player, victim)) {
getlfname(victim, victimname);
msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname));
}
} else {
@ -1515,6 +1518,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum
if (isplayer(victim)) {
msg("Your %s protects you.", noprefix(obname));
} else if (cansee(player, victim)) {
getlfname(victim, victimname);
msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname));
}
} else {
@ -1528,6 +1532,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum
if (isplayer(victim)) {
msg("Your %s protects you.", noprefix(obname));
} else if (cansee(player, victim)) {
getlfname(victim, victimname);
msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname));
}
} else {

392
data.c

File diff suppressed because it is too large Load Diff

Binary file not shown.

20
defs.h
View File

@ -29,6 +29,9 @@
#define DEF_TURNPCT 40
#define DEF_WINDOWPCT 5
// lifeform defaults
#define DEF_HITDICE "1d4"
// getrandomemptycell() params
#define WE_WALKABLE 1
#define WE_EMPTY 2
@ -39,6 +42,8 @@
// Booleans
#define B_FALSE (0)
#define B_TRUE (-1)
#define B_ONPURPOSE (-1)
#define B_CHANGEDIR (-1)
#define B_VIS (1)
#define B_UNKNOWN (0)
#define B_NOVIS (-1)
@ -596,6 +601,7 @@ enum CELLTYPE {
CT_CORRIDOR,
CT_DIRT,
CT_VILLAGEGROUND,
CT_FAKE,
CT_FLOORSHOP,
CT_FLOORWOOD,
CT_GRASS,
@ -711,7 +717,7 @@ enum BLESSTYPE {
B_CURSED = -1
};
#define RARITYVARIANCELF (5)
#define RARITYVARIANCELF (1)
#define RARITYVARIANCEOB (10)
enum RARITY {
@ -1232,6 +1238,7 @@ enum OBTYPE {
// -- translocation
OT_S_APPORTATION,
OT_S_BLINK,
OT_S_BLINKASS,
OT_S_DISPERSAL,
OT_S_GATE,
OT_S_PLANESHIFT,
@ -1456,8 +1463,10 @@ enum OBTYPE {
// armour - ears
OT_EARPLUGS,
// armour - eyes
OT_SUNGLASSES,
OT_SAFETYGLASSES,
OT_SPECTACLES,
OT_EYEPATCH,
OT_SUNGLASSES,
// armour - shields
OT_BUCKLER,
OT_SHIELD,
@ -2304,7 +2313,7 @@ enum FLAG {
// ie 'magic armour', 'force field'
// v0 is power left.
F_ASLEEP, // lf is asleep.
// if v1 is set, means we are 'meditating' instead
// v1 is enum sleeptype st_xxx
// if v2 is set, means we are sleeping on
// purpose and will wake up when at full hp/mp/etc.
F_ATTACHEDTO, // you are attached to lf id v0, and will move with it
@ -2493,6 +2502,7 @@ enum FLAG {
F_VAULTATONEOF, // v0=thingtype, v1 = pctchance
// text=(x,y)(x,y)(x,y)...(x,y) thingname
F_VAULTBOX, // v0=thingtype, v1=pctchance, v2=fill?, text=x1,y1,x2,y2,thingname
F_VAULTENTERTEXT, // text = what to show when player enters
F_VAULTDLEVMIN, // v0 = mininum map depth/difficulty for this vault
F_VAULTDLEVMAX, // v0 = maximum map depth/difficulty for this vault
F_VAULTEXIT, // v0/1=x,y for exit.
@ -2548,7 +2558,7 @@ enum INJURY {
IJ_LEGBROKEN,
IJ_LEGBRUISE,
IJ_NOSEBROKEN,
IJ_RIBCRACKED,
IJ_RIBCRACKED, // can be from explosive too
IJ_SHOULDERDISLOCATED,
IJ_WINDPIPECRUSHED,
// slashing
@ -2562,7 +2572,9 @@ enum INJURY {
IJ_EYELIDSCRAPED,
IJ_EYEDESTROYED,
// explosive
IJ_EARSRINGING,
IJ_HANDMISSING,
IJ_LUNGCOLLAPSED,
};

View File

@ -61,6 +61,8 @@ Flags can be:
dlevmax:xxx // can only randomly appear at or before dungeon
// levle xxx
entertext:xxx // show xxx when a non-blind player enters
goesin:xxx // can only randomly appear in habitat xxx
margin:x,y // must be x/y away from edges of map

251
io.c
View File

@ -465,6 +465,7 @@ void animsky(cell_t *src, char ch, int colour) {
char askchar(char *prompt, char *validchars, char *def, int showchars) {
char buf[BUFLEN];
char msghistbuf[BUFLEN];
char *p;
char temp[2];
char ch;
@ -510,6 +511,11 @@ char askchar(char *prompt, char *validchars, char *def, int showchars) {
}
}
curs_set(0);
// update messaage history
sprintf(msghistbuf, "%s%c", buf, ch);
addmsghist(msghistbuf);
clearmsg();
if ((ch == 10) && def) {
return def[0];
@ -771,7 +777,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
}
// hp
if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) ||
(getlorelevel(player, c->lf->race->raceclass->id) >= PR_ADEPT)
(getlorelevel(player, c->lf->race->raceclass->id) >= PR_SKILLED)
) {
char buf2[BUFLEN];
// show actual hp
@ -1013,7 +1019,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
// retbuf must already be allocated
// "def" is optional
char *askstring(char *prompt, char punc, char *retbuf, int retBUFLEN, char *def) {
char buf[BUFLEN];
char buf[BUFLEN],msghistbuf[BUFLEN];
char *ending;
more();
@ -1040,6 +1046,10 @@ char *askstring(char *prompt, char punc, char *retbuf, int retBUFLEN, char *def)
if (def && (strlen(retbuf) == 0)) {
strcpy(retbuf, def);
}
snprintf(msghistbuf, BUFLEN, "%s%s",buf,retbuf);
addmsghist(msghistbuf);
drawcursor();
return retbuf;
}
@ -1915,6 +1925,9 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
break;
case F_FLEEFROM:
msg("%s stop%s fleeing.", lfname, isplayer(lf) ? "" : "s");
if (!isplayer(lf)) {
dblog("xx");
}
donesomething = B_TRUE;
break;
case F_FRIENDLY:
@ -2466,7 +2479,8 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
int c,i;
object_t *mylist[MAXPILEOBS+1];
char myletters[MAXPILEOBS+1];
char numstring[BUFLEN];
char msghistbuf[BUFLEN],numstring[BUFLEN],fullprompt[BUFLEN];
char obname[BUFLEN];
int firstob = 0;
int nextpage = -1;
int lastline = SCREENH-4;
@ -2581,13 +2595,16 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
}
// draw prompt
if (strlen(numstring) > 0) {
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit) [%s]: ",prompt,
snprintf(fullprompt, BUFLEN, "%s (%sESC to quit) [%s]: ",prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
numstring);
} else {
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit): ", prompt,
snprintf(fullprompt, BUFLEN, "%s (%sESC to quit): ", prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "");
}
mvwprintw(mainwin, 0, 0, "%s", fullprompt);
if (nextpage != -1) {
mvwprintw(mainwin, y, 0, MORESTRING);
}
@ -2633,12 +2650,19 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
// display game windows again
clearmsg();
restoregamewindows();
getobname(o, obname, count ? *count : o->amt);
sprintf(msghistbuf, "%s%s",fullprompt,obname);
addmsghist(msghistbuf);
return o;
}
} else if ((ch == '-') && (opts & AO_INCLUDENOTHING)) { // select nothing
reason = E_SELNOTHING;
// display game windows again
restoregamewindows();
sprintf(msghistbuf, "%s-",fullprompt);
addmsghist(msghistbuf);
return NULL;
} else if (isdigit(ch) && count) {
char temp[2];
@ -2660,6 +2684,8 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
}
}
sprintf(msghistbuf, "%s-",fullprompt);
addmsghist(msghistbuf);
// display game windows again
restoregamewindows();
return NULL;
@ -2671,7 +2697,7 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
int selected[MAXPILEOBS+1];
int selcount[MAXPILEOBS+1];
char myletters[MAXPILEOBS+1];
char numstring[BUFLEN];
char msghistbuf[BUFLEN],numstring[BUFLEN];
char pbuf[BUFLEN];
int firstob = 0;
int nextpage = -1;
@ -2706,8 +2732,6 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
useobletters = B_FALSE;
}
// construct a list of objects
c = 0;
i = 0;
@ -2857,6 +2881,8 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
reason = E_SELNOTHING;
nretobs = 0;
// display game windows again
sprintf(msghistbuf, "%s-", pbuf);
addmsghist(msghistbuf);
restoregamewindows();
return B_TRUE;
} else if (ch == ',') { // toggle all/none
@ -2906,6 +2932,9 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
// clear msg bar
clearmsg();
sprintf(msghistbuf, "%s", pbuf);
addmsghist(msghistbuf);
// display game windows again
restoregamewindows();
if (nretobs <= 0) {
@ -3801,6 +3830,7 @@ void doeat(obpile_t *op) {
ch = askchar(buf, "yn","n", B_TRUE);
if (ch == 'y') {
eatob = o;
break;
}
}
}
@ -4272,6 +4302,17 @@ char *makedesc_ob(object_t *o, char *retbuf) {
}
}
if ((f = hasflag(o->flags, F_IMPASSABLE)) != NULL) {
if ((f->val[0] == SZ_MIN) && (f->val[1] == SZ_MAX)) {
snprintf(buf, BUFLEN, "It is %simpassable.\n", hasflag(o->flags, F_DOOR) ? "currently " : "");
} else {
snprintf(buf, BUFLEN, "It is %simpassable for %s to %s sized creatures.\n",
hasflag(o->flags, F_DOOR) ? "currently " : "",
getsizetext(f->val[0]), getsizetext(f->val[1]));
}
strncat(retbuf, buf, HUGEBUFLEN);
}
if (isedible(o)) {
int basenutr;
basenutr = getnutritionbase(o);
@ -5164,10 +5205,20 @@ char *makedesc_spell(objecttype_t *ot, char *retbuf) {
// properties
f = hasflag(ot->flags, F_SPELLLEVEL);
if (f) {
flag_t *sf;
sf = hasflag(ot->flags, F_SPELLSCHOOL);
assert(sf);
sprintf(buf, "It is a level %d %s spell.\n",f->val[0], getschoolname(sf->val[0]));
char schoollist[BUFLEN];
strcpy(schoollist, "");
getflags(ot->flags, retflag, &nretflags, F_SPELLSCHOOL, F_NONE);
for (i = 0; i < nretflags; i++) {
if (streq(schoollist, "")) { // first one
strcpy(schoollist, getschoolname(retflag[i]->val[0]));
} else {
strcat(schoollist, "/");
strcat(schoollist, getschoolname(retflag[i]->val[0]));
}
}
assert(strlen(schoollist));
sprintf(buf, "It is a level %d %s spell.\n",f->val[0], schoollist);
strncat(retbuf, buf, BUFLEN);
}
@ -6606,7 +6657,7 @@ enum COLOUR getattrcolour(enum ATTRBRACKET brack) {
char getchoice(prompt_t *prompt) {
int i;
int y;
char ch;
char ch,msghistbuf[BUFLEN],fullprompt[BUFLEN];
int sel;
int gotheadings;
int first= 0;
@ -6657,8 +6708,9 @@ char getchoice(prompt_t *prompt) {
}
// display prompt question
mvwprintw(mainwin, 0, 0, "%s %s", prompt->q[prompt->whichq],
prompt->maycancel ? "[ESC to cancel] " : "");
snprintf(fullprompt, BUFLEN, "%s %s", prompt->q[prompt->whichq], prompt->maycancel ? "[ESC to cancel] " : "");
mvwprintw(mainwin, 0, 0, "%s", fullprompt);
wrefresh(mainwin);
// ask for choice...
@ -6699,6 +6751,10 @@ char getchoice(prompt_t *prompt) {
}
curs_set(0);
restoregamewindows();
snprintf(msghistbuf, BUFLEN, "%s%s",fullprompt,prompt->choice[i].desc);
addmsghist(msghistbuf);
// return NUL or result char
if (ch == 27) {
return '\0';
@ -6717,6 +6773,7 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
int lastline = SCREENH - 4;
char inpstring[BUFLEN];
char curheading[BUFLEN];
char msghistbuf[BUFLEN];
int doneheading;
int nvalid;
char promptstr[BUFLEN];
@ -7007,6 +7064,14 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
if ((gamemode == GM_GAMESTARTED)) {
restoregamewindows();
}
snprintf(promptstr, BUFLEN, "%s [%s%s] ",
prompt->q[prompt->whichq],
prompt->maycancel ? "ESC," : "",
showall ? "'=next page,?=toggle" : "?=list" );
snprintf(msghistbuf, BUFLEN, "%s%s",promptstr,prompt->choice[i].text);
addmsghist(msghistbuf);
// return NUL or result char
if (ch == 27) {
return '\0';
@ -7648,7 +7713,8 @@ void msg_real(char *format, ... ) {
assert(2 == 3);
}
assert(!strchr(buf, '#'));
//assert(!strchr(buf, '#'));
// ie. can the message buffer fit:
// what is already there + 2 spaces + the new text + '--more--' ?
//if (strlen(msgbuf) + 2 + strlen(buf) + strlen(MORESTRING) >= SCREENW) {
@ -8440,13 +8506,13 @@ void showlfstats(lifeform_t *lf, int showall) {
if (showall ||
(getseenlfconditioncutoff(player) == C_HEALTHY) ||
(lorelev >= PR_ADEPT)) {
(lorelev >= PR_SKILLED)) {
int xx,yy;
doheadingsmall(mainwin, y, 0, ftext, "HP");
if (lorelev >= PR_ADEPT) setcol(mainwin, lorecol);
if (lorelev >= PR_SKILLED) setcol(mainwin, lorecol);
wprintw(mainwin, "%d/%d ", lf->hp , lf->maxhp);
if (lorelev >= PR_ADEPT) unsetcol(mainwin, lorecol);
if (lorelev >= PR_SKILLED) unsetcol(mainwin, lorecol);
getyx(mainwin, yy, xx);
doheadingsmall(mainwin, y, xx, "%5s:", "Stam");
@ -8598,7 +8664,6 @@ void showlfstats(lifeform_t *lf, int showall) {
y2++;
// current weapon + dam
nweps = 0;
o = getweapon(lf);
@ -8613,70 +8678,83 @@ void showlfstats(lifeform_t *lf, int showall) {
}
}
for (i = 0; i < nweps; i++) {
if (w[i]) {
int mindam,maxdam;
int bonus,speed;
// weapon
if (showall) {
char buf2[BUFLEN];
// calculate damage
f = hasflag(w[i]->flags, F_BONUS);
if (f && f->known) {
// only tell player about bonuses if they are known.!
bonus = f->val[0];
if (nweps == 0) {
int speed;
// no weapon
snprintf(buf, BUFLEN, "(innate attack)");
doheadingsmall(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
// attack speed
acc = getlfaccuracy(lf, NULL);
speed = getattackspeed(lf);
getspeedname(speed, buf2);
capitalise(buf2);
snprintf(buf, BUFLEN, "%s, %d%%",buf2,acc);
mvwprintw(mainwin, y2, x2, "%14s", " ");
wprintw(mainwin, "%-20s", buf); y2++;
} else {
for (i = 0; i < nweps; i++) {
if (w[i]) {
int mindam,maxdam;
int bonus,speed;
// weapon
if (showall) {
char buf2[BUFLEN];
// calculate damage
f = hasflag(w[i]->flags, F_BONUS);
if (f && f->known) {
// only tell player about bonuses if they are known.!
bonus = f->val[0];
} else {
bonus = 0;
}
f = hasflag(w[i]->flags, F_DAM);
if (f) {
getdamrange(f, &mindam, &maxdam);
} else {
mindam = 0;
maxdam = 0;
}
mindam += bonus;
maxdam += bonus;
// apply damage mod for strength
if (!hasflag(w[i]->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
mindam = (int)((float)mindam * dammod);
maxdam = (int)((float)maxdam * dammod);
}
if (mindam < 0) mindam = 0;
if (maxdam < 0) maxdam = 0;
snprintf(buf, BUFLEN, "%s (%d-%d dmg)", w[i]->type->name,(int)mindam,(int)maxdam);
doheadingsmall(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
// attack speed
acc = getlfaccuracy(lf, w[i]);
speed = getattackspeed(lf);
getspeedname(speed, buf2);
capitalise(buf2);
snprintf(buf, BUFLEN, "%s, %d%%",buf2,acc);
mvwprintw(mainwin, y2, x2, "%14s", " ");
wprintw(mainwin, "%-20s", buf); y2++;
} else {
bonus = 0;
// just show weapon name
snprintf(buf, BUFLEN, "%s", w[i]->type->name);
doheadingsmall(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
}
f = hasflag(w[i]->flags, F_DAM);
if (f) {
getdamrange(f, &mindam, &maxdam);
} else {
mindam = 0;
maxdam = 0;
}
mindam += bonus;
maxdam += bonus;
// apply damage mod for strength
if (!hasflag(w[i]->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
mindam = (int)((float)mindam * dammod);
maxdam = (int)((float)maxdam * dammod);
}
if (mindam < 0) mindam = 0;
if (maxdam < 0) maxdam = 0;
snprintf(buf, BUFLEN, "%s (%d-%d dmg)", w[i]->type->name,(int)mindam,(int)maxdam);
doheadingsmall(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
// attack speed
acc = getlfaccuracy(lf, w[i]);
speed = getattackspeed(lf);
getspeedname(speed, buf2);
capitalise(buf2);
snprintf(buf, BUFLEN, "%s, %d%%",buf2,acc);
mvwprintw(mainwin, y2, x2, "%14s", " ");
wprintw(mainwin, "%-20s", buf); y2++;
} else {
// just show weapon name
snprintf(buf, BUFLEN, "%s", w[i]->type->name);
doheadingsmall(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
}
} else {
// no weapon
snprintf(buf, BUFLEN, "N/A");
doheadingsmall(mainwin, y2, x2, ftext, "Current Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
}
} // end for each weapon
} // end for each weapon
}
// skip a line
y2++;
@ -9482,6 +9560,15 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
if (lfhasflag(lf, F_CANCAST)) {
int chance;
chance = getmiscastchance(lf);
if (chance) {
mvwprintw(mainwin, y, 0, "%s spells have a %d%% chance of failing due to cumbersome armour.", your(lf), chance);
y++;
}
}
// flags which aren't really intrinsics
if (lfhasflag(lf, F_AQUATIC)) {
mvwprintw(mainwin, y, 0, "%s %s aquatic, and move normally through water.", you(lf), is(lf));
@ -9564,8 +9651,8 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s %s confused.", you(lf), is(lf));
y++;
}
f = lfhasknownflag(lf, F_DEAF);
if (f) {
if (isdeaf(lf)) {
mvwprintw(mainwin, y, 0, "%s %s deaf.", you(lf), is(lf));
y++;
}

266
lf.c
View File

@ -25,6 +25,8 @@ extern FILE *logfile;
extern void (*precalclos)(lifeform_t *);
extern int noredraw;
extern map_t *firstmap;
extern race_t *firstrace, *lastrace;
extern raceclass_t *firstraceclass, *lastraceclass;
@ -36,6 +38,8 @@ extern lifeform_t *player;
extern glyph_t playerglyph;
extern glyph_t tempglyph;
extern int maxmonhitdice;
extern npcname_t *npcname;
extern int numnpcnames;
@ -684,7 +688,7 @@ int canhear(lifeform_t *lf, cell_t *dest, int volume) {
// can't hear if you are deaf or have no ears
if (!hasbp(lf, BP_EARS)) return B_FALSE;
if (lfhasflag(lf, F_DEAF)) return B_FALSE;
if (isdeaf(lf)) return B_FALSE;
// can't hear when training
if (lfhasflag(lf, F_TRAINING)) return B_FALSE;
@ -1293,6 +1297,15 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
// lose mp
losemp(lf, cost);
// miscast chance?
if (isplayer(lf)) {
if (pctchance(getmiscastchance(lf))) {
msg("^WYour cumbersome armour makes you miscast your spell!");
return B_FALSE;
}
}
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 20 + power, 0)) {
if (power > 1) {
// half strength
@ -1300,7 +1313,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
if (power <= 1) power = 1;
if (isplayer(lf)) {
msg("^wYour magic resistance interferes with your spell!");
msg("^wYour magic resistance lowers your spell's power.");
}
}
}
@ -2209,6 +2222,33 @@ void dumplf(void) {
dblog("END LIFEFORM DUMP (%d found)",count);
}
void dumpmonsters(void) {
race_t *r;
flag_t *f;
int count = 0,wanthd;
dblog("START MONSTER DUMP:");
for (wanthd = 0; wanthd < maxmonhitdice ; wanthd++) {
dblog("%d HIT DICE MONSTERS:",wanthd);
for (r = firstrace ; r ; r = r->next) {
int thishd;
thishd = gethitdicerace(r);
if (thishd == wanthd) {
int ndice,nsides,bonus,min,max;
f = hasflag(r->flags, F_HITDICE);
texttodice(f->text ? f->text : DEF_HITDICE, &ndice,&nsides,&bonus);
min = ndice + bonus;
max = (ndice*nsides) + bonus;
dblog("\t%s (%d avg hp)",r->name, (min+max)/2);
count++;
}
}
}
dblog("END MONSTER DUMP (%d found)",count);
}
void genxplist(void) {
race_t *r;
race_t *racetemp;
@ -2488,37 +2528,34 @@ void dumplev(void) {
race_t *r;
objecttype_t *ot;
flag_t *f;
dblog("Start monster dump");
dblog("Start lev monster dump");
dblog("------------------\n");
// NOTE: this code copied from getrandomrace(), which is used by addmonster().
for (i = 1; i <= 25; i++) {
int min,max,prevmin,prevmax;
getrarityrange(i-1, &prevmin, &prevmax, RARITYVARIANCELF, B_FALSE);
getrarityrange(i, &min, &max, RARITYVARIANCELF, B_FALSE);
fprintf(logfile, "Dlev %d (rar >= %d): ",i,min);
gethitdicerange(i-1, &prevmin, &prevmax, RARITYVARIANCELF, B_FALSE);
gethitdicerange(i, &min, &max, RARITYVARIANCELF, B_FALSE);
fprintf(logfile, "Dlev %d (hd >= %d): ",i,min);
for (r = firstrace ; r; r = r->next) {
int rarity = 0;
f = hasflagval(r->flags, F_RARITY, H_DUNGEON, NA, NA, NULL);
if (f) {
rarity = f->val[1];
// ok this lev?
if ((rarity >= min) && (rarity <= max)) {
char buf[BUFLEN];
strcpy(buf, "");
// ok on previous lev too?
if ((rarity >= prevmin) && (rarity <= prevmax)) {
// only print if dlev is 1
if (i == 1) {
snprintf(buf, BUFLEN, "%s, ", r->name);
}
} else {
// ie. new mosnter for this lev
//snprintf(buf, BUFLEN, "*%s*, ", r->name);
//makeuppercase(buf);
int hd = 0;
hd = gethitdicerace(r);
// ok this lev?
if ((hd >= min) && (hd <= max)) {
char buf[BUFLEN];
strcpy(buf, "");
// ok on previous lev too?
if ((hd >= prevmin) && (hd <= prevmax)) {
// only print if dlev is 1
if (i == 1) {
snprintf(buf, BUFLEN, "%s, ", r->name);
}
fprintf(logfile, "%s", buf);
}
} else {
// ie. new mosnter for this lev
//snprintf(buf, BUFLEN, "*%s*, ", r->name);
//makeuppercase(buf);
snprintf(buf, BUFLEN, "%s, ", r->name);
}
fprintf(logfile, "%s", buf);
}
}
fprintf(logfile, "\n");
@ -2527,7 +2564,6 @@ void dumplev(void) {
dblog("Start object dump");
dblog("------------------\n");
// NOTE: this code copied from getrandomrace(), which is used by addmonster().
for (i = 1; i <= 25; i++) {
int min,max,prevmin,prevmax;
getrarityrange(i-1, &prevmin, &prevmax, RARITYVARIANCEOB, B_FALSE);
@ -3280,7 +3316,7 @@ void enhanceskills(lifeform_t *lf) {
// psionics sometimes lets you learn spells
slev = getskill(lf, SK_SS_MENTAL);
if (pctchance(slev*10)) {
if (pctchance(slev*20)) {
// construct list of castable mental spells
makespellchoicelist(&prompt, lf, "Learn which new psionic power:","Describe which psionic power:", SS_MENTAL, B_TRUE, B_FALSE, B_FALSE, player->maxmp);
if (prompt.nchoices > 0) {
@ -3347,7 +3383,7 @@ int fall(lifeform_t *lf, lifeform_t *fromlf, int announce) {
}
}
}
taketime(lf, SP_NORMAL*2);
//taketime(lf, SP_NORMAL*2);
addflag(lf->flags, F_PRONE, B_TRUE, NA, NA, NULL);
loseconcentration(lf);
@ -3626,20 +3662,21 @@ int flee(lifeform_t *lf) {
if (!nretflags) return B_FALSE;
}
// now determine who to flee from.
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_FLEEFROM) {
lifeform_t *thisone;
thisone = findlf(lf->cell->map, f->val[0]);
if (thisone) {
if (cansee(lf, thisone)) {
// TODO: this really means that the monster is cheating
if (haslof(lf->cell, thisone->cell, LOF_WALLSTOP, NULL)) {
// if not fleeing from anyone, or this one is closer...
if (!fleefrom || getcelldist(lf->cell, thisone->cell) < getcelldist(lf->cell, fleefrom->cell)) {
fleefrom = thisone;
}
} else {
// if we can't see the person we're running from, and it's not enforced for
// if we don't have LOF to the person we're running from, and it's not enforced for
// a certain time period (ie. f->lifetime == PERMENANT), we can now stop fleeing.
if (f->lifetime == PERMENANT) {
// player let something flee?
@ -3653,6 +3690,8 @@ int flee(lifeform_t *lf) {
fleefrom = thisone;
}
}
} else {
killflag(f);
}
}
}
@ -5084,6 +5123,17 @@ int gethitdice(lifeform_t *lf) {
return (lf->maxhp / 4);
}
int gethitdicerace(race_t *r) {
flag_t *f;
f = hasflag(r->flags, F_HITDICE);
if (f) {
int ndice,nsides,bonus;
texttodice(f->text ? f->text : DEF_HITDICE, &ndice,&nsides,&bonus);
return ((ndice*nsides)+bonus) / 4;
}
return 1;
}
int gethppct(lifeform_t *lf) {
float pct;
pct = (int)(((float)lf->hp / (float)lf->maxhp) * 100);
@ -5218,7 +5268,7 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
if (wep) {
acc = getobaccuracy(wep, lf);
} else {
acc = 100; // fists
acc = 100; // innate attack
}
// dual weilding?
@ -5415,6 +5465,18 @@ int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions) {
return *nminions;
}
int getmiscastchance(lifeform_t *lf) {
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
int chance = 0;
getflags(lf->flags, retflag, &nretflags, F_ARMOURPENALTY, F_SHIELDPENALTY, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->val[0] != NA) chance += retflag[i]->val[0];
if (retflag[i]->val[1] != NA) chance += retflag[i]->val[1];
}
return chance;
}
int getnightvisrange(lifeform_t *lf) {
int range = 0; // default
flag_t *f;
@ -5704,7 +5766,13 @@ float getmaxpushweight(lifeform_t *lf) {
}
float getmaxstamina(lifeform_t *lf) {
return (getattr(lf, A_CON) / 2);
int stam = 0;
if (lfhasflagval(lf, F_INJURY, IJ_LUNGCOLLAPSED, NA, NA, NULL)) {
return 0;
}
stam = (getattr(lf, A_CON) / 2);
stam += (getskill(lf, SK_ATHLETICS)*2);
return stam;
}
int getmr(lifeform_t *lf) {
@ -6352,7 +6420,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
int selidx;
int db = B_FALSE;
int depth;
int raritymin,raritymax;
int hdmin,hdmax;
enum RARITY wantrr = RR_COMMON;
// determine rarity of lf to generate
@ -6362,7 +6430,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
depth = getmapdifficulty((c && c->map) ? c->map : NULL);
}
getrarityrange(depth, &raritymin, &raritymax, RARITYVARIANCELF, B_TRUE);
gethitdicerange(depth, &hdmin, &hdmax, RARITYVARIANCELF, B_TRUE);
// pick rr...
wantrr = RR_COMMON;
@ -6370,7 +6438,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
wantrr++;
}
if (db) dblog("finding random lf with rarity val %d-%d and rr <= %d\n",raritymin,raritymax, wantrr);
if (db) dblog("finding random lf with hitdice %d-%d and rr <= %d\n",hdmin,hdmax, wantrr);
// try to find a lf of this type which will
// fit in the map's habitat
@ -6378,23 +6446,31 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
while (nposs == 0) {
for (r = firstrace ; r ; r = r->next) {
int valid = B_FALSE;
int thishd;
enum RARITY thisrr = RR_NEVER;
flag_t *rarflag = NULL;
// correct rarity?
rarflag = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!rarflag) {
if (c) {
rarflag = hasflagval(r->flags, F_RARITY, c->habitat->id, NA, NA, NULL);
} else {
rarflag = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL);
thishd = gethitdicerace(r);
if ((thishd < hdmin) || (thishd > hdmax)) {
valid = B_FALSE;
} else {
// correct rarity?
rarflag = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!rarflag) {
if (c) {
rarflag = hasflagval(r->flags, F_RARITY, c->habitat->id, NA, NA, NULL);
} else {
rarflag = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL);
}
}
}
if (rarflag) {
if ((rarflag->val[1] >= raritymin) && (rarflag->val[1] <= raritymax)) {
if (rarflag) {
if ((rarflag->val[2] == NA) || (rarflag->val[2] <= wantrr)) {
valid = B_TRUE;
thisrr = rarflag->val[2];
}
} else {
valid = B_FALSE;
}
}
@ -6415,7 +6491,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
}
if (valid) {
if (db) dblog("-> possibility: %s, rarity=%d",r->name, rarflag->val[1]);
if (db) dblog("-> possibility: %s, hitdice=%d, rarity=%s",r->name, thishd, getrarityname(thisrr));
poss[nposs] = r;
nposs++;
if (nposs >= MAXRANDOMLFCANDIDATES) break;
@ -6424,17 +6500,17 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
// nothing found?
if (nposs == 0) {
// already at lowest rarity?
if ((raritymax >= 100) && (raritymin <= 0)) {
// already at lowest hitdice?
if ((hdmax >= maxmonhitdice) && (hdmin <= 0)) {
// give up
if (db) dblog("no possible lf at all! giving up.");
return NULL;
}
// expand range and try again
raritymax += 10; if (raritymax > 100) raritymax = 100;
raritymin -= 10; if (raritymin < 0) raritymin = 0;
if (db) dblog("no possible lfs like this. trying again with rarity %d-%d\n",raritymin,raritymax);
hdmax ++; if (hdmax > maxmonhitdice) hdmax = maxmonhitdice;
hdmin --; if (hdmin < 0) hdmin = 0;
if (db) dblog("no possible lfs like this. trying again with hitdice %d-%d\n",hdmin,hdmax);
}
}
@ -7893,13 +7969,13 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
switch (where) {
case BP_BODY:
switch (rnd(1,2)) {
case 1:
break;
case 1: // collapsed lung
inj = IJ_LUNGCOLLAPSED;
desc = strdup("lungs have collapsed^lose all stamina points");
case 2:
inj = IJ_RIBCRACKED; desc = strdup("ribs are cracked^carrying capacity halved"); break;
break;
}
// massive burns
// collapsed lung
break;
case BP_HANDS:
// lose limb
@ -7936,8 +8012,15 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
}
break;
case BP_HEAD:
// ringing ears
// burnt eyes
switch (rnd(1,2)) {
case 1: // ringing ears
inj = IJ_EARSRINGING;
desc = strdup("ears are ringing^cannot hear sounds");
case 2: // blinded
addtempflag(lf->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(50,100));
break;
}
break;
case BP_LEGS:
// lose limb
@ -8651,6 +8734,12 @@ void killlf(lifeform_t *lf) {
}
}
int isdeaf(lifeform_t *lf) {
if (lfhasflag(lf, F_DEAF)) return B_TRUE;
if (lfhasflagval(lf, F_INJURY, IJ_EARSRINGING, NA, NA, NULL)) return B_TRUE;
return B_TRUE;
}
// returns second weapon if you are dual weilding
object_t *isdualweilding(lifeform_t *lf) {
object_t *priwep,*secwep;
@ -9102,7 +9191,6 @@ race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcol
lastrace = a;
a->next = NULL;
// props
a->id = id;
a->baseid = id; // default
@ -10807,14 +10895,14 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
// adjust it if you're deaf
strcpy(realseetext, seetext);
quotepos = strchr(realseetext, '\"');
if (lfhasflag(l, F_DEAF) && quotepos) {
if (isdeaf(l) && quotepos) {
*quotepos = '\0';
strcat(realseetext, "something");
}
msg("%s %s.", lfname, realseetext);
rv = B_TRUE;
}
} else if (text && !lfhasflag(l, F_DEAF) && ((nt != NC_WALK) || !lfhasflag(l, F_DONELISTEN))) {
} else if (text && !isdeaf(l) && ((nt != NC_WALK) || !lfhasflag(l, F_DONELISTEN))) {
// this means you can only hear one 'walk' sound per turn
char textnopunc[BUFLEN];
char punc;
@ -11070,8 +11158,7 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int want
if (!failed) {
// warn if it is too heavy
if (isplayer(lf) && !isburdened(lf) &&
(getobpileweight(lf->pack) + (getobunitweight(what)*howmany) > getmaxcarryweight(lf)) ) {
if (isplayer(lf) && !isburdened(lf) && willburden(lf, what, howmany)) {
char ch,buf[BUFLEN];
snprintf(buf, BUFLEN, "Picking up %s will burden you. Continue", obname);
ch = askchar(buf, "yn","n", B_TRUE);
@ -11281,6 +11368,8 @@ void precalclos_new(lifeform_t *lf) {
enum SKILLLEVEL plev;
flag_t *missingeye;
if (lf->cell->type->id == CT_FAKE) return;
f = hasflag(lf->flags, F_XRAYVIS);
if (f) {
startxray = f->val[0];
@ -12450,7 +12539,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
break;
case SC_LISTEN:
// if you are asleep, listen check doesn't help.
if (lfhasflag(lf, F_ASLEEP) || lfhasflag(lf, F_DEAF)) {
if (lfhasflag(lf, F_ASLEEP) || isdeaf(lf)) {
attrib = 0;
} else {
attrib = getskill(lf, SK_LISTEN);
@ -12983,7 +13072,7 @@ void startlfturn(lifeform_t *lf) {
int nretcells;
getradiuscells(lf->cell, 2, DT_COMPASS, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 0);
for (i = 0; i < nretcells; i++) {
if (retcell[i]->lf && !areallies(lf, retcell[i]->lf)) {
if (retcell[i]->lf && areenemies(lf, retcell[i]->lf)) {
int dir,reldir;
dir = getdirtowards(lf->cell, retcell[i], NULL, B_FALSE, DT_ORTH);
reldir = getrelativedir(lf, dir);
@ -12991,7 +13080,7 @@ void startlfturn(lifeform_t *lf) {
if (isplayer(lf)) {
if (f->val[2] >= 5) {
char buf[BUFLEN];
getlfname(retcell[i]->lf, buf);
real_getlfnamea(retcell[i]->lf, buf, B_FALSE);
warn("^WYour sixth sense warns you of %s %s you!", buf,
(reldir == RD_BACKWARDS) ? "behind" : "beside" );
} else if (f->val[2] >= 3) {
@ -13003,7 +13092,15 @@ void startlfturn(lifeform_t *lf) {
warn("^WYour sixth sense warns you of something %s you!",
(reldir == RD_BACKWARDS) ? "behind" : "beside" );
}
more();
if (f->val[2] >= 7) {
char ch;
ch = askchar("Turn to face the threat", "yn","y", B_TRUE);
if (ch == 'y') {
turntoface(lf, retcell[i]);
}
} else {
more();
}
}
stopspell(lf, OT_S_SIXTHSENSE);
break;
@ -13166,7 +13263,7 @@ void startlfturn(lifeform_t *lf) {
if (!lfhasflag(lf, F_TRAINING) && haslos(lf, l->cell)) {
int bonus = 0;
int dist;
if (!lfhasflag(l, F_SILENTMOVE) && !lfhasflag(lf, F_DEAF)) {
if (!lfhasflag(l, F_SILENTMOVE) && !isdeaf(lf)) {
bonus += getskill(lf, SK_LISTEN);
}
@ -13744,14 +13841,14 @@ void stopresting(lifeform_t *lf) {
// stop resting!
f = isresting(lf);
if (f) {
killflag(f);
if (isplayer(lf)) {
msg("Your %s is interrupted!", (f->val[1] == ST_MEDITATING) ? "meditation" : "rest");
} else if (cansee(player, lf)) {
char buf[BUFLEN];
getlfname(lf, buf);
msg("%s stops %s.",buf, (f->val[1] == NA) ? "resting" : "meditating");
msg("%s stops %s.",buf, (f->val[1] == ST_MEDITATING) ? "meditating" : "resting");
}
killflag(f);
statdirty = B_TRUE;
}
}
@ -14689,21 +14786,23 @@ int validateraces(void) {
// generate xp list
genxplist();
// make a fake cell
fakemap.lf = NULL;
fakemap.lastlf = NULL;
setcelltype(&fakecell, CT_CORRIDOR);
fakecell.lf = NULL;
fakecell.map = &fakemap;
createfakes(&fakemap, &fakecell);
for (r = firstrace ; r ; r = r->next) {
lifeform_t *lf;
int thishd;
// add a fake lf
lf = addlf(&fakecell, r->id, 1);
givestartskills(lf, lf->flags);
// remember max. hitdice for use in dumpmonsters()
thishd = gethitdice(lf);
if (thishd > maxmonhitdice) {
maxmonhitdice = thishd;
}
if (!hasflag(r->flags, F_SIZE)) {
printf("ERROR in race '%s' - missing F_SIZE.\n", r->name);
goterror = B_TRUE;
@ -14804,6 +14903,10 @@ int validateraces(void) {
}
}
killfakes(&fakemap, &fakecell);
noredraw = B_FALSE;
return goterror;
}
@ -15610,6 +15713,15 @@ int willbleedfrom(lifeform_t *lf, enum BODYPART bp) {
}
// if lf picks up 'o', will they be burdened afterwards?
// (if they are _already_ burdened, then stil return true)
int willburden(lifeform_t *lf, object_t *o, int howmany) {
if (getobpileweight(lf->pack) + (getobunitweight(o)*howmany) > getmaxcarryweight(lf) ) {
return B_TRUE;
}
return B_FALSE;
}
// will the lf flee after taking damage?
int willflee(lifeform_t *lf) {
enum ATTRBRACKET iqb;

5
lf.h
View File

@ -67,6 +67,7 @@ int digup(lifeform_t *lf, object_t *o);
void do_eyesight_adjust(lifeform_t *lf);
void dumplev(void);
void dumplf(void);
void dumpmonsters(void);
void dumpxp(void);
int eat(lifeform_t *lf, object_t *o);
void endlfturn(lifeform_t *lf);
@ -132,6 +133,7 @@ int getguntargetid(lifeform_t *lf);
int gethearingrange(lifeform_t *lf);
int gethidemodifier(lifeform_t *lf);
int gethitdice(lifeform_t *lf);
int gethitdicerace(race_t *r);
int gethppct(lifeform_t *lf);
enum COLOUR gethungercol(enum HUNGER hlev);
enum HUNGER gethungerlevel(int hunger);
@ -144,6 +146,7 @@ char getlfcol(lifeform_t *lf, enum MSGCHARCOL cc);
enum LFCONDITION getlfcondition(lifeform_t *lf);
enum SKILLLEVEL getmaxskilllevel(lifeform_t *lf, enum SKILL skid);
int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions);
int getmiscastchance(lifeform_t *lf);
int getnightvisrange(lifeform_t *lf);
char *getlfconditionname(enum LFCONDITION cond);
object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp);
@ -247,6 +250,7 @@ int isblind(lifeform_t *lf);
enum BURDENED isburdened(lifeform_t *lf);
int ischarmable(lifeform_t *lf);
int isdead(lifeform_t *lf);
int isdeaf(lifeform_t *lf);
object_t *isdualweilding(lifeform_t *lf);
int isfleeing(lifeform_t *lf);
int isfreebp(lifeform_t *lf, enum BODYPART bp);
@ -366,5 +370,6 @@ int validateraces(void);
int wear(lifeform_t *lf, object_t *o);
int weild(lifeform_t *lf, object_t *o);
int willbleedfrom(lifeform_t *lf, enum BODYPART bp);
int willburden(lifeform_t *lf, object_t *o, int howmany);
int willflee(lifeform_t *lf);
//int youhear(cell_t *c, char *text);

111
map.c
View File

@ -1352,6 +1352,20 @@ enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf) {
}
// returns the closest cell next to 'dst', when coming from 'src'
// ie. if you start walking from src to dst, where will you end up?
cell_t *get_closest_adjcell(cell_t *src, cell_t *dst) {
cell_t *retcell[MAXRETCELLS];
int nretcell,i;
calcbresnham(src->map, src->x, src->y, dst->x, dst->y, retcell, &nretcell);
for (i = 1; i < nretcell; i++) {
if (retcell[i] == dst) {
return retcell[i-1];
}
}
return NULL;
}
int getdoorlockdiff(int depth) {
return 19 + depth;
}
@ -2144,6 +2158,18 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
}
}
void createfakes(map_t *map, cell_t *cell) {
map->region = NULL;
map->lf = NULL;
map->lastlf = NULL;
map->name = strdup("fake map");
map->habitat = findhabitat(H_DUNGEON);
setcelltype(cell, CT_FAKE);
cell->lf = NULL;
cell->map = map;
cell->obpile = addobpile(NULL, NULL, NULL);
}
void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob, int nclearings) {
int x,y;
enum CELLTYPE emptycell;
@ -2302,7 +2328,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
enum HABITAT habitat;
regionthing_t *thing[MAXOUTLINETHINGS];
int nthings = 0,failed;
int db = B_FALSE;
int db = B_TRUE;
// determine habitat based on region
// note: we might override this later based on our region outline
@ -2569,6 +2595,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
if (failed) {
dblog("********* got errors - restarting map creation. *********");
unlinkstairsto(map);
}
}
@ -2905,6 +2932,11 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r
return B_FALSE;
}
void killfakes(map_t *map, cell_t *cell) {
killobpile(cell->obpile);
free(map->name);
}
// link a single cell up to the rest of the map.
// make sure it links to an empty cell of a DIFFERENT roomid.
// if 'wantfilled' is set, only link to "filled" cells.
@ -4516,6 +4548,7 @@ void initmap(void) {
addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 3, 70, 0, MAXVISRANGE);
// cell types
addcelltype(CT_FAKE, "fake cell", '.', C_GREEN, B_EMPTY, B_TRANS, MT_STONE, 0);
addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
addcelltype(CT_WALLWOOD, "wooden wall", '#', C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0);
addcelltype(CT_WALLGLASS, "glass wall", '#', C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0);
@ -4951,8 +4984,10 @@ int linkstairs(object_t *o, object_t *o2) {
}
}
if (!found) {
dblog("ERROR - stairs link to existing map %d(depth %d), but it has no free stairs.",othermap->id, othermap->depth);
msg("ERROR - stairs link to existing map %d(depth %d), but it has no free stairs.",othermap->id, othermap->depth);
dblog("ERROR - stairs link to existing map %d('%s', depth %d), but it has no free stairs.",othermap->id,
othermap->name, othermap->depth);
msg("ERROR - stairs link to existing map %d('%s', depth %d), but it has no free stairs.",othermap->id,
othermap->name, othermap->depth);
more();
}
} // end if othermap
@ -5352,6 +5387,76 @@ int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring) {
return rv;
}
int unlinkstairsto(map_t *unlinkmap) {
map_t *m;
object_t *o;
cell_t *c;
long badid[MAXCANDIDATES];
int x,y,nbadids = 0,nretflags,i;
int db = B_TRUE;
flag_t *retflag[MAXCANDIDATES];
if (db) dblog("starting unlinkstairsto for unlikmap='%s'",unlinkmap->name);
// get a list of all stair object ids on this unlinkmap.
for (y = 0; y < unlinkmap->h; y++) {
for (x = 0; x < unlinkmap->w; x++) {
c = getcellat(unlinkmap, x,y);
for (o = c->obpile->first ; o ; o = o->next) {
if (hasflag(o->flags, F_MAPLINK)) {
badid[nbadids++] = o->id;
}
}
}
}
if (db) dblog(" found %d stairs on unlinkmap.",nbadids);
// go through all maps and remove any stairs which link to unlinkmap
if (db) dblog(" searching other maps for stairs linking to unlinkmap.");
for (m = firstmap ; m ; m = m->next) {
for (y = 0; y < m->h; y++) {
for (x = 0; x < m->w; x++) {
c = getcellat(m, x,y);
for (o = c->obpile->first ; o ; o = o->next) {
getflags(o->flags, retflag, &nretflags, F_MAPLINK, F_NONE);
for (i = 0; i < nretflags; i++) {
int killit = B_FALSE,n;
if (retflag[i]->val[0] == unlinkmap->id) {
if (db) dblog(" on map '%s': found '%s' linking to unlinkmap's id.", m->name,o->type->name);
killit = B_TRUE;
} else {
for (n = 0; n < nbadids; n++) {
if (atol(retflag[i]->text) == badid[n]) {
killit = B_TRUE;
if (db) dblog(" on map '%s': found '%s' linking to obid of stairs on unlinkmap.", m->name,o->type->name);
break;
}
}
}
if (killit) {
killflag(retflag[i]);
}
}
}
}
}
}
// now remove all links from stairs on unlinkmap
if (db) dblog(" removing maplinks from stairs on unlinkmap.");
for (y = 0; y < unlinkmap->h; y++) {
for (x = 0; x < unlinkmap->w; x++) {
c = getcellat(unlinkmap, x,y);
for (o = c->obpile->first ; o ; o = o->next) {
killflagsofid(o->flags, F_MAPLINK);
}
}
}
if (db) dblog("finished unlinkstairsto for unlikmap='%s'",unlinkmap->name);
return B_FALSE;
}
void updateknowncells(void) {
int x,y;
map_t *map;

4
map.h
View File

@ -25,6 +25,7 @@ int getcelldist(cell_t *src, cell_t *dst);
int getcelldistorth(cell_t *src, cell_t *dst);
void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer);
enum DEPTH getcellwaterdepth(cell_t *c, lifeform_t *lf);
cell_t *get_closest_adjcell(cell_t *src, cell_t *dst);
int getdoorlockdiff(int depth);
int getdoorsecretdiff(int depth);
flag_t *getmapcoords(map_t *m, int *x, int *y);
@ -45,6 +46,7 @@ int countcellexits(cell_t *cell);
int countcellexitsfor(lifeform_t *lf);
int countmapobs(map_t *m, enum OBTYPE oid);
void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob);
void createfakes(map_t *map, cell_t *cell);
void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob, int nclearings);
void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob);
void createheaven(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob);
@ -114,6 +116,7 @@ int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m);
int isroom(cell_t *c);
int iswallindir(cell_t *cell, int dir);
void killfakes(map_t *map, cell_t *cell);
int linkexit(cell_t *c, int wantfilled, int *ncellsadded);
int linkexits(map_t *m, int roomid);
int linkholes(map_t *map);
@ -129,6 +132,7 @@ void setcellknown(cell_t *cell, int forcelev);
void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype);
void setcelltype(cell_t *cell, enum CELLTYPE id);
int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring);
int unlinkstairsto(map_t *unlinkmap);
void updateknowncells(void);
int validateregions(void);
int validateregionthing(regionthing_t *thing);

54
move.c
View File

@ -962,7 +962,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
int didmsg = B_FALSE;
flag_t *f;
int changedlev = B_FALSE;
int preroom = -1, postroom = -1;
room_t *preroom = NULL, *postroom = NULL;
int preshop = -1;
int prespeed = B_FALSE, postspeed = B_FALSE;
int prewater = B_FALSE;
@ -986,7 +986,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// remember current cell + room id
prespeed = getmovespeed(lf);
preroom = getroomid(lf->cell);
preroom = lf->cell->room;
v = getcellvault(lf->cell);
if (v && hasflag(v->flags, F_VAULTISSHOP)) {
preshop = getroomid(lf->cell);
@ -1042,7 +1042,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
assert(!newcell->lf);
// remember new room...
postroom = getroomid(lf->cell);
postroom = lf->cell->room;
postspeed = getmovespeed(lf);
// update new cell
@ -1241,8 +1241,18 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
*/
}
// does anyone else see you?
if (gamemode == GM_GAMESTARTED) {
if (isplayer(lf) && !isblind(lf)) {
// see the vault
if (!preroom && postroom && postroom->vault) {
f = hasflag(postroom->vault->flags, F_VAULTENTERTEXT);
if (f) {
msg("%s", f->text);
}
}
}
// does anyone else see you?
for (l = newcell->map->lf ; l ; l = l->next) {
if (l != lf) {
flag_t *alarm;
@ -1408,8 +1418,8 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
}
}
// see objects on ground
if (isplayer(lf)) {
// see/feel objects on ground
int numobs;
numobs = countnoncosmeticobs(newcell->obpile, B_TRUE);
if ((numobs == 0) && !newcell->writing) {
@ -1915,7 +1925,6 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
for (o = lf->cell->obpile->first ; o ; o = nexto) {
nexto = o->next;
f = obrestrictsmovement(o, lf);
if (f) {
char lfname[BUFLEN];
@ -2067,7 +2076,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
return B_FALSE;
}
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int onpurpose) {
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir, int onpurpose) {
cell_t *cell1,*cell2;
cell1 = lf1->cell;
@ -2084,6 +2093,13 @@ void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int onpurpose) {
lf2->cell = cell1;
cell1->lf = lf2;
if (changedir) {
int tempfacing;
tempfacing = lf2->facing;
setfacing(lf2, lf1->facing);
setfacing(lf1, tempfacing);
}
// remember that we just swapped
if (!isplayer(lf1)) {
addflag(lf1->flags, F_NOSWAP, B_TRUE, NA, NA, NULL);
@ -2179,17 +2195,24 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
reldir = getrelativedir(lf, dir);
// if the given dir is behind us, just turn.
if (onpurpose && !strafe) {
if (reldir != RD_FORWARDS) {
if (!lfhasflag(lf, F_AWARENESS)) {
if (onpurpose) {
if ((reldir != RD_FORWARDS) && !lfhasflag(lf, F_AWARENESS)) {
// if the given dir is behind us, just turn.
if (!strafe) {
setfacing(lf, dir);
taketime(lf, getturnspeed(lf));
return B_FALSE;
} else {
// player can't strafe while stuck.
if (isstuck(lf) && isplayer(lf)) {
msg("You can't move %s while stuck!", (reldir == RD_BACKWARDS) ? "backwards" : "sideways");
return B_TRUE;
}
}
}
}
f = lfhasflag(lf, F_DRUNK);
if (f) {
if (!hasjob(lf, J_PIRATE)) {
@ -2476,15 +2499,16 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
// otherwise swap locations.
lfinway = cell->lf;
swapplaces(lf, lfinway, onpurpose);
if (onpurpose) taketime(lf, getmovespeed(lf));
if (isplayer(lf)) {
char lfname[BUFLEN];
getlfname(lfinway, lfname);
msg("You swap places with %s.", lfname);
}
swapplaces(lf, lfinway, B_FALSE, onpurpose);
if (onpurpose) taketime(lf, getmovespeed(lf));
} else {
if (!onpurpose || canandwillmove(lf, dir, &errcode)) {
return attackcell(lf, cell, B_FALSE);

2
move.h
View File

@ -27,7 +27,7 @@ int pullnextto(lifeform_t *lf, cell_t *c);
int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg);
int isorthogonal(int dir);
int ispossiblemove(lifeform_t *lf, int dir);
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int onpurpose);
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir, int onpurpose);
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke);
void triggertrap(lifeform_t *lf, object_t *o, object_t *trapob, cell_t *where);
int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe);

21
nexus.c
View File

@ -43,6 +43,8 @@ hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
npcname_t *npcname;
int numnpcnames;
int maxmonhitdice = 0; // highest number of hitdice for any monster
double presin[360];
double precos[360];
@ -810,6 +812,23 @@ void donextturn(map_t *map) {
}
}
void gethitdicerange(int depth, int *min, int *max, int range, int oodok) {
int mid;
// adjust depth for out-of-depth monsters
if (oodok && (onein(6))) {
depth++;
// repeated chances of incing level
while (onein(6)) {
depth++;
}
}
mid = (depth/2);
*min = mid - range; limit(min, 0, maxmonhitdice);
*max = mid + range; limit(max, *min, maxmonhitdice);
}
enum COLOUR getpctcol(float num, float max) {
float pct;
@ -1180,7 +1199,7 @@ int rollhitdice(lifeform_t *lf) {
ndice = 1;
nsides = 4;
plus = 0;
myroll = roll("1d4");
myroll = roll(DEF_HITDICE);
}
mod = 100 + getstatmod(lf, A_CON);

View File

@ -9,6 +9,7 @@ void dbtimeend(char *text);
void dbtimestart(char *text);
void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, int dinc2, int *xinc, int *yinc, int *dinc);
void donextturn(map_t *map);
void gethitdicerange(int depth, int *min, int *max, int range, int oodok);
enum COLOUR getpctcol(float num, float max);
void getrarityrange(int depth, int *min, int *max, int range, int oodok);
int init(void);

151
objects.c
View File

@ -680,7 +680,15 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
////////////////////////////////////
// handle special object names
////////////////////////////////////
if (strstr(p, "corpse")) {
if (strstr(p, "chunk of roast ") || strstr(p, "roast meat")) {
char racename[BUFLEN];
p2 = strstr(p, "roast");
p2 += 6;
p2 = readuntil(racename, p2, ' ');
corpserace = findracebyname(racename);
ot = findot(OT_ROASTMEAT);
} else if (strstr(p, "corpse")) {
int len;
char racename[BUFLEN];
p2 = strstr(p, "corpse");
@ -1226,32 +1234,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
if (rf) {
cf = hasflag(o->flags, F_EDIBLE);
if (cf) {
switch (rf->val[0]) {
case SZ_MINI:
cf->val[1] = 1;
break;
case SZ_TINY:
cf->val[1] = 10;
break;
case SZ_SMALL:
cf->val[1] = 25;
break;
case SZ_MEDIUM:
cf->val[1] = 75;
break;
case SZ_HUMAN:
cf->val[1] = 120;
break;
case SZ_LARGE:
cf->val[1] = 150;
break;
case SZ_HUGE:
cf->val[1] = 200;
break;
case SZ_ENORMOUS:
cf->val[1] = 250;
break;
}
cf->val[1] = sizetonutrition(rf->val[0]);
}
}
} else if (o->type->id == OT_STATUE) {
@ -1264,8 +1247,9 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// select random race
if (where) {
corpserace = getrandomrace(where, NA);
} else {
// ie. vending machine
}
if (!corpserace) {
// ie. vending machine, or inside another object/fake cell?
corpserace = getrandomrace(NULL, NA);
}
}
@ -1300,7 +1284,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
f->val[1] = maxhp;
}
}
} else if (o->type->id == OT_HEAD) {
flag_t *rf, *cf;
@ -1318,35 +1301,30 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
if (rf) {
cf = hasflag(o->flags, F_EDIBLE);
if (cf) {
switch (rf->val[0]) {
case SZ_MINI:
cf->val[1] = 1;
break;
case SZ_TINY:
cf->val[1] = 2;
break;
case SZ_SMALL:
cf->val[1] = 5;
break;
case SZ_MEDIUM:
cf->val[1] = 25;
break;
case SZ_HUMAN:
cf->val[1] = 50;
break;
case SZ_LARGE:
cf->val[1] = 75;
break;
case SZ_HUGE:
cf->val[1] = 100;
break;
case SZ_ENORMOUS:
cf->val[1] = 150;
break;
}
cf->val[1] = sizetonutrition(rf->val[0]) / 3;
}
}
} else if (o->type->id == OT_ROASTMEAT) {
flag_t *rf, *cf;
if (!corpserace) {
// random one.
corpserace = getrandomrace(NULL, NA);
}
o->weight = corpserace->weight / 2;
// remember the race type
addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL);
// override ot_roastmeat nutrition flag based on race's size
rf = hasflag(corpserace->flags, F_SIZE);
if (rf) {
cf = hasflag(o->flags, F_EDIBLE);
if (cf) {
cf->val[1] = sizetonutrition(rf->val[0]);
}
}
} else if (o->type->id == OT_WATERDEEP) {
f = hasflag(o->flags, F_DEEPWATER);
if (f && (f->val[0] != wantdepth)) {
@ -2177,8 +2155,12 @@ int canseeob(lifeform_t *lf, object_t *o) {
// can't see
return B_FALSE;
}
if (o->pile->where && hasobwithflag(o->pile, F_BLOCKSVIEW)) {
return B_FALSE;
if (o->pile->where) {
object_t *blockob;
blockob = hasobwithflag(o->pile, F_BLOCKSVIEW);
if (blockob && (blockob != o)) {
return B_FALSE;
}
}
f = hasflag(o->flags, F_TRAIL);
@ -2305,7 +2287,7 @@ int changemat(object_t *o, enum MATERIAL mat) {
o->material = m;
// inherit flags from new material
copyflags(m->flags, o->flags, FROMMAT);
copyflags(o->flags, m->flags, FROMMAT);
if (mat == MT_ICE) {
obmod_t *om;
@ -3864,6 +3846,16 @@ char *getobdesc(object_t *o, char *buf) {
} else {
snprintf(buf, BUFLEN, "%s", o->type->desc);
}
} else if (o->type->id == OT_ROASTMEAT) {
flag_t *f;
f = hasflag(o->flags, F_CORPSEOF);
if (f) {
race_t *corpserace;
corpserace = findrace(f->val[0]);
snprintf(buf, BUFLEN, "A chunk of flame-roasted flesh from %s %s.", isvowel(corpserace->name[0]) ? "an" : "a", corpserace->name);
} else {
snprintf(buf, BUFLEN, "%s", o->type->desc);
}
} else if (o->type->id == OT_STATUE) {
flag_t *f;
f = hasflag(o->flags, F_CORPSEOF);
@ -4094,7 +4086,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
if (who) {
char lfname[BUFLEN];
real_getlfnamea(who, lfname, B_FALSE);
snprintf(buf, BUFLEN, "%s%s%s %sscent",adjective,lfname,getpossessive(lfname));
snprintf(buf, BUFLEN, "a %s%s scent",adjective,r->name);
} else {
snprintf(buf, BUFLEN, "%s%s scent",adjective, r->name );
}
@ -4245,6 +4237,13 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
snprintf(basename, BUFLEN, "%s %s",corpserace->name, o->type->name);
}
}
} else if (o->type->id == OT_ROASTMEAT) {
f = hasflag(o->flags, F_CORPSEOF);
if (f) {
race_t *corpserace;
corpserace = findrace(f->val[0]);
snprintf(basename, BUFLEN, "chunk of roast %s meat",corpserace->name);
}
} else if (o->type->id == OT_FOUNTAIN) {
objecttype_t *ot;
// find out what kind of fountain this is
@ -5045,9 +5044,9 @@ char *getschoolname(enum SPELLSCHOOL sch) {
case SS_ENCHANTMENT: return "Enchantments";
case SS_WILD: return "Wild Magic";
case SS_MENTAL: return "Psionic Powers";
case SS_AIR: return "Elemental/Air Magic";
case SS_FIRE: return "Elemental/Fire Magic";
case SS_COLD: return "Elemental/Cold Magic";
case SS_AIR: return "Air Magic";
case SS_FIRE: return "Fire Magic";
case SS_COLD: return "Cold Magic";
case SS_MODIFICATION: return "Modification Magic";
case SS_DEATH: return "Necromancy";
case SS_NATURE: return "Nature";
@ -5646,6 +5645,7 @@ int isdrinkable(object_t *o) {
}
int isedible(object_t *o) {
if (hasflag(o->flags, F_CREATEDBYSPELL)) return B_FALSE;
if (hasflag(o->flags, F_EDIBLE)) {
return B_TRUE;
}
@ -9713,6 +9713,29 @@ void shufflehiddennames(void) {
}
}
int sizetonutrition(enum LFSIZE size) {
switch (size) {
case SZ_MINI:
return 1;
case SZ_TINY:
return 10;
case SZ_SMALL:
return 25;
case SZ_MEDIUM:
return 75;
case SZ_HUMAN:
return 120;
case SZ_LARGE:
return 150;
case SZ_HUGE:
return 200;
case SZ_ENORMOUS:
return 250;
default: break;
}
return 0;
}
object_t *splitob(object_t *o) {
object_t *newob;
// decrease count on original stack temporarily, in case we
@ -9946,6 +9969,7 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
meat = addob(o->pile, "chunk of roast meat");
// purposely don't use getweight!
meat->weight = o->weight;
copyflag(meat->flags, o->flags, F_CORPSEOF);
}
// fire turns things to ash
addob(o->pile, "pile of ash");
@ -10430,6 +10454,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (!lfhasflag(target, F_NOPACK) && hasbp(target, BP_HANDS) &&
lfhasflag(target, F_HUMANOID) &&
canpickup(target, o, o->amt) &&
!willburden(target, o, o->amt) &&
!isimmobile(target) &&
skillcheck(target, SC_DEX, 15*speed, catchmod)) {
willcatch = B_TRUE;

View File

@ -232,6 +232,7 @@ void setobcreatedby(object_t *o, lifeform_t *lf);
void setwaterdepth(cell_t *c, int depth);
int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf);
void shufflehiddennames(void);
int sizetonutrition(enum LFSIZE size);
object_t *splitob(object_t *o);
int takedamage(object_t *o, unsigned int howmuch, int damtype);
int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantannounce);

53
spell.c
View File

@ -112,9 +112,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (abilid == OT_A_CHARGE) {
cell_t *adjcell = NULL,*origcell;
char targetname[BUFLEN];
int i;
cell_t *retcell[MAXRETCELLS];
int nretcell;
if (isimmobile(user)) {
if (isplayer(user)) msg("You can't move!");
@ -134,7 +131,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
}
}
if (!targcell) {
if (isplayer(user)) {
snprintf(buf, BUFLEN, "Charge who (max range %d)?",range);
@ -167,13 +163,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
getlfname(target, targetname);
// find cell on the way...
calcbresnham(user->cell->map, user->cell->x, user->cell->y, targcell->x, targcell->y, retcell, &nretcell);
for (i = 1; i < nretcell; i++) {
if (retcell[i] == targcell) {
adjcell = retcell[i-1];
break;
}
}
adjcell = get_closest_adjcell(user->cell, targcell);
if (!adjcell) {
if (isplayer(user)) {
msg("There is no space nearby for you to attack!");
@ -1900,6 +1890,12 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
addchoice(&prompt, o->letter, buf, NULL, o, NULL);
}
}
addchoice(&prompt, '-', "(nothing)", NULL, NULL, NULL);
if (prompt.nchoices == 1) {
msg("You don't have anything which you can inspect.");
return B_TRUE;
}
getchoice(&prompt);
o = (object_t *)prompt.result;
if (!o) {
@ -2498,6 +2494,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
targcell = poss[rnd(0,nposs-1)];
}
teleportto(caster, targcell, B_TRUE);
} else if (spellid == OT_S_BLINKASS) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
return B_TRUE;
}
// find cell behind caster
targcell = getcellindir(targcell, diropposite(target->facing));
if (!cellwalkable(caster, targcell, NULL)) {
fizzle(caster);
return B_TRUE;
}
teleportto(caster, targcell, B_TRUE);
setfacing(caster, target->facing);
} else if (spellid == OT_S_LOWERMETAB) {
flag_t *f;
// ie. 2 - 4
@ -3335,8 +3349,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
wear(target, o);
// set its values
f = hasflag(o->flags, F_ARMOURRATING);
if (f) f->val[0] = power;
f = hasflag(o->flags, F_OBHP);
if (f) {
f->val[0] = power*5;
@ -7649,7 +7661,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (cansee(player, caster)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
swapplaces(caster, target, B_FALSE);
swapplaces(caster, target, B_CHANGEDIR, B_ONPURPOSE);
} else if ((spellid == OT_S_SUMMONANIMALSSM) ||
(spellid == OT_S_SUMMONANIMALSMD) ||
(spellid == OT_S_SUMMONANIMALSLG) ||
@ -8406,10 +8418,21 @@ int getmpcost(lifeform_t *lf, enum OBTYPE oid) {
if (f) {
cost = f->val[0];
} else {
cost = getspelllevel(oid);
/*
f = hasflag(ot->flags, F_SPELLLEVEL);
if (f) {
cost = f->val[0] * f->val[0];
switch (getspellschool(oid)) {
case SS_MENTAL:
case SS_ALLOMANCY:
cost = f->val[0];
break;
default:
cost = f->val[0] * f->val[0];
break;
}
}
*/
}
return cost;
}

2
text.c
View File

@ -384,6 +384,7 @@ char *getrarityname(enum RARITY rr) {
char *getsizetext(enum LFSIZE sz) {
switch (sz) {
case SZ_MAX:
case SZ_ENORMOUS:
return "enormous";
case SZ_HUGE:
@ -398,6 +399,7 @@ char *getsizetext(enum LFSIZE sz) {
return "small";
case SZ_TINY:
return "tiny";
case SZ_MIN:
case SZ_MINI:
return "miniscule";
default:

View File

@ -11,6 +11,7 @@ random(4,4)
goesin:dungeon
autodoors:25
autopop
entertext:It looks like the roof here has collapsed.
scatter(1,1,-2,-2) ob:boulder:25%
scatter(1,1,-2,-2) ob:25-75 stones:50%
rarity:uncommon

View File

@ -9,6 +9,7 @@ random(4,4)
@flags
goesin:dungeon
entertext:You enter a dining room.
autodoors:75
autopop
! tables & chairs

View File

@ -21,6 +21,7 @@ m:ob:landmine trap
@end
@flags
entertext:You enter an ornate shrine.
shrine
norandom
mayrotate

View File

@ -11,6 +11,7 @@ random(5,5)
goesin:dungeon
autodoors:25
autopop
entertext:You enter a small shrubbery.
scatter(1,1,-2,-2) ob:fountain:1:75
scatter(1,1,-2,-2) ob:tree:25%
scatter(1,1,-2,-2) ob:shrub:50%

View File

@ -27,6 +27,7 @@ m:mon:minotaur
@flags
goesin:dungeon
entertext:You enter a labyrinth.
! the reward
at(7,7) ob:200-450 gold
at(7,7) ob:good weapon

View File

@ -14,6 +14,6 @@ autodoors:100
scatter(1,1,-2,-2) ob:statue:25%
scatter(1,1,-2,-2) mon:cockatrice:1
scatter(1,1,-2,-2) ob:1-10 stones:1-5
rarity:rare
rarity:vrare
@end

View File

@ -10,6 +10,7 @@ random(4,4)
@flags
autodoors:50
autopop
entertext:It seems very muddy here!
goesin:dungeon
! add mud to 50% of room cells
scatter(1,1,-2,-2) ob:pool of mud:50%