* [+] operate a candlabrum on the ground confers permenant light
producing! * [+] bug - water appearing in walls. - [+] make armour less common in forests - [+] too many --more--s when enhancing stats. use drawmsg() rather than more(). - [+] when i go up/down stairs, i keep ending up BESIDE them?? * [+] "you hear footstepszzzzzzzzzzzzzzzzzzzzzzz" (random junk) - [+] when i start training with a spell active, it gets interrupted. try again, interrupted again! works 3rd time. - [+] replace lockpicking with "locksmithing" - [+] replace 'body control' with 'slow metabolism' - [+] pit traps broken - fixed now. - [+] doheading issue in @M still. * [+] how did zombie get 28 hp? bug in rollhitdice. - [+] blind a skeleton with light. it gets blind, starts fleeing. but because it can't SEE you, it stops fleeing instantly! * [+] getflags(flagpile_t *fp, ... ) - [+] stun spell - [+] only say "x2" etc if msgbuf we are going to draw still contains the original text. - [+] when you level up, your psionic skill determines your chance of learning a new psionic spell? - [+] when you teleport/use stairs, get all allies in SIGHT, not adjacent. * [+] more traps! * [+] prisoners in cells - [+] recruitment: instead of outright refusing to join, just up the price. * [+] make spellbook contents depend on map difficulty - [+] cloak of shadows - give invisibility when in darkness * [+] limited wish: - [+] casting WISH reduces max hp by 50%! - [+] monster ai code: if inventory full (or close), put non-eqiupped stuff into containers * [+] infinite loop in firedam to lf - [+] pot of xp isn't working for monsters. they get no more hp!! - [+] summonmosnter should jsut relocate existing uniques - [+] 'planeshift' spell for gods - "unsummon"s them. * [+] diety - greedgod * [+] more village contents
This commit is contained in:
parent
ce878f6ae8
commit
07844bb69e
56
ai.c
56
ai.c
|
@ -603,7 +603,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
|
|||
} else {
|
||||
// spell succesful
|
||||
|
||||
if (spell == OT_A_STEAL) {
|
||||
if ((spell == OT_A_STEAL) && !lfhasflag(lf, F_NOFLEE)) {
|
||||
// run away for a few turns
|
||||
fleefrom(lf, spelllf, rnd(3,7), B_TRUE);
|
||||
}
|
||||
|
@ -800,7 +800,7 @@ int aipickup(lifeform_t *lf, object_t *o) {
|
|||
if (isedible(o)) {
|
||||
return eat(lf, o);
|
||||
} else {
|
||||
return pickup(lf, o, o->amt, B_TRUE);
|
||||
return pickup(lf, o, o->amt, B_TRUE, B_TRUE);
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -918,6 +918,53 @@ void aiturn(lifeform_t *lf) {
|
|||
// use items, talk,etc
|
||||
///////////////////////////////////////////////
|
||||
|
||||
if ((lf->race->id == R_PRISONER) && master && isplayer(master) && cansee(lf, master)) {
|
||||
if (isoutdoors(lf->cell->map) && pctchance(20)) {
|
||||
object_t *o;
|
||||
say(lf, "Thanks for getting me out!", SV_TALK);
|
||||
o = addob(master->pack, "manual");
|
||||
if (o) {
|
||||
char obname[BUFLEN];
|
||||
say(lf, "Here, let me teach you something as a reward.", SV_TALK);
|
||||
getobname(o, obname, o->amt);
|
||||
msgnocap("%c - %s", o->letter, obname);
|
||||
}
|
||||
killflagsofid(lf->flags, F_PETOF);
|
||||
}
|
||||
}
|
||||
|
||||
// too many objects?
|
||||
i = countobs(lf->pack, B_FALSE);
|
||||
if (i >= (MAXPILEOBS - 5)) {
|
||||
object_t *container;
|
||||
// get largest container with space
|
||||
container = getbestcontainer(lf->pack);
|
||||
if (container) {
|
||||
object_t *o;
|
||||
// find object which will fit
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
if ((o != container) && !isequipped(o) && obfits(o, container->contents)) {
|
||||
// put it in.
|
||||
moveob(o, container->contents, ALL);
|
||||
if (cansee(player, lf)) {
|
||||
char obname[BUFLEN];
|
||||
char lfname[BUFLEN];
|
||||
char containername[BUFLEN];
|
||||
// announce
|
||||
getobname(o, obname, o->amt);
|
||||
getobname(container, containername, 1);
|
||||
getlfname(lf, lfname);
|
||||
msg("%s puts %s into %s.", lfname, obname, containername);
|
||||
}
|
||||
// timetime
|
||||
taketime(lf, getactspeed(lf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// talking
|
||||
f = lfhasflag(lf, F_RANDOMTALKPCT);
|
||||
if (f) {
|
||||
|
@ -1572,6 +1619,11 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
|
|||
if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) {
|
||||
specificcheckok = B_FALSE;
|
||||
}
|
||||
if ((ot->id == OT_A_STEAL) || (ot->id == OT_S_CONFISCATE)) {
|
||||
if (!countobs(victim->pack, B_FALSE)) {
|
||||
specificcheckok = B_FALSE;
|
||||
}
|
||||
}
|
||||
if ((ot->id == OT_A_SWOOP) || (ot->id == OT_A_CHARGE)) {
|
||||
flag_t *willflag;
|
||||
flag_t *srflag;
|
||||
|
|
28
attack.c
28
attack.c
|
@ -84,8 +84,10 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty
|
|||
actualdam *= multiplier;
|
||||
}
|
||||
|
||||
// actually apply the damage to the armour
|
||||
damtaken = takedamage(armour,actualdam, damtype);
|
||||
if (actualdam > 0) {
|
||||
// actually apply the damage to the armour
|
||||
damtaken = takedamage(armour,actualdam, damtype);
|
||||
}
|
||||
}
|
||||
return damtaken;
|
||||
}
|
||||
|
@ -351,15 +353,15 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
} else if (attacktype == AT_OB) {
|
||||
if (attackob(lf, (object_t *)attacktarget, wep[i], damflag[i])) break;
|
||||
}
|
||||
}
|
||||
attacksdone++;
|
||||
attacksdone++;
|
||||
|
||||
// stop attacking if they somehow got out of range
|
||||
// (eg. dodging)
|
||||
if (attacktype == AT_LF) {
|
||||
if (getcelldist(lf->cell, ((lifeform_t *)attacktarget)->cell) > 1) {
|
||||
attacksdone = maxattacks;
|
||||
break;
|
||||
// stop attacking if they somehow got out of range
|
||||
// (eg. dodging)
|
||||
if (attacktype == AT_LF) {
|
||||
if (getcelldist(lf->cell, ((lifeform_t *)attacktarget)->cell) > 1) {
|
||||
attacksdone = maxattacks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -789,7 +791,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
|
|||
}
|
||||
} else if (lfhasflag(lf, F_QUIVERINGPALM)) {
|
||||
// victim explodes!
|
||||
losehp_real(victim, victim->hp, DT_EXPLOSIVE, lf, "a quivering palm strike", B_FALSE);
|
||||
losehp_real(victim, victim->hp, DT_EXPLOSIVE, lf, "a quivering palm strike", B_FALSE, NULL);
|
||||
} else {
|
||||
char attackername2[BUFLEN];
|
||||
real_getlfname(lf, attackername2, B_FALSE);
|
||||
|
@ -805,7 +807,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
|
|||
strcpy(buf, attackername2);
|
||||
}
|
||||
|
||||
losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE);
|
||||
losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, NULL);
|
||||
|
||||
// victim's armour loses hp
|
||||
if (reduceamt) {
|
||||
|
@ -850,7 +852,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
|
|||
char lfname[BUFLEN];
|
||||
dam = rolldie(f->val[0], f->val[1]) + f->val[2];
|
||||
real_getlfname(lf, lfname, B_FALSE);
|
||||
losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE);
|
||||
losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE, NULL);
|
||||
if (isplayer(victim) || cansee(player, victim)) {
|
||||
msg("^%c%s bites %s!", isplayer(victim) ? 'b' : 'n', lfname, victimname);
|
||||
}
|
||||
|
|
29
defs.h
29
defs.h
|
@ -47,6 +47,8 @@ enum NOISECLASS {
|
|||
|
||||
enum SAYPHRASE {
|
||||
SP_BEG,
|
||||
SP_BEGATTACK,
|
||||
SP_BEGTHANKS,
|
||||
SP_DRUNK,
|
||||
SP_PAYWARN,
|
||||
SP_PAYTHREAT,
|
||||
|
@ -641,6 +643,7 @@ enum RACECLASS {
|
|||
RC_ANIMAL,
|
||||
RC_AQUATIC,
|
||||
RC_DEMON,
|
||||
RC_GOD,
|
||||
RC_HUMANOID,
|
||||
RC_INSECT,
|
||||
RC_SLIME,
|
||||
|
@ -659,7 +662,10 @@ enum RACE {
|
|||
R_BANDIT,
|
||||
R_BEGGAR,
|
||||
R_DRUNK,
|
||||
R_PRISONER,
|
||||
R_TOWNGUARD,
|
||||
// gods
|
||||
R_GODGREED,
|
||||
// monsters
|
||||
R_BEHOLDER,
|
||||
R_BUGBEAR,
|
||||
|
@ -841,14 +847,20 @@ enum OBTYPE {
|
|||
// terrain
|
||||
OT_WATERDEEP,
|
||||
// traps
|
||||
OT_TRAPALARM,
|
||||
OT_TRAPARROW,
|
||||
OT_TRAPARROWP,
|
||||
OT_TRAPEBLAST,
|
||||
OT_TRAPFIRE,
|
||||
OT_TRAPGAS,
|
||||
OT_TRAPMINE,
|
||||
OT_TRAPNEEDLEP,
|
||||
OT_TRAPPIT,
|
||||
OT_TRAPROCK,
|
||||
OT_TRAPSUMMON,
|
||||
OT_TRAPTELEPORT,
|
||||
OT_TRAPTRIP,
|
||||
OT_TRAPWIND,
|
||||
// rocks / plants
|
||||
OT_GOLD,
|
||||
OT_STONE,
|
||||
|
@ -1012,15 +1024,18 @@ enum OBTYPE {
|
|||
OT_S_HEALING,
|
||||
OT_S_HEALINGMIN,
|
||||
OT_S_HEALINGMAJ,
|
||||
OT_S_SPEAKDEAD,
|
||||
OT_S_TURNUNDEAD,
|
||||
// -- mental / psionic
|
||||
OT_S_BODYCONTROL,
|
||||
OT_S_CHARM,
|
||||
OT_S_HUNGER,
|
||||
OT_S_MINDSCAN,
|
||||
OT_S_SLEEP,
|
||||
OT_S_TELEKINESIS,
|
||||
OT_S_LOWERMETAB,
|
||||
OT_S_PACIFY,
|
||||
OT_S_PSYARMOUR,
|
||||
OT_S_CHARM,
|
||||
OT_S_SLEEP,
|
||||
OT_S_STUN,
|
||||
OT_S_TELEKINESIS,
|
||||
// -- modification
|
||||
OT_S_DARKNESS,
|
||||
OT_S_ENCHANT,
|
||||
|
@ -1076,6 +1091,7 @@ enum OBTYPE {
|
|||
OT_S_BLINK,
|
||||
OT_S_DISPERSAL,
|
||||
OT_S_GATE,
|
||||
OT_S_PLANESHIFT,
|
||||
OT_S_SUCK,
|
||||
OT_S_TELEPORT,
|
||||
OT_S_TWIDDLE,
|
||||
|
@ -1090,7 +1106,9 @@ enum OBTYPE {
|
|||
OT_S_CREATEVAULT,
|
||||
OT_S_GIFT,
|
||||
OT_S_WISH,
|
||||
OT_S_WISHLIMITED,
|
||||
OT_A_BLINDALL,
|
||||
OT_S_CONFISCATE,
|
||||
OT_A_DEBUG,
|
||||
OT_A_ENHANCE,
|
||||
OT_A_LEARN,
|
||||
|
@ -1153,6 +1171,7 @@ enum OBTYPE {
|
|||
OT_PICKAXE,
|
||||
OT_ROPE,
|
||||
OT_SACK,
|
||||
OT_SACKHUGE,
|
||||
OT_SAFEBOX,
|
||||
OT_TORCH,
|
||||
OT_TOWEL,
|
||||
|
@ -1559,6 +1578,7 @@ enum FLAG {
|
|||
F_NOBLESS, // can't be blessed or cursed
|
||||
F_NOQUALITY, // can't be masterwork / shoddy
|
||||
F_CORPSEOF, // this is a corpse of montype val0.
|
||||
// text is how it died.
|
||||
F_DTCONVERT, // damtype val0 converts this to f->text
|
||||
F_DTCREATEOB, // damtype val0 creates object f->text here
|
||||
// v1 = radius to burst in
|
||||
|
@ -1977,6 +1997,7 @@ enum FLAG {
|
|||
F_HITDICE, // val0: # d4 to roll for maxhp per level. val1: +xx
|
||||
F_MPDICE, // val0: # d4 to roll for maxmp per level. val1: +xx
|
||||
F_JOB, // val0 = player's class/job
|
||||
F_GODOF, // text = what this lf is the god of. use capitals.
|
||||
F_NAME, // text = lf's name
|
||||
F_XPMOD, // add/subtract this much from calculated xpval
|
||||
F_BLOODOB, // text = type of object to drop for blood
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
^B very bad
|
||||
^b bad
|
||||
^w warning
|
||||
^g good
|
||||
^G very good
|
|
@ -0,0 +1 @@
|
|||
Avamon God of greed (neutral)
|
31
flag.c
31
flag.c
|
@ -10,6 +10,9 @@
|
|||
#include "spell.h"
|
||||
#include "text.h"
|
||||
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags;
|
||||
|
||||
extern enum GAMEMODE gamemode;
|
||||
extern int needredraw;
|
||||
extern int statdirty;
|
||||
|
@ -1016,6 +1019,34 @@ void timeeffectsflag(flag_t *f, int howlong) {
|
|||
}
|
||||
}
|
||||
|
||||
// populates retflag & nretflags with matching flags
|
||||
int getflags(flagpile_t *fp, ... ) {
|
||||
va_list flags;
|
||||
enum FLAG wantflag[MAXCANDIDATES];
|
||||
int nwantflags,i;
|
||||
flag_t *f;
|
||||
|
||||
va_start(flags, fp);
|
||||
nwantflags = 0;
|
||||
wantflag[nwantflags] = va_arg(flags, enum FLAG);
|
||||
while (wantflag[nwantflags] != F_NONE) {
|
||||
nwantflags++;
|
||||
wantflag[nwantflags] = va_arg(flags, enum FLAG);
|
||||
}
|
||||
va_end(flags);
|
||||
|
||||
// now populate retflag[] with matches flags
|
||||
nretflags = 0;
|
||||
for (i = 0; i < nwantflags; i++) {
|
||||
f = hasflag(fp, wantflag[i]);
|
||||
while (f && (f->id == wantflag[i])) {
|
||||
retflag[nretflags++] = f;
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
return nretflags;
|
||||
}
|
||||
|
||||
int modcounter(flagpile_t *fp, int amt) {
|
||||
flag_t *f;
|
||||
f = hasflag(fp, F_COUNTER);
|
||||
|
|
1
flag.h
1
flag.h
|
@ -14,6 +14,7 @@ int countflags(flagpile_t *fp);
|
|||
int flagcausesredraw(lifeform_t *lf, enum FLAG fid);
|
||||
int flagcausesstatredraw(lifeform_t *lf, enum FLAG fid);
|
||||
int flagstacks(enum FLAG fid);
|
||||
int getflags(flagpile_t *fp, ... );
|
||||
int modcounter(flagpile_t *fp, int amt);
|
||||
flag_t *hasflag(flagpile_t *fp, int id);
|
||||
flag_t *hasflagknown(flagpile_t *fp, int id);
|
||||
|
|
84
io.c
84
io.c
|
@ -1174,7 +1174,10 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
|
|||
objecttype_t *ot;
|
||||
ot = findot(f->val[0]);
|
||||
if (ot) {
|
||||
msg("^gYou have learned the spell '%s'.", ot->name);
|
||||
enum SPELLSCHOOL school;
|
||||
school = getspellschoolknown(lf, ot->id);
|
||||
msg("^gYou have learned the %s '%s'.",
|
||||
(school = SS_MENTAL) ? "psionic power" : "spell", ot->name);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -1392,7 +1395,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
|
|||
lf2 = findlf(NULL, f->val[0]);
|
||||
if (lf2) {
|
||||
getlfname(lf2, buf);
|
||||
msg("^w%s %s %s!",buf, isplayer(lf2) ? "grab" : "grabs", lfname);
|
||||
msg("^%c%s %s %s!",getlfcol(lf, CC_VBAD), buf, isplayer(lf2) ? "grab" : "grabs", lfname);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
break;
|
||||
|
@ -3956,6 +3959,7 @@ void doclose(void) {
|
|||
|
||||
void docomms(lifeform_t *lf) {
|
||||
cell_t *where;
|
||||
int i;
|
||||
char buf[BUFLEN];
|
||||
char lfname[BUFLEN];
|
||||
char ch;
|
||||
|
@ -4008,7 +4012,15 @@ void docomms(lifeform_t *lf) {
|
|||
addchoice(&prompt, '>', "Keep your distance.", NULL, NULL);
|
||||
}
|
||||
} else if (ishirable(lf) ) {
|
||||
addchoice(&prompt, 'j', "Join me on my quest!", NULL, NULL);
|
||||
if (lf->race->id == R_PRISONER) {
|
||||
addchoice(&prompt, 'j', "Join me, and I will help you escape.", NULL, NULL);
|
||||
} else {
|
||||
addchoice(&prompt, 'j', "Join me on my quest!", NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if ((lf->race->id == R_BEGGAR) && countmoney(player)) {
|
||||
addchoice(&prompt, 'd', "(donate a gold coin)", NULL, NULL);
|
||||
}
|
||||
|
||||
f = lfhasflag(lf, F_OWNSSHOP);
|
||||
|
@ -4060,6 +4072,57 @@ void docomms(lifeform_t *lf) {
|
|||
aigoto(lf, c, MR_OTHER, NULL, AI_FOLLOWTIME);
|
||||
}
|
||||
break;
|
||||
case 'd': // donate to beggar
|
||||
givemoney(player, lf, 1); // we already checked that we had enough.
|
||||
if (countmoney(lf) == 1) {
|
||||
i = rnd(1,100);
|
||||
if (i <= 5) { // attack you
|
||||
sayphrase(lf, SP_BEGATTACK, SV_SHOUT, NA, NULL);
|
||||
fightback(lf, player);
|
||||
} else if (i <= 10) { // limited wish
|
||||
// change to a god.
|
||||
setrace(lf, R_GODGREED, B_TRUE);
|
||||
// behold! i am me!
|
||||
say(lf, "Behold mortal! It is I, Avamon!", SV_SHOUT);
|
||||
say(lf, "For your selfless act, I grant you a wish.", SV_TALK);
|
||||
// grant a wish.
|
||||
castspell(lf, OT_S_WISHLIMITED, player, NULL, NULL);
|
||||
say(lf, "Until next time, mortal!", SV_TALK);
|
||||
unsummon(lf, B_TRUE);
|
||||
} else if (i <= 20) { // identify
|
||||
object_t *poss[MAXPILEOBS],*o;
|
||||
int nposs = 0;
|
||||
sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL);
|
||||
// get random unknown item from player's pack
|
||||
for (o = player->pack->first ; o ; o = o->next){
|
||||
if (!isknown(o)) {
|
||||
poss[nposs++] = o;
|
||||
}
|
||||
}
|
||||
if (nposs) {
|
||||
char oldobname[BUFLEN];
|
||||
char newobname[BUFLEN];
|
||||
o = poss[rnd(0,nposs-1)];
|
||||
|
||||
getobname(o, oldobname, o->amt);
|
||||
makeknown(o->type->id);
|
||||
getobname(o, newobname, o->amt);
|
||||
msg("%s points at your pack.", lfname);
|
||||
msg("Hey I recognise %s %s.",
|
||||
(o->amt == 1) ? "that" : "those",
|
||||
oldobname);
|
||||
msg("%s %s.",
|
||||
(o->amt == 1) ? "It's" : "They're",
|
||||
newobname);
|
||||
}
|
||||
} else { // nothing
|
||||
sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL);
|
||||
}
|
||||
} else {
|
||||
// they already had some money
|
||||
sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL);
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
sprintf(buf, "Tell %s to go where?",lfname);
|
||||
sprintf(buf2, "%s->Goto->",lfname);
|
||||
|
@ -5025,7 +5088,7 @@ int dopickup(obpile_t *op, int forceask) {
|
|||
}
|
||||
|
||||
for (i = 0; i < nretobs; i++) {
|
||||
pickup(player, retobs[i],retobscount[i], B_TRUE);
|
||||
pickup(player, retobs[i],retobscount[i], B_TRUE, B_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5724,12 +5787,14 @@ void drawlevelfor(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
void doheading(WINDOW *win, int *y, int x, char *what) {
|
||||
int len;
|
||||
int len,i;
|
||||
char *buf;
|
||||
len = strlen(what) + 1;
|
||||
buf = malloc(len * sizeof(char));
|
||||
memset(buf, '-', (size_t)(len-1));
|
||||
buf[len] = '\0';
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = '-';
|
||||
}
|
||||
buf[i] = '\0';
|
||||
setcol(win, C_WHITE);
|
||||
mvwprintw(win, *y, x, what); (*y)++;
|
||||
mvwprintw(win, *y, x, buf); (*y)++;
|
||||
|
@ -6850,7 +6915,10 @@ void msg_real(char *format, ... ) {
|
|||
vsprintf( buf, format, args );
|
||||
va_end(args);
|
||||
|
||||
if (streq(buf, prevmsg) && !strchr(buf, '^')) {
|
||||
assert(buf[0] != '\0');
|
||||
|
||||
// ie repeat of previous message, doesn't have colours, prev msg still on screen
|
||||
if (streq(buf, prevmsg) && !strchr(buf, '^') && strstr(msgbuf, prevmsg)) {
|
||||
msgmulti++;
|
||||
sprintf(buf, "x%d",msgmulti);
|
||||
} else {
|
||||
|
|
471
lf.c
471
lf.c
|
@ -27,6 +27,9 @@ extern skill_t *firstskill, *lastskill;
|
|||
extern objecttype_t *objecttype;
|
||||
extern lifeform_t *player;
|
||||
|
||||
extern flag_t *retflag[];
|
||||
extern int nretflags;
|
||||
|
||||
extern glyph_t playerglyph;
|
||||
extern glyph_t tempglyph;
|
||||
|
||||
|
@ -821,6 +824,7 @@ int cansee(lifeform_t *viewer, lifeform_t *viewee) {
|
|||
flag_t *f;
|
||||
int xray = 0;
|
||||
int dist;
|
||||
int tremordist;
|
||||
|
||||
if (gamemode < GM_GAMESTARTED) {
|
||||
return B_TRUE;
|
||||
|
@ -836,6 +840,16 @@ int cansee(lifeform_t *viewer, lifeform_t *viewee) {
|
|||
xray = 0;
|
||||
}
|
||||
dist = getcelldist(viewer->cell, viewee->cell);
|
||||
f = lfhasflag(viewer, F_TREMORSENSE);
|
||||
if (f) {
|
||||
if (f->val[0] > 0) {
|
||||
tremordist = f->val[0];
|
||||
} else {
|
||||
tremordist = dist;
|
||||
}
|
||||
} else {
|
||||
tremordist = -1;
|
||||
}
|
||||
|
||||
// viewer asleep?
|
||||
if (lfhasflag(viewer, F_ASLEEP)) {
|
||||
|
@ -852,11 +866,21 @@ int cansee(lifeform_t *viewer, lifeform_t *viewee) {
|
|||
|
||||
// viewee is invisible?
|
||||
if (lfhasflag(viewee, F_INVISIBLE)) {
|
||||
if (!lfhasflag(viewer, F_SEEINVIS)) {
|
||||
if (!lfhasflag(viewer, F_SEEINVIS) && (tremordist < dist)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// cloak of shadows?
|
||||
o = getequippedob(viewee->pack, BP_SHOULDERS);
|
||||
if (o && hasflagval(o->flags, F_HASBRAND, BR_SHADOWS, NA, NA, NULL)) {
|
||||
if (!islit(viewee->cell)) {
|
||||
if (!lfhasflag(viewer, F_SEEINVIS) && (tremordist < dist)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// viewee hiding?
|
||||
if (lfhasflag(viewee, F_HIDING) && (viewee != viewer)) {
|
||||
if (!lfhasflagval(viewer, F_SPOTTED, viewee->id, NA, NA, NULL)) {
|
||||
|
@ -1780,6 +1804,13 @@ void die(lifeform_t *lf) {
|
|||
addflag(corpse->flags, f->val[0], f->val[1], f->val[2], NA, f->text);
|
||||
}
|
||||
}
|
||||
|
||||
// remember what killed us.
|
||||
f = hasflag(corpse->flags, F_CORPSEOF);
|
||||
if (f) {
|
||||
free(f->text);
|
||||
f->text = strdup(lf->lastdam);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2486,6 +2517,7 @@ void enhanceskills(lifeform_t *lf) {
|
|||
char ch = 'a';
|
||||
int newskillcost = 1;
|
||||
float hpratio,mpratio;
|
||||
enum SKILLLEVEL slev;
|
||||
|
||||
lf->level = lf->newlevel;
|
||||
|
||||
|
@ -2547,7 +2579,7 @@ void enhanceskills(lifeform_t *lf) {
|
|||
drawstatus();
|
||||
wrefresh(statwin);
|
||||
// wait for player to acknowledge 'you feel stronger' etc
|
||||
more();
|
||||
drawmsg(); // TODO: this use to be more()
|
||||
}
|
||||
f = lfhasflag(lf, F_STATGAINREADY);
|
||||
}
|
||||
|
@ -2842,6 +2874,27 @@ void enhanceskills(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
|
||||
// psionics sometimes lets you learn spells
|
||||
slev = getskill(lf, SK_SS_MENTAL);
|
||||
if (pctchance(slev*10)) {
|
||||
// construct list of castable mental spells
|
||||
makespellchoicelist(&prompt, lf, "Learn which new psionic power:","Describe which psionic power:", SS_MENTAL, B_TRUE, B_FALSE, player->maxmp);
|
||||
if (prompt.nchoices > 0) {
|
||||
objecttype_t *ot;
|
||||
msg("You have developed a new psionic power!"); more();
|
||||
getchoicestr(&prompt, B_TRUE, B_TRUE);
|
||||
ot = prompt.result;
|
||||
if (ot) {
|
||||
if (prompt.whichq == 0) { // learn the spell
|
||||
addflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL);
|
||||
} else {
|
||||
describespell(ot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
killflagsofid(lf->flags, F_HASNEWLEVEL);
|
||||
|
||||
// ready for another level?
|
||||
|
@ -3029,6 +3082,17 @@ lifeform_t *findlf(map_t *m, int lfid) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
lifeform_t *findlfunique(enum RACE rid) {
|
||||
lifeform_t *lf;
|
||||
map_t *thismap;
|
||||
for (thismap = firstmap ; thismap ; thismap = thismap->next) {
|
||||
for (lf = thismap->lf ; lf ; lf = lf->next) {
|
||||
if (lf->race->id == rid) return lf;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
race_t *findrace(enum RACE id) {
|
||||
race_t *r;
|
||||
for (r = firstrace; r ; r = r->next) {
|
||||
|
@ -3151,8 +3215,10 @@ int flee(lifeform_t *lf) {
|
|||
// a certain time period (ie. f->lifetime == PERMENANT), we can now stop fleeing.
|
||||
if (f->lifetime == PERMENANT) {
|
||||
killflag(f);
|
||||
} else {
|
||||
// if the flag is temporary, wait for it to time out normally
|
||||
fleefrom = thisone;
|
||||
}
|
||||
// if the flag is temporary, wait for it to time out normally
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3161,6 +3227,9 @@ int flee(lifeform_t *lf) {
|
|||
// found someone who we are fleeing from?
|
||||
if (fleefrom) {
|
||||
object_t *stairs;
|
||||
|
||||
breakallgrabs(lf);
|
||||
|
||||
// ways of fleeing other than movement?
|
||||
if (!isplayer(lf)) {
|
||||
enum OBTYPE spell;
|
||||
|
@ -3478,23 +3547,38 @@ int getactspeed(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
// include allies or enemies which will follow you up/down stairs etc
|
||||
// ie. allies within LOS
|
||||
// ie. adjacent enemies
|
||||
void getadjallies(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *nadjallies) {
|
||||
int d;
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
cell_t *c;
|
||||
c = getcellindir(lf->cell, d);
|
||||
if (c && c->lf) {
|
||||
if (areallies(lf, c->lf) || areenemies(lf, c->lf)) {
|
||||
int x,y;
|
||||
for (y = 0; y < lf->cell->map->h; y++) {
|
||||
for (x = 0; x < lf->cell->map->w; x++) {
|
||||
cell_t *c;
|
||||
c = getcellat(lf->cell->map, x, y);
|
||||
if (c && c->lf && (c->lf != lf)) {
|
||||
if (!isimmobile(c->lf) && cansee(c->lf, lf)) {
|
||||
int ok = B_TRUE;
|
||||
// if this was a pit, only flying things will follow
|
||||
if (stairob && hasflag(stairob->flags, F_PIT)) {
|
||||
if (!lfhasflag(c->lf, F_FLYING)) {
|
||||
ok = B_FALSE;
|
||||
int ok = B_FALSE;
|
||||
if (areallies(lf, c->lf) && haslof(c->lf->cell, lf->cell, LOF_WALLSTOP, NULL)) {
|
||||
// ally with a clear path to you
|
||||
ok = B_TRUE;
|
||||
} else if (areenemies(lf, c->lf) && (getcelldist(c, lf->cell) == 1)) {
|
||||
// adjacent enemy
|
||||
ok = B_TRUE;
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
// if this was a pit, only flying things will follow
|
||||
if (stairob && hasflag(stairob->flags, F_PIT)) {
|
||||
if (!lfhasflag(c->lf, F_FLYING)) {
|
||||
ok = B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) { // still ok?
|
||||
adjally[*nadjallies] = c->lf;
|
||||
(*nadjallies)++;
|
||||
}
|
||||
}
|
||||
adjally[*nadjallies] = c->lf;
|
||||
(*nadjallies)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4352,6 +4436,8 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
|
|||
// get weapon
|
||||
if (wep) {
|
||||
acc = getobaccuracy(wep, lf);
|
||||
} else {
|
||||
acc = 100; // fists
|
||||
}
|
||||
|
||||
// dual weilding?
|
||||
|
@ -7493,6 +7579,8 @@ void initjobs(void) {
|
|||
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_SWIMMING, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_THROWING, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_RANGED, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL);
|
||||
addflag(lastjob->flags, F_CANLEARN, SK_CLUBS, NA, NA, NULL);
|
||||
// abilities
|
||||
|
@ -7547,7 +7635,7 @@ void initjobs(void) {
|
|||
addflag(lastjob->flags, F_LEVFLAG, 2, F_MPDICE, 1, NULL);
|
||||
addflag(lastjob->flags, F_LEVSPELL, 2, OT_S_CALMANIMALS, NA, NULL);
|
||||
// 2: body control - low metabolism
|
||||
addflag(lastjob->flags, F_LEVSPELL, 3, OT_S_BODYCONTROL, NA, NULL);
|
||||
addflag(lastjob->flags, F_LEVSPELL, 3, OT_S_LOWERMETAB, NA, NULL);
|
||||
// 4: self-healing (mp), immune to haste/slow (innate)
|
||||
addflag(lastjob->flags, F_LEVFLAG, 4, F_DISEASEIMMUNE, B_TRUE, NULL);
|
||||
addflag(lastjob->flags, F_LEVABIL, 5, OT_A_HEAVYBLOW, 3, NULL);
|
||||
|
@ -7795,6 +7883,7 @@ void initrace(void) {
|
|||
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);
|
||||
addraceclass(RC_GOD, "god", "dieties", SK_NONE);
|
||||
addraceclass(RC_HUMANOID, "humanoid", "humanoid creatures", SK_LORE_HUMANOID);
|
||||
addraceclass(RC_INSECT, "insect", "insects and animals", SK_LORE_NATURE);
|
||||
addraceclass(RC_MAGIC, "magical creature", "magical creatures", SK_LORE_ARCANA);
|
||||
|
@ -7856,6 +7945,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_STARTJOB, 75, J_RANDOM, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "shouts^a shout");
|
||||
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL);
|
||||
|
||||
// human monsters...
|
||||
addrace(R_BANDIT, "bandit", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID);
|
||||
|
@ -7917,6 +8007,22 @@ void initrace(void) {
|
|||
f = addflag(lastrace->flags, F_DRUNK, 5, NA, NA, NULL);
|
||||
addcondition(f, FC_NOCONDITION, 30);
|
||||
addaltval(f, F_DRUNK, 3, NA, NA, NULL);
|
||||
|
||||
addrace(R_PRISONER, "prisoner", 60, '@', C_GREY, MT_FLESH, RC_HUMANOID);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2");
|
||||
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-2 stones");
|
||||
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_WANTSBETTERARM, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HIREPRICE, 0, NA, NA, NULL);
|
||||
|
||||
addrace(R_TOWNGUARD, "town guard", 100, '@', C_GREY, MT_FLESH, RC_HUMANOID);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "12-18");
|
||||
|
@ -7943,6 +8049,38 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
|
||||
|
||||
// gods
|
||||
addrace(R_GODGREED, "Avamon", 300, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "20");
|
||||
addflag(lastrace->flags, F_STARTATT, A_DEX, NA, NA, "10");
|
||||
addflag(lastrace->flags, F_STARTATT, A_WIS, NA, NA, "9");
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, NA, NA, "10");
|
||||
addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "8");
|
||||
addflag(lastrace->flags, F_STARTATT, A_CHA, NA, NA, "6");
|
||||
addflag(lastrace->flags, F_DONTSTARTASLEEP, NA, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 30, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_UNIQUE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_ACTIONSPEED, SP_SLOW, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2");
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "blessed ring of hunger");
|
||||
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10 huge sacks");
|
||||
//addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_WANTSOBFLAG, F_RARITY, NA, NA, NULL); // ie. everything
|
||||
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_THIEVERY, PR_MASTER, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, "waves his hand");
|
||||
// god abilities
|
||||
addflag(lastrace->flags, F_GODOF, NA, NA, NA, "Greed");
|
||||
addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_OBESE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_CALLWIND, NA, NA, "pw:10;");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_CONFISCATE, NA, NA, "pw:10;");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_HUNGER, NA, NA, "pw:1;");
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
|
||||
|
||||
// monsters
|
||||
addrace(R_BEHOLDER, "beholder", 5, 'e', C_MAGENTA, MT_FLESH, RC_MAGIC);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_VHIGH, NA, NULL);
|
||||
|
@ -9315,7 +9453,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining");
|
||||
addrace(R_DOGBLINK, "blink dog", 35, 'd', C_BLUE, MT_FLESH, RC_ANIMAL);
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_NUMAPPEAR, 2, 8, NA, "");
|
||||
addflag(lastrace->flags, F_NUMAPPEAR, 2, 4, NA, "");
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
|
||||
|
@ -9981,13 +10119,14 @@ void initrace(void) {
|
|||
// undead
|
||||
addrace(R_ZOMBIE, "zombie", 50, 'Z', C_BLUE, MT_FLESH, RC_UNDEAD);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "6");
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_NUMAPPEAR, 2, 4, NA, NULL);
|
||||
addflag(lastrace->flags, F_NUMAPPEAR, 1, 3, NA, NULL);
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 2, 4, 1, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 2, 4, NA, NULL);
|
||||
addflag(lastrace->flags, F_ARMOURRATING, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
|
||||
|
@ -10421,9 +10560,15 @@ int isingunrange(lifeform_t *lf, cell_t *where) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
int isgod(lifeform_t *lf) {
|
||||
if (lf->race->raceclass->id == RC_GOD) return B_TRUE;
|
||||
if (hasjob(lf, J_GOD)) return B_TRUE;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
// can you try to recruit this lf?
|
||||
int ishirable(lifeform_t *lf) {
|
||||
if (!isplayer(lf) && ispeaceful(lf) && lfhasflag(lf, F_JOB)) {
|
||||
if (!isplayer(lf) && ispeaceful(lf)) {
|
||||
if (lfhasflag(lf, F_HIRABLE)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -11151,8 +11296,10 @@ void applywalkdam(lifeform_t *lf, int dam, enum DAMTYPE damtype, object_t *o) {
|
|||
msg("^b%s %ss you!", buf, getattackverb(NULL, NULL, damtype, dam,lf->maxhp));
|
||||
} else if (cansee(player, lf)) {
|
||||
char lfname[BUFLEN];
|
||||
char buf2[BUFLEN];
|
||||
getlfname(lf, lfname);
|
||||
msg("^c%s %ss %s!", getlfcol(lf, CC_BAD), buf, getattackverb(NULL, NULL, damtype, dam,lf->maxhp), lfname);
|
||||
sprintf(buf2, "^%c%s %ss %s!", getlfcol(lf, CC_BAD), buf, getattackverb(NULL, NULL, damtype, dam,lf->maxhp), lfname);
|
||||
msg("%s", buf2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11607,10 +11754,10 @@ void loseconcentration(lifeform_t *lf) {
|
|||
|
||||
// lose hp, and adjust damage based on resistances
|
||||
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc) {
|
||||
return losehp_real(lf, amt, damtype, fromlf, damsrc, B_TRUE);
|
||||
return losehp_real(lf, amt, damtype, fromlf, damsrc, B_TRUE, NULL);
|
||||
}
|
||||
|
||||
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam) {
|
||||
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob) {
|
||||
char buf[BUFLEN];
|
||||
char buf2[BUFLEN];
|
||||
char lfname[BUFLEN];
|
||||
|
@ -11800,7 +11947,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
|
|||
}
|
||||
|
||||
// elemental effects on held objects
|
||||
if (damtype == DT_FIRE) {
|
||||
if ((damtype == DT_FIRE) && !fromob) {
|
||||
object_t *o, *nexto;
|
||||
// fire: dam*10 chance of burning each object which is vulnerable to fire
|
||||
for (o = lf->pack->first ; o ; o = nexto) {
|
||||
|
@ -11813,7 +11960,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
|
|||
takedamage(o, newdam, DT_FIRE);
|
||||
}
|
||||
}
|
||||
} else if (damtype == DT_COLD) {
|
||||
} else if ((damtype == DT_COLD) && !fromob) {
|
||||
object_t *o, *nexto;
|
||||
// cold: dam*10 chance of shattering potions, or damaging other things.
|
||||
for (o = lf->pack->first ; o ; o = nexto) {
|
||||
|
@ -12254,7 +12401,7 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
|
|||
// something, its ->cell will be null here!
|
||||
dist = getcelldist(l->cell, c);
|
||||
|
||||
if ((l != noisemaker) && (l->cell)) {
|
||||
if (l != noisemaker) {
|
||||
int difficulty;
|
||||
int lbonus;
|
||||
//if (canhear(l, c) && haslos(l, c)) {
|
||||
|
@ -12265,14 +12412,15 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
|
|||
// you always hear it, as long as you're in range
|
||||
difficulty = 0;
|
||||
} else {
|
||||
difficulty = (int) ( ((float)getcelldist(l->cell, c) / (float)gethearingrange(l)) * 20);
|
||||
//difficulty = (int) ( ((float)getcelldist(l->cell, c) / (float)gethearingrange(l)) * 20);
|
||||
difficulty = (int) ( ((float)getcelldist(l->cell, c) / ((float)gethearingrange(l) + volume)) * 20);
|
||||
}
|
||||
|
||||
// listen bonus is the sound volume
|
||||
lbonus = volume;
|
||||
if (lfhasflag(l, F_ASLEEP)) {
|
||||
lbonus = 0;
|
||||
} else {
|
||||
lbonus = volume;
|
||||
lbonus -= 5;
|
||||
limit(&lbonus, 0, NA);
|
||||
}
|
||||
|
||||
// skillcheck to hear this
|
||||
|
@ -12294,9 +12442,11 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
|
|||
char punc;
|
||||
int dist;
|
||||
|
||||
punc = text[strlen(text)-1];
|
||||
strncpy(textnopunc, text, strlen(text)-1);
|
||||
textnopunc[strlen(text)] = '\0';
|
||||
//punc = text[strlen(text)-1];
|
||||
//strncpy(textnopunc, text, strlen(text)-1);
|
||||
strcpy(textnopunc, text);
|
||||
punc = textnopunc[strlen(textnopunc)-1];
|
||||
textnopunc[strlen(textnopunc)-1] = '\0';
|
||||
|
||||
dist = getcelldist(l->cell, c);
|
||||
|
||||
|
@ -12357,15 +12507,17 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
|
|||
rv = B_TRUE;
|
||||
}
|
||||
// only hear one thing per turn.
|
||||
addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL);
|
||||
practice(l, SK_LISTEN, 1);
|
||||
if (isplayer(l)) {
|
||||
addflag(l->flags, F_DONELISTEN, B_TRUE, NA, NA, NULL);
|
||||
practice(l, SK_LISTEN, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// wake up a little
|
||||
f = lfhasflag(l, F_ASLEEP);
|
||||
if (f) {
|
||||
if (f->lifetime > 0) { // ie. temporary
|
||||
timeeffectsflag(f, rnd(1,10));
|
||||
timeeffectsflag(f, volume + rnd(1,3));
|
||||
} else if (f->lifetime == PERMENANT) {
|
||||
if (f->val[2] == NA) { // ie asleep rather than 'resting'
|
||||
// wake up!
|
||||
|
@ -12403,8 +12555,6 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, cha
|
|||
isplayer(l) ? "" : "s",
|
||||
isplayer(l) ? "your" : "its");
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12432,7 +12582,7 @@ void petify(lifeform_t *lf, lifeform_t *owner) {
|
|||
}
|
||||
|
||||
|
||||
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground) {
|
||||
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int wantannounce) {
|
||||
char obname[BUFLEN];
|
||||
object_t *o;
|
||||
//flag_t *f;
|
||||
|
@ -12511,14 +12661,16 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground) {
|
|||
// try to move whatever was selected
|
||||
o = moveob(what, lf->pack, howmany);
|
||||
if (o) { // if pickup was successful...
|
||||
if (isplayer(lf)) {
|
||||
// refresh obname to copd with stacking
|
||||
getobname(o, obname, o->amt);
|
||||
msgnocap("%c - %s",o->letter, obname);
|
||||
} else if (cansee(player, lf)) {
|
||||
char buf[BUFLEN];
|
||||
getlfname(lf, buf);
|
||||
msg("%s picks up %s.",buf, obname);
|
||||
if (wantannounce) {
|
||||
if (isplayer(lf)) {
|
||||
// refresh obname to copd with stacking
|
||||
getobname(o, obname, o->amt);
|
||||
msgnocap("%c - %s",o->letter, obname);
|
||||
} else if (cansee(player, lf)) {
|
||||
char buf[BUFLEN];
|
||||
getlfname(lf, buf);
|
||||
msg("%s picks up %s.",buf, obname);
|
||||
}
|
||||
}
|
||||
/*
|
||||
taketime(lf, (SPEED_PICKUP * howmany));
|
||||
|
@ -12677,25 +12829,26 @@ void practice(lifeform_t *lf, enum SKILL skid, int amt) {
|
|||
void precalclos(lifeform_t *lf) {
|
||||
int x,y;
|
||||
cell_t *c;
|
||||
cell_t **los;
|
||||
int maxvisrange;
|
||||
cell_t *los[MAX_MAPW * MAX_MAPH];
|
||||
int nlos;
|
||||
int oldnlos = -1,nlos = 0;
|
||||
int i;
|
||||
|
||||
los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
|
||||
|
||||
// free existing structures
|
||||
if (lf->los) {
|
||||
free(lf->los);
|
||||
oldnlos = lf->nlos;
|
||||
free(lf->los); lf->los = NULL;
|
||||
}
|
||||
|
||||
|
||||
nlos = 0;
|
||||
|
||||
maxvisrange = getvisrange(lf);
|
||||
for (y = lf->cell->y - maxvisrange; y <= lf->cell->y + maxvisrange ; y++) {
|
||||
for (x = lf->cell->x - maxvisrange; x <= lf->cell->x + maxvisrange ; x++) {
|
||||
c = getcellat(lf->cell->map, x, y);
|
||||
//
|
||||
if ((c != lf->cell) && haslos(lf, c)) {
|
||||
if (c && (c != lf->cell) && haslos(lf, c)) {
|
||||
los[nlos] = c;
|
||||
nlos++;
|
||||
}
|
||||
|
@ -12708,6 +12861,7 @@ void precalclos(lifeform_t *lf) {
|
|||
lf->los[i] = los[i];
|
||||
}
|
||||
lf->nlos = nlos;
|
||||
free(los);
|
||||
}
|
||||
|
||||
int push(lifeform_t *lf, object_t *o, int dir) {
|
||||
|
@ -12766,7 +12920,11 @@ int readytotrain(lifeform_t *lf) {
|
|||
|
||||
int recruit(lifeform_t *lf) {
|
||||
int rv = B_FALSE;
|
||||
if (!lfhasflag(lf, F_NOHIRE)) {
|
||||
if (lfhasflag(lf, F_NOHIRE)) {
|
||||
// refusing to join at all.
|
||||
sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL);
|
||||
rv = B_TRUE;
|
||||
} else {
|
||||
int dohire = B_FALSE;
|
||||
int askingprice = -1;
|
||||
char lfname[BUFLEN];
|
||||
|
@ -12788,8 +12946,9 @@ int recruit(lifeform_t *lf) {
|
|||
addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL);
|
||||
} else {
|
||||
if (difficulty - result >= 10) {
|
||||
// will never join
|
||||
askingprice = -1;
|
||||
// very expensive
|
||||
askingprice = rnd(gethitdice(lf)*250, gethitdice(lf)*300 );
|
||||
addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL);
|
||||
} else {
|
||||
// expensive
|
||||
askingprice = rnd(gethitdice(lf)*100, gethitdice(lf)*200 );
|
||||
|
@ -12798,14 +12957,7 @@ int recruit(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
|
||||
if (askingprice == -1) {
|
||||
// refusing to join at all.
|
||||
sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL);
|
||||
rv = B_TRUE;
|
||||
if (!lfhasflag(lf, F_NOHIRE)) {
|
||||
addflag(lf->flags, F_NOHIRE, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
} else {
|
||||
if (askingprice != 0) {
|
||||
// modify by charisma
|
||||
askingprice = pctof(100 + getstatmod(player, A_CHA), askingprice);
|
||||
|
||||
|
@ -12821,22 +12973,25 @@ int recruit(lifeform_t *lf) {
|
|||
dohire = B_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dohire = B_TRUE;
|
||||
}
|
||||
|
||||
if (dohire) {
|
||||
char *p = NULL;
|
||||
petify(lf, player);
|
||||
if (dohire) {
|
||||
char *p = NULL;
|
||||
petify(lf, player);
|
||||
|
||||
// give them a name
|
||||
if (getjob(lf)) {
|
||||
p = assignnpcname(lf);
|
||||
}
|
||||
sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p);
|
||||
// give them a name
|
||||
//if (getjob(lf)) {
|
||||
if (lf->race->raceclass->id == RC_HUMANOID) {
|
||||
p = assignnpcname(lf);
|
||||
}
|
||||
sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p);
|
||||
} else {
|
||||
if (askingprice > countmoney(player)) {
|
||||
sayphrase(lf, SP_RECRUIT_DECLINE_CANTPAY, SV_TALK, askingprice, NULL);
|
||||
} else {
|
||||
if (askingprice > countmoney(player)) {
|
||||
sayphrase(lf, SP_RECRUIT_DECLINE_CANTPAY, SV_TALK, askingprice, NULL);
|
||||
} else {
|
||||
sayphrase(lf, SP_RECRUIT_DECLINE_WONTPAY, SV_TALK, askingprice, NULL);
|
||||
}
|
||||
sayphrase(lf, SP_RECRUIT_DECLINE_WONTPAY, SV_TALK, askingprice, NULL);
|
||||
}
|
||||
}
|
||||
} // end if !nohire
|
||||
|
@ -12923,6 +13078,11 @@ int startresting(lifeform_t *lf, int willtrain) {
|
|||
// stop hiding
|
||||
killflagsofid(lf->flags, F_HIDING);
|
||||
|
||||
// stop all spells
|
||||
stopallspells(lf);
|
||||
|
||||
killflagsofid(lf->flags, F_INTERRUPTED);
|
||||
|
||||
if (willtrain) {
|
||||
addflag(lf->flags, F_TRAINING, B_TRUE, NA, traincounter, NULL);
|
||||
} else {
|
||||
|
@ -13088,6 +13248,22 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
|
|||
}
|
||||
rv = say(lf, buf, volume);
|
||||
break;
|
||||
case SP_BEGATTACK:
|
||||
switch (rnd(1,3)) {
|
||||
case 1: sprintf(buf, "Now give me the everything else!"); break;
|
||||
case 2: sprintf(buf, "Rich fool!"); break;
|
||||
case 3: sprintf(buf, "Is that all?"); break;
|
||||
}
|
||||
rv = say(lf, buf, volume);
|
||||
break;
|
||||
case SP_BEGTHANKS:
|
||||
switch (rnd(1,3)) {
|
||||
case 1: sprintf(buf, "A thousand thanks, good sir!"); break;
|
||||
case 2: sprintf(buf, "Oh thank you!"); break;
|
||||
case 3: sprintf(buf, "My family shall eat tonight!"); break;
|
||||
}
|
||||
rv = say(lf, buf, volume);
|
||||
break;
|
||||
case SP_DRUNK:
|
||||
// random blurred speech
|
||||
strcpy(buf, "");
|
||||
|
@ -13132,10 +13308,18 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
|
|||
rv = say(lf, buf, volume);
|
||||
break;
|
||||
case SP_RECRUIT_ACCEPT:
|
||||
if (text) {
|
||||
sprintf(buf, "I will join you - my name is %s.", text);
|
||||
if (lf->race->id == R_PRISONER) {
|
||||
if (text) {
|
||||
sprintf(buf, "Thank you! My name is %s.", text);
|
||||
} else {
|
||||
sprintf(buf, "Thank you!");
|
||||
}
|
||||
} else {
|
||||
sprintf(buf, "I will join you.");
|
||||
if (text) {
|
||||
sprintf(buf, "I will join you - my name is %s.", text);
|
||||
} else {
|
||||
sprintf(buf, "I will join you.");
|
||||
}
|
||||
}
|
||||
rv = say(lf, buf, volume);
|
||||
break;
|
||||
|
@ -13180,6 +13364,7 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) {
|
|||
|
||||
// immune to fear?
|
||||
if (lfhasflag(lf, F_UNDEAD)) return B_FALSE;
|
||||
if (isgod(lf)) return B_FALSE;
|
||||
|
||||
if (lfhasflag(lf, F_ASLEEP)) {
|
||||
return B_FALSE;
|
||||
|
@ -13342,7 +13527,12 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
|
|||
msg("^wYou transform into %s %s!", isvowel(newrace->name[0]) ? "an" : "a", newrace->name);
|
||||
} else if (cansee(player, lf)) {
|
||||
getlfname(lf, buf);
|
||||
msg("^w%s transforms into %s %s!", buf, isvowel(newrace->name[0]) ? "an" : "a", newrace->name);
|
||||
f = lfhasflag(lf, F_GODOF);
|
||||
if (f) {
|
||||
msg("^w%s transforms into %s, the God of %s!", buf, newrace->name, f->text);
|
||||
} else {
|
||||
msg("^w%s transforms into %s %s!", buf, isvowel(newrace->name[0]) ? "an" : "a", newrace->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13579,7 +13769,7 @@ void initskills(void) {
|
|||
addskilldesc(SK_SHIELDS, PR_SKILLED, "^gShield accuracy penalties are reduced by 20%.", B_FALSE);
|
||||
addskilldesc(SK_SHIELDS, PR_EXPERT, "^gShield accuracy penalties are reduced by 25%.", B_FALSE);
|
||||
addskilldesc(SK_SHIELDS, PR_MASTER, "^gShield accuracy penalties are reduced by 30%.", B_FALSE);
|
||||
addskill(SK_SPEECH, "Speech", "Your skill at haggling prices, or swaying others through speech.", 50);
|
||||
addskill(SK_SPEECH, "Negotiation", "Your skill at haggling prices, or swaying others through speech.", 50);
|
||||
addskilldesc(SK_SPEECH, PR_NOVICE, "^gShop item prices are reduced by 5%.", B_FALSE);
|
||||
addskilldesc(SK_SPEECH, PR_BEGINNER, "^gShop item prices are reduced by 10%.", B_FALSE);
|
||||
addskilldesc(SK_SPEECH, PR_ADEPT, "^gShop item prices are reduced by 15%.", B_FALSE);
|
||||
|
@ -14285,7 +14475,6 @@ int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag) {
|
|||
char buf[BUFLEN];
|
||||
sprintf(buf, "Steal what (%d of %d)?", i+1, nsteals);
|
||||
initprompt(&prompt, buf);
|
||||
addchoice(&prompt, '-', "Nothing", NULL, NULL);
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
int ok = B_TRUE;
|
||||
if ((slev < PR_SKILLED) && (getobunitweight(o) >= 3)) {
|
||||
|
@ -14307,7 +14496,8 @@ int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag) {
|
|||
}
|
||||
}
|
||||
if (prompt.nchoices > 1) {
|
||||
if (slev >= PR_ADEPT) {
|
||||
if (isplayer(lf) && (slev >= PR_ADEPT)) {
|
||||
addchoice(&prompt, '-', "Nothing", NULL, NULL);
|
||||
// pick what you want
|
||||
getchoice(&prompt);
|
||||
o = (object_t *)prompt.result;
|
||||
|
@ -14448,32 +14638,51 @@ void stopsprinting(lifeform_t *lf) {
|
|||
|
||||
// very much like addmonster(), but announce that it appears
|
||||
// and make it worth zero xp.
|
||||
//
|
||||
// for unique monsters, they move from their current position.
|
||||
lifeform_t *summonmonster(lifeform_t *caster, cell_t *c, enum RACE rid, int randomjobsok, job_t *forcejob, int lifetime, int wantfriendly) {
|
||||
lifeform_t *newlf = NULL;
|
||||
char buf[BUFLEN];
|
||||
newlf = addmonster(c, rid, randomjobsok, 1, B_FALSE, NULL);
|
||||
if (newlf) {
|
||||
// assign job if required
|
||||
if (forcejob) {
|
||||
givejob(newlf, forcejob->id);
|
||||
race_t *r;
|
||||
r = findrace(rid);
|
||||
|
||||
if (r && hasflag(r->flags, F_UNIQUE)) {
|
||||
// does it already exist?
|
||||
newlf = findlfunique(rid);
|
||||
|
||||
// if so, move it here, then exit.
|
||||
if (newlf) {
|
||||
teleportto(newlf, c, B_FALSE);
|
||||
}
|
||||
if (haslos(player, c)) {
|
||||
//char *newbuf;
|
||||
getlfnamea(newlf, buf);
|
||||
capitalise(buf);
|
||||
msg("%s appears!", buf);
|
||||
}
|
||||
|
||||
if (!newlf) {
|
||||
newlf = addmonster(c, rid, randomjobsok, 1, B_FALSE, NULL);
|
||||
if (newlf) {
|
||||
// assign job if required
|
||||
if (forcejob) {
|
||||
givejob(newlf, forcejob->id);
|
||||
}
|
||||
if (haslos(player, c)) {
|
||||
//char *newbuf;
|
||||
getlfnamea(newlf, buf);
|
||||
capitalise(buf);
|
||||
msg("%s appears!", buf);
|
||||
}
|
||||
// summoned
|
||||
if (caster) {
|
||||
addflag(newlf->flags, F_SUMMONEDBY, caster->id, lifetime, NA, NULL);
|
||||
if (wantfriendly) {
|
||||
addflag(newlf->flags, F_PETOF, caster->id, NA, NA, NULL);
|
||||
if (areallies(player, caster)) {
|
||||
makefriendly(newlf, PERMENANT);
|
||||
}
|
||||
}
|
||||
}
|
||||
// not worth any xp
|
||||
killflagsofid(newlf->flags, F_XPVAL);
|
||||
addflag(newlf->flags, F_XPVAL, 0, NA, NA, NULL);
|
||||
}
|
||||
// summoned
|
||||
addflag(newlf->flags, F_SUMMONEDBY, caster->id, lifetime, NA, NULL);
|
||||
if (wantfriendly) {
|
||||
addflag(newlf->flags, F_PETOF, caster->id, NA, NA, NULL);
|
||||
if (areallies(player, caster)) {
|
||||
makefriendly(newlf, PERMENANT);
|
||||
}
|
||||
}
|
||||
// not worth any xp
|
||||
killflagsofid(newlf->flags, F_XPVAL);
|
||||
addflag(newlf->flags, F_XPVAL, 0, NA, NA, NULL);
|
||||
}
|
||||
return newlf;
|
||||
}
|
||||
|
@ -14625,10 +14834,9 @@ void timeeffectslf(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
|
||||
f = lfhasflag(lf, F_INTERRUPTED);
|
||||
if (f) {
|
||||
if (lfhasflag(lf, F_INTERRUPTED)) {
|
||||
interrupt(lf);
|
||||
killflag(f);
|
||||
killflagsofid(lf->flags, F_INTERRUPTED);
|
||||
}
|
||||
|
||||
if (isdead(lf)) {
|
||||
|
@ -14756,7 +14964,7 @@ void turneffectslf(lifeform_t *lf) {
|
|||
map_t *map;
|
||||
enum ERROR error;
|
||||
object_t *o;
|
||||
flag_t *f, *nextf;
|
||||
flag_t *f;
|
||||
flag_t *asp;
|
||||
char buf[BUFLEN];
|
||||
lifeform_t *l;
|
||||
|
@ -14849,7 +15057,9 @@ void turneffectslf(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
// MP regeneration
|
||||
for (f = lf->flags->first ; f ; f = f->next) {
|
||||
getflags(lf->flags, F_MPREGEN, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
if (f->id == F_MPREGEN) {
|
||||
gainmp(lf, f->val[0]);
|
||||
}
|
||||
|
@ -15055,7 +15265,7 @@ void turneffectslf(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
f = hasflag(o->flags, F_TRAPPED);
|
||||
if (f && (f->val[2] != B_TRUE)) {
|
||||
if (f && (f->val[2] != B_TRUE) && !hasflag(o->flags, F_SECRET)) {
|
||||
objecttype_t *ot;
|
||||
flag_t *trapflag;
|
||||
int diff;
|
||||
|
@ -15237,7 +15447,9 @@ void turneffectslf(lifeform_t *lf) {
|
|||
|
||||
|
||||
// for flags which can occur multiple times
|
||||
for (f = o->flags->first ; f ; f = f->next) {
|
||||
getflags(o->flags, F_DEEPWATER, F_WALKDAMBP, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
if ((f->id == F_DEEPWATER) && !isairborne(lf)) {
|
||||
checkfordrowning(lf, o);
|
||||
if (isdead(lf)) return;
|
||||
|
@ -15282,8 +15494,10 @@ void turneffectslf(lifeform_t *lf) {
|
|||
if (isdead(lf)) return;
|
||||
|
||||
|
||||
for (f = lf->flags->first ; f ; f = nextf) {
|
||||
nextf = f->next;
|
||||
getflags(lf->flags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_FLEEFROM, F_GRABBEDBY, F_GRABBING, F_BOOSTSPELL, F_FEIGNINGDEATH,
|
||||
F_NOFLEEFROM, F_PETOF, F_SPOTTED, F_STABBEDBY, F_TARGETCELL, F_TARGETLF, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
// remove impossible flags
|
||||
if ((f->id == F_BOOSTSPELL) && (f->val[0] == OT_S_PASSWALL)) {
|
||||
if (!lfhasflag(lf, F_NONCORPOREAL)) {
|
||||
|
@ -15515,11 +15729,17 @@ void unsummon(lifeform_t *lf, int vanishobs) {
|
|||
|
||||
if (cansee(player, lf)) {
|
||||
char lfname[BUFLEN];
|
||||
int doyour = B_FALSE;
|
||||
|
||||
if (creator && (creator == player)) {
|
||||
if (!hasflag(lf->flags, F_UNIQUE)) {
|
||||
doyour = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
getlfname(lf, lfname);
|
||||
msg("%s%s vanishes.",
|
||||
(creator && (creator == player)) ? "Your " : "",
|
||||
(creator && (creator == player)) ? noprefix(lfname) : lfname
|
||||
);
|
||||
msg("%s%s vanishes.", doyour ? "Your " : "",
|
||||
doyour ? noprefix(lfname) : lfname);
|
||||
}
|
||||
|
||||
if (vanishobs) {
|
||||
|
@ -15983,9 +16203,18 @@ int validateraces(void) {
|
|||
addflag(r->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
|
||||
addflag(r->flags, F_DTIMMUNE, DT_WATER, NA, NA, NULL);
|
||||
} else if (r->raceclass->id == RC_DEMON) {
|
||||
addflag(lastrace->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
|
||||
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
|
||||
} else if (r->raceclass->id == RC_GOD) {
|
||||
addflag(r->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL);
|
||||
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
|
||||
addflag(r->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL);
|
||||
addflag(r->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL);
|
||||
addflag(r->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL);
|
||||
addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL);
|
||||
addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL);
|
||||
addflag(r->flags, F_MORALE, 40, NA, NA, NULL);
|
||||
} else if (r->raceclass->id == RC_MAGIC) {
|
||||
addflag(lastrace->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
|
||||
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
|
||||
} else if (r->raceclass->id == RC_PLANT) {
|
||||
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
|
||||
addflag(r->flags, F_DTRESIST, DT_BASH, NA, NA, NULL);
|
||||
|
|
6
lf.h
6
lf.h
|
@ -69,6 +69,7 @@ void fightback(lifeform_t *lf, lifeform_t *attacker);
|
|||
job_t *findjob(enum JOB jobid);
|
||||
job_t *findjobbyname(char *name);
|
||||
lifeform_t *findlf(map_t *m, int lfid);
|
||||
lifeform_t *findlfunique(enum RACE rid);
|
||||
race_t *findrace(enum RACE id);
|
||||
race_t *findracebyname(char *name);
|
||||
raceclass_t *findraceclass(enum RACECLASS id);
|
||||
|
@ -223,6 +224,7 @@ int isfleeing(lifeform_t *lf);
|
|||
int isfreebp(lifeform_t *lf, enum BODYPART bp);
|
||||
int isfriendly(lifeform_t *lf);
|
||||
int isgenius(lifeform_t *lf);
|
||||
int isgod(lifeform_t *lf);
|
||||
int ishirable(lifeform_t *lf);
|
||||
int isimmobile(lifeform_t *lf);
|
||||
flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt);
|
||||
|
@ -253,7 +255,7 @@ int loadfirearm(lifeform_t *lf, object_t *gun, object_t *ammo);
|
|||
int loadfirearmfast(lifeform_t *lf);
|
||||
void loseconcentration(lifeform_t *lf);
|
||||
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc);
|
||||
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam);
|
||||
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob);
|
||||
void losemp(lifeform_t *lf, int amt);
|
||||
void makefriendly(lifeform_t *lf, int howlong);
|
||||
int makenauseated(lifeform_t *lf, int amt, int howlong);
|
||||
|
@ -269,7 +271,7 @@ int needstorest(lifeform_t *lf, char *validchars);
|
|||
int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, char *text, char *seetext);
|
||||
void outfitlf(lifeform_t *lf);
|
||||
void petify(lifeform_t *lf, lifeform_t *owner);
|
||||
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground);
|
||||
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int antannounce);
|
||||
void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *fromwhat);
|
||||
int poisoncausesvomit(enum POISONTYPE ptype);
|
||||
int poisonthreatenslife(lifeform_t *lf, flag_t *f);
|
||||
|
|
8
map.c
8
map.c
|
@ -1105,7 +1105,7 @@ flag_t *getmapcoords(map_t *m, int *x, int *y) {
|
|||
int getmapdifficulty(map_t *m) {
|
||||
int diff = 1;
|
||||
if (m) {
|
||||
if (m->region == RG_WORLDMAP) {
|
||||
if (isoutdoors(m)) {
|
||||
int x,y;
|
||||
// depth is distance from 0,0
|
||||
getmapcoords(m, &x, &y);
|
||||
|
@ -2541,14 +2541,14 @@ int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
|
|||
int bestdist = 999;
|
||||
if (db) dblog(" Need to link.");
|
||||
// link it. starting from the door, count the number of cells in
|
||||
// each direction until we hit an empty (walkable) cell not of this room.
|
||||
// each direction until we hit an empty (walkable) cell which isn't a room.
|
||||
// if we hit a cell of this roomid, mark this dir as invalid.
|
||||
for (d = D_N; d <= D_W; d++) {
|
||||
dist[d] = 0;
|
||||
c = getcellindir(poss[i], d);
|
||||
while (c) {
|
||||
dist[d]++;
|
||||
if (c->roomid == roomid) {
|
||||
if (isroom(c)) {
|
||||
// mark dir as invalid
|
||||
dist[d] = 999;
|
||||
break;
|
||||
|
@ -3915,7 +3915,7 @@ int isonmap(map_t *map, int x, int y) {
|
|||
}
|
||||
|
||||
int isoutdoors(map_t *m) {
|
||||
if (m->region == RG_WORLDMAP) {
|
||||
if (m->region->rtype->id == RG_WORLDMAP) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
|
|
20
move.c
20
move.c
|
@ -1467,8 +1467,8 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
return B_TRUE;
|
||||
} else {
|
||||
if (lf) {
|
||||
// has known trap?
|
||||
if (isplayer(lf)) {
|
||||
// has known trap?
|
||||
if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) {
|
||||
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_AVERAGE) {
|
||||
char ch;
|
||||
|
@ -1480,6 +1480,24 @@ int opendoor(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// hear water behind it?
|
||||
if (getskill(lf, SK_LISTEN)) {
|
||||
int dir;
|
||||
cell_t *pastdoorcell;
|
||||
dir = getdirtowards(doorcell, lf->cell, NULL, B_FALSE, DT_ORTH);
|
||||
pastdoorcell = getcellindir(doorcell, dir);
|
||||
if (pastdoorcell && getcellwaterdepth(pastdoorcell, NULL)) {
|
||||
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_AVERAGE) {
|
||||
char ch;
|
||||
sprintf(buf,"Your hear running water behind %s. Really open it?", obname);
|
||||
ch = askchar(buf,"yn","n", B_TRUE);
|
||||
if (ch != 'y') {
|
||||
msg("Cancelled.");
|
||||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
taketime(lf, getactspeed(lf));
|
||||
|
|
14
nexus.c
14
nexus.c
|
@ -1183,15 +1183,14 @@ int rollhitdice(lifeform_t *lf) {
|
|||
}
|
||||
if (db) dblog("rollhitdice() for %s - rolling %dd4 + %d",lf->race->name,ndice,plus);
|
||||
|
||||
mod = getstatmod(lf, A_CON);
|
||||
if (mod > 0) mod *= 2;
|
||||
mod = 100 + getstatmod(lf, A_CON);
|
||||
if (db) dblog("rollhitdice() - mod is +%0.0f%%",mod);
|
||||
|
||||
if (ndice == 0) {
|
||||
int thisroll;
|
||||
// just the bonus
|
||||
thisroll = plus;
|
||||
thisroll = thisroll + (int)((float)thisroll * (mod/100));
|
||||
|
||||
if (thisroll < 1) thisroll = 1;
|
||||
|
||||
roll += thisroll;
|
||||
|
@ -1206,8 +1205,8 @@ int rollhitdice(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
if (db) dblog("TOTAL: %d",roll);
|
||||
roll = roll + (int)((float)roll * (mod/100));
|
||||
// must be at least 1!!
|
||||
// modify for fitness/con
|
||||
roll = pctof(mod, roll);
|
||||
limit(&roll, 1, NA);
|
||||
if (db) dblog(" -> modified to: %d",roll);
|
||||
return roll;
|
||||
|
@ -1227,12 +1226,11 @@ int rollmpdice(lifeform_t *lf) {
|
|||
} else {
|
||||
return 0;
|
||||
}
|
||||
mod = getstatmod(lf, A_IQ);
|
||||
if (mod > 0) mod *= 2;
|
||||
mod = 100 + getstatmod(lf, A_IQ);
|
||||
|
||||
roll = rolldie(ndice, 4) + plus;
|
||||
|
||||
roll = roll + (int)((float)roll * (mod/100));
|
||||
roll = pctof(mod, roll);
|
||||
return roll;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ objecttype_t *findot(enum OBTYPE id);
|
|||
objecttype_t *findotn(char *name); // find objecttype by name
|
||||
void fragments(cell_t *centre, char *what, int speed, int howfar);
|
||||
void genhiddennames(void);
|
||||
object_t *getbestcontainer(obpile_t *op);
|
||||
int getchargeinfo(object_t *o, int *cur, int *max);
|
||||
int getcharges(object_t *o);
|
||||
int geteffecttime(int min, int max, enum BLESSTYPE isblessed);
|
||||
|
|
438
spell.c
438
spell.c
|
@ -19,6 +19,7 @@
|
|||
extern lifeform_t *player;
|
||||
extern skill_t *firstskill, *lastskill;
|
||||
extern race_t *firstrace, *lastrace;
|
||||
extern knowledge_t *knowledge;
|
||||
|
||||
extern int needredraw;
|
||||
|
||||
|
@ -1814,15 +1815,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
int d;
|
||||
float totweight = 0;
|
||||
int powerinc = 0;
|
||||
object_t *o;
|
||||
for (d = DC_N; d <= DC_NW; d++) {
|
||||
c = getcellindir(caster->cell, d);
|
||||
if (c) {
|
||||
object_t *o;
|
||||
for (o = c->obpile->first ; o ; o = o->next){
|
||||
if (o->type->obclass->id == OC_FLORA) totweight += getobweight(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (o = caster->cell->obpile->first ; o ; o = o->next){
|
||||
if (o->type->obclass->id == OC_FLORA) totweight += getobweight(o);
|
||||
}
|
||||
for (o = caster->pack->first ; o ; o = o->next){
|
||||
if (o->type->obclass->id == OC_FLORA) totweight += getobweight(o);
|
||||
}
|
||||
powerinc = totweight / 50;
|
||||
if (powerinc > 0) {
|
||||
power += powerinc;
|
||||
|
@ -2150,7 +2157,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
teleportto(caster, targcell, B_TRUE);
|
||||
}
|
||||
} else if (spellid == OT_S_BODYCONTROL) {
|
||||
} else if (spellid == OT_S_LOWERMETAB) {
|
||||
flag_t *f;
|
||||
// ie. 2 - 4
|
||||
f = addtempflag(caster->flags, F_SLOWMETAB, 2+(power/4), NA, NA, NULL, FROMSPELL);
|
||||
|
@ -2213,6 +2220,62 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (cansee(player, caster)) {
|
||||
needredraw = B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_CONFISCATE) {
|
||||
object_t *o;
|
||||
char ch = 'a';
|
||||
char obname[BUFLEN];
|
||||
// ask for a target cell
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
|
||||
|
||||
target = targcell->lf;
|
||||
if (!target) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
// take an object
|
||||
initprompt(&prompt, "Confiscate which object?");
|
||||
addchoice(&prompt, '-', "(Cancel)", NULL, NULL);
|
||||
for (o = target->pack->first ; o ; o = o->next) {
|
||||
getobname(o, obname, o->amt);
|
||||
addchoice(&prompt, ch, obname, NULL, o);
|
||||
if (ch == 'z') {
|
||||
ch = 'A';
|
||||
} else {
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
if (isplayer(caster)) {
|
||||
// select one
|
||||
getchoice(&prompt);
|
||||
o = (object_t *)prompt.result;
|
||||
} else {
|
||||
// random one
|
||||
o = (object_t *) prompt.choice[rnd(0,prompt.nchoices-1)].data;
|
||||
}
|
||||
if (o) {
|
||||
if (isplayer(target)) {
|
||||
getobname(o, obname, o->amt);
|
||||
msg("^%cYour %s vanish%s!", getlfcol(target, CC_VBAD), noprefix(obname), (o->amt == 1) ? "es" : "");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (isplayer(caster)) {
|
||||
char targname[BUFLEN];
|
||||
getlfname(target, targname);
|
||||
getobname(o, obname, o->amt);
|
||||
msg("%s%s %s appear%s in your pack!", targname, getpossessive(targname),
|
||||
noprefix(obname), (o->amt == 1) ? "es" : "");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (cansee(player, target)) {
|
||||
char targname[BUFLEN];
|
||||
getlfname(target, targname);
|
||||
getobname(o, obname, o->amt);
|
||||
msg("^%c%s%s %s vanish%s!", getlfcol(target, CC_VBAD), targname, getpossessive(targname), noprefix(obname),
|
||||
(o->amt == 1) ? "es" : "");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
moveob(o, caster->pack, ALL);
|
||||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_CALLLIGHTNING) {
|
||||
int failed = B_FALSE;
|
||||
// ask for a target cell
|
||||
|
@ -3311,30 +3374,32 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
int range;
|
||||
int x,y;
|
||||
// announce
|
||||
if (isplayer(caster) || cansee(player, caster)) {
|
||||
msg("%s emit%s a radial blast of energy!",castername,isplayer(caster) ? "" : "s");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
if (caster) {
|
||||
if (!targcell) targcell = caster->cell;
|
||||
if (isplayer(caster) || cansee(player, caster)) {
|
||||
msg("%s emit%s a radial blast of energy!",castername,isplayer(caster) ? "" : "s");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
range = 2 + (power / 4);
|
||||
animradial(caster->cell, range, '}', C_CYAN);
|
||||
animradial(targcell, range, '}', C_CYAN);
|
||||
|
||||
for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) {
|
||||
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
|
||||
targcell = getcellat(caster->cell->map, x,y);
|
||||
if (targcell && (getcelldist(caster->cell, targcell) <= range)) {
|
||||
if (targcell->lf && (targcell->lf != caster) && haslof(caster->cell, targcell, B_FALSE, NULL)) {
|
||||
for (y = targcell->y - range ; y <= targcell->y + range; y++) {
|
||||
for (x = targcell->x - range ; x <= targcell->x + range; x++) {
|
||||
cell_t *c;
|
||||
c = getcellat(targcell->map, x,y);
|
||||
if (c && (getcelldist(targcell, c) <= range)) {
|
||||
if (c->lf && (c->lf != caster) && haslof(targcell, c, B_FALSE, NULL)) {
|
||||
// automatic hit
|
||||
if (isplayer(targcell->lf)) {
|
||||
if (isplayer(c->lf)) {
|
||||
msg("A blast of energy hits you!");
|
||||
}
|
||||
/*
|
||||
if (haslos(caster, targcell)) {
|
||||
} else if (cansee(player, c->lf)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(c->lf, lfname);
|
||||
msg("A blast of energy hits %s.",lfname);
|
||||
}
|
||||
*/
|
||||
losehp(targcell->lf, rnd(2,6), DT_MAGIC, caster, "an energy blast");
|
||||
losehp(c->lf, rnd(2,6), DT_MAGIC, caster, "an energy blast");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4154,6 +4219,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
msg("%s glows for a moment.",buf);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if (spellid == OT_S_HUNGER) {
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
|
||||
|
||||
target = targcell->lf;
|
||||
if (!target) {
|
||||
fizzle(caster);
|
||||
return B_FALSE;
|
||||
}
|
||||
if (isplayer(target)) {
|
||||
// make more hungry
|
||||
modhunger(target, HUNGERCONST);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else {
|
||||
if (cansee(player, target)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(target, lfname);
|
||||
msg("%s looks ravenously hungry!", lfname);
|
||||
if (!lfhasflagval(target, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL)) {
|
||||
addflag(target->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL);
|
||||
}
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_ICEEDGE) {
|
||||
object_t *wep;
|
||||
enum DAMTYPE dt;
|
||||
|
@ -4533,6 +4621,17 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// 5 is the same as AT_VHIGH strength
|
||||
// 10 = gun speed
|
||||
fireat(caster, targob, 1, targcell, 8 + (power / 2) , NULL);
|
||||
} else if (spellid == OT_S_PLANESHIFT) {
|
||||
if (isplayer(caster)) {
|
||||
msg("^B__not yet implemented__");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else {
|
||||
if (cansee(player, caster)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
// for now, just disappear.
|
||||
unsummon(caster, B_TRUE);
|
||||
}
|
||||
} else if (spellid == OT_S_PARALYZE) {
|
||||
int howlong;
|
||||
int saved = B_FALSE;
|
||||
|
@ -5442,15 +5541,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
int i;
|
||||
char targname[BUFLEN];
|
||||
|
||||
if (isoutdoors(caster->cell->map)) {
|
||||
power += 5;
|
||||
limit(&power, NA, 10);
|
||||
}
|
||||
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER|TT_OBJECT, spellid, power, frompot)) return B_TRUE;
|
||||
|
||||
target = targcell->lf;
|
||||
|
||||
if (isoutdoors(targcell->map)) {
|
||||
power += 5;
|
||||
limit(&power, NA, 10);
|
||||
}
|
||||
|
||||
if (target) {
|
||||
getlfname(target, targname);
|
||||
// objects held by target
|
||||
|
@ -6000,7 +6100,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
return B_FALSE;
|
||||
}
|
||||
howlong = getspellduration(5,10,blessed) + (power/2);
|
||||
fallasleep(target, F_ASLEEP);
|
||||
fallasleep(target, howlong);
|
||||
if (isplayer(target) || haslos(player, target->cell)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
|
@ -6121,6 +6221,53 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_SPEAKDEAD) {
|
||||
object_t *corpse = NULL;
|
||||
|
||||
if (!isplayer(caster)) {
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
corpse = hasobwithflag(caster->cell->obpile, F_CORPSEOF);
|
||||
if (corpse) {
|
||||
char buf[BUFLEN],corpsename[BUFLEN];
|
||||
char ch;
|
||||
getobname(corpse, corpsename, 1);
|
||||
sprintf(buf, "What will you ask %s?", corpsename);
|
||||
initprompt(&prompt, buf);
|
||||
addchoice(&prompt, 'a', "How did you die?", NULL, NULL);
|
||||
addchoice(&prompt, '-', "(nothing)", NULL, NULL);
|
||||
|
||||
ch = getchoice(&prompt);
|
||||
if (ch == 'a') {
|
||||
flag_t *f;
|
||||
char *p;
|
||||
|
||||
sprintf(buf, "%s whispers:", corpsename);
|
||||
msg(buf);
|
||||
|
||||
f = hasflag(corpse->flags, F_CORPSEOF);
|
||||
if (f && strlen(f->text)) {
|
||||
char killer[BUFLEN];
|
||||
char weapon[BUFLEN];
|
||||
p = readuntil(killer, f->text, '^');
|
||||
if (strstr(p, "weilding")) {
|
||||
p = readuntil(weapon, p, '^');
|
||||
} else {
|
||||
strcpy(weapon, "");
|
||||
}
|
||||
sprintf(buf, "\"I was killed by %s", killer);
|
||||
if (strlen(weapon)) {
|
||||
strcat(buf, ", ");
|
||||
strcat(buf, weapon);
|
||||
}
|
||||
strcat(buf, ".\"");
|
||||
msg(buf);
|
||||
} else {
|
||||
msg("\"I do not know what killed me.\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_STENCH) {
|
||||
int howlong;
|
||||
if (!validatespellcell(caster, &targcell,TT_OBJECT | TT_MONSTER, spellid, power, frompot)) return B_TRUE;
|
||||
|
@ -6271,6 +6418,36 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_STUN) {
|
||||
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
|
||||
target = targcell->lf;
|
||||
|
||||
if (lfhasflag(target, F_ASLEEP) || !ischarmable(target)) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
|
||||
if (isplayer(target)) {
|
||||
msg("You shrug off a mental attack.");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, target->cell)) {
|
||||
getlfname(target, buf);
|
||||
msg("%s shrugs off %s mental attack.", buf, isplayer(caster) ? "your" : "a");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
} else {
|
||||
if (isplayer(target)) {
|
||||
msg("You are stunned!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (haslos(player, target->cell)) {
|
||||
getlfname(target, buf);
|
||||
msg("%s is stunned!", buf);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
taketime(target, getactspeed(target)*2);
|
||||
}
|
||||
} else if (spellid == OT_S_SUCK) {
|
||||
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
|
||||
|
||||
|
@ -7028,6 +7205,203 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
f = addtempflag(caster->flags, F_WINDSHIELD, power, NA, NA, NULL, FROMSPELL);
|
||||
f->obfrom = spellid;
|
||||
} else if (spellid == OT_S_WISHLIMITED) {
|
||||
object_t *o;
|
||||
char obname[BUFLEN];
|
||||
char ch;
|
||||
if (!target) target = caster;
|
||||
initprompt(&prompt, "For what do you wish?");
|
||||
addchoice(&prompt, 'a', "Wealth", NULL, NULL);
|
||||
addchoice(&prompt, 'b', "Power", NULL, NULL);
|
||||
addchoice(&prompt, 'c', "Protection", NULL, NULL);
|
||||
addchoice(&prompt, 'd', "Fame", NULL, NULL);
|
||||
addchoice(&prompt, 'e', "Knowledge", NULL, NULL);
|
||||
addchoice(&prompt, 'f', "Magic", NULL, NULL);
|
||||
if (isplayer(target)) {
|
||||
ch = getchoice(&prompt);
|
||||
} else {
|
||||
ch = 'e';
|
||||
// ie. don't select 'knowledge'
|
||||
while (ch == 'e') {
|
||||
ch = rnd('a', 'f');
|
||||
}
|
||||
}
|
||||
if (ch == 'a') { // wealth (gold, bad: goldtouch)
|
||||
sprintf(buf, "1000-2000 gold coins");
|
||||
} else if (ch == 'b') { // power (weapons, bad: battery)
|
||||
skill_t *sk,*poss[MAXSKILLS];
|
||||
int nposs = 0;
|
||||
// get a list of all valid weapon skills
|
||||
for (sk = firstskill ; sk ; sk = sk->next) {
|
||||
if (isweaponskill(sk->id) && getskill(target, sk->id)) {
|
||||
poss[nposs++] = sk;
|
||||
}
|
||||
}
|
||||
if (nposs) {
|
||||
int nweps = 0;
|
||||
objecttype_t *ot;
|
||||
// pick a random one
|
||||
sk = poss[rnd(0,nposs-1)];
|
||||
// find all associated weapons
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (hasflagval(ot->flags, F_USESSKILL, sk->id, NA, NA, NULL)) {
|
||||
nweps++;
|
||||
}
|
||||
}
|
||||
if (nweps) {
|
||||
int sel,n = 0;
|
||||
sel = rnd(0,nweps-1);
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if (hasflagval(ot->flags, F_USESSKILL, sk->id, NA, NA, NULL)) {
|
||||
if (n == sel) break;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
sprintf(buf, "excellent branded %s", ot->name);
|
||||
} else {
|
||||
sprintf(buf, "stick");
|
||||
}
|
||||
} else {
|
||||
sprintf(buf, "stick");
|
||||
}
|
||||
} else if (ch == 'c') { // protection. bad: turn to stone
|
||||
enum BODYPART bp,poss[MAXBODYPARTS];
|
||||
int nposs = 0;
|
||||
// get a list of all valid body parts
|
||||
for (bp = 0; bp <= MAXBODYPARTS; bp++) {
|
||||
if (!lfhasflagval(target, F_NOBODYPART, bp, NA, NA, NULL)) {
|
||||
poss[nposs++] = bp;
|
||||
}
|
||||
}
|
||||
if (nposs) {
|
||||
int narms = 0;
|
||||
objecttype_t *ot;
|
||||
// pick a random body part
|
||||
bp = poss[rnd(0,nposs-1)];
|
||||
// find all associated armour
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if ((ot->obclass->id == OC_ARMOUR) && hasflagval(ot->flags, F_GOESON, bp, NA, NA, NULL)) {
|
||||
narms++;
|
||||
}
|
||||
}
|
||||
if (narms) {
|
||||
int sel,n = 0;
|
||||
sel = rnd(0,narms-1);
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if ((ot->obclass->id == OC_ARMOUR) && hasflagval(ot->flags, F_GOESON, bp, NA, NA, NULL)) {
|
||||
if (n == sel) break;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
sprintf(buf, "excellent branded %s", ot->name);
|
||||
} else {
|
||||
sprintf(buf, "sun hat");
|
||||
}
|
||||
} else {
|
||||
sprintf(buf, "sun hat");
|
||||
}
|
||||
} else if (ch == 'd') { // fame (allies bad: useless allies)
|
||||
lifeform_t *lf;
|
||||
cell_t *c;
|
||||
job_t *j;
|
||||
char *p,lfname[BUFLEN];
|
||||
// summon a human
|
||||
c = getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
||||
j = getrandomjob(B_TRUE);
|
||||
lf = addlf(c, R_HUMAN, target->level);
|
||||
givejob(lf, j->id);
|
||||
getlfnamea(lf, lfname);
|
||||
if (cansee(player, lf)) {
|
||||
msg("%s appears!", lfname);
|
||||
}
|
||||
petify(lf, target);
|
||||
|
||||
if (isplayer(target)) {
|
||||
p = assignnpcname(lf);
|
||||
sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p);
|
||||
}
|
||||
|
||||
strcpy(buf, "");
|
||||
} else if (ch == 'e') { // knowledge (makeknown everything you have plus 5-10 others. bad: insanity)
|
||||
// only possible for the player!
|
||||
strcpy(buf, "");
|
||||
if (isplayer(target)) {
|
||||
knowledge_t *k;
|
||||
msg("^GKnowledge floods into your mind!");
|
||||
for (o = target->pack->first ; o ; o = o->next) {
|
||||
if (!isidentified(o)) {
|
||||
identify(o);
|
||||
getobname(o, obname, o->amt);
|
||||
msgnocap("%c - %s.", o->letter, obname);
|
||||
}
|
||||
}
|
||||
// now identify everything that you have tried,
|
||||
// and 10% chance of identifying others
|
||||
for (k = knowledge; k ; k = k->next) {
|
||||
if ((k->known == B_TRIED) || pctchance(10)) {
|
||||
makeknown(k->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ch == 'f') { // magic (spellbooks)
|
||||
objecttype_t *ot,*poss[MAXCANDIDATES];
|
||||
int nposs = 0;
|
||||
// find all castable spells (spellpower > 0)
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if ((ot->obclass->id == OC_SPELL) && getspellpower(target, ot->id)) {
|
||||
poss[nposs++] = ot;
|
||||
}
|
||||
}
|
||||
if (!nposs) {
|
||||
// give knowledge of a random spell school plus sorcery
|
||||
enum SPELLSCHOOL school;
|
||||
skill_t *poss2[MAXSKILLS],*sk;
|
||||
int nposs2 = 0;
|
||||
giveskill(target, SK_SPELLCASTING);
|
||||
for (school = SS_AIR; school < SS_LAST; school++) {
|
||||
sk = findskill(getschoolskill(school));
|
||||
poss2[nposs2++] = sk;
|
||||
}
|
||||
sk = poss2[rnd(0,nposs2-1)];
|
||||
giveskill(target, sk->id);
|
||||
|
||||
// ... then try to find castable spells again
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
if ((ot->obclass->id == OC_SPELL) && getspellpower(target, ot->id)) {
|
||||
poss[nposs++] = ot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nposs) {
|
||||
// pick a random spell from this list
|
||||
ot = poss[rnd(0,nposs-1)];
|
||||
sprintf(buf, "spellbook of %s",ot->name);
|
||||
} else {
|
||||
strcpy(buf, "");
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(buf)) {
|
||||
// give the object
|
||||
o = addob(target->pack, buf);
|
||||
getobname(o, obname, o->amt);
|
||||
msgnocap("%c - %s.", o->letter, obname);
|
||||
}
|
||||
|
||||
// now age the caster
|
||||
if (!isgod(caster)) {
|
||||
caster->maxhp -= pctof(25,caster->maxhp);
|
||||
limit(&caster->hp, NA, caster->maxhp);
|
||||
if (isplayer(caster)) {
|
||||
msg("^BYour body ages unnaturally!");
|
||||
statdirty = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (isplayer(target)) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
} else if ((spellid == OT_S_WISH) || (spellid == OT_S_GIFT)) {
|
||||
object_t *o;
|
||||
if (isplayer(caster)) {
|
||||
|
@ -7091,6 +7465,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// couldn't make it appear - ob doesn't exist
|
||||
msg("The air in front of %s seems to ripple for a while.", lfname);
|
||||
}
|
||||
|
||||
// now age the caster
|
||||
if (!isgod(caster)) {
|
||||
caster->maxhp -= pctof(50,caster->maxhp);
|
||||
limit(&caster->hp, NA, caster->maxhp);
|
||||
if (isplayer(caster)) {
|
||||
msg("^BYour body ages unnaturally!");
|
||||
statdirty = B_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// monsters can't wish
|
||||
}
|
||||
|
@ -7127,7 +7511,9 @@ void fizzle(lifeform_t *caster) {
|
|||
}
|
||||
}
|
||||
|
||||
enum OBTYPE getrandomspell(void) {
|
||||
|
||||
// maxlev <= 0 means 'any lev'
|
||||
enum OBTYPE getrandomspell(int maxlev) {
|
||||
int wantlev;
|
||||
objecttype_t *ot,*poss[MAXCANDIDATES];
|
||||
int nposs = 0;
|
||||
|
@ -7136,6 +7522,7 @@ enum OBTYPE getrandomspell(void) {
|
|||
while (rnd(1,2) == 1) {
|
||||
wantlev++;
|
||||
}
|
||||
limit(&wantlev, 1, maxlev);
|
||||
|
||||
// get list of all spells of this level
|
||||
for (ot = objecttype ; ot ; ot = ot->next) {
|
||||
|
@ -7343,6 +7730,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
|
|||
if (db) {
|
||||
dblog("-->power = %d (from canwill)", power);
|
||||
}
|
||||
// note that this power _can_ override max spell power
|
||||
return power;
|
||||
}
|
||||
}
|
||||
|
@ -7740,7 +8128,7 @@ void pullobto(object_t *o, lifeform_t *lf) {
|
|||
if (isplayer(lf) || haslos(player, lf->cell)) {
|
||||
msg("%s %s %s.", lfname, isplayer(lf) ? "catch" : "catches", obname);
|
||||
}
|
||||
pickup(lf, o, o->amt, B_FALSE);
|
||||
pickup(lf, o, o->amt, B_FALSE, B_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
spell.h
2
spell.h
|
@ -8,7 +8,7 @@ objecttype_t *findspelln(char *buf);
|
|||
void fizzle(lifeform_t *caster);
|
||||
//int getiqreq(enum OBTYPE oid);
|
||||
int getmpcost(lifeform_t *lf, enum OBTYPE oid);
|
||||
enum OBTYPE getrandomspell(void);
|
||||
enum OBTYPE getrandomspell(int maxlev);
|
||||
enum SKILL getschoolskill(enum SPELLSCHOOL ss);
|
||||
char *getspellcosttext(lifeform_t *lf, enum OBTYPE spellid, int power, char *buf);
|
||||
int getspellduration(int min,int max,int blessed);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#:cell:rock wall
|
||||
|:ob:locked iron gate
|
||||
,:ob:1-4 bones:50
|
||||
,:mon:prisoner:50
|
||||
+:ob:wooden door
|
||||
/:ob:wooden table
|
||||
-:ob:wooden footstool
|
||||
|
|
Loading…
Reference in New Issue