- [+] change how critical hits work

- [+] must score a hit first THEN pass a critical hit % check.
- [+] when asking for an object form the player's pack, default to NOT
      showing long format
- [+] in askobject, pass in actionchar. remember choice for each
      actionchar. and use it as a default.
- [+] warning system
    - [+] warnabout(char *warntext)
        - [+] if already confirmed it, keep going
        - [+] otherwise ask to confirm
        - [+] confirmations time out after some time...
    - [+] replace injury warnings
- [+] reduce spell range
- [+] big bug - way too many critical hits!
- [+] askcoods: accept 'enter' to select a cell
- [+] armour should never reduce damage under 1
- [+] for playable races, show bonus/penalties when selecting them.
- [+] add f_hatesracewithflag with ashkari
- [+] mammoan - no athletics!
- [+] bug writing hiscores - need to escape 's.
- [+] add v2 to F_ATTREQ - scaling.
    - [+] will scale up to 3 above/below
    - [+] v2 = 1 means "+/- v2 per point above/below"
    - [+] more than 3 below means you can't use it. modify "meetsattreq"
    - [+] more than 3 above gives no extra bonus.
    - [+] this is MANDATORY. add to checks.
    - [+] add messages if your skill it slightly too low
    - [+] STR scales damage, AGI scales tohit and crit chance
        - [+] make sure showlfstats takes this into account
        - [+] make sure rolltohit / getdamrange takes this into account
    - [+] what do I do with attreq IQ??? mus tmeet it.
    - [+] missile weapons: no scaling, must meet reqs
    - [+] reduce regular strength dam mod 
    - [+] you only get attr bonuses if you are skilled with the weapon.
- [+] crash: getrandomrace(NULL, NA) returning null!
- [+] don't give away invisible creature locations in askcoords
    - [+] does fireat automatically re-calc lof based on obstacles?
    - [+] if so then change haslof in askcoords to be hasKNOWNlof!
- [+] catlike race - ashkari
    - [+] bonus
        - [+] has climbing, listen
        - [+] jump ability
        - [+] agi+
        - [+] unarmed attack is claws
        - [+] balance (stability?)
        - [+] eyesight, darkvision
        - [+] enhancesmell (only low)
    - [+] pens:
        - [+] hunger faster
        - [+] carnivore
        - [+] low-- wis (ie vuln to magic)
        - [+] vuln to magic
        - [+] vuln to water
        - [+] vuln to sound
        - [+] low str
        - [+] auto rage on dog/wolf/mouse/bird/chicken
- [+] races CANT ahve certain flags
    - [+] apply this during giveskill()
This commit is contained in:
Rob Pearce 2011-11-21 21:26:33 +00:00
parent 3c7fa61324
commit c20802fc6e
15 changed files with 814 additions and 264 deletions

8
ai.c
View File

@ -1550,6 +1550,14 @@ void aiturn(lifeform_t *lf) {
if (db) dblog(".oO { found an enemy target - lfid %d (%s) ! }",who->id, who->race->name);
poss[nposs++] = who;
}
} else {
getflags(lf->flags, retflag, &nretflags, F_HATESRACEWITHFLAG, F_NONE);
for (i = 0; i < nretflags; i++) {
if (lfhasflag(who, retflag[i]->id)) {
if (db) dblog(".oO { found a target with hated flags - lfid %d (%s) ! }",who->id, who->race->name);
hateposs[nhateposs++] = who;
}
}
}
}
}

View File

@ -132,7 +132,7 @@ void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *
divideby = ar/2;
if (divideby <= 0) divideby = 1;
lowerlimit = (*dam / divideby);
limit(&lowerlimit, 0, 3);
limit(&lowerlimit, 1, NA);
limit(&newdam, lowerlimit, NA); // don't reduce too far.
}
@ -184,6 +184,12 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
// anyone there? if so just attack.
if (c->lf) {
if (!force && isplayer(lf) && isprone(lf)) {
if (!warnabout("Really attack while prone (-40% accuracy)?")) {
return B_TRUE;
}
}
if (!force && isplayer(lf) && !areenemies(lf,c->lf) && (getraceclass(c->lf) != RC_PLANT) && cansee(lf, c->lf)
&& !lfhasflag(lf, F_RAGE)) {
char ch;
@ -1747,6 +1753,7 @@ int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) {
// if damflag isn't passed in, it will be taken from the object
void getdamrange(object_t *o, flag_t *f, int *min, int *max) {
int mindam,maxdam;
if (!f) {
f = hasflag(o->flags, F_DAM);
}
@ -1771,6 +1778,7 @@ void getdamrange(object_t *o, flag_t *f, int *min, int *max) {
maxdam = 0;
}
limit(&mindam, 0, NA);
limit(&maxdam, mindam, NA);
@ -1850,26 +1858,14 @@ float getstrdammod(lifeform_t *lf) {
// 9,10,11,12 = average
// >12 = bonus
if (lfhasflag(lf, F_RAGE)) {
base = 20;
} else {
base = getattr(lf, A_STR);
}
base = getattr(lf, A_STR);
if ((base >= 9) && (base <= 12)) {
mod = 1;
} else if (base > 12) {
base -= 12; // ie. 1 - 6
// 13 = 1 = 1.1
// 14 = 2 = 1.2
// 15 = 3 = 1.3
// 16 = 4 = 1.4
// 17 = 5 = 1.6
// 18 = 6 = 1.5
mod = 1 + (base / 10.0);
mod = 1 + (base / 20.0); // ie. up to 1.3 / +30%
} else { // ie. 0 through 8
// 0 = 0.1
// 1 = 0.2
@ -1976,23 +1972,6 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
lorelev = getlorelevel(lf, victim->race->raceclass->id);
// critical chance - check this first.
if (critical) {
int critroll;
critroll = rnd(1,100);
// default
*critical = 0;
// modify for lore level
if (lorelev != PR_INEPT) {
critroll -= (lorelev*5); // ie. up to 30% bonus
}
limit(&critroll, 1, 100);
if (critroll <= getcritchance(lf, wep,victim)) *critical = 1;
}
f = lfhasflag(lf, F_TRUESTRIKE);
if (f) {
if (f->val[0] > 1) {
@ -2045,7 +2024,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
// victim immobile or asleep?
if (isimmobile(victim) || lfhasflag(victim, F_EATING)) acc += 50;
// modify for lore level
if (lorelev != PR_INEPT) lorelev += (lorelev*10);
if (lorelev != PR_INEPT) acc += (lorelev*10);
// modify for attacking while climbing
if (isclimbing(lf)) {
@ -2067,8 +2046,29 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
if (pctchance(acc)) gothit = B_TRUE;
}
if (gothit && lfhasflag(lf, F_AIMEDSTRIKE) && critical) {
*critical = 1;
// critical chance
if (critical) {
// default
*critical = 0;
if (gothit) {
if (lfhasflag(lf, F_AIMEDSTRIKE)) {
*critical = 1;
} else {
int critroll;
critroll = rnd(1,100);
// modify for lore level > pr_novice
if (lorelev > PR_NOVICE) {
int lorebonus;
lorebonus = ((lorelev-1)*5); // ie. up to 25% bonus
critroll -= lorebonus;
}
limit(&critroll, 1, 100);
if (critroll <= getcritchance(lf, wep,victim)) *critical = 1;
}
}
}
return gothit;

344
data.c

File diff suppressed because it is too large Load Diff

Binary file not shown.

22
defs.h
View File

@ -18,6 +18,7 @@
#define DEF_RESTHEALTIME (3)
#define DEF_SCREENW 80
#define DEF_SCREENH 24
#define DEF_RAGETIME 10
#define DEF_SHOPIDENTPRICE (50) // cost to identify a just-purchased item
#define DEF_VAULTMARGIN (3)
#define DEF_VISRANGE (7)
@ -29,6 +30,8 @@
#define DEF_TURNPCT 40
#define DEF_WINDOWPCT 5
#define DEF_WARNINGTIME 20
// lifeform defaults
#define DEF_HITDICE "1d4"
@ -804,6 +807,7 @@ enum RACE {
// unique monstesr
R_JAILER,
// playable races
R_ASHKARI,
R_AVIAD,
R_CYBORG,
R_DWARF,
@ -2117,6 +2121,8 @@ enum FLAG {
F_CANHAVEOBMOD, // weapon can have obmod om_v0 applied
// optional: v1 is chance of randomly having it
F_ATTREQ, // requires attrib v0 to be at least v1
// can adjust dam or tohit by up to (v2*10)% if you are
// too low or extra high.
//F_DAMTYPE, // val0 = damage type
F_CRITCHANCE, // v0 = %chance of critical hit with this weapon
F_CRITPROTECTION, // v0 = %chance of preventing critical hits
@ -2211,8 +2217,12 @@ enum FLAG {
F_STAMCOST, // v0=stamina cost of ability. default is 0.
F_ONGOING, // this spell has an ongoing cost
F_CASTINGTIME, // this spell takes v0 turns to cast
F_EXTRADESC, // extra descriptions for this object
F_EXTRADESC, // text=extra descriptions for this object
// v0 is the order in which these are displayed (0-5)
F_BONDESC, // text=extra description for playable races.
// v0 is the display order.
F_PENDESC, // text=extra description for playable races.
// v0 is the display order.
//F_SPELLLETTER, // text[0] = letter to cast this spell
F_AICASTTOFLEE, // AI can cast this spell to help flee/heal
// v0 is who to target
@ -2326,6 +2336,7 @@ enum FLAG {
// (for ghosts)
F_NOCORPSE, // monster's body crumbles to dust after death
F_NOCTURNAL, // monster sleeps during the day
F_NOSKILL, // lifeform CANNOT ever learn skill v0
F_DIURNAL, // monster sleeps at night
F_LFSUFFIX, // text = suffix. eg. "skeleton"
F_VISRANGE, // how far you can see (in the light)
@ -2410,6 +2421,7 @@ enum FLAG {
F_GUARD, // this lf is a guard, who can be called by shopkeepers
F_HATESRACE, // lf will attack lfs with race=v0 or baseid=v0 on
// sight
F_HATESRACEWITHFLAG, // lf will attack lfs with flag v0 on sight
F_HARMLESS, // it is safe to rest around this lf
F_RNDHOSTILE, // v0% chance of being hostile.
F_HOSTILE, // lf will attack the player if in sight
@ -2504,6 +2516,8 @@ enum FLAG {
F_AQUATIC, // this race can attack normally in water and suffers no
// movement penalties
F_BODYPARTNAME, // for this race, bodypart v0 is called 'text'
F_AVIAN, // this race is an avian
F_CANINE, // this race is a canine
F_HUMANOID, // this race can wear armour / use weapons
F_INSECT, // this race is classed as an insect
F_UNDEAD, // this race is classed as undead
@ -2994,6 +3008,12 @@ typedef struct command_s {
struct command_s *next, *prev;
} command_t;
typedef struct warning_s {
char *text;
int lifetime;
struct warning_s *next, *prev;
} warning_t;
enum REGIONTYPE {
RG_WORLDMAP,
RG_FIRSTDUNGEON,

301
io.c
View File

@ -946,18 +946,25 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
trailtarg = c;
if (LOFTYPE != LOF_DONTNEED) {
cell_t *newcell;
if (!haslof(srclf->cell, c, LOFTYPE, &newcell)) {
int bad = B_FALSE;
if (srclf) {
if (!haslof_real(srclf->cell, c, LOFTYPE, &newcell, srclf)) {
bad = B_TRUE;
}
} else {
if (!haslof(srclf->cell, c, LOFTYPE, &newcell)) {
bad = B_TRUE;
}
}
if (bad) {
inlof = B_FALSE;
strcat(buf, " ^B[no-lof]^n");
valid = B_FALSE;
}
if (newcell) {
trailtarg = newcell;
if (newcell) trailtarg = newcell;
}
}
// throwing hitchance?
f = lfhasflag(player, F_THROWING);
if (f && valid) {
char throwbuf[BUFLEN];
@ -1012,7 +1019,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
// get input
ch = getch();
if ((ch == '.') && valid) {
if (valid && ((ch == '.') || (ch == 10))) { // 10 = enter
clearmsg();
// remember this target
@ -1028,10 +1035,10 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
} else if (haslos(player, c)) {
object_t *o;
// show objects
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, AO_NONE, F_NONE);
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE);
while (o) {
describeob(o);
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, AO_NONE, F_NONE);
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE);
}
}
} else if (ch == 27) { // esc - cancel
@ -2431,24 +2438,17 @@ int confirm_badfeeling(object_t *o) {
char ch;
ch = askchar("You have a bad feeling about this. Continue?", "yn", "n", B_TRUE, B_FALSE);
if (ch == 'y') return B_TRUE;
if (o && !hasflag(o->flags, F_KNOWNBAD)) {
addflag(o->flags, F_KNOWNBAD, B_TRUE, NA, NA, NULL);
}
return B_FALSE;
}
// returns true if the player wants to continue (or if there is no problem)
int confirm_injury_action(enum BODYPART bp, enum DAMTYPE dt, char *actionname) {
char ch;
char ques[BUFLEN];
if (hasbleedinginjury(player, bp) && willbleedfrom(player, bp)) {
snprintf(ques, BUFLEN, "Your %s injury will cause damage if you %s - continue?",
getinjuredbpname(bp), actionname);
ch = askchar(ques, "yn","n", B_TRUE, B_FALSE);
if (ch == 'n') {
return B_FALSE;
}
return warnabout(ques);
}
return B_TRUE;
}
@ -2494,12 +2494,16 @@ lifeform_t *askgod(char *prompttext, int onlyprayed) {
return lf;
}
object_t *askobject(obpile_t *op, char *prompt, int *count, long opts) {
return doaskobject(op, prompt, count, B_TRUE, B_FALSE, opts, F_NONE);
object_t *askobject(obpile_t *op, char *prompt, int *count, char action, long opts) {
int showlong = B_TRUE;
if (op->owner && isplayer(op->owner)) {
showlong = B_FALSE;
}
return doaskobject(op, prompt, count, showlong, B_TRUE, B_FALSE, action, opts, F_NONE);
}
object_t *askobjectwithflag(obpile_t *op, char *prompt, int *count, long opts, enum FLAG withflag) {
return doaskobject(op, prompt, count, B_TRUE, B_FALSE, opts, withflag, F_NONE);
object_t *askobjectwithflag(obpile_t *op, char *prompt, int *count, char action, long opts, enum FLAG withflag) {
return doaskobject(op, prompt, count, B_TRUE, B_TRUE, B_FALSE, action, opts, withflag, F_NONE);
}
/*
@ -2597,8 +2601,13 @@ void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int fi
*counter = i;
}
object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int showpoints, long opts, ...) {
object_t *doaskobject(obpile_t *op, char *prompt, int *count, int showlong, int forpickup, int showpoints, char action, long opts, ...) {
int c,i;
char defchar = '\0';
static char defaults[52] = {'\0'};
static int defaultcounts[52] = { 0 };
object_t *defob = NULL;
int defcount = 0;
object_t *mylist[MAXPILEOBS+1];
char myletters[MAXPILEOBS+1];
char msghistbuf[BUFLEN],numstring[BUFLEN],fullprompt[BUFLEN];
@ -2647,6 +2656,22 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
// otherwise just label them a, b, c, etc.
if (op->owner && isplayer(op->owner)) {
useobletters = B_TRUE;
// cope with defaults...
if (action) {
// find the default obchar for this action
defchar = defaults[action - 'a'];
if (defchar) {
defob = findobl(op, defchar);
}
// got a default?
if (defob) {
defcount = defaultcounts[action - 'a'];
} else {
// remove the default
defaults[action - 'a'] = '\0';
defaultcounts[action - 'a'] = 0;
}
}
} else {
useobletters = B_FALSE;
}
@ -2702,13 +2727,17 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
while (!finished) {
int y;
int ch;
char fullnumstring[BUFLEN];
char defobstring[BUFLEN];
cls();
if (showlong) {
cls();
// list the objects
y = 2;
// list the objects
y = 2;
listobs(mainwin, mylist, NULL, NULL, firstob, &i, lastline, &y, useobletters ? NULL : myletters , forpickup, showpoints);
listobs(mainwin, mylist, NULL, NULL, firstob, &i, lastline, &y, useobletters ? NULL : myletters , forpickup, showpoints);
}
if (mylist[i] == NULL) {
nextpage = -1;
@ -2717,18 +2746,39 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
}
// draw prompt
if (strlen(numstring) > 0) {
snprintf(fullprompt, BUFLEN, "%s (%sESC to quit) [%s]: ",prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
numstring);
strcpy(fullnumstring, " [");
strcat(fullnumstring, numstring);
strcat(fullnumstring, "]");
} else {
snprintf(fullprompt, BUFLEN, "%s (%sESC to quit): ", prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "");
strcpy(fullnumstring, "");
}
snprintf(fullprompt, BUFLEN, "%s (%sESC=quit%s)%s: ",prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
showlong ? "" : ",?=list",
fullnumstring);
mvwprintw(mainwin, 0, 0, "%s", fullprompt);
if (nextpage != -1) {
mvwprintw(mainwin, y, 0, MORESTRING);
if (defob) {
getobname(defob, defobstring, defcount);
} else {
strcpy(defobstring, "");
}
if (strlen(defobstring)) {
int cx,cy;
// remember coords
getyx(mainwin, cy, cx);
wprintw(mainwin, "%s", defobstring);
// restore cursor pos
wmove(mainwin, cy, cx);
}
if (showlong) {
if (nextpage != -1) {
mvwprintw(mainwin, y, 0, MORESTRING);
}
}
// update screen
wrefresh(mainwin);
@ -2747,19 +2797,26 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
} else {
firstob = nextpage;
}
} else if (ch == '?') {
showlong = B_TRUE;
} else if ((ch == '\\') && (gamemode == GM_GAMESTARTED)) {
doknowledgelist();
} else if (isalpha(ch) || (ch == '$')) {
} else if (isalpha(ch) || (ch == '$') || ((ch == 10) && defob)) { // 27 == enter
object_t *o;
// describe that object
if (useobletters) {
o = findobl(op, ch);
// find that object
if (ch == 10) {
o = defob;
if (count) *count = defcount;
} else {
o = NULL;
for (i = firstob ; (mylist[i] != NULL) && (y < lastline); i++) {
if (myletters[i] == ch) {
o = mylist[i];
break;
if (useobletters) {
o = findobl(op, ch);
} else {
o = NULL;
for (i = firstob ; (mylist[i] != NULL) && (y < lastline); i++) {
if (myletters[i] == ch) {
o = mylist[i];
break;
}
}
}
}
@ -2774,10 +2831,21 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
clearmsg();
restoregamewindows();
getobname(o, obname, count ? *count : o->amt);
sprintf(msghistbuf, "%s%s",fullprompt,obname);
addmsghist(msghistbuf);
// update default
if (action && o->letter) {
defaults[action - 'a'] = o->letter;
if (count) {
defaultcounts[action - 'a'] = *count;
} else {
defaultcounts[action - 'a'] = 1;
}
}
return o;
}
} else if ((ch == '-') && (opts & AO_INCLUDENOTHING)) { // select nothing
@ -3331,7 +3399,7 @@ void describerace(enum RACE rid) {
wmove(mainwin, 2, 0);
buf2 = malloc(HUGEBUFLEN * sizeof(char));
makedesc_race(rid, buf2);
makedesc_race(rid, buf2, B_FALSE);
textwithcol(mainwin, buf2);
free(buf2);
@ -3625,7 +3693,7 @@ void docomms(lifeform_t *lf) {
case 'd': // donate
// ask what to give
snprintf(buf, BUFLEN, "What will you give to %s?",lfname);
o = askobject(player->pack, buf, &count, AO_NONE);
o = askobject(player->pack, buf, &count, '\0', AO_NONE);
if (o) {
if (o->type->id == OT_GOLD) {
char countbuf[BUFLEN];
@ -3913,7 +3981,7 @@ void dodrop(obpile_t *op, int wantmulti, obpile_t *dst) {
if (wantmulti) {
askobjectmulti(op, buf, AO_NONE);
} else {
o = askobject(op, buf, &count, AO_NONE);
o = askobject(op, buf, &count, '\0', AO_NONE);
if (o) {
retobs[0] = o;
retobscount[0] = count;
@ -4050,7 +4118,7 @@ void doeat(obpile_t *op) {
return;
}
eatob = askobject(op, "Eat what", NULL, AO_EDIBLE);
eatob = askobject(op, "Eat what", NULL, 'e', AO_EDIBLE);
}
if (eatob) {
if (isunknownbadobject(eatob) && skillcheck(player, A_WIS, 30, 0)) {
@ -4066,7 +4134,7 @@ void doeat(obpile_t *op) {
int dowear(obpile_t *op) {
object_t *o;
int rv;
o = askobject(op, "Wear what", NULL, AO_WEARABLE);
o = askobject(op, "Wear what", NULL, 'W', AO_WEARABLE);
if (o) {
if (isunknownbadobject(o) && skillcheck(player, A_WIS, 30, 0)) {
if (!confirm_badfeeling(o)) {
@ -4088,7 +4156,7 @@ int doweild(obpile_t *op) {
object_t *o;
int count = ALL;
int rv;
o = askobject(op, "Weild what", &count, AO_WEILDABLE | AO_INCLUDENOTHING);
o = askobject(op, "Weild what", &count, 'w', AO_WEILDABLE | AO_INCLUDENOTHING);
if (o) {
if (isunknownbadobject(o) && skillcheck(player, A_WIS, 30, 0)) {
if (!confirm_badfeeling(o)) {
@ -5463,14 +5531,27 @@ char *makedesc_ob(object_t *o, char *retbuf) {
i = B_FALSE;
for (f = o->flags->first ; f ; f = f->next) {
if (f->id == F_ATTREQ) {
enum COLOUR col;
int pctmod;
int usable = B_TRUE;
if (!meetsattreq(player, f, o)) {
if (!meetsattreq(player, f, o, &pctmod)) {
col = C_RED;
usable = B_FALSE;
} else {
col = C_GREY;
}
if (!usable) setcol(mainwin, C_RED);
sprintf(buf, "It requires at least %d %s to use.\n", f->val[1], getattrname(f->val[0]));
sprintf(buf, "^%dIt requires at least %d %s to use%s.^n\n", col, f->val[1], getattrname(f->val[0]),
(f->val[2] == 0) ? "" : " effectively");
strncat(retbuf, buf, HUGEBUFLEN);
if (!usable) unsetcol(mainwin, C_RED);
if (usable && isweapon(o)) {
if (pctmod > 0) {
sprintf(buf, "^%dYour high %s will increase your effectiveness with this weapon.^n", C_GREEN, getattrname(f->val[0]));
strncat(retbuf, buf, HUGEBUFLEN);
} else if (pctmod < 0) {
sprintf(buf, "^%dYour low %s will decrease your effectiveness with this weapon.^n", C_BROWN, getattrname(f->val[0]));
strncat(retbuf, buf, HUGEBUFLEN);
}
}
i = B_TRUE;
}
}
@ -5485,9 +5566,9 @@ char *makedesc_ob(object_t *o, char *retbuf) {
if (f && (f->val[0] != SK_NONE)) {
enum SKILLLEVEL slev;
slev = getskill(player, f->val[0]);
sprintf(buf, "It falls into the '%s' category (your skill: ",getskillname(f->val[0]));
sprintf(buf, "^nIt falls into the '%s' category (your skill: ",getskillname(f->val[0]));
strncat(retbuf, buf, HUGEBUFLEN);
sprintf(buf, "^%d%s^n)\n", getskilllevelcolour(slev), getskilllevelname(getskill(player, f->val[0])) );
sprintf(buf, "^%d%s^n).\n", getskilllevelcolour(slev), getskilllevelname(getskill(player, f->val[0])) );
strncat(retbuf, buf, HUGEBUFLEN);
}
}
@ -5567,9 +5648,11 @@ char *makedesc_ob(object_t *o, char *retbuf) {
return retbuf;
}
char *makedesc_race(enum RACE rid, char *retbuf) {
char *makedesc_race(enum RACE rid, char *retbuf, int showbonpen) {
race_t *r;
char buf[HUGEBUFLEN];
flag_t *retflag[MAXCANDIDATES],*f;
int nretflags,i;
strcpy(retbuf, "");
@ -5578,6 +5661,62 @@ char *makedesc_race(enum RACE rid, char *retbuf) {
snprintf(buf, HUGEBUFLEN, "%s\n\n", r->desc);
strncat(retbuf, buf, HUGEBUFLEN);
if (showbonpen) {
int curidx,donesomething;
// bonuses
getflags(r->flags, retflag, &nretflags, F_BONDESC, F_NONE);
if (nretflags) {
snprintf(buf, HUGEBUFLEN, "^%dBonuses^n:\n", C_WHITE);
strncat(retbuf, buf, HUGEBUFLEN);
donesomething = B_TRUE;
curidx = 0;
while (donesomething) {
donesomething = B_FALSE;
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->val[0] == curidx) {
snprintf(buf, HUGEBUFLEN, "@- %s\n", f->text);
strncat(retbuf, buf, HUGEBUFLEN);
donesomething = B_TRUE;
curidx++;
break;
}
}
}
} else {
snprintf(buf, HUGEBUFLEN, "^%dBonuses^n:\n@None.\n", C_WHITE);
strncat(retbuf, buf, HUGEBUFLEN);
}
getflags(r->flags, retflag, &nretflags, F_PENDESC, F_NONE);
if (nretflags) {
snprintf(buf, HUGEBUFLEN, "^%dPenalties^n:\n", C_WHITE);
strncat(retbuf, buf, HUGEBUFLEN);
donesomething = B_TRUE;
curidx = 0;
while (donesomething) {
donesomething = B_FALSE;
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->val[0] == curidx) {
snprintf(buf, HUGEBUFLEN, "@- %s\n", f->text);
strncat(retbuf, buf, HUGEBUFLEN);
donesomething = B_TRUE;
curidx++;
break;
}
}
}
} else {
snprintf(buf, HUGEBUFLEN, "^%dPenalties^n:\n@None.\n", C_WHITE);
strncat(retbuf, buf, HUGEBUFLEN);
}
while (donesomething) {
donesomething = B_FALSE;
}
}
return retbuf;
}
@ -6088,7 +6227,7 @@ void dooperate(obpile_t *op) {
}
// ask which object to read
o = askobject(op, "Operate what", NULL, AO_OPERABLE);
o = askobject(op, "Operate what", NULL, 'o', AO_OPERABLE);
if (o) {
operate(player, o, NULL);
}
@ -6222,12 +6361,12 @@ void doexplain(char *question) {
void dofinaloblist(obpile_t *op) {
object_t *o;
o = doaskobject(op, "Your final possessions were", NULL, B_FALSE, B_TRUE, AO_NONE, F_NONE);
o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, AO_NONE, F_NONE);
while (o) {
// describe it
describeob(o);
// ask for another one
o = doaskobject(op, "Your final possessions were", NULL, B_FALSE, B_TRUE, AO_NONE, F_NONE);
o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, AO_NONE, F_NONE);
}
real_clearmsg(B_TRUE);
}
@ -6359,12 +6498,12 @@ void doinventory(obpile_t *op) {
maxweight = getmaxcarryweight(player);
pct = (packweight / maxweight) * 100;
snprintf(buf, BUFLEN, "Inventory (%0.0f/%0.0f kg, %0.0f%%)", packweight, maxweight, pct);
o = askobject(op, buf, NULL, AO_NONE);
o = doaskobject(op, buf, NULL, B_TRUE, B_TRUE, B_FALSE, AO_NONE, F_NONE);
while (o) {
// describe it
describeob(o);
// ask for another one
o = askobject(op, buf, NULL, AO_NONE);
o = askobject(op, buf, NULL, '\0', AO_NONE);
}
real_clearmsg(B_TRUE);
}
@ -6400,7 +6539,7 @@ void doquaff(obpile_t *op) {
// ask which object to quaff
if (!liquid) {
liquid = askobjectwithflag(op, "Quaff what", NULL, AO_NONE, F_DRINKABLE);
liquid = askobjectwithflag(op, "Quaff what", NULL, 'q', AO_NONE, F_DRINKABLE);
}
if (liquid) {
if (canquaff(player, liquid)) {
@ -6451,7 +6590,7 @@ void dolockpick(obpile_t *op) {
targ = hasobwithflag(c->obpile, F_LOCKED);
if (targ) {
// ask which object to use
o = askobjectwithflag(op, "Lockpick using what", NULL, AO_NONE, F_PICKLOCKS);
o = askobjectwithflag(op, "Lockpick using what", NULL, 'p', AO_NONE, F_PICKLOCKS);
if (o) {
if (hasflag(o->flags, F_PICKLOCKS)) {
lockpick(player, targ, o);
@ -6530,7 +6669,7 @@ void dopour(obpile_t *op) {
object_t *o;
// ask which object to read
o = askobject(op, "Pour what", NULL, AO_POURABLE);
o = askobject(op, "Pour what", NULL, 'P', AO_POURABLE);
if (o) {
if (ispourable(o)) {
pour(player, o);
@ -6560,7 +6699,7 @@ void doread(obpile_t *op) {
// ask which object to read
o = askobject(op, "Read what", NULL, AO_READABLE);
o = askobject(op, "Read what", NULL, 'r', AO_READABLE);
if (o) {
if (isreadable(o)) {
readsomething(player, o);
@ -6653,7 +6792,7 @@ int dotakeoff(obpile_t *op) {
int rv = B_TRUE;
// ask which object to read
o = askobject(op, "Take off what", NULL, AO_EQUIPPEDNONWEAPON );
o = askobject(op, "Take off what", NULL, 'T', AO_EQUIPPEDNONWEAPON );
if (o) {
if (isarmour(o)) {
f = hasflag(o->flags, F_EQUIPPED);
@ -6682,7 +6821,7 @@ void dothrow(obpile_t *op) {
}
// ask which object to throw
o = askobject(op, "Throw what", NULL, AO_NONE);
o = askobject(op, "Throw what", NULL, 't', AO_NONE);
if (o) {
int maxdist;
char subprompt[BUFLEN],oidbuf[BUFLENSMALL];
@ -7167,6 +7306,12 @@ void dumpweps(void) {
}
void forceredraw(void) {
needredraw = B_TRUE;
statdirty = B_TRUE;
wclear(gamewin); // this forces a redraw even though the glyphs didn't change
drawscreen();
}
enum COLOUR getattrcolour(enum ATTRBRACKET brack) {
switch (brack) {
@ -9498,7 +9643,7 @@ void showlfstats(lifeform_t *lf, int showall) {
int x=0;
// description first.
descbuf = malloc(HUGEBUFLEN * sizeof(char));
makedesc_race(lf->race->id, descbuf);
makedesc_race(lf->race->id, descbuf, B_FALSE);
//mvwprintw(mainwin, y, 0, "%s", descbuf);
wrapprint(mainwin, &y, &x, "%s", descbuf);
free(descbuf);
@ -11141,6 +11286,28 @@ void tombstone(lifeform_t *lf) {
endwin();
}
//
// returns TRUE if you answered 'Yes' or you'd already accepted this warning
int warnabout(char *what) {
char ch = 'n';
warning_t *w;
// have we already warned about this?
w = findwarning(what);
if (w) {
w->lifetime = DEF_WARNINGTIME;
ch = 'y';
} else {
char ques[BUFLEN];
sprintf(ques, "%s", what);
ch = askchar(what, "yn", "n", B_TRUE, B_FALSE);
}
if (ch == 'y') {
addwarning(what);
return B_TRUE;
}
return B_FALSE;
}
// @ = tab
void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) {
char word[HUGEBUFLEN],buf[HUGEBUFLEN];

10
io.h
View File

@ -19,9 +19,9 @@ void announceobflagloss(object_t *o, flag_t *f);
int confirm_badfeeling(object_t *o);
int confirm_injury_action(enum BODYPART bp, enum DAMTYPE dt, char *actionname);
lifeform_t *askgod(char *prompt, int onlyprayed);
object_t *askobject(obpile_t *op, char *title, int *count, long opts);
object_t *askobjectwithflag(obpile_t *op, char *title, int *count, long opts, enum FLAG withflag);
object_t *doaskobject(obpile_t *op, char *title, int *count, int forpickup, int showpoints, long opts, ...);
object_t *askobject(obpile_t *op, char *title, int *count, char action, long opts);
object_t *askobjectwithflag(obpile_t *op, char *title, int *count, char action, long opts, enum FLAG withflag);
object_t *doaskobject(obpile_t *op, char *title, int *count, int showlong, int forpickup, int showpoints, char action, long opts, ...);
int askobjectmulti(obpile_t *op, char *prompt, long opts);
char askchar(char *prompt, char *validchars, char *def, int showchars, int maycancel);
cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *srclf, int maxrange, enum LOFTYPE loftype, int wanttrail);
@ -85,6 +85,7 @@ void drawstatus(void);
int drop(object_t *o, int count);
void dumpspells(void);
void dumpweps(void);
void forceredraw(void);
enum COLOUR getattrcolour(enum ATTRBRACKET brack);
char getchoice(prompt_t *prompt);
char getchoicestr(prompt_t *prompt, int useshortcuts, int showlallatstart);
@ -100,7 +101,7 @@ int keycodetokey(int keycode, int escseqok);
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints);
char *makedesc_god(lifeform_t *god, char *retbuf);
char *makedesc_ob(object_t *o, char *retbuf);
char *makedesc_race(enum RACE rid, char *retbuf);
char *makedesc_race(enum RACE rid, char *retbuf, int showbonpen);
char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite);
char *makedesc_spell(objecttype_t *ot, char *retbuf);
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard,int mpcutoff);
@ -129,4 +130,5 @@ void textwithcol_real(WINDOW *win, char *buf, int resetcolatend);
void tombstone(lifeform_t *lf);
void updatestatus(void);
int updateviewfor(cell_t *cell);
int warnabout(char *what);
void wrapprint(WINDOW *win, int *y, int *x, char *format, ... );

156
lf.c
View File

@ -826,6 +826,10 @@ int cannotmove(lifeform_t *lf) {
int canlearn(lifeform_t *lf, enum SKILL skid) {
if (ismaxedskill(lf, skid)) return B_FALSE;
if (lfhasflagval(lf, F_NOSKILL, skid, NA, NA, NULL)) {
return B_FALSE;
}
if (lfhasflagval(lf, F_CANLEARN, skid, NA, NA, NULL)) {
return B_TRUE;
}
@ -1175,7 +1179,7 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) {
f = retflag[i];
if (f->id == F_ATTREQ) {
// meetsattreq will set 'reason' for us.
if (!meetsattreq(lf, f, o)) {
if (!meetsattreq(lf, f, o, NULL)) {
return B_FALSE;
}
}
@ -1318,7 +1322,7 @@ int canweild(lifeform_t *lf, object_t *o) {
f = retflag[i];
if (f->id == F_ATTREQ) {
// meetsattreq will set 'reason' for us.
if (!meetsattreq(lf, f, o)) {
if (!meetsattreq(lf, f, o, NULL)) {
return B_FALSE;
}
} else if (f->id == F_TWOHANDED) {
@ -4933,7 +4937,7 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) {
}
// modified?
getflags(lf->flags, retflag, &nretflags, F_ATTRMOD, F_DRUNK, F_INJURY, F_NONE);
getflags(lf->flags, retflag, &nretflags, F_ATTRMOD, F_DRUNK, F_INJURY, F_RAGE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if ((f->id == F_ATTRMOD) && (f->val[0] == attr)) {
@ -4957,8 +4961,12 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) {
val -= 6;
}
}
if ((f->id == F_RAGE) && (attr == A_STR)) {
val += 5;
}
}
if (val < 0) val = 0;
return val;
@ -5757,6 +5765,17 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
}
}
// agi scaling on weapon
getflags(wep->flags, retflag, &nretflags, F_ATTREQ, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->val[0] == A_AGI) {
int pctmod;
meetsattreq(lf, retflag[i], wep, &pctmod);
acc += pctmod;
}
}
// modify for nausea
if (lfhasflag(lf, F_NAUSEATED)) {
acc -= 25;
@ -6845,9 +6864,11 @@ int getracerarity(map_t *map, enum RACE rid) {
if (map) {
f = hasflagval(r->flags, F_RARITY, map->habitat->id, NA, NA, NULL);
}
if (!f) {
f = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!f) {
f = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
}
} else {
f = hasflag(r->flags, F_RARITY);
}
/*if (!f) {
f = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL);
@ -6993,11 +7014,14 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
int hdmin,hdmax;
enum RARITY wantrr = RR_FREQUENT;
// determine rarity of lf to generate
if (forcedepth != NA) {
depth = forcedepth;
} else {
} else if (c) {
depth = getmapdifficulty((c && c->map) ? c->map : NULL);
} else {
depth = rnd(1,MAXDEPTH);
}
gethitdicerange(depth, &hdmin, &hdmax, RARITYVARIANCELF, B_TRUE);
@ -7021,12 +7045,15 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
if ((thishd < hdmin) || (thishd > hdmax)) {
valid = B_FALSE;
} else {
if (db) dblog("%s hitdice %d ok (between %d - %d)",r->name,thishd,hdmin,hdmax);
// correct rarity?
if (c) {
rarflag = hasflagval(r->flags, F_RARITY, c->habitat->id, NA, NA, NULL);
}
if (!rarflag) {
rarflag = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!rarflag) {
rarflag = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
}
} else {
rarflag = hasflag(r->flags, F_RARITY);
}
/*if (!rarflag) {
rarflag = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL);
@ -7034,10 +7061,14 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
if (rarflag) {
if ((rarflag->val[2] == NA) || (rarflag->val[2] <= wantrr)) {
if (db) dblog("%s has correct rarity rr (%d <= wantr(%d)).",r->name, rarflag->val[2], wantrr);
valid = B_TRUE;
thisrr = rarflag->val[2];
} else {
if (db) dblog("%s has wrong rr (%d, wantrr=%d).",r->name, rarflag->val[2], wantrr);
}
} else {
if (db) dblog("%s has no rarity flag.",r->name);
valid = B_FALSE;
}
}
@ -7705,6 +7736,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
// inherit all flags except:
// - hpmod ones
// - skills which we already have f_noskill for.
for (f = j->flags->first ; f ; f = f->next) {
int ignorethis = B_FALSE;
int val[3];
@ -7745,6 +7777,9 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
case F_JOBATTRMOD:
ignorethis = B_TRUE;
break;
case F_CANLEARN:
if (lfhasflagval(lf, F_NOSKILL, f->val[0], NA, NA, NULL)) ignorethis = B_TRUE;
break;
default:
break;
}
@ -7967,6 +8002,10 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
flag_t *f = NULL, *newf;
skill_t *sk;
if (lfhasflagval(lf, F_NOSKILL, id, NA, NA, NULL)) {
return NULL;
}
sk = findskill(id);
if (!sk) {
return NULL;
@ -9060,9 +9099,14 @@ flag_t *hasactivespell(lifeform_t *lf, enum OBTYPE sid) {
return lfhasflagval(lf, F_BOOSTSPELL, sid, NA, NA, NULL);
}
// got line of fire to dest? if lof is blocked, return last cell in 'newdest'
//int haslof(lifeform_t *viewer, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest) {
int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest) {
return haslof_real(src, dest, loftype, newdest, NULL);
}
// got line of fire to dest? if lof is blocked, return last cell in 'newdest'
// if 'srclf' is set, we are checking whether 'srclf' THINKS they have line of fire. ie invisible/unseed
// lifeforms don't block lof.
int haslof_real(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest, lifeform_t *srclf) {
int numpixels;
int i;
int x1,y1,x2,y2;
@ -9154,10 +9198,13 @@ int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest) {
// - they're in the first cell (ie the one doing the throwing/firing/shooting/etc)
// - they're in our destination
if (cell->lf && (!isprone(cell->lf)) && (loftype & LOF_LFSSTOP)) {
// if not in first cell...
if (i != 0) {
// if not in last cell...
if (i != (numpixels-1)) {
int lfcanblocklof = B_TRUE;
if (srclf && !cansee(srclf, cell->lf)) {
lfcanblocklof = B_FALSE;
}
if (lfcanblocklof) {
// if not in first or last cell...
if ((i != 0) && (i != (numpixels-1)) ) {
reason = E_NOLOF;
return B_FALSE;
}
@ -10483,6 +10530,19 @@ void applylfdammod(int *dam, lifeform_t *lf, object_t *wep) {
if (!hasflag(wep->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
*dam = (int)((float)*dam * getstrdammod(lf));
}
// strength scaling on weapon
getflags(wep->flags, retflag, &nretflags, F_ATTREQ, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->val[0] == A_STR) {
int pctmod;
meetsattreq(lf, retflag[i], wep, &pctmod);
if (pctmod != 0) {
*dam = pctof(100 + pctmod, *dam);
}
}
}
// modify for injuries
getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE);
for (i = 0; i < nretflags; i++) {
@ -11493,12 +11553,16 @@ void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how) {
// if you don't meet it, return why not in 'reason'
int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o) {
int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o, int *pctmod) {
enum ATTRIB att;
int valneeded;
int myval;
int diff;
int scaleamt;
att = f->val[0];
valneeded = f->val[1];
scaleamt = f->val[2];
if (scaleamt == NA) scaleamt = 10;
// modify for masterwork
if (o) {
@ -11509,8 +11573,32 @@ int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o) {
}
myval = getattr(lf, att);
diff = myval - valneeded;
limit(&diff,-4, 3);
if (myval < valneeded) {
// for firearms or scaleamt == 0, you MUST meet the requirement.
if (diff < 0) {
if (scaleamt == 0) {
diff = -4;
} else if (o && isarmour(o)) {
diff = -4;
} else if (o && isfirearm(o)) {
diff = -4;
}
} else if (diff > 0) {
// no bonusses if you're unskilled
if (o && !getweaponskill(lf, o)) {
diff = 0;
}
}
if (pctmod) {
*pctmod = (diff * scaleamt);
}
// too low?
if (diff <= -4) {
switch (att) {
case A_AGI:
reason = E_LOWDEX;
@ -14475,6 +14563,26 @@ void startlfturn(lifeform_t *lf) {
// special effects
if (lf->race->id == R_ASHKARI) {
lifeform_t *otherlf;
for (i = 1; i < lf->nlos; i++) {
otherlf = lf->los[i]->lf;
if (otherlf) {
if (lfhasflag(otherlf, F_CANINE) || lfhasflag(otherlf, F_AVIAN)) {
f = lfhasflag(lf, F_RAGE);
if (f && f->lifetime > 0) {
f->lifetime = DEF_RAGETIME/2;
} else {
addtempflag(lf->flags, F_RAGE, B_TRUE, NA, NA, NULL, DEF_RAGETIME/2);
if (getstamina(lf) < 1) setstamina(lf, 1);
forceredraw();
}
}
}
}
}
f = lfhasflag(lf, F_AUTOCREATEOB);
if (f) {
int radius;
@ -17155,6 +17263,18 @@ int weild(lifeform_t *lf, object_t *o) {
sk = getobskill(o);
if (sk && !getskill(lf, sk->id)) {
msg("^wYou feel rather inept with this weapon.");
} else {
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
// warn about not meeting attrib reqs
getflags(o->flags, retflag, &nretflags, F_ATTREQ, F_NONE);
for (i = 0; i < nretflags; i++) {
int pctmod;
meetsattreq(lf, retflag[i], o, &pctmod);
if (pctmod < 0) {
msg("^wYou lack of %s will hinder your usage of this weapon.", getattrname(retflag[i]->val[0]));
}
}
}
}
} else if (cansee(player, lf)) {

3
lf.h
View File

@ -260,6 +260,7 @@ void loseobflags(lifeform_t *lf, object_t *o, int kind);
int hasbp(lifeform_t *lf, enum BODYPART bp);
flag_t *hasactivespell(lifeform_t *lf, enum OBTYPE sid);
int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest);
int haslof_real(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest, lifeform_t *srclf);
int haslos(lifeform_t *viewer, cell_t *dest);
int haslos_fast(lifeform_t *viewer, cell_t *dest);
void interrupt(lifeform_t *lf);
@ -324,7 +325,7 @@ void makenoise(lifeform_t *lf, enum NOISETYPE nid);
void makepeaceful(lifeform_t *lf);
lifeform_t *makezombie(object_t *o);
void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how);
int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o);
int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o, int *modpct);
int mightflee(lifeform_t *lf);
int modattr(lifeform_t *lf, enum ATTRIB attr, int amt);
void modhunger(lifeform_t *lf, int amt);

8
map.c
View File

@ -5052,9 +5052,11 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
return TT_OBJECT;
}
} else if ((f->id == F_ENHANCESMELL) && issmellableob(o)) {
*thing = o;
set_scanned_glyph(TT_OBJECT, o, " (smelled)", desc, glyph);
return TT_OBJECT;
if (getcelldistorth(player->cell, c) <= f->val[0]) {
*thing = o;
set_scanned_glyph(TT_OBJECT, o, " (smelled)", desc, glyph);
return TT_OBJECT;
}
}
}
}

75
nexus.c
View File

@ -44,6 +44,8 @@ hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
npcname_t *npcname;
int numnpcnames;
warning_t *firstwarning = NULL,*lastwarning = NULL;
int maxmonhitdice = 0; // highest number of hitdice for any monster
double presin[360];
@ -205,7 +207,11 @@ int main(int argc, char **argv) {
ch = 'a';
for (r = firstrace ; r ; r = r->next) {
if (hasflag(r->flags, F_PLAYABLE)) {
addchoice(&prompt, ch++, r->name, NULL, r, r->desc);
char *longdesc;
longdesc = malloc(HUGEBUFLEN * sizeof(char));
makedesc_race(r->id, longdesc, B_TRUE);
addchoice(&prompt, ch++, r->name, NULL, r, longdesc);
free(longdesc);
}
}
startrace = NULL;
@ -553,6 +559,31 @@ celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, i
return a;
}
warning_t *addwarning(char *text) {
warning_t *a;
// add to the end of the list
if (firstwarning == NULL) {
firstwarning = malloc(sizeof(celltype_t));
a = firstwarning;
a->prev = NULL;
} else {
// go to end of list
a = lastwarning;
a->next = malloc(sizeof(warning_t));
a->next->prev = a;
a = a->next;
}
lastwarning = a;
a->next = NULL;
// set props
a->text = strdup(text);
a->lifetime = DEF_WARNINGTIME;
return a;
}
void checkdeath(void) {
lifeform_t *lf, *nextlf;
@ -870,6 +901,14 @@ void donextturn(map_t *map) {
}
}
warning_t *findwarning(char *text) {
warning_t *w;
for (w = firstwarning ; w ; w = w->next) {
if (streq(w->text, text)) return w;
}
return NULL;
}
void gethitdicerange(int depth, int *min, int *max, int range, int oodok) {
int mid;
@ -1076,6 +1115,32 @@ int isplayerturn(void) {
return B_FALSE;
}
void killwarning(warning_t *w) {
warning_t *nextone, *lastone;
// free mem
if (w->text) free(w->text);
// remove from list
nextone = w->next;
if (nextone != NULL) {
nextone->prev = w->prev;
} else { /* last */
lastwarning = w->prev;
}
if (w->prev == NULL) {
/* first */
nextone = w->next;
free(firstwarning);
firstwarning = nextone;
} else {
lastone = w->prev;
free (lastone->next );
lastone->next = nextone;
}
}
int limit(int *what, int min, int max) {
int limited = B_FALSE;
if (min != NA) {
@ -1445,6 +1510,7 @@ void timeeffectsworld(map_t *map, int updategametime) {
int x,y;
long firstlftime;
enum SKILLLEVEL cartskill;
warning_t *w,*nextw;
cartskill = getskill(player, SK_CARTOGRAPHY);
@ -1583,6 +1649,13 @@ void timeeffectsworld(map_t *map, int updategametime) {
timeeffectslf(l);
}
// time out warnings
for (w = firstwarning ;w ; w = nextw) {
nextw = w->next;
w->lifetime--;
if (w->lifetime <= 0) killwarning(w);
}
//dblog("AFTER SORT AND ADJUST.....");
//dumplf();
} // end if timespent

View File

@ -1,6 +1,7 @@
#include "defs.h"
celltype_t *addcelltype(int id, char *name, char glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight);
warning_t *addwarning(char *text);
void checkdeath(void);
void checkendgame(void);
void cleanup(void);
@ -9,6 +10,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);
warning_t *findwarning(char *text);
void gethitdicerange(int depth, int *min, int *max, int range, int oodok);
enum COLOUR getpctcol(float num, float max);
char getpctletter(float num, float max);
@ -17,6 +19,7 @@ int init(void);
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);
int isplayerturn(void);
void killwarning(warning_t *w);
int limit(int *what, int min, int max);
int limitf(float *what, float min, float max);
int limitd(double *what, double min, double max);

View File

@ -5235,9 +5235,11 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat,
// correct rarity number?
if (hab) {
rarflag = hasflagval(ot->flags, F_RARITY, hab->id, NA, NA, NULL);
}
if (!rarflag) {
rarflag = hasflagval(ot->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!rarflag) {
rarflag = hasflagval(ot->flags, F_RARITY, H_ALL, NA, NA, NULL);
}
} else {
rarflag = hasflag(ot->flags, F_RARITY);
}
/*if (!rarflag) {
rarflag = hasflag(ot->flags, F_RARITY);
@ -7764,7 +7766,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
return B_TRUE;
} else {
snprintf(buf, BUFLEN, "Load %s with what ammo",obname);
oo = askobject(lf->pack, buf, NULL, AO_SPECIFIED);
oo = askobject(lf->pack, buf, NULL, 'l', AO_SPECIFIED);
if (oo) {
if (isammofor(oo->type, o)) {
loadfirearm(lf, o, oo);
@ -8497,7 +8499,7 @@ int pour(lifeform_t *lf, object_t *o) {
} else {
snprintf(buf, BUFLEN, "Pour %s onto what", obname);
// tip onto another object
dst = askobject(lf->pack, buf, NULL, AO_NONE);
dst = askobject(lf->pack, buf, NULL, '\0', AO_NONE);
if (!dst) {
msg("Cancelled.");
return B_TRUE;
@ -9484,7 +9486,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
if (needsob && isplayer(lf) && !isknown(o)) {
flag_t *f2;
f2 = addflag(o->flags, F_BEINGUSED, B_TRUE, NA, NA, NULL);
targob = askobject(lf->pack, "Target which object", NULL, AO_NONE);
targob = askobject(lf->pack, "Target which object", NULL, '\0', AO_NONE);
killflag(f2);
if (!targob) {
noeffect = B_TRUE;
@ -9681,7 +9683,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
removeob(o, 1);
} else if (o->type->id == OT_SCR_PERMENANCE) {
if (isplayer(lf)) {
targob = askobject(lf->pack, "Target which object", NULL, AO_NONE);
targob = askobject(lf->pack, "Target which object", NULL, '\0', AO_NONE);
}
if (targob) {
@ -11551,7 +11553,7 @@ void timeeffectsob(object_t *o) {
char noisebuf[BUFLEN];
switch (o->type->id) {
case OT_TEMPLE: strcpy(noisebuf, "voices chanting."); break;
default: strcpy(noisebuf, "the chime of a cash register."); break;
default: strcpy(noisebuf, "a cash register chiming."); break;
}
noise(location, NULL, NC_OTHER, 3, noisebuf, NULL);
}
@ -12263,6 +12265,11 @@ int validateobs(void) {
goterror = B_TRUE;
}
}
f = hasflag(ot->flags, F_ATTREQ);
if (f && (f->val[2] == NA)) {
printf("ERROR in object '%s' - f_attreq missing scale factor.\n", ot->name);
goterror = B_TRUE;
}
}
if (hasflagval(ot->flags, F_PICKLOCKS, NA, B_BLUNTONFAIL, NA, NULL) && hasflag(ot->flags, F_STACKABLE)) {
printf("ERROR in object '%s' - cannot have F_BLUNTONFAIL on stackable objects.\n", ot->name);
@ -12400,12 +12407,26 @@ int getcritchance(lifeform_t *lf, object_t *o, lifeform_t *victim) {
if (lf) {
enum SKILLLEVEL weplev = PR_INEPT;
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
weplev = getweaponskill(lf, o);
if (weplev != PR_INEPT) {
chance += (weplev*5); // ie. up to 30% bonus
}
// agi scaling on weapon
getflags(o->flags, retflag, &nretflags, F_ATTREQ, F_NONE);
for (i = 0; i < nretflags; i++) {
if (f->val[0] == A_AGI) {
int pctmod;
meetsattreq(lf, retflag[i], o, &pctmod);
chance += pctmod;
}
}
}
// double crit chance if victim is vulnerable to this weapon
if (victim && lfhasflagval(victim, F_MATVULN, o->material->id, NA, NA, NULL)) {
chance *= 2;

10
save.c
View File

@ -1075,6 +1075,7 @@ int showhiscores(lifeform_t *lf, int min, int max) {
rc = sqlite3_exec(db, cmd, showhiscoreline, hilitescoretext, &errmsg);
if (rc != SQLITE_OK) {
msg("error writing hiscores: '%s'", errmsg);
dblog("query was: '%s'", cmd);
dblog("error writing hiscores: '%s'\n sql command: [%s]", errmsg, cmd);
sqlite3_free(errmsg);
}
@ -1093,6 +1094,7 @@ int writehiscore(lifeform_t *lf, int *rank) {
char racename[BUFLEN];
char jobname[BUFLEN];
char killedby[BUFLEN];
char *escaped;
char *errmsg = NULL;
sqlite3_stmt *smt;
job_t *j;
@ -1118,16 +1120,22 @@ int writehiscore(lifeform_t *lf, int *rank) {
makekillertext(killedby, lf->killverb, lf->lastdam, B_FALSE);
// add escapes
escaped = strdup(killedby);
escaped = strrep(escaped, "'", "\\'", NULL);
if (!lfhasflag(lf, F_NOSCORE)) {
asprintf(&cmd, "insert into 'hiscores' (score,name,job,killedby) VALUES (%ld, '%s', '%s', '%s')", score, pname, jobname, killedby);
asprintf(&cmd, "insert into 'hiscores' (score,name,job,killedby) VALUES (%ld, '%s', '%s', '%s')", score, pname, jobname, escaped);
rc = sqlite3_exec(db, cmd, NULL, NULL, &errmsg);
free(cmd);
if (rc != SQLITE_OK) {
msg("error writing hiscores: '%s'", errmsg);
dblog("error writing hiscores: '%s'", errmsg);
dblog("query was: '%s'", cmd);
sqlite3_free(errmsg);
}
}
free(escaped);
if (rank) {
if (lfhasflag(lf, F_NOSCORE)) {

31
spell.c
View File

@ -276,9 +276,9 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// announce the check, so that the player has feedback
// if map generation takes a while.
if (ch == 'l') {
msg("You sniff %s...",obname);
} else if (ch == 's') { // smell
msg("You listen at %s...",obname);
} else if (ch == 's') { // smell
msg("You sniff %s...",obname);
} else if (ch == 'f') { // footprints
msg("You inspect %s...",obname);
} else if (ch == 'p') { // peek
@ -1367,13 +1367,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
}
return B_TRUE;
}
howlong = 10;
howlong = DEF_RAGETIME;
addtempflag(user->flags, F_RAGE, B_TRUE, NA, NA, NULL, howlong);
if (isplayer(user)) {
needredraw = B_TRUE;
statdirty = B_TRUE;
wclear(gamewin); // this forces a redraw even though the glyphs didn't change
drawscreen();
forceredraw();
}
} else if (abilid == OT_A_REPAIR) {
object_t *o,*helpob = NULL;
@ -2126,7 +2123,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
cell_t *cell1 = NULL,*cell2 = NULL;
cell1 = getcellindir(user->cell, dir);
if (cell1 && cellwalkable(user, cell1, NULL)) {
if (cell1) {
cell2 = getcellindir(cell1, dir);
} else {
if (isplayer(user)) msg("There is no room to tumble that way!");
@ -3280,7 +3277,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (targcell->obpile->first) {
// select object from cell...
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
targob = askobject(targcell->obpile, "Target which object", NULL, '\0', AO_NONE);
if (!targob) {
failed = B_TRUE;
}
@ -3643,7 +3640,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (targcell->obpile->first) {
// select object from cell...
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
targob = askobject(targcell->obpile, "Target which object", NULL, '\0', AO_NONE);
if (!targob) {
failed = B_TRUE;
}
@ -5291,7 +5288,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
o = targob;
} else {
// ask for an object
o = askobjectwithflag(caster->pack, "Enchant which object", NULL, AO_NONE, F_ENCHANTABLE);
o = askobjectwithflag(caster->pack, "Enchant which object", NULL, '\0', AO_NONE, F_ENCHANTABLE);
}
if (!o) {
fizzle(caster);
@ -6009,7 +6006,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
o = targob;
} else {
// ask for an object
o = askobject(caster->pack, "Identify which object", NULL, AO_NOTIDENTIFIED);
o = askobject(caster->pack, "Identify which object", NULL, '\0', AO_NOTIDENTIFIED);
}
if (!o) {
fizzle(caster);
@ -6275,7 +6272,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
flag_t *f;
if (!targob) {
// ask for an object
targob = askobject(caster->pack, "Fire which object", NULL, AO_NONE);
targob = askobject(caster->pack, "Fire which object", NULL, 't', AO_NONE);
}
if (!targob || !ismetal(targob->material->id) ) {
fizzle(caster);
@ -6647,7 +6644,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (targcell->obpile->first) { // no lifeform there
targob = NULL;
// select object from cell...
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
targob = askobject(targcell->obpile, "Target which object", NULL, '\0', AO_NONE);
if (targob) {
if (ismetal(targob->material->id)) {
@ -7388,7 +7385,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
o = targob;
} else {
// ask for an object
o = askobject(caster->pack, "Mend which object", NULL, AO_DAMAGED);
o = askobject(caster->pack, "Mend which object", NULL, '\0', AO_DAMAGED);
}
if (!o) {
fizzle(caster);
@ -7608,7 +7605,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
o = targob;
} else {
// ask for an object
o = askobject(caster->pack, "Purify what?", NULL, AO_EDIBLE | AO_DRINKABLE);
o = askobject(caster->pack, "Purify what?", NULL, '\0', AO_EDIBLE | AO_DRINKABLE);
}
if (!o) {
fizzle(caster);
@ -8720,7 +8717,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (where && haslos(caster, where)) {
if (where->obpile->first) {
// select object from cell...
targob = askobject(where->obpile, "Target which object", NULL, AO_NONE);
targob = askobject(where->obpile, "Target which object", NULL, '\0', AO_NONE);
if (!targob) {
failed = B_TRUE;
}