- [+] flak jacket too powerful

- [+] make it only protect against missiles?  no AR as such
- [+] facing N, walk NW.  turn instead of walk! bug in
      getrelativedir(). fixed.
- [+] ctrl+dir = turn.
- [+] make novice level listen more useful.
- [+] l2 tech: "styptic" -
    - [+]  heals certain bleeding injuries
    - [+] then if still bleeding() due to low hp, heal back up.
* [+] tool: bandage -fix blood loss
- [+] change enhancedsmell to happen in same place as 'detectlife'
- [+] spells:
    - [+] sixth sense - l1 - warns if someone is within 2 cells behind
          you.  lasts for a single use.
    - [+] canine tracking - l2 divination spell, gives temporary
          enhanced smell for short range (3).
    - [+] heightened awareness - l3 ongoing divination spell to enhance
          FOV to 360 degrees
    - [+] scrolls for the second two
    - [+] apportation
- [+] let wizards pick two secondary spell schools
    - [+] start with beginner in primary, novice in sec
This commit is contained in:
Rob Pearce 2011-09-12 23:52:21 +00:00
parent c8a42323d2
commit 7370b60375
15 changed files with 564 additions and 129 deletions

View File

@ -432,8 +432,9 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
}
if (lfhasflagval(lf, F_INJURY, NA, BP_HANDS, DT_SLASH, NULL)) {
bleed(lf, B_FALSE);
losehp(lf, 1, DT_DIRECT, NULL, "blood loss");
if (!bleedfrom(lf, BP_HANDS, B_FALSE)) {
losehp(lf, 1, DT_DIRECT, NULL, "blood loss");
}
}
// god effects...
@ -1910,8 +1911,10 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) {
if (victim) {
if (lfhasflagval(victim, F_INJURY, NA, BP_BODY, DT_SLASH, NULL)) {
// extra damage
dam += rnd(1,2);
if (willbleedfrom(victim, BP_BODY)) {
// extra damage
dam += rnd(1,2);
}
}
}

Binary file not shown.

75
defs.h
View File

@ -50,7 +50,7 @@
#define B_DONTKILL (-1)
#define B_APPENDYOU (-1)
#define B_SPLATTER (-1)
#define B_FROMINJURY (-1)
#define B_FROMINJURY (-2)
#define B_KEEPDIR (-2)
@ -257,6 +257,16 @@ enum RELATIVEDIR {
#define MSGMORESTRING "^n--More--"
#define SOLDOUTSTRING "--SOLD OUT--"
// COMMAND CHARACTERS
#define CH_TURN_W (8) // ctrl-h
#define CH_TURN_N (10) // ctrl-j
#define CH_TURN_S (11) // ctrl-k
#define CH_TURN_E (12) // ctrl-l
#define CH_TURN_NW (25) // ctrl-y
#define CH_TURN_NE (21) // ctrl-u
#define CH_TURN_SW (2) // ctrl-b
#define CH_TURN_SE (14) // ctrl-n
// SPECIAL NUMBERS/CONSTANTS
#define DUMMYCELLTYPE 0xabcd
#define UNLIMITED (-9876)
@ -1030,7 +1040,9 @@ enum OBTYPE {
// scrolls
OT_MAP,
OT_GRAPHPAPER,
OT_SCR_AWARENESS,
OT_SCR_NOTHING,
OT_SCR_CANINETRACKING,
OT_SCR_CREATEMONSTER,
OT_SCR_DETECTAURA,
OT_SCR_DETECTLIFE,
@ -1079,16 +1091,19 @@ enum OBTYPE {
OT_S_SMITEGOOD,
OT_S_STENCH,
// -- divination
OT_S_AWARENESS,
OT_S_CANINETRACKING,
OT_S_DETECTAURA,
OT_S_DETECTLIFE,
OT_S_DETECTOBS,
OT_S_DETECTMAGIC,
OT_S_IDENTIFY,
OT_S_LOCATEOBJECT,
OT_S_LORE,
OT_S_MAPPING,
OT_S_REVEALHIDDEN,
OT_S_SEEINVIS,
OT_S_IDENTIFY,
OT_S_MAPPING,
OT_S_SIXTHSENSE,
// -- elemental - air
OT_S_JOLT,
OT_S_AIRBLAST,
@ -1205,6 +1220,7 @@ enum OBTYPE {
OT_S_CREATEMONSTER,
OT_S_SUMMONWEAPON,
// -- translocation
OT_S_APPORTATION,
OT_S_BLINK,
OT_S_DISPERSAL,
OT_S_GATE,
@ -1284,6 +1300,7 @@ enum OBTYPE {
OT_BAGOFHOLDING,
OT_BAGOFHOLDINGLARGE,
OT_BAGOFHOLDINGHUGE,
OT_BANDAGE,
OT_BLANKET,
OT_BLINDFOLD,
OT_BUGLAMP,
@ -1301,26 +1318,34 @@ enum OBTYPE {
OT_SAFEBOX,
OT_TORCH,
OT_TOWEL,
// tech
OT_POCKETWATCH,
OT_C4,
// tech l0
OT_CREDITCARD,
OT_PAPERCLIP,
OT_SLEEPINGBAG,
// tech l1
OT_POCKETWATCH,
OT_DIGITALWATCH,
OT_INSECTICIDE,
OT_LANTERNLED,
OT_TENT,
// tech l2
OT_C4,
OT_FLASHBANG,
OT_GRENADE,
OT_INFOVISOR,
OT_INSECTICIDE,
OT_JETPACK,
OT_LANTERNLED,
OT_LOCKHACKER,
OT_MOTIONSCANNER,
OT_NVGOGGLES,
OT_PAPERCLIP,
OT_STYPTIC,
// tech l3
OT_INFOVISOR,
OT_LOCKHACKER,
OT_PORTLADDER,
OT_SLEEPINGBAG,
// tech l4
OT_JETPACK,
// tech l5
OT_TELEPAD,
OT_TENT,
OT_XRAYGOGGLES,
// tech l6
// none yet.
// furniture
OT_CANDELABRUM,
OT_COFFIN,
@ -2235,6 +2260,7 @@ enum FLAG {
F_ASLEEP, // is asleep. 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
F_AWARENESS, // you can see 360 degrees around yourself
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
F_BLIND, // cannot see anything
F_CONFUSED, // move randomly about
@ -2465,25 +2491,28 @@ enum HUNGER {
// injuries
enum INJURY {
IJ_NONE,
// bashing
IJ_ANKLESWOLLEN,
IJ_ARTERYPIERCE,
IJ_BLACKEYE,
IJ_CHESTBLEED,
IJ_CONCUSSION,
IJ_EYELIDSCRAPED,
IJ_EYEDESTROYED,
IJ_FINGERBROKEN,
IJ_FINGERMISSING,
IJ_HAMSTRUNG,
IJ_HANDBLEED,
IJ_LEGBLEED,
IJ_LEGBROKEN,
IJ_LEGBRUISE,
IJ_NOSEBROKEN,
IJ_RIBCRACKED,
IJ_SHOULDERDISLOCATED,
IJ_TENDONCUT,
IJ_WINDPIPECRUSHED,
// slashing
IJ_ARTERYPIERCE,
IJ_CHESTBLEED,
IJ_HAMSTRUNG,
IJ_HANDBLEED,
IJ_LEGBLEED,
IJ_TENDONCUT,
IJ_FINGERMISSING,
IJ_EYELIDSCRAPED,
IJ_EYEDESTROYED,
//
};

2
flag.c
View File

@ -361,6 +361,7 @@ int flagcausesloscalc(enum FLAG fid) {
case F_NIGHTVISRANGEMOD:
case F_PRONE:
case F_SEEINDARK:
case F_AWARENESS:
case F_VISRANGE:
case F_VISRANGEMOD:
return B_TRUE;
@ -388,6 +389,7 @@ int flagcausesredraw(lifeform_t *lf, enum FLAG fid) {
case F_SECRET:
case F_SEEINDARK:
case F_SEEINVIS:
case F_AWARENESS:
case F_SPRINTING:
case F_SLOWMOVE:
case F_TIRED:

65
io.c
View File

@ -1,6 +1,7 @@
#include <assert.h>
#include <ctype.h>
#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -1181,6 +1182,11 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
msg("^%c%s begin%s to turn to stone!",isplayer(lf) ? 'B' : 'n', lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_AWARENESS:
if (isplayer(lf)) {
msg("You can suddenly see out the back of your head!");
}
break;
case F_BLIND:
if (isplayer(lf)) {
msg("^WYou cannot see!");
@ -1748,6 +1754,11 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("The fragments of stone around %s%s body drop%s away.",lfname, getpossessive(lfname), isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_AWARENESS:
if (isplayer(lf)) {
msg("You can no longer see out the back of your head.");
}
break;
case F_BLIND:
msg("%s can see again.",lfname);
donesomething = B_TRUE;
@ -2911,14 +2922,14 @@ void centre(WINDOW *win, enum COLOUR col, int y, char *format, ... ) {
int chartodir(char c) {
switch (tolower(c)) {
case 'h': return DC_W;
case 'j': return DC_S;
case 'k': return DC_N;
case 'l': return DC_E;
case 'y': return DC_NW;
case 'u': return DC_NE;
case 'b': return DC_SW;
case 'n': return DC_SE;
case CH_TURN_W: case 'h': return DC_W;
case CH_TURN_N: case 'j': return DC_S;
case CH_TURN_S: case 'k': return DC_N;
case CH_TURN_E: case 'l': return DC_E;
case CH_TURN_NW: case 'y': return DC_NW;
case CH_TURN_NE: case 'u': return DC_NE;
case CH_TURN_SW: case 'b': return DC_SW;
case CH_TURN_SE: case 'n': return DC_SE;
}
return D_NONE;
}
@ -3677,6 +3688,9 @@ void describeob(object_t *o) {
case F_ATTRSET:
mvwprintw(mainwin, y, 0, "%s modifies your %s.", buf, getattrname(f->val[1])); y++;
break;
case F_AWARENESS:
mvwprintw(mainwin, y, 0, "%s grants you enhanced awareness.", buf); y++;
break;
case F_BLIND:
mvwprintw(mainwin, y, 0, "%s prevents you from seeing anything.", buf); y++;
break;
@ -6232,6 +6246,7 @@ void initgfx(void) {
noecho();
cbreak();
//raw();
nodelay(mainwin, FALSE);
getmaxyx(mainwin, SCREENH, SCREENW);
@ -6271,6 +6286,9 @@ void initgfx(void) {
snprintf(prevmsg, BUFLEN, "!nolastmessage!");
msgmulti = 1;
// handle sigstop (ctrl-y)
signal(SIGTSTP, handle_ctrl_y);
}
int drop(object_t *o, int count) {
@ -6743,7 +6761,6 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
int getkey(void) {
int key_code=0;
key_code = getch();
// XXX NEW CODE:
@ -6779,6 +6796,10 @@ enum COLOUR getskilllevelcolour(enum SKILLLEVEL slev) {
return C_GREY;
}
void handle_ctrl_y(int arg) {
ungetch(25); // put 'ctrl-y' char onto keyboard queue
}
void handleinput(void) {
int ch;
//char buf[BUFLEN];
@ -6969,7 +6990,9 @@ void handleinput(void) {
switch (tolower(ch)) {
case 'h': case 'j': case 'k': case 'l':
case 'y': case 'u': case 'b': case 'n':
break;
case CH_TURN_N: case CH_TURN_E: case CH_TURN_S: case CH_TURN_W:
case CH_TURN_NE: case CH_TURN_SE: case CH_TURN_SW: case CH_TURN_NW:
break;
default:
stoprunning(player);
if (hasactivespell(player, OT_S_SLIDE)) stopspell(player, OT_S_SLIDE);
@ -7004,6 +7027,24 @@ void handleinput(void) {
trymove(player, dir, B_TRUE, B_TRUE);
}
break;
// turn
case CH_TURN_N:
case CH_TURN_E:
case CH_TURN_S:
case CH_TURN_W:
case CH_TURN_NE:
case CH_TURN_SE:
case CH_TURN_SW:
case CH_TURN_NW:
dir = chartodir(ch);
if (dir != player->facing) {
if (getrelativedir(player, dir) != RD_FORWARDS) {
taketime(player, getturnspeed(player));
}
setfacing(player, dir);
drawscreen();
}
break;
case 's': // slowwalk
trysneak(player, D_NONE);
break;
@ -9136,6 +9177,10 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
}
if (lfhasknownflag(lf, F_AWARENESS)) {
mvwprintw(mainwin, y, 0, "%s can see things which are behind %s.", you(lf), you(lf));
y++;
}
f = lfhasknownflag(lf, F_MAGICARMOUR);
if (f && (f->known)) {

1
io.h
View File

@ -85,6 +85,7 @@ char getchoice(prompt_t *prompt);
char getchoicestr(prompt_t *prompt, int useshortcuts, int showlallatstart);
int getkey(void);
enum COLOUR getskilllevelcolour(enum SKILLLEVEL slev);
void handle_ctrl_y(int arg);
void handleinput(void);
void doheading(WINDOW *win, int *y, int x, char *what);
void doheadingsmall(WINDOW *win, int y, int x, char *format, char *heading);

166
lf.c
View File

@ -200,6 +200,14 @@ void bleed(lifeform_t *lf, int splatter) {
}
}
int bleedfrom(lifeform_t *lf, enum BODYPART bp, int splatter) {
if (willbleedfrom(lf, bp)) {
bleed(lf, splatter);
return B_FALSE;
}
return B_TRUE;
}
void breakgrabs(lifeform_t *lf, int fromme, int tome) {
flag_t *f;
lifeform_t *alf;
@ -6822,6 +6830,13 @@ int getthrowspeed(int str) {
return speed;
}
int getturnspeed(lifeform_t *lf) {
int speed;
speed = getmovespeed(lf) / 2;
limit(&speed, 1, NA);
return speed;
}
void getwantdistance(lifeform_t *lf, int *min, int *max, int attacking) {
flag_t *f;
@ -8523,7 +8538,6 @@ void initjobs(void) {
}
}
addflag(lastjob->flags, F_NOSCORE, B_TRUE, NA, NA, NULL);
addflag(lastjob->flags, F_ENHANCESMELL, 5, NA, NA, NULL);
addjob(J_ADVENTURER, "Adventurer");
// stats
@ -9016,7 +9030,7 @@ void initrace(void) {
flag_t *f;
objecttype_t *ot;
// race classes
addraceclass(RC_OTHER, "misc. creature", "miscellaneous creatures", SK_NONE);
addraceclass(RC_OTHER, "strange creature", "strange creatures", SK_NONE);
addraceclass(RC_ANIMAL, "animal", "animals and insects", SK_LORE_NATURE);
addraceclass(RC_AQUATIC, "aquatic creature", "aquatic creatures", SK_LORE_NATURE);
addraceclass(RC_DEMON, "demon", "demons", SK_LORE_DEMONS);
@ -11949,6 +11963,7 @@ int isaquatic(lifeform_t *lf) {
return B_FALSE;
}
// returns B_FALSE, B_TRUE, or B_FROMINJURY
int isbleeding(lifeform_t *lf) {
float hppct;
hppct = ((float)lf->hp / (float) lf->maxhp) * 100;
@ -11956,7 +11971,7 @@ int isbleeding(lifeform_t *lf) {
if (hppct <= 40) return B_TRUE;
if (lfhasflagval(lf, F_INJURY, NA, NA, DT_SLASH, NULL)) {
return B_TRUE;
return B_FROMINJURY;
}
return B_FALSE;
}
@ -13165,6 +13180,15 @@ void autotarget(lifeform_t *lf) {
}
}
int issmellablelf(lifeform_t *lf) {
if (lf->race->raceclass->id != RC_UNDEAD) {
return B_TRUE;
}
return B_FALSE;
}
int isswimming(lifeform_t *lf) {
if (!lf) return B_FALSE;
if (gamemode != GM_GAMESTARTED) {
@ -14198,21 +14222,25 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
if (noisemaker) {
enum SKILLLEVEL slev;
char lfname[BUFLEN];
char distbuf[BUFLEN];
char distbuf[BUFLEN],distbufbad[BUFLEN];
char dirbuf[BUFLEN];
int dir;
real_getlfnamea(noisemaker, lfname, B_FALSE);
if (dist >= 20) { // 20+
strcpy(distbuf, " far away");
strcpy(distbuf, " very far away");
strcpy(distbufbad, " far away");
} else if (dist >= 10) { // 10 - 19
strcpy(distbuf, "");
strcpy(distbuf, " far away");
} else if (dist >= 5) { // 5 - 9
strcpy(distbuf, " nearby");
strcpy(distbufbad, " nearby");
} else if (dist >= 2) { // 2 - 4
strcpy(distbuf, " very nearby");
strcpy(distbufbad, " nearby");
} else { // 1
strcpy(distbuf, " right beside you");
strcpy(distbufbad, " nearby");
}
dir = getdirtowards(l->cell, c, NULL, B_FALSE, DT_COMPASS);
@ -14244,6 +14272,9 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
} else if (slev >= PR_BEGINNER) {
msg("You hear %s%s%c", textnopunc, distbuf, punc);
rv = B_TRUE;
} else if (slev >= PR_NOVICE) {
msg("You hear %s%s%c", textnopunc, distbufbad, punc);
rv = B_TRUE;
} else {
assert(text);
msg("You hear %s", text);
@ -14624,7 +14655,7 @@ void precalclos_new(lifeform_t *lf) {
int numpixels;
//int db = B_FALSE;
enum SKILLLEVEL plev;
flag_t *missingeye,*enhancesmell;
flag_t *missingeye;
f = hasflag(lf->flags, F_XRAYVIS);
if (f) {
@ -14636,11 +14667,6 @@ void precalclos_new(lifeform_t *lf) {
// right eye missing?
missingeye = lfhasflagval(lf, F_INJURY, IJ_EYEDESTROYED, NA, NA, NULL);
// enhanced smell means we can "see" lifeforms and "smelly" objects in all
// directions.
enhancesmell = lfhasflag(lf, F_ENHANCESMELL);
los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
blocker = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
nlos = 0;
@ -14656,7 +14682,7 @@ void precalclos_new(lifeform_t *lf) {
nendcells = 0;
if (MAXOF(maxvisrange, nightvisrange) == 0) {
} else if (lf->facing == D_ALL) {
} else if (lfhasflag(lf, F_AWARENESS) || (lf->facing == D_ALL)) {
get_circular_fov_endpoints(lf, maxvisrange, endx, endy, &nendcells);
} else {
enum QUADRANT startq, endq,curq;
@ -14748,6 +14774,7 @@ void precalclos_new(lifeform_t *lf) {
assert(nlos < (MAX_MAPW * MAX_MAPH));
// deal with enhanced smell - do a second sweep in all directions.
/*
if (enhancesmell) {
int n;
get_circular_fov_endpoints(lf, enhancesmell->val[0], endx, endy, &nendcells);
@ -14771,6 +14798,7 @@ void precalclos_new(lifeform_t *lf) {
}
}
}
*/
// now fill in lifeform structure
lf->los = malloc(sizeof(cell_t *) * nlos);
@ -15705,7 +15733,8 @@ void initskills(void) {
addskilldesc(SK_FIRSTAID, PR_INEPT, "- Determines how long poison effects will last.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_ADEPT, "^gYou can now recognise when poison is potentially fatal.", B_TRUE);
addskill(SK_LISTEN, "Listen", "How good you are at hearing and interpreting sounds.", 200);
addskilldesc(SK_LISTEN, PR_BEGINNER, "^gYou now gauge the distance of sounds.", B_TRUE);
addskilldesc(SK_LISTEN, PR_NOVICE, "^gYou now gauge the distance of sounds.", B_TRUE);
addskilldesc(SK_LISTEN, PR_BEGINNER, "^gYou now more accurately gauge the distance of sounds.", B_TRUE);
addskilldesc(SK_LISTEN, PR_ADEPT, "^gYou can now determine the direction sounds are coming from.", B_TRUE);
addskilldesc(SK_LISTEN, PR_EXPERT, "^gYou can now identify monsters based on sound.", B_TRUE);
addskilldesc(SK_LISTEN, PR_MASTER, "^gYou can now locate monsters based on sound.", B_TRUE);
@ -16573,8 +16602,9 @@ void startlfturn(lifeform_t *lf) {
}
if (lfhasflagval(lf, F_INJURY, IJ_ARTERYPIERCE, NA, NA, NULL)) {
bleed(lf, B_SPLATTER);
losehp(lf, rnd(1,8), DT_DIRECT, NULL, "blood loss");
if (!bleedfrom(lf, BP_HANDS, B_SPLATTER)) {
losehp(lf, rnd(1,8), DT_DIRECT, NULL, "blood loss");
}
}
// get more hungry
@ -16616,6 +16646,43 @@ void startlfturn(lifeform_t *lf) {
}
}
// sixth sense spell warnings
f = hasactivespell(lf, OT_S_SIXTHSENSE);
if (f) {
cell_t *retcell[MAXCANDIDATES];
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)) {
int dir,reldir;
dir = getdirtowards(lf->cell, retcell[i], NULL, B_FALSE, DT_ORTH);
reldir = getrelativedir(lf, dir);
if (reldir != RD_FORWARDS) {
if (isplayer(lf)) {
if (f->val[2] >= 5) {
char buf[BUFLEN];
getlfname(retcell[i]->lf, buf);
warn("^WYour sixth sense warns you of %s %s you!", buf,
(reldir == RD_BACKWARDS) ? "behind" : "beside" );
} else if (f->val[2] >= 3) {
warn("^WYour sixth sense warns you of %s %s %s you!",
needan(retcell[i]->lf->race->raceclass->name) ? "an" : "a",
retcell[i]->lf->race->raceclass->name,
(reldir == RD_BACKWARDS) ? "behind" : "beside" );
} else {
warn("^WYour sixth sense warns you of something %s you!",
(reldir == RD_BACKWARDS) ? "behind" : "beside" );
}
more();
}
stopspell(lf, OT_S_SIXTHSENSE);
break;
}
}
}
}
if (hasactivespell(lf, OT_S_SUMMONWEAPON) && !hasobwithflagval(lf->pack, F_CREATEDBYSPELL, OT_S_SUMMONWEAPON, NA, NA, NULL)) {
stopspell(lf, OT_S_SUMMONWEAPON);
}
@ -18661,16 +18728,16 @@ int wear(lifeform_t *lf, object_t *o) {
enum BODYPART bp;
flag_t *retflag[MAXCANDIDATES];
int nretflags;
int showpos = B_FALSE;
// this might impact your AR
if (isplayer(lf)) {
statdirty = B_TRUE;
}
getobname(o, obname, 1);
// check for already equipped first!
// check if it is already equipped first!
f = hasflag(o->flags, F_EQUIPPED);
if (f) {
if (isplayer(lf)) {
@ -18686,7 +18753,7 @@ int wear(lifeform_t *lf, object_t *o) {
// metal objects and magshield?
if (lfhasflag(lf, F_MAGSHIELD)) {
if (isplayer(lf)) {
msg("^wYour %s evades your grasp!", noprefix(buf));
msg("^wYour %s evades your grasp!", noprefix(obname));
}
return B_TRUE;
}
@ -18712,13 +18779,45 @@ int wear(lifeform_t *lf, object_t *o) {
bp = possbp[0];
} else { // multiple possible locations
int i;
// go in first possible place
bp = BP_NONE;
for (i = 0; i < nparts; i++) {
if (!hasobwithflagval(lf->pack, F_EQUIPPED, possbp[i], NA, NA, NULL)) {
bp = possbp[i];
break;
showpos = B_TRUE;
// rings go in first possible place
if (o->type->obclass->id == OC_RING) {
bp = BP_NONE;
for (i = 0; i < nparts; i++) {
if (!hasobwithflagval(lf->pack, F_EQUIPPED, possbp[i], NA, NA, NULL)) {
bp = possbp[i];
break;
}
}
if ((bp == BP_NONE) && isplayer(lf)) msg("You have no room to wear that.");
} else {
char ch = 'a';
// ask where to put it
snprintf(buf, BUFLEN, "Where will you wear %s?",obname);
initprompt(&prompt, buf);
for (i = 0; i < nparts; i++) {
object_t *inway;
inway = getequippedob(lf->pack, possbp[i]);
if (inway) {
char inwayname[BUFLEN];
getobname(inway, inwayname, inway->amt);
snprintf(buf, BUFLEN, "%s (replace %s)", getbodypartname(possbp[i]), inwayname);
} else {
snprintf(buf, BUFLEN, "%s", getbodypartname(possbp[i]));
}
addchoice(&prompt, ch++, buf, NULL, &possbp[i]);
}
addchoice(&prompt, '-', "(cancel)", NULL, NULL);
ch = getchoice(&prompt);
if (ch == '-') {
bp = BP_NONE;
if (isplayer(lf)) msg("Cancelled.");
} else bp = *((enum BODYPART *)prompt.result);
}
if (bp == BP_NONE) {
if (isplayer(lf)) {
@ -18859,7 +18958,11 @@ int wear(lifeform_t *lf, object_t *o) {
if ((gamemode == GM_GAMESTARTED) && lf->created) {
if (isplayer(lf)) {
msg("You are now wearing %s.", obname);
if (showpos) {
msg("You are now wearing %s (%s your %s).", obname, getbodypartequipname(bp), getbodypartname(bp));
} else {
msg("You are now wearing %s.", obname);
}
} else if (cansee(player, lf)) {
getlfname(lf, buf);
capitalise(buf);
@ -19192,6 +19295,17 @@ int weild(lifeform_t *lf, object_t *o) {
return B_FALSE;
}
int willbleedfrom(lifeform_t *lf, enum BODYPART bp) {
object_t *o;
o = getequippedob(lf->pack, bp);
if (o && (o->type->id == OT_BANDAGE)) {
// don't bleed.
return B_FALSE;
}
return B_TRUE;
}
// will the lf flee after taking damage?
int willflee(lifeform_t *lf) {
enum ATTRBRACKET iqb;

4
lf.h
View File

@ -22,6 +22,7 @@ void autoweild(lifeform_t *lf);
int appearsrandomly(enum RACE rid);
void awardxpfor(lifeform_t *killed, float pct);
void bleed(lifeform_t *lf, int splatter);
int bleedfrom(lifeform_t *lf, enum BODYPART bp, int splatter);
void breakgrabs(lifeform_t *lf, int fromme, int tome);
long calcscore(lifeform_t *lf);
int calcxp(lifeform_t *lf);
@ -203,6 +204,7 @@ char *getskilldesc(enum SKILL id );
char *getskillname(enum SKILL id );
char *getskilllevelname(enum SKILLLEVEL sl);
int getthrowspeed(int str);
int getturnspeed(lifeform_t *lf);
void getwantdistance(lifeform_t *lf, int *min, int *max, int attacking);
object_t *getweapon(lifeform_t *lf);
long getxpforlev(int level);
@ -267,6 +269,7 @@ int isprone(lifeform_t *lf);
flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt);
flag_t *isresting(lifeform_t *lf);
object_t *isstuck(lifeform_t *lf);
int issmellablelf(lifeform_t *lf);
int isswimming(lifeform_t *lf);
int isundead(lifeform_t *lf);
flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt);
@ -358,5 +361,6 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose);
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 willflee(lifeform_t *lf);
//int youhear(cell_t *c, char *text);

74
map.c
View File

@ -4532,19 +4532,13 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
int nretflags;
int i;
// handle scanner
f = lfhasflag(player, F_DETECTLIFE);
if (f) {
if (c->lf) {
if (c->lf) {
f = lfhasflag(player, F_DETECTLIFE);
if (f) {
if (getcelldistorth(player->cell, c) <= f->val[0]) {
*thing = c->lf;
if (f->val[1] == B_TRUE) {
if (desc) {
real_getlfnamea(c->lf, desc, B_FALSE);
strcat(desc, " (detected)");
}
if (glyph) {
*glyph = *(getlfglyph(c->lf));
}
set_scanned_glyph(TT_MONSTER, c->lf, " (detected)", desc, glyph);
} else {
if (desc) {
char *p;
@ -4560,7 +4554,22 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
return TT_MONSTER;
}
}
f = lfhasflag(player, F_ENHANCESMELL);
if (f && issmellablelf(c->lf)) {
if (getcelldistorth(player->cell, c) <= f->val[0]) {
set_scanned_glyph(TT_MONSTER, c->lf, " (smelled)", desc, glyph);
*thing = c->lf;
return TT_MONSTER;
}
}
if (lfhasflagval(player, F_CANHEARLF, c->lf->id, NA, NA, NULL)) {
// can hear them using master level listen skill?
set_scanned_glyph(TT_MONSTER, c->lf, " (heard)", desc, glyph);
*thing = c->lf;
return TT_MONSTER;
}
}
f = lfhasflag(player, F_DETECTMETAL);
if (f) {
if (getcelldistorth(player->cell, c) <= f->val[0]) {
@ -4587,30 +4596,17 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
}
}
}
}
} // end if hasflag detectmetal
// can hear them using master level listen skill?
if (c->lf && lfhasflagval(player, F_CANHEARLF, c->lf->id, NA, NA, NULL)) {
if (glyph) {
*glyph = *(getlfglyph(c->lf));
}
if (desc) {
real_getlfnamea(c->lf, desc, B_FALSE);
strcat(desc, " (heard)");
}
*thing = c->lf;
return TT_MONSTER;
}
// get list of all detected ob ids.
getflags(player->flags, retflag, &nretflags, F_DETECTOBS, F_NONE);
getflags(player->flags, retflag, &nretflags, F_DETECTOBS, F_ENHANCESMELL, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (getcelldistorth(player->cell, c) <= f->val[0]) {
object_t *o;
for (o = c->obpile->first ; o ; o = o->next) {
if ((f->val[1] == NA) || (o->type->id == f->val[1])) {
if ((f->id == F_DETECTOBS) && ((f->val[1] == NA) || (o->type->id == f->val[1]))) {
if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_DOOR)) {
*thing = o;
if (glyph) {
@ -4626,6 +4622,10 @@ 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;
}
}
}
@ -5089,6 +5089,28 @@ int remove_deadends(map_t *m, int howmuch) {
return count;
}
void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph) {
if (targettype == TT_MONSTER) {
if (desc) {
real_getlfnamea((lifeform_t *)what, desc, B_FALSE);
strcat(desc, descappend);
}
if (glyph) {
*glyph = *(getlfglyph((lifeform_t *) what));
}
} else if (targettype == TT_OBJECT) {
object_t *o;
o = (object_t *)what;
if (desc) {
getobname(o, desc, o->amt);
strcat(desc, descappend);
}
if (glyph) {
*glyph = *(getglyph(o));
}
}
}
void setcellknown(cell_t *cell, int forcelev) {
enum SKILLLEVEL slev;

1
map.h
View File

@ -121,6 +121,7 @@ void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);
void mapentereffects(map_t *m);
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob);
int remove_deadends(map_t *m, int howmuch);
void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph);
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);

53
move.c
View File

@ -346,13 +346,26 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
}
enum RELATIVEDIR getrelativedir(lifeform_t *lf, int dir) {
int diff;
diff = abs(lf->facing - dir);
if (diff <= 1) {
return RD_FORWARDS;
} else if (diff == 2) {
return RD_SIDEWAYS;
}
int tempdir;
// facing N, dir N == forwards
if (lf->facing == dir) return RD_FORWARDS;
// facing N, dir NE == forwards
tempdir = lf->facing + 1; if (tempdir > DC_NW) tempdir -= MAXDIR_COMPASS;
if (tempdir == dir) return RD_FORWARDS;
// facing N, dir NW == forwards
tempdir = lf->facing - 1; if (tempdir < DC_N) tempdir += MAXDIR_COMPASS;
if (tempdir == dir) return RD_FORWARDS;
// facing N, dir E == sideways
tempdir = lf->facing + 2; if (tempdir > DC_NW) tempdir -= MAXDIR_COMPASS;
if (tempdir == dir) return RD_SIDEWAYS;
// facing N, dir W == sideways
tempdir = lf->facing - 2; if (tempdir < DC_N) tempdir += MAXDIR_COMPASS;
if (tempdir == dir) return RD_SIDEWAYS;
// anything else is backwards
return RD_BACKWARDS;
}
@ -897,8 +910,9 @@ int moveeffects(lifeform_t *lf) {
if (isbleeding(lf)) {
if (lfhasflagval(lf, F_INJURY, NA, BP_LEGS, DT_SLASH, NULL)) {
bleed(lf, B_FALSE);
losehp(lf, 1, DT_DIRECT, NULL, "blood loss");
if (!bleedfrom(lf, BP_LEGS, B_FALSE)) {
losehp(lf, 1, DT_DIRECT, NULL, "blood loss");
}
} else {
if (rnd(1,2) == 1) {
bleed(lf, B_FALSE);
@ -2156,18 +2170,21 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
int moveok;
int rndmove = B_FALSE;
int howlong;
int reldir;
flag_t *f;
howlong = getmovespeed(lf);
reldir = getrelativedir(lf, dir);
// if the given dir is behind us, just turn.
if (onpurpose && !strafe) {
// if the given dir is behind us, just turn.
if (getrelativedir(lf, dir) != RD_FORWARDS) {
howlong /= 2;
limit(&howlong, 1, NA);
setfacing(lf, dir);
taketime(lf, howlong);
return B_FALSE;
if (reldir != RD_FORWARDS) {
if (!lfhasflag(lf, F_AWARENESS)) {
setfacing(lf, dir);
taketime(lf, getturnspeed(lf));
return B_FALSE;
}
}
}
@ -2258,8 +2275,8 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
moveto(lf, cell, rndmove ? B_FALSE : onpurpose, dontclearmsg);
if (onpurpose) {
// strafing sideways/backwards takes longer
if (strafe) {
switch (getrelativedir(lf, dir)) {
if (strafe && !lfhasflag(lf, F_AWARENESS)) {
switch (reldir) {
case RD_SIDEWAYS: howlong = pctof(125, howlong); break;
case RD_BACKWARDS: howlong = pctof(150, howlong); break;
case RD_FORWARDS:

28
nexus.c
View File

@ -250,13 +250,13 @@ int main(int argc, char **argv) {
// extra choices for some jobs
if (j->id == J_WIZARD) {
skill_t *sk;
initprompt(&prompt, "Select your spell specialty:");
initprompt(&prompt, "Select your primary spell specialty:");
addchoice(&prompt, 'a', getskillname(SK_SS_AIR), NULL, findskill(SK_SS_AIR));
addchoice(&prompt, 'c', getskillname(SK_SS_COLD), NULL, findskill(SK_SS_COLD));
addchoice(&prompt, 'f', getskillname(SK_SS_FIRE), NULL, findskill(SK_SS_FIRE));
getchoice(&prompt);
sk = (skill_t *) prompt.result;
giveskill(player, sk->id);
giveskilllev(player, sk->id, PR_BEGINNER);
switch (sk->id) {
case SK_SS_AIR:
addflag(player->flags, F_CANCAST, OT_S_MIST, NA, NA, NULL);
@ -270,6 +270,30 @@ int main(int argc, char **argv) {
default:
break;
}
initprompt(&prompt, "Select your secondary spell school:");
addchoice(&prompt, 'd', getskillname(SK_SS_DIVINATION), NULL, findskill(SK_SS_DIVINATION));
addchoice(&prompt, 'm', getskillname(SK_SS_MODIFICATION), NULL, findskill(SK_SS_MODIFICATION));
addchoice(&prompt, 's', getskillname(SK_SS_SUMMONING), NULL, findskill(SK_SS_SUMMONING));
addchoice(&prompt, 't', getskillname(SK_SS_TRANSLOCATION), NULL, findskill(SK_SS_TRANSLOCATION));
getchoice(&prompt);
sk = (skill_t *) prompt.result;
giveskilllev(player, sk->id, PR_NOVICE);
switch (sk->id) {
case SK_SS_DIVINATION:
addflag(player->flags, F_CANCAST, OT_S_SIXTHSENSE, NA, NA, NULL);
break;
case SK_SS_MODIFICATION:
addflag(player->flags, F_CANCAST, OT_S_HOLDPORTAL, NA, NA, NULL);
break;
case SK_SS_SUMMONING:
addflag(player->flags, F_CANCAST, OT_S_FLOATINGDISC, NA, NA, NULL);
break;
case SK_SS_TRANSLOCATION:
addflag(player->flags, F_CANCAST, OT_S_APPORTATION, NA, NA, NULL);
break;
default:
break;
}
}

134
objects.c
View File

@ -6465,7 +6465,6 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_VILLAGE, 100, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small puddle of water");
modflag(lastot->flags, F_HASHIDDENNAME, NA, NA, NA, "clear potion");
addot(OT_POT_HEALING, "potion of healing", "Restores 10-20 health to whoever drinks it.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL);
@ -6552,6 +6551,14 @@ void initobjects(void) {
// scrolls
addot(OT_SCR_AWARENESS, "scroll of awareness", "Mimics the effects of a 'heightened awareness' spell.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_LINKSPELL, OT_S_AWARENESS, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addot(OT_SCR_CANINETRACKING, "scroll of canine tracking", "Mimics the effects of a 'canine tracking' spell.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_LINKSPELL, OT_S_CANINETRACKING, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addot(OT_SCR_REMOVECURSE, "scroll of remove curse", "Removes curses from all weilded equipment.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
@ -6638,6 +6645,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addot(OT_SCR_TURNUNDEAD, "scroll of turn undead", "Instills fear in undead creatures.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, RR_UNCOMMON, NULL);
@ -6797,30 +6805,45 @@ void initobjects(void) {
// divination
///////////////////
// l1
addot(OT_S_DETECTLIFE, "detect life", "Senses the size of creatures near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the detection range.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power VI, exact creatures types are detected.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
// l2
addot(OT_S_LOCATEOBJECT, "locate object", "Locates any object within an area the caster has previously travelled.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addot(OT_S_SIXTHSENSE, "sixth sense", "Warns the caster of any creature attempting to sneak up behind them.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power III, the creature's species will be detected.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V, the exact creature type will be detected.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL);
// l2
addot(OT_S_CANINETRACKING, "canine tracking", "Enhances the caster's sense of smell, allowing them to detect exact scents within a 3 cell radius.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Power determines the spell duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addot(OT_S_MAPPING, "sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the detection range.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addot(OT_S_DETECTLIFE, "detect life", "Senses the size of creatures within a 10-cell radius of the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the detection range.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power VIII, exact creatures types are detected.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
// l3
addot(OT_S_AWARENESS, "heightened awareness", "This spell effectively gives the caster \"eyes in the back of their head\", expending their field of vision to a full 360 degrees.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addot(OT_S_DETECTOBS, "detect objects", "Senses objects near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the detection range and spell duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addot(OT_S_SEEINVIS, "see invisible", "Allows the caster to see invisible creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addot(OT_S_DETECTOBS, "detect objects", "Senses objects near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the detection range and spell duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
// l4
addot(OT_S_DETECTAURA, "detect aura", "Senses holiness or evil near the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
@ -7584,6 +7607,12 @@ void initobjects(void) {
///////////////////
// translocation
///////////////////
// l1
addot(OT_S_APPORTATION, "apportation", "Instantly transports a single visible object up to 10kg in weight to the caster's pack.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l2
addot(OT_S_BLINK, "blink", "Teleports the caster to a random location within view.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power VI you can choose where to blink to.");
@ -7879,6 +7908,12 @@ void initobjects(void) {
addflag(lastot->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
// tools
addot(OT_BANDAGE, "bandage", "A small medical bandage. When worn, it will counteract bleeding.", MT_CLOTH, 0.5, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
addot(OT_BLANKET, "wool blanket", "A warm wool blanket for those cold winter nights.", MT_CLOTH, 2, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 10, NA, NA, NULL);
@ -8210,6 +8245,12 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, 5, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_STYPTIC, "styptic", "A medical compound designed to inhibit bleeding.", MT_METAL, 0.5, OC_TECH, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
// tech - l3
@ -8259,8 +8300,6 @@ void initobjects(void) {
// tech - l6 ???
// misc
addot(OT_BONE, "bone", "A bone from an unknown creature.", MT_BONE, 0.1, OC_MISC, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
@ -8908,10 +8947,10 @@ void initobjects(void) {
addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL);
addflag(lastot->flags, F_OBHP, 60, 60, NA, NULL);
addot(OT_FLAKJACKET, "flak jacket", "Heavy metal body armour. Designed to stop a bullet, but only once.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM);
addot(OT_FLAKJACKET, "flak jacket", "Heavy metal body armour. Designed to stop a bullet, but ineffective against melee attacks.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 10, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 10, 10, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 10, NA, NULL);
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
@ -10471,6 +10510,13 @@ flag_t *isshield(object_t *o) {
return hasflag(o->flags, F_SHIELD);
}
int issmellableob(object_t *o) {
if (hasflag(o->flags, F_SMELLY)) {
return B_TRUE;
}
return B_FALSE;
}
int isthrownmissile(object_t *o) {
if (hasflag(o->flags, F_THROWMISSILE)) {
return B_TRUE;
@ -10900,6 +10946,7 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
object_t *o, *existob;
int i,preburdened = B_FALSE;
int db = B_FALSE;
int redrawaftermove = B_FALSE;
flag_t *f;
reason = E_OK;
@ -10932,6 +10979,16 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
preburdened = isburdened(dst->owner);
}
// is the object moving FROM a cell that the player can see?
if (src->pile->where && haslos(player, src->pile->where)) {
if ((src->pile->where->lf) && !cansee(player, src->pile->where->lf)) {
redrawaftermove = B_TRUE;
} else {
redrawaftermove = B_TRUE;
}
}
if (db) dblog("DB: moveob() - moving %d x %s",howmany, src->type->name);
if (stackok) {
existob = canstackob(dst, src);
@ -11016,7 +11073,11 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
}
}
if (o && dst->where && !hasflag(o->flags, F_NOGLYPH) && haslos(player, dst->where)) {
if (redrawaftermove) {
needredraw = B_TRUE;
drawscreen();
} else if (o && !hasflag(o->flags, F_NOGLYPH) && dst->where && haslos(player, dst->where)) {
// the object is moving to a cell that the player can see
if ((dst->where->lf) && !cansee(player, dst->where->lf)) {
// we can see the floor here
// someone invisible there who we can't see
@ -11028,7 +11089,8 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
needredraw = B_TRUE;
drawscreen();
}
}
}
// special effects when an object moves
f = hasflag(o->flags, F_SHOPITEM);
@ -12305,6 +12367,41 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
if (!donesomething) {
if (isplayer(lf)) msg("There is nothing to use your spanner on there!");
}
} else if (o->type->id == OT_STYPTIC) {
flag_t *retflag[MAXCANDIDATES];
int i,nretflags = 0;
int donesomething = B_FALSE;
getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE);
for (i = 0;i < nretflags; i++) {
switch (f->id) {
case IJ_ARTERYPIERCE:
case IJ_CHESTBLEED:
case IJ_HAMSTRUNG:
case IJ_HANDBLEED:
case IJ_LEGBLEED:
case IJ_EYELIDSCRAPED:
donesomething = B_TRUE;
killflag(f);
break;
default: break;
}
}
// fix bleeding too?
if (isbleeding(lf) == B_TRUE) {
donesomething = B_TRUE;
while (isbleeding(lf) == B_TRUE) {
gainhp(lf, 1);
}
}
if (donesomething) {
if (isplayer(lf)) msg("^gThe styptic has stopped your wounds from bleeding.");
removeob(o, 1);
taketime(lf, getactspeed(lf));
} else {
if (isplayer(lf)) msg("You are not bleeding right now.");
}
} else if (o->type->id == OT_TELEPAD) {
map_t *m;
cell_t *c,*dst = NULL;
@ -12887,7 +12984,6 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
}
break;
case OT_POT_RUM:
// kill coffee flags
killtransitoryflags(lf->flags, F_CAFFEINATED);
if (lfhasflag(lf, F_CAFFEINATED)) {

View File

@ -180,6 +180,7 @@ int isreadable(object_t *o);
int isrotting(object_t *o);
flag_t *issecretdoor(object_t *o);
flag_t *isshield(object_t *o);
int issmellableob(object_t *o);
int isthrownmissile(object_t *o);
int istried(object_t *o);
int istriedot(objecttype_t *ot);

78
spell.c
View File

@ -2314,6 +2314,74 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
fizzle(caster);
}
} else if (spellid == OT_S_APPORTATION) {
int failed = B_FALSE;
float maxweight;
// if no target object...
if (!targob) {
// ask for a target cell (to take objects from)
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE;
if (targcell->obpile->first) {
// select object from cell...
targob = askobject(targcell->obpile, "Target which object", NULL, AO_NONE);
if (!targob) {
failed = B_TRUE;
}
} else {
failed = B_TRUE;
}
}
if (!failed) {
char obname[BUFLEN];
cell_t *obloc;
obloc = getoblocation(targob);
getobname(targob, obname, 1);
targcell = caster->cell;
// not liftable?
if (hasflag(targob->flags, F_NOPICKUP)) {
if (isplayer(caster)) {
nothinghappens();
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
return B_FALSE;
}
// modify by power
maxweight = 10;
if (getobweight(targob) > maxweight) {
if (haslos(player, obloc)) {
msg("%s fades out of view slightly, then reappears.",obname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
return B_FALSE;
}
if (moveob(targob, caster->pack, 1)) {
if (isplayer(caster)) {
msg("%s appears in your pack!", obname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, obloc)) {
msg("%s vanishes!", obname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
failed = B_TRUE;
}
}
if (failed) {
fizzle(caster);
}
} else if (spellid == OT_S_AWARENESS) {
flag_t *f;
f = addtempflag(caster->flags, F_AWARENESS, B_TRUE, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
} else if (spellid == OT_S_BAFFLE) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
@ -2517,6 +2585,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (cansee(player, caster)) {
needredraw = B_TRUE;
}
} else if (spellid == OT_S_CANINETRACKING) {
int howlong;
howlong = getspellduration(20,30,blessed) + (power*10);
addtempflag(caster->flags, F_ENHANCESMELL, 4, NA, NA, NULL, howlong);
} else if (spellid == OT_S_CONFISCATE) {
char ch = 'a';
char obname[BUFLEN];
@ -3484,7 +3556,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int howlong,radius;
howlong = getspellduration(10,20,blessed) + (power*2);
radius = power * 10;
addtempflag(target->flags, F_DETECTLIFE, 10, (power >= 5) ? B_TRUE : NA, NA, NULL, howlong);
addtempflag(target->flags, F_DETECTLIFE, 10, (power >= 8) ? B_TRUE : NA, NA, NULL, howlong);
} else {
// monsters can't use this
}
@ -6646,6 +6718,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!shattercell(targcell, caster, buf)) {
fizzle(caster);
}
} else if (spellid == OT_S_SIXTHSENSE) {
if (isplayer(caster)) {
msg("You will now be warned of creatures behind you.");
}
} else if (spellid == OT_S_SLEEP) {
int howlong;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;