* [+] darkmantle DARKNES isn't working! (but it does work if i cast it)

* [+] "you arrive at level 2" "it is pitch black" - but it isn't
- [+] make detect magic find more things
* [+] make some objects harder to identify? from easy->hard
* [+] magic item usage skill
- [+] with 'R', ask "heal mp, hp or both?"
- [+] make dt_fire damage evaporate water.
- [+] make ring of sight increase nightvis and nomal visrange slightly
      too
- [+] FIX seeindark to give RANGE.
* [+] BUG: monster moved on top of me!
* [+] boost spells
* [+] more boost spells
- [+] modify accuracy based on size difference.
* [+] ooze should hurt objects it steps on
* [+] resist magic save
- [+] potion of blood
- [+] ability to fill a potion with blood / water
- [+] better potion -> splash code.
- [+] stop stoning when you polymorph
- [+] can't stone incorporeal or gaseos things
- [+] cockatrice blood
- [+] cockatrice
- [+] when being stoned, give 1 turn's grace
- [+] gain/lose text for "CANWILL" 
- [+] things killed by poison gas should have tainted corpses
- [+] make troglodyte corpses poisonous
* [+] smallteeth vs teeth
- [+] fix hitconfer code
This commit is contained in:
Rob Pearce 2011-03-22 07:06:28 +00:00
parent cc969bb800
commit 4edc66af47
23 changed files with 2449 additions and 10349 deletions

42
ai.c
View File

@ -618,7 +618,7 @@ void aimove(lifeform_t *lf) {
// need to heal?
if ((lf->hp < lf->maxhp) ||
((lf->mp < lf->maxmp) && lfhasflag(lf, F_RESTHEALMPAMT)) ) {
((lf->mp < getmaxmp(lf)) && lfhasflag(lf, F_RESTHEALMPAMT)) ) {
if (lf->hp < (lf->maxhp/2)) {
if (!useitemwithflag(lf, F_AIHEALITEM)) {
return;
@ -700,20 +700,34 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
strcpy(why, "spell too powerful");
} else if (reason == E_NOTREADY) {
strcpy(why, "abil not ready");
} else if (reason == E_NEEDGRAB) {
strcpy(why, "needs grab");
} else {
strcpy(why, "unknown reason");
}
if (ot) {
dblog(".oO { can't cast %s right now (%s) (mpcost=%d, i have %d) }",
ot ? ot->name : "?unkownspell?", why,
getmpcost(ot->id), lf->mp);
} else {
dblog(".oO { can't cast ?unknownspell? right now }");
if (db) {
if (ot) {
dblog(".oO { can't cast %s right now (%s) (mpcost=%d, i have %d) }",
ot ? ot->name : "?unkownspell?", why,
getmpcost(lf, ot->id), lf->mp);
} else {
dblog(".oO { can't cast ?unknownspell? right now }");
}
}
}
return B_FALSE;
}
// boost spell already active?
if (hasflag(ot->flags, F_ONGOING)) {
if (lfhasflagval(lf, F_BOOSTSPELL, ot->id, NA, NA, NULL)) {
if (db) {
dblog(".oO { can't cast %s - it is already active.", ot ? ot->name : "?unkownspell?");
}
return B_FALSE;
}
}
f = hasflag(ot->flags, purpose);
if (f) {
int range;
@ -817,12 +831,26 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if ((ot->id == OT_S_HEALINGMIN) && (lf->hp >= lf->maxhp)) {
return B_FALSE;
}
if ((ot->id == OT_S_PARALYZE) && lfhasflag(victim, F_PARALYZED)) {
return B_FALSE;
}
if ((ot->id == OT_S_SLEEP) && lfhasflag(victim, F_ASLEEP)) {
return B_FALSE;
}
if ((ot->id == OT_S_SLOW) && lfhasflag(victim, F_SLOWACT)) {
return B_FALSE;
}
if ((ot->id == OT_A_SPRINT) && lfhasflag(lf, F_SPRINTING)) {
return B_FALSE;
}
if ((ot->id == OT_S_WEAKEN)) {
flag_t *lff;
for (lff = lf->flags->first; lff ; lff = lff->next) {
if ((lff->id == F_ATTRMOD) && (lff->val[0] == A_STR) && (lff->obfrom == OT_S_WEAKEN)) {
return B_FALSE;
}
}
}
return B_TRUE;
}

201
attack.c
View File

@ -103,6 +103,14 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
aidb = B_TRUE;
}
moveeffects(lf);
if (isdead(lf)) {
return B_TRUE;
}
// get names
getlfname(lf, attackername);
@ -273,7 +281,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
if (fatal) {
verb = getkillverb(victim, damtype[i], dam[i], victim->maxhp);
} else {
verb = getattackverb(damtype[i], dam[i], victim->maxhp);
verb = getattackverb(lf, wep, damtype[i], dam[i], victim->maxhp);
}
warn("You %s %s%s%s",
verb,
@ -304,7 +312,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
strcpy(withwep, "");
}
strcpy(attackverb, getattackverb(damtype[i],dam[i],victim->maxhp));
strcpy(attackverb, getattackverb(lf, wep, damtype[i],dam[i],victim->maxhp));
if ((dam[i] == 0) && (damtype[i] != DT_TOUCH)) {
strcpy(nodamstr, " but does no damage");
} else {
@ -354,7 +362,9 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
} // end foreach damtype
// special weapon effects
wepeffects(wep, victim->cell);
if (dam[0]) {
wepeffects(wep->flags, victim->cell);
}
if (!isdead(victim)) {
if (unarmedflag) {
@ -404,6 +414,32 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
}
}
// confer flags from attacker?
if (dam[0]) {
wepeffects(lf->flags, victim->cell);
}
// special lifeform-based effects
if ((lf->race->id == R_COCKATRICE) && dam[0]) {
// first saving throw...
if (skillcheck(victim, SC_CON, 25, 0)) {
// slowed
addtempflag(victim->flags, F_SLOWMOVE, 15, NA, NA, NULL, 2);
addtempflag(victim->flags, F_SLOWACT, 15, NA, NA, NULL, 2);
} else {
// second saving throw...
if (skillcheck(victim, SC_CON, 25, 0)) {
// paralyzed
addtempflag(victim->flags, F_PARALYZED, B_TRUE, NA, NA, NULL, 5);
} else {
if (!lfhasflag(lf, F_BEINGSTONED)) {
// stoned!
addflag(victim->flags, F_BEINGSTONED, 2, NA, NA, NULL);
}
}
}
}
}
} else { // miss!
if (aidb) dblog(".oO { i missed! }");
@ -477,6 +513,8 @@ int attackob(lifeform_t *lf, object_t *o) {
//int aidb = B_TRUE;
int maxhp;
moveeffects(lf);
if (isdead(lf)) return B_TRUE;
// get names
getlfname(lf, attackername);
@ -546,7 +584,7 @@ int attackob(lifeform_t *lf, object_t *o) {
} else {
strcpy(extradambuf, "");
}
msg("You %s %s.", getattackverb(damtype[i], dam[i], maxhp),
msg("You %s %s.", getattackverb(lf, wep, damtype[i], dam[i], maxhp),
obname, extradambuf);
} else if (cansee(player, lf)) {
char withwep[BUFLEN];
@ -558,7 +596,7 @@ int attackob(lifeform_t *lf, object_t *o) {
}
msg("%s %ss %s%s.", attackername,
getattackverb(damtype[i],dam[i],maxhp), obname,withwep);
getattackverb(lf, wep, damtype[i],dam[i],maxhp), obname,withwep);
} else {
youhear(lf->cell, "sounds of fighting");
}
@ -579,7 +617,9 @@ int attackob(lifeform_t *lf, object_t *o) {
} // end foreach damtype
// special weapon effects
wepeffects(wep, obloc);
if (dam[0]) {
wepeffects(wep->flags, obloc);
}
if (unarmedflag) {
// touch effects
@ -624,10 +664,27 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d
// returns a const char *
char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) {
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp) {
float pct;
enum LFSIZE ownersize = SZ_HUMAN;
if (lf) {
ownersize = getlfsize(lf);
}
pct = (int)(((float) dam / (float) maxhp) * 100.0);
if (damtype == DT_BASH) {
if (wep) {
flag_t *f;
f = hasflag(wep->flags, F_ATTACKVERB);
if (f) {
return f->text;
}
}
if (damtype == DT_ACID) {
return "burn";
} else if (damtype == DT_BASH) {
if (pct <= 5) {
return "whack";
} else if (pct <= 20) {
@ -640,12 +697,20 @@ char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp) {
return "pummel";
}
} else if (damtype == DT_BITE) {
if (pct <= 5) {
return "gnaw";
} else if (pct <= 30) {
return "bite";
if (lf && (ownersize <= SZ_SMALL)) {
if (pct <= 5) {
return "nip";
} else if (pct <= 30) {
return "bite";
}
} else {
return "savage";
if (pct <= 5) {
return "gnaw";
} else if (pct <= 30) {
return "bite";
} else {
return "savage";
}
}
} else if (damtype == DT_CLAW) {
if (pct <= 5) {
@ -1088,6 +1153,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
object_t *wep;
obpile_t *op = NULL;
int gothit;
enum LFSIZE szlf,szvictim;
if (critical) {
*critical = 0;
@ -1100,6 +1166,19 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
ev = getevasion(victim);
acc -= ev;
// size difference
szlf = getlfsize(lf);
szvictim = getlfsize(victim);
if (szvictim < szlf) {
// if defender is smaller...
// -7% per size difference
acc -= (7 * (szlf - szvictim));
} else if (szvictim > szlf) {
// if defender is bigger...
// +7% per size difference
acc += (7 * (szvictim - szlf));
}
// modify if we can't see the victim
if (!cansee(lf, victim)) {
acc -= 50;
@ -1134,16 +1213,19 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
return gothit;
}
void wepeffects(object_t *wep, cell_t *where) {
void wepeffects(flagpile_t *fp, cell_t *where) {
flag_t *f;
lifeform_t *victim;
lifeform_t *owner;
owner = wep->pile->owner;
victim = where->lf;
object_t *wep;
if (!where) return;
for (f = wep->flags->first ; f ; f = f->next) {
wep = fp->ob;
owner = fp->owner;
victim = where->lf;
for (f = fp->first ; f ; f = f->next) {
if (f->id == F_FLAMESTRIKE) {
if (!hasob(where->obpile, OT_FIRESMALL)) {
// ignite!
@ -1154,36 +1236,6 @@ void wepeffects(object_t *wep, cell_t *where) {
f->known = B_KNOWN;
}
}
} else if ((f->id == F_HITCONFER) && victim && !isdead(victim)) {
enum FLAG fid;
int val0,val1;
int min,max,howlong;
fid = f->val[0];
if (!lfhasflag(victim, fid)) {
val0 = f->val[1];
val1 = f->val[2];
if (f->text) {
char loctext[BUFLEN];
char *word, *dummy;
strcpy(loctext,f->text);
word = strtok_r(loctext, "-", &dummy);
if (word) {
min = atoi(word);
word = strtok_r(NULL, "-", &dummy);
if (word) {
max = atoi(word);
howlong = rnd(min,max);
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
addtempflag(victim->flags, fid, val0, val1, NA, NULL, howlong);
}
} else if ((f->id == F_REVENGE) && victim && !isdead(victim)) {
lifeform_t *owner;
owner = wep->pile->owner;
@ -1230,6 +1282,57 @@ void wepeffects(object_t *wep, cell_t *where) {
dir = getdirtowards(owner->cell, victim->cell, victim, B_FALSE);
knockback(victim, dir , 2, owner);
f->known = B_TRUE;
}
} else if ((f->id == F_HITCONFER) && victim ) {
enum FLAG fid;
int min,max,howlong;
fid = f->val[0];
if (!lfhasflag(victim, fid)) {
int passedcheck = B_FALSE;
if (!f->val[1] == NA) {
int scdiff;
if (f->val[2] == NA) {
scdiff = 20; // default
} else {
scdiff = f->val[2];
}
if (skillcheck(victim, f->val[1], scdiff, 0)) {
passedcheck = B_TRUE;
}
}
if (!passedcheck) {
int val0;
val0 = f->val[1];
if (f->text) {
char loctext[BUFLEN];
char *word, *dummy;
strcpy(loctext,f->text);
word = strtok_r(loctext, "-", &dummy);
if (word) {
min = atoi(word);
word = strtok_r(NULL, "-", &dummy);
if (word) {
max = atoi(word);
howlong = rnd(min,max);
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
} else {
howlong = PERMENANT;
}
addtempflag(victim->flags, fid, val0, NA, NA, NULL, howlong);
} // end if passedcheck
} // end (if victim doesn't already have the flag)
// was this from a poisoned weapon? if so the poison vanishes
if ((f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
killflag(f);
}
} // end if (fid == hitconfer)
}
}

View File

@ -5,8 +5,9 @@ void applyarmourdamreduction(lifeform_t *lf, object_t *wep, int reduceamt, int *
int attackcell(lifeform_t *lf, cell_t *c);
int attacklf(lifeform_t *lf, lifeform_t *victim);
int attackob(lifeform_t *lf, object_t *o);
void confereffects(flagpile_t *fp, lifeform_t *victim);
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype);
char *getattackverb(enum DAMTYPE damtype, int dam, int maxhp);
char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
object_t *getattackwep(lifeform_t *lf, obpile_t **unarmedpile, flag_t **unarmedflag);
enum DAMTYPE getdamtype(object_t *wep);
int getextradam(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam);
@ -19,4 +20,4 @@ int getdamrollfromflag(flag_t *f);
float getstrdammod(lifeform_t *lf);
obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical);
void wepeffects(object_t *wep, cell_t *where);
void wepeffects(flagpile_t *fp, cell_t *where);

82
defs.h
View File

@ -45,6 +45,9 @@ enum CHECKTYPE {
SC_SLIP,
SC_MORALE,
SC_OPENLOCKS,
SC_POISON,
SC_RESISTMAG,
SC_WILL,
};
enum BURDENED {
@ -86,6 +89,7 @@ enum LFCONDITION {
#define FROMBLESSING (-9866)
#define FROMBRAND (-9865)
#define FROMOBMOD (-9864)
#define FROMSPELL (-9863)
#define IFKNOWN (-9772) // used by f_xxconfer. only confer a flag if item is known.
@ -367,9 +371,11 @@ enum DAMTYPE {
DT_LIGHT = 21,
DT_CRUSH = 22,
DT_FALL = 23,
DT_NONE = 24, // for direclty dealt damage, not really any type
DT_PETRIFY = 24,
DT_POISON = 25,
DT_NONE = 26, // for direclty dealt damage, not really any type
};
#define MAXDAMTYPE 25
#define MAXDAMTYPE 27
// Object Classes
enum OBCLASS {
@ -423,7 +429,9 @@ enum RACE {
R_NONE, R_RANDOM,
R_HUMAN,
// monsters
R_BEHOLDER,
R_BUGBEAR,
R_COCKATRICE,
R_DARKMANTLE,
R_EYEBAT,
R_GIANTHILL,
@ -456,9 +464,13 @@ enum RACE {
R_TROLL,
R_XAT,
// small animals
R_ANT,
R_ANTS,
R_BAT,
R_HAWK,
R_NEWT,
R_RAT,
R_SNAKE,
R_WOLF,
// insects
R_BUTTERFLY,
@ -518,6 +530,7 @@ enum MATERIAL {
MT_GAS = 20,
MT_SLIME = 21,
MT_WAX = 22,
MT_ACID = 23,
};
// Object Types
@ -572,6 +585,8 @@ enum OBTYPE {
OT_POT_ACID,
OT_POT_ACROBATICS,
OT_POT_AMBROSIA,
OT_POT_BLOOD,
OT_POT_BLOODC,
OT_POT_COMPETENCE,
OT_POT_ELEMENTENDURE,
OT_POT_ELEMENTIMMUNE,
@ -614,8 +629,10 @@ enum OBTYPE {
OT_MAN_ATHLETICS,
OT_MAN_FIRSTAID,
OT_MAN_LOCKPICKING,
OT_MAN_MAGITEMUSAGE,
OT_MAN_RESEARCH,
OT_MAN_SPELLCASTING,
OT_MAN_TECHUSAGE,
// manuals of weaponry
OT_MAN_AXES,
OT_MAN_CLUBS,
@ -638,12 +655,12 @@ enum OBTYPE {
OT_MAN_SS_SUMMONING,
OT_MAN_SS_TRANSLOCATION,
OT_MAN_SS_WILD,
OT_MAN_TECHUSAGE,
// SPELLBOOKS
// allomancy can't be learned from books
// -- death
OT_SB_ANIMATEDEAD,
OT_SB_PAIN,
OT_SB_PARALYZE,
OT_SB_INFINITEDEATH,
OT_SB_WEAKEN,
OT_SB_BLINDNESS,
@ -653,6 +670,7 @@ enum OBTYPE {
OT_SB_IDENTIFY,
OT_SB_MAPPING,
// -- elemental - air
OT_SB_AIRBLAST,
OT_SB_CLOUDKILL,
// -- elemental - fire
OT_SB_SPARK,
@ -665,16 +683,20 @@ enum OBTYPE {
OT_SB_CONECOLD,
OT_SB_FREEZEOB,
// -- gravity
OT_SB_GRAVLOWER,
OT_SB_GRAVBOOST,
OT_SB_HASTE,
OT_SB_FLIGHT,
OT_SB_SLOW,
OT_SB_LEVITATION,
// -- life
OT_SB_HEALING,
OT_SB_HEALINGMIN,
OT_SB_TURNUNDEAD,
// -- mental
// -- mental / psionic
OT_SB_MINDSCAN,
OT_SB_TELEKINESIS,
OT_SB_PSYARMOUR,
// -- modification
OT_SB_GASEOUSFORM,
OT_SB_KNOCK,
@ -705,6 +727,7 @@ enum OBTYPE {
// -- death
OT_S_ANIMATEDEAD,
OT_S_PAIN,
OT_S_PARALYZE,
OT_S_INFINITEDEATH,
OT_S_WEAKEN,
OT_S_BLINDNESS,
@ -715,6 +738,7 @@ enum OBTYPE {
OT_S_IDENTIFY,
OT_S_MAPPING,
// -- elemental - air
OT_S_AIRBLAST,
OT_S_CLOUDKILL,
// -- elemental - fire
OT_S_SPARK,
@ -727,17 +751,21 @@ enum OBTYPE {
OT_S_CONECOLD,
OT_S_FREEZEOB,
// -- gravity
OT_S_GRAVLOWER,
OT_S_GRAVBOOST,
OT_S_HASTE,
OT_S_SLOW,
OT_S_LEVITATION,
OT_S_FLIGHT,
// -- life
OT_S_HEALING,
OT_S_HEALINGMIN,
OT_S_TURNUNDEAD,
// -- mental
// -- mental / psionic
OT_S_MINDSCAN,
OT_S_SLEEP,
OT_S_TELEKINESIS,
OT_S_PSYARMOUR,
// -- modification
OT_S_ENCHANT,
OT_S_GASEOUSFORM,
@ -776,6 +804,7 @@ enum OBTYPE {
OT_A_EMPLOY,
OT_A_HEAVYBLOW,
OT_A_INSPECT,
OT_A_STINGACID, // need to define dam in f_canwill
// wands
OT_WAND_COLD,
OT_WAND_DETONATION,
@ -826,11 +855,14 @@ enum OBTYPE {
OT_ICESHEET,
OT_PUDDLEWATER,
OT_PUDDLEWATERL,
OT_ACIDPUDDLE,
OT_ACIDPOOL,
OT_SLIMEPOOL,
OT_VOMITPOOL,
OT_BLOODSTAIN,
OT_BLOODSPLASH,
OT_BLOODPOOL,
OT_BLOODCSPLASH,
OT_MELTEDWAX,
OT_SOGGYPAPER,
OT_FLESHCHUNK,
@ -839,6 +871,8 @@ enum OBTYPE {
OT_FIREMED,
OT_FIRESMALL,
OT_MAGICBARRIER,
OT_STEAMCLOUD,
OT_STEAMPUFF,
OT_SMOKECLOUD,
OT_SMOKEPUFF,
OT_POISONCLOUD,
@ -899,8 +933,10 @@ enum OBTYPE {
// animal weapons
OT_CLAWS,
OT_FISTS,
OT_STING,
OT_TAIL,
OT_TEETH,
OT_TEETHSM,
OT_TENTACLE,
OT_ZAPPER,
// monster weapons
@ -1052,8 +1088,7 @@ enum FLAG {
F_ACTIVATECONFER, // gives flag v0+v1 when activated. v2 specifies if it must be id'd.
F_HITCONFER, // hitting with this gives flagid=v0
// with flagval0 = val1
// with flagval1 = val2
// unless you pass a val1 skillcheck, diff val2
// with timeleft = text ("min-max")
F_ACTIVATED, // val0 = is this object turned on?
F_GRENADE, // this obkejct will drain charge when activated, then die
@ -1114,8 +1149,10 @@ enum FLAG {
F_MASTERWORK, // weps do higher damager, armour protects better
F_SHODDY, // weps do less damage, armour protects less.
// weapon flags
F_ATTACKVERB, // text=verb for attacking. ie. "hit" "slash" "sting" etc
F_OBATTACKDELAY, // how long weapon takes to attack
F_USESSKILL, // weapon needs skill sk_v0
F_CANHAVEOBMOD, // weapon can have obmod om_v0 applied
F_DAMTYPE, // val0 = damage type
F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod
F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier)
@ -1149,6 +1186,8 @@ enum FLAG {
F_NOOBDAMTEXT, // don't anounce damage to this object
F_NOOBDIETEXT, // don't anounce destruction of this object
F_NODIECONVERTTEXT, // don't anounce when this object changes
// misc flags
F_LINKOB, // val0 = linked object id
// scroll flags
F_LINKSPELL, // val0 = spell this scroll will cast when read
// v1 = spell power
@ -1158,12 +1197,15 @@ enum FLAG {
F_HASHIDDENNAME, // whether this object class has a hidden name
F_IDENTIFIED, // whether this object is fully identified
// bad flags
F_WALKDAM, // val0 = dam per sec, val1 = damtype
F_WALKDAM, // val0 = damtype, text = dam per sec
// abilities
F_NEEDSGRAB, // this ability needs to to grab someone first.
// magic
F_SPELLSCHOOL, // val0 = SPELLSCHOOL enum
F_SPELLLEVEL, // val0 = difficulty level of spell
F_MAXPOWER, // val0 = max power of this spell (1-10)
F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2
F_ONGOING, // this spell has an ongoing cost
//F_SPELLLETTER, // text[0] = letter to cast this spell
F_AICASTTOFLEE, // AI can cast this spell to help flee
// v0 is who to target
@ -1205,8 +1247,9 @@ enum FLAG {
F_GUNTARGET, // current projectile weapon target
F_CASTINGSPELL, // set while the player is casting a spell
// v0 is spell id
// ABILITY FLAGS
// ABILITY/SPELL FLAGS
F_FAILEDINSPECT, // lf has failed an inspect check for item id v0
F_BOOSTSPELL, // v0 is active boost spell
// MONSTER AI FLAGS
F_XPVAL, // force xp val for killing this lf to v0
F_HOSTILE, // lf will attack the player if in sight
@ -1260,6 +1303,7 @@ enum FLAG {
F_NOPACK, // this race cannot hold objects
F_NOSPELLS, // this race cannot cast spells
F_INDUCEFEAR, // causes fear when you attack it
F_POISONOUS, // lf's corpse will be poisonous
F_AUTOCREATEOB, // produces obtype 'text' wherever it walks, v0=radius
// (only if ob of that type not already there)
F_PACKATTACK, // deal v0 extra damage of type v1 if there are
@ -1267,13 +1311,17 @@ enum FLAG {
// to the victim
F_PHALANX, // gain v0 AR if v2 or more adj monsters matching f->text
// INTRINSICS
F_ARBOOST,// armour is magically boosted
F_ASLEEP, // is asleep
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
F_BLIND, // cannot see anything
F_CANCAST, // can cast the spell val0 (need MP)
F_CANWILL, // can cast the spell val0 without using MP
// v1 is counter untiluse
// v2 is what you need to use it
// ie. when v1 == v2, ability is ready.
// text is other options, semicolon seperated:
// pw:xx; cast the spell at power xx
F_DETECTAURAS, // autodetect bless/curse
F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0
F_DETECTMAGIC, // autodetect magic/special objects
@ -1282,7 +1330,7 @@ enum FLAG {
F_FLYING, // lf is flying
F_FASTACT, // modifier for action speed
F_FASTMOVE, // modifier for move speed
F_FOODPOISONED, // has food poisoning
F_POISONED, // has food poisoning
F_FREEZINGTOUCH,// next thing touched turns to ice!
F_GRABBEDBY,// you've been grabbed by lf id v0
F_GRABBING, // you are grabbing lf id v0
@ -1292,7 +1340,7 @@ enum FLAG {
F_QUICKBITE, // deals v0 d d1 + d2 damage when you hit a bleeding victim
// (bypasses armour)
F_GRAVBOOSTED,// cannot walk or throw stuff
F_PAIN, // take damage if you walk
F_PAIN, // take damage if you walk. v0=damtype,text is damage (xdy+z).
F_PARALYZED,// cannot do anything
F_FROZEN, // made of ice
F_LEVITATING, // like flying but uncontrolled
@ -1302,7 +1350,7 @@ enum FLAG {
F_OMNIPOTENT, // knows extra info
F_PHOTOMEM, // you don't forget your surroundings
F_REGENERATES, // regenerate HP at val0 per turn
F_RESISTMAG, // immune to most magic effects
F_RESISTMAG, // immunity to magic effects. v0=amt (1-20)
F_MPREGEN, // regenerate MP at val0 per turn
F_SEEINDARK, // nightvis range is val0
F_SEEINVIS, // can see invisible things
@ -1329,12 +1377,14 @@ enum FLAG {
// damage (x y-sided dice + z)
F_EVASION, // % chance of evading an attack
// healing
// healing/resting/training
F_STATGAINREADY, // ready to increase str/int etc. v2 is how many times
// we can do it.
F_RESTING, // are we resting? cleared on any action other than rest.
// v2 = if not, NA it is the training counter.
// when it hits 0, you finish trainign.
F_RESTUNTILHP, // resting until we have full hp
F_RESTUNTILMP, // resting until we have full mp
//
F_RUNNING, // are we running?
// nutrition
@ -1476,6 +1526,7 @@ enum ERROR {
E_CANTMOVE = 34,
E_NOTKNOWN = 35,
E_TOOPOWERFUL = 36,
E_NEEDGRAB = 37,
};
@ -1547,6 +1598,7 @@ typedef struct cell_s {
struct obpile_s *obpile;
enum LIGHTLEV lit;
enum LIGHTLEV origlit;
int origlittimer;
int littimer;
char *writing;
@ -1680,8 +1732,10 @@ enum SKILL {
SK_ATHLETICS,
SK_FIRSTAID,
SK_LOCKPICKING,
SK_MAGITEMUSAGE,
SK_RESEARCH,
SK_SPELLCASTING,
SK_TECHUSAGE,
// weaponry
SK_AXES,
SK_CLUBS,
@ -1704,7 +1758,6 @@ enum SKILL {
SK_SS_SUMMONING,
SK_SS_TRANSLOCATION,
SK_SS_WILD,
SK_TECHUSAGE,
};
#define MAXSKILLS 31
@ -1794,6 +1847,7 @@ enum OBMOD {
OM_FROZEN,
OM_HEADLESS,
OM_MASTERWORK,
OM_POISONED,
OM_SHODDY,
};
#define MAXOBMODS 4

View File

@ -5,7 +5,8 @@ objects.c:
add an addmaterial() line
update adjustdammaterial() as required
update getmaterialvalue()
update issolidmat()
update getmaterialstate()
update ismetal()
update willshatter()

View File

@ -1,11 +1,11 @@
defs.h:
add the OT_xxx enum
(optional) add a scroll to do the same effect
(optional) add a potion to do the same effect
(optional) add a scroll to do the same effect - not for boosts though
(optional) add a potion to do the same effect - not for boosts though
objects.c:
define the spell
remember to have spelllevle
remember to have spelllevel
(optional) add a scroll to do the same effect, use F_LINKSPELL
(optional) add a potion to do the same effect
(optional) add a spellbook to learn it
@ -22,4 +22,5 @@ spell.c:
ai.c
update aigetspelltarget();
update aigetattackspell();
update aispellok();

40
flag.c
View File

@ -6,6 +6,7 @@
#include "io.h"
#include "lf.h"
#include "objects.h"
#include "spell.h"
#include "text.h"
extern enum GAMEMODE gamemode;
@ -31,6 +32,10 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
known = B_KNOWN;
}
if ((id == F_POISONED) && isimmuneto(fp, DT_POISON)) {
return NULL;
}
// certain flags stack...
if (flagstacks(id)) {
f = hasflag(fp, id);
@ -151,6 +156,20 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
}
}
// special effects
if (f->pile->owner) {
switch (f->id) {
case F_ASLEEP:
stopallspells(f->pile->owner);
break;
case F_NONCORPOREAL:
killflagsofid(f->pile->owner->flags, F_BEINGSTONED);
break;
default:
break;
}
}
if ((gamemode == GM_GAMESTARTED) && doredraw) {
statdirty = B_TRUE;
needredraw = B_TRUE;
@ -192,20 +211,20 @@ int flagstacks(enum FLAG fid) {
}
flag_t *hasflag(flagpile_t *fp, int id) {
return hasflag_real(fp, id, NA);
return hasflag_real(fp, id, NA, NULL);
}
flag_t *hasflagknown(flagpile_t *fp, int id) {
return hasflag_real(fp, id, B_TRUE);
return hasflag_real(fp, id, B_TRUE, NULL);
}
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown) {
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
flag_t *f;
lifeform_t *owner;
owner = fp->owner;
for (f = fp->first ; f ; f = f->next) {
if (f->id == id) {
if ((f->id == id) && (f != exception)) {
int valid = B_TRUE;
if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE;
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) {
@ -453,6 +472,19 @@ void timeeffectsflag(flag_t *f) {
}
}
}
if (f->id == F_BEINGSTONED) {
f->val[0]--;
if (f->val[0] == 0) {
if (!stone(f->pile->owner)) {
// lf turned to stone!
return;
} else {
// stoning failed. stop being stoned.
killflag(f);
}
}
}
}
void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2) {

2
flag.h
View File

@ -10,7 +10,7 @@ void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int flagstacks(enum FLAG fid);
flag_t *hasflag(flagpile_t *fp, int id);
flag_t *hasflagknown(flagpile_t *fp, int id);
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown);
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception);
flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *text);
flag_t *hasflagvalknown(flagpile_t *fp, int id, int val1, int val2, int val3, char *text);
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown);

301
io.c
View File

@ -664,10 +664,18 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
}
donesomething = B_TRUE;
break;
case F_ARBOOST:
msg("A magical shield appears around %s!",lfname);
donesomething = B_TRUE;
break;
case F_ASLEEP:
msg("%s fall%s asleep.",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_BEINGSTONED:
msg("%s begin%s to turn to stone!",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_BLIND:
if (isplayer(lf)) {
msg("%s cannot see!",lfname);
@ -685,6 +693,15 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
}
}
break;
case F_CANWILL:
if (isplayer(lf)) { // don't know if monsters get it
objecttype_t *ot;
ot = findot(f->val[0]);
if (ot) {
msg("You have learned the ability '%s'.", ot->name);
}
}
break;
case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel immune to %s!", getdamnamenoun(f->val[0]));
@ -703,18 +720,6 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
}
break;
case F_CANWILL:
if (isplayer(lf)) { // don't know if monsters get it
switch (f->val[0]) {
case OT_A_JUMP:
msg("You feel like you could leap a tall building in a single bound!");
donesomething = B_TRUE;
break;
default:
break;
}
}
break;
case F_DETECTAURAS:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel aware of spiritual auras around you.");
@ -777,7 +782,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
cansee(player, lf2) ? buf : "something");
}
break;
case F_FOODPOISONED:
case F_POISONED:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel very sick.");
donesomething = B_TRUE;
@ -862,7 +867,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
break;
case F_RESISTMAG:
if (isplayer(lf)) { // don't know if monsters get it
msg("You feel immune to magic.");
msg("You feel %simmune to magic.", hasflag_real(lf->flags, F_RESISTMAG, NA, f) ? "more " : "");
donesomething = B_TRUE;
}
break;
@ -993,16 +998,24 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
}
break;
case F_ARBOOST:
msg("%s%s magical shield vanishes.",lfname,getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_ASLEEP:
msg("%s wake%s up.",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_BEINGSTONED:
msg("The fragments of stone around %s%s body drop%s away.",lfname, getpossessive(lfname), isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_BLIND:
msg("%s can see again.",lfname);
donesomething = B_TRUE;
break;
case F_CANCAST:
if (isplayer(lf)) { // don't know if monsters get it
if (isplayer(lf)) { // don't know if monsters lose it
objecttype_t *ot;
ot = findot(f->val[0]);
if (ot) {
@ -1011,6 +1024,16 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
}
}
break;
case F_CANWILL:
if (isplayer(lf)) { // don't know if monsters lose it
objecttype_t *ot;
ot = findot(f->val[0]);
if (ot) {
msg("You can no longer use the ability '%s'.", ot->name);
donesomething = B_TRUE;
}
}
break;
case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer immune to %s.", getdamnamenoun(f->val[0]));
@ -1041,24 +1064,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("%s stop%s fleeing.", lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_FOODPOISONED:
case F_POISONED:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You feel less sick now.");
donesomething = B_TRUE;
}
break;
case F_CANWILL:
if (isplayer(lf)) { // don't know if monsters lose it
switch (f->val[0]) {
case OT_A_JUMP:
msg("You no longer feel so good at jumping.");
donesomething = B_TRUE;
break;
default:
break;
}
}
break;
case F_DODGES:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You can no longer dodge attacks.");
@ -1154,8 +1165,10 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
break;
case F_PAIN:
msg("%s skin returns to normal.",lfname, getpossessive(lfname));
donesomething = B_TRUE;
if (isplayer(lf)) { // don't konw if it expires for monsters
msg("Your skin stops hurting.");
donesomething = B_TRUE;
}
break;
case F_PARALYZED:
if (isplayer(lf)) { // don't konw if it expires for monsters
@ -1181,7 +1194,11 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
break;
case F_RESISTMAG:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer immune to magic.");
if (hasflag_real(lf->flags, F_RESISTMAG, NA, f)) {
msg("You feel less immune to magic.");
} else {
msg("You are no longer immune to magic.");
}
donesomething = B_TRUE;
}
break;
@ -2217,6 +2234,13 @@ void describeob(object_t *o) {
y++;
}
for (f = o->flags->first ; f ; f = f->next) {
if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
mvwprintw(mainwin, y, 0, "It has been coated with poison.");
y++;
}
}
// now special flags...
y++;
@ -2373,7 +2397,8 @@ void describeob(object_t *o) {
mvwprintw(mainwin, y, 0, "%s allows you to regenerate health%s.", buf,buf2); y++;
break;
case F_RESISTMAG:
mvwprintw(mainwin, y, 0, "%s grants you immunity from magic.", buf); y++;
mvwprintw(mainwin, y, 0, "%s grants you %s immunity to magic.", buf,
(f->val[0] >= 10) ? "strong" : "minor"); y++;
break;
case F_SEEINVIS:
mvwprintw(mainwin, y, 0, "%s allows you to see invisible things.", buf); y++;
@ -2424,6 +2449,14 @@ void describeob(object_t *o) {
}
y++;
// skill type?
f = hasflag(o->flags, F_USESSKILL);
if (f) {
mvwprintw(mainwin, y, 0, "It falls into the '%s' category of weapons.",getskillname(f->val[0]));
y++;
}
if (hasflag(o->flags, F_NOBLESS)) {
mvwprintw(mainwin, y, 0, "%s cannot be blessed or cursed.", (o->amt == 1) ? "It" : "They" );
y++;
@ -2484,9 +2517,13 @@ void describespell(objecttype_t *ot) {
y++;
}
i = getmpcost(ot->id);
i = getmpcost(NULL, ot->id);
if (i > 0) {
mvwprintw(mainwin, y, 0, "It costs %d MP to cast.",i);
if (hasflag(ot->flags, F_ONGOING)) {
mvwprintw(mainwin, y, 0, "It takes %d MP to keep active - this is an ongoing cost.",i);
} else {
mvwprintw(mainwin, y, 0, "It costs %d MP to cast.",i);
}
y++;
}
@ -2983,6 +3020,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2)
int mpcost[MAXCANDIDATES];
char mpdesc[MAXCANDIDATES][BUFLEN];
int validspell[MAXCANDIDATES];
int deactspell[MAXCANDIDATES];
int nposs = 0;
int i,n;
enum SPELLSCHOOL lastschool;
@ -2997,6 +3035,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2)
if (f) {
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) {
poss[nposs] = ot->id;
deactspell[nposs] = B_FALSE; // default
mpcost[nposs] = -1;
if (f->val[2] == NA) {
sprintf(mpdesc[nposs], "(ready)");
@ -3028,7 +3067,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2)
if (lfhasflagval(lf, F_CANCAST, ot->id, NA, NA, NULL)) {
int cost;
int found = B_FALSE;
cost = getmpcost(ot->id);
cost = getmpcost(lf, ot->id);
for (n = 0; n < nposs; n++) {
if (poss[n] == ot->id) {
found = B_TRUE;
@ -3040,10 +3079,22 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2)
// add to list
poss[nposs] = ot->id;
mpcost[nposs] = cost;
deactspell[nposs] = B_FALSE; // default
power = getspellpower(lf, ot->id);
if (power > 0) {
sprintf(mpdesc[nposs], "(%d MP)", mpcost[nposs]);
if (lf->mp >= cost) {
if (lfhasflagval(lf, F_BOOSTSPELL, ot->id, NA, NA, NULL)) {
cost = 0;
mpcost[nposs] = 0;
strcpy(mpdesc[nposs], "(Deactivate, at will)");
deactspell[nposs] = B_TRUE;
} else {
int ongoing = B_FALSE;
if (hasflag(ot->flags, F_ONGOING)) ongoing = B_TRUE;
sprintf(mpdesc[nposs], "(%d MP%s)", mpcost[nposs],
ongoing ? ", ongoing" : "");
}
if (lf->mp >= mpcost[nposs]) {
validspell[nposs] = B_TRUE;
} else {
validspell[nposs] = B_FALSE;
@ -3090,6 +3141,10 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2)
}
getspellname(ot->id, player, buf2);
if (deactspell[i]) {
strcat(buf2, "/deact");
}
if (validspell[i]) {
strcpy(costbuf, "");
@ -3609,22 +3664,49 @@ void dorest(void) {
}
// if not training, only rest if we need to.
if (!willtrain) {
if (player->hp >= player->maxhp) {
char norestmsg[BUFLEN];
strcpy(norestmsg, "");
if (player->maxmp > 0) {
if (player->mp >= player->maxmp) {
// no need to rest
strcpy(norestmsg, "Not resting - already at full health and mana.");
}
} else {
// no need to rest
strcpy(norestmsg, "Not resting - already at full health.");
char validchars[BUFLEN];
char ques[BUFLEN];
char ch;
strcpy(validchars, "");
if (player->hp < player->maxhp) {
strcat(validchars, "h");
}
if ((getmaxmp(player) > 0) && (player->mp < getmaxmp(player))) {
strcat(validchars, "m");
}
if (strchr(validchars, 'h') && strchr(validchars, 'm')) {
strcat(validchars, "b");
strcpy(ques, "Rest until full HP, Mana, Both or none");
ch = askchar(ques, validchars, "b", B_TRUE);
if (ch == 'b') {
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
} else if (ch == 'h') {
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
} else if (ch == 'm') {
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
}
if (strlen(norestmsg)) {
msg(norestmsg);
return;
} else if (strchr(validchars, 'h')) {
strcpy(ques, "Rest until full HP");
ch = askchar(ques, "yn", "y", B_TRUE);
if (ch == 'y') {
addflag(player->flags, F_RESTUNTILHP, B_TRUE, NA, NA, NULL);
}
} else if (strchr(validchars, 'm')) {
strcpy(ques, "Rest until full Mana");
ch = askchar(ques, "yn", "y", B_TRUE);
if (ch == 'y') {
addflag(player->flags, F_RESTUNTILMP, B_TRUE, NA, NA, NULL);
}
} else {
msg("You don't need to rest at the moment.");
return;
}
if (!lfhasflag(player, F_RESTUNTILHP) && !lfhasflag(player, F_RESTUNTILMP)) {
msg("Cancelled.");
return;
}
}
startresting(player, willtrain);
@ -4225,8 +4307,10 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
// display prompt question
sprintf(promptstr, "%s %s %s",
prompt->q[prompt->whichq], prompt->maycancel ? "[ESC=cancel, '=next page] " : "",
sprintf(promptstr, "%s [%s%s] %s",
prompt->q[prompt->whichq],
prompt->maycancel ? "ESC," : "",
showall ? "'=next page,?=toggle" : "?=list",
inpstring);
mvwprintw(mainwin, 0, 0, "%s", promptstr);
wclrtoeol(mainwin);
@ -4853,6 +4937,7 @@ void drawstatus(void) {
char buf2[BUFLEN];
char waitbuf[BUFLEN];
char pname[BUFLEN];
char maxmpstr[BUFLEN];
flag_t *f;
int str,dex,iq,con;
long xpleft;
@ -4902,8 +4987,8 @@ void drawstatus(void) {
}
// show certain flags
if (lfhasflag(player, F_FOODPOISONED)) {
strcat(buf, " Sick");
if (lfhasflag(player, F_POISONED)) {
strcat(buf, " Poisoned");
}
mvwprintw(statwin, 0, 0, buf);
@ -4954,9 +5039,16 @@ void drawstatus(void) {
iq = getattr(player, A_IQ);
con = getattr(player, A_CON);
//redraw();
sprintf(buf, "HP:%d/%d MP:%d/%d $:%d St:%d%c Dx:%d%c Iq:%d%c Cn:%d%c DLev:%d",
if (getmaxmp(player) == player->maxmp) {
strcpy(maxmpstr, "");
} else {
sprintf(maxmpstr, "(%d)",player->maxmp);
}
sprintf(buf, "HP:%d/%d MP:%d/%d%s $:%d St:%d%c Dx:%d%c Iq:%d%c Cn:%d%c DLev:%d",
player->hp,player->maxhp,
player->mp, player->maxmp,
player->mp, getmaxmp(player), maxmpstr,
countmoney(player),
str, (str == player->baseatt[A_STR]) ? ' ' : '*',
dex, (dex == player->baseatt[A_DEX]) ? ' ' : '*',
@ -5227,8 +5319,16 @@ void showlfstats(lifeform_t *lf, int showall) {
}
}
if (showall) {
char maxmpstr[BUFLEN];
if (getmaxmp(lf) == lf->maxmp) {
strcpy(maxmpstr, "");
} else {
sprintf(maxmpstr, "(%d)",lf->maxmp);
}
mvwprintw(mainwin, y, 0, ftext, "Mana");
wprintw(mainwin, "%d / %d", lf->mp , lf->maxmp); y++;
wprintw(mainwin, "%d / %d%s", lf->mp , lf->maxmp,maxmpstr); y++;
}
if (showall) {
mvwprintw(mainwin, y, 0, ftext, "Exp Level");
@ -5697,6 +5797,11 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s %s sleeping.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasknownflag(lf, F_BEINGSTONED);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s being turning to stone.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasknownflag(lf, F_FLYING);
if (f && (f->known)) {
@ -5776,13 +5881,29 @@ void showlfstats(lifeform_t *lf, int showall) {
f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (f && (f->known)) {
char expirebuf[BUFLEN];
char eb2[BUFLEN];
int needgrab = B_FALSE;
if (f->val[2] == NA) {
sprintf(expirebuf, " (at will)");
sprintf(expirebuf, "at will");
} else {
sprintf(expirebuf, " (every %d turn%s)",f->val[2],
sprintf(expirebuf, "every %d turn%s",f->val[2],
(f->val[2] == 1) ? "" : "s");
}
sprintf(buf, "%-12s%s%s", ot->name, ot->desc, expirebuf);
// extra options?
texttospellopts(f->text, NULL, NULL, &needgrab);
if (needgrab) {
strcat(expirebuf, ",after grab");
}
if (strlen(expirebuf)) {
sprintf(eb2,"(%s)",expirebuf);
} else {
strcpy(eb2, "");
}
sprintf(buf, "%-12s%s%s", ot->name, ot->desc, eb2);
mvwprintw(mainwin, y, 0, buf);
if (downline(&y, h, "ABILITIES", NULL, prompt, cmdchars, &ch)) {
exitnow = B_TRUE;
@ -5798,10 +5919,11 @@ void showlfstats(lifeform_t *lf, int showall) {
centre(mainwin, y, "SKILLS"); y += 2;
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_HASSKILL) {
mvwprintw(mainwin, y, 0, "%c %s %s%s",
mvwprintw(mainwin, y, 0, "%c %s (%s%s)",
ismaxedskill(lf, f->val[0]) ? '*' : '-',
getskilllevelname(f->val[1]), getskillname(f->val[0]),
ismaxedskill(lf, f->val[0]) ? " (max)" : "");
getskillname(f->val[0]),
getskilllevelname(f->val[1]),
ismaxedskill(lf, f->val[0]) ? "/MAX" : "");
if (downline(&y, h, "SKILLS", NULL, prompt, cmdchars, &ch)) {
exitnow = B_TRUE;
break;
@ -5837,11 +5959,27 @@ void showlfstats(lifeform_t *lf, int showall) {
char mpbuf[BUFLEN];
int power;
int mpcost;
mpcost = getmpcost(ot->id);
if (mpcost) {
sprintf(mpbuf, "%d MP", mpcost);
if (f->id == F_CANWILL) {
mpcost = 0;
if (f->val[2] == NA) {
sprintf(mpbuf, "At will");
} else {
sprintf(mpbuf, "At will, every %d turn%s",f->val[2],
(f->val[2] == 1) ? "" : "s");
}
} else {
sprintf(mpbuf, "At will");
mpcost = getmpcost(lf, ot->id);
if (mpcost) {
if (hasflag(ot->flags, F_ONGOING)) {
sprintf(mpbuf, "%d MP ongoing", mpcost);
} else {
sprintf(mpbuf, "%d MP", mpcost);
}
} else {
sprintf(mpbuf, "At will");
}
}
power = getspellpower(lf, ot->id);
@ -5895,6 +6033,13 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
}
f = lfhasknownflag(lf, F_ARBOOST);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s protected by a magical shield.", you(lf), isplayer(lf) ? "are" : "is");
y++;
}
f = lfhasknownflag(lf, F_NOPACK);
if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s cannot carry objects.", you(lf));
@ -5934,9 +6079,9 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s receive enhanced knowledge about the world.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_FOODPOISONED);
f = lfhasknownflag(lf, F_POISONED);
if (f && (f->known)) {
sprintf(buf, "%s have food poisoning.", you(lf));
sprintf(buf, "%s %s poisoned.", you(lf), isplayer(lf) ? "are" : "is");
if (lfhasflag(lf, F_EXTRAINFO) || lfhasflag(lf, F_OMNIPOTENT)) {
char buf2[BUFLEN];
sprintf(buf2, " [%d left]", f->lifetime);
@ -6041,7 +6186,21 @@ void showlfstats(lifeform_t *lf, int showall) {
}
f = lfhasknownflag(lf, F_RESISTMAG);
if (f) {
mvwprintw(mainwin, y, 0, "Magic does not affect %s.", you(lf));
int mr;
char adjective[BUFLEN];
mr = getmr(lf);
if (mr <= 5) {
strcpy(adjective, "slightly");
} else if (mr <= 10) {
strcpy(adjective, "quite");
} else if (mr <= 15) {
strcpy(adjective, "very");
} else if (mr <= 20) {
strcpy(adjective, "extremely");
} else { // ie. 21 upwards
strcpy(adjective, "incredibly");
}
mvwprintw(mainwin, y, 0, "%s %s %s resistant to magic.", you(lf), isplayer(lf) ? "are" : "is", adjective);
y++;
}
f = lfhasknownflag(lf, F_TIRED);

609
lf.c

File diff suppressed because it is too large Load Diff

5
lf.h
View File

@ -78,7 +78,9 @@ char getlfglyph(lifeform_t *lf);
enum MATERIAL getlfmaterial(lifeform_t *lf);
float getmaxcarryweight(lifeform_t *lf);
float getmaxliftweight(lifeform_t *lf);
int getmaxmp(lifeform_t *lf);
float getmaxpushweight(lifeform_t *lf);
int getmr(lifeform_t *lf);
int getvisrange(lifeform_t *lf);
int getmovespeed(lifeform_t *lf);
char *getmoveverb(lifeform_t *lf);
@ -115,15 +117,16 @@ void givestartobs(lifeform_t *lf, flagpile_t *fp);
void givestartskills(lifeform_t *lf, flagpile_t *fp);
map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs);
job_t *hasjob(lifeform_t *lf, enum JOB job);
int lfcanbestoned(lifeform_t *lf);
flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid);
flag_t *lfhasflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, char *text);
flag_t *lfhasknownflag(lifeform_t *lf, enum FLAG fid);
flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, char *text);
int lockpick(lifeform_t *lf, object_t *target, object_t *device);
void loseobflags(lifeform_t *lf, object_t *o, int kind);
int hasbp(lifeform_t *lf, enum BODYPART bp);
int haslof(lifeform_t *viewer, cell_t *dest);
int haslos(lifeform_t *viewer, cell_t *dest);
int hasmr(lifeform_t *lf);
void initjobs(void);
void initrace(void);
void initskills(void);

9975
log.txt

File diff suppressed because it is too large Load Diff

5
map.c
View File

@ -34,6 +34,7 @@ cell_t *addcell(map_t *m, int x, int y) {
cell->lit = L_NOTLIT;
cell->origlit = L_NOTLIT;
cell->littimer = 0;
cell->origlittimer = 0;
cell->writing = NULL;
cell->known = B_FALSE;
return cell;
@ -2092,8 +2093,10 @@ void makelit(cell_t *c, enum LIGHTLEV how, int howlong) {
}
}
if (howlong > 0) {
c->littimer = howlong;
// TODO: use a stack here instead
c->origlit = c->lit;
c->origlittimer = c->littimer;
c->littimer = howlong;
}
c->lit = how;
}

77
move.c
View File

@ -459,6 +459,28 @@ int moveawayfrom(lifeform_t *lf, cell_t *dst ) {
}
void moveeffects(lifeform_t *lf) {
flag_t *f;
if (isbleeding(lf)) {
if (rnd(1,2) == 1) {
bleed(lf);
}
}
f = lfhasflag(lf, F_PAIN);
if (f) {
if (isplayer(lf)) {
msg("Your body is wracked with pain!");
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s convulses in pain!",lfname);
}
losehp(lf, roll(f->text), f->val[0], NULL, "extreme pain");
}
if (isdead(lf)) return;
}
// returns TRUE if something happened
@ -468,9 +490,14 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
lifeform_t *l;
int didmsg = B_FALSE;
flag_t *f;
int changedlev = B_FALSE;
getlfname(lf, lfname);
if (newcell->map != lf->cell->map) {
changedlev = B_TRUE;
}
// update current cell
lf->cell->lf = NULL;
@ -491,20 +518,13 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// update new cell
newcell->lf = lf;
if (isbleeding(lf)) {
if (rnd(1,2) == 1) {
bleed(lf);
}
}
if (lfhasflag(lf, F_PAIN)) {
losehp(lf, rolldie(2,4)+2, DT_DIRECT, NULL, "extreme pain");
if (isplayer(lf)) {
msg("Your body is wracked with pain!");
} else if (cansee(player, lf)) {
msg("%s convulses in pain!",lfname);
}
// update light
if (changedlev && isplayer(lf)) {
calclight(lf->cell->map);
}
moveeffects(lf);
// remove grabs
f = lfhasflag(lf, F_GRABBING);
if (f) {
@ -617,6 +637,8 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose) {
dontclearmsg = B_TRUE;
}
assert(!newcell->lf);
getlfname(lf, lfname);
// is current cell dark?
@ -870,7 +892,8 @@ int closedoor(lifeform_t *lf, object_t *o) {
if (lf && isplayer(lf)) {
char inwayname[BUFLEN];
getobname(oo, inwayname, oo->amt);
msg("%s is in the way!", haslos(lf, cell) ? inwayname : "Something");
msg("%s %s in the way!", haslos(lf, cell) ? inwayname : "Something",
(haslos(lf,cell) && (oo->amt > 1)) ? "are" : "is" );
}
return B_TRUE;
}
@ -1029,12 +1052,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
}
// slipping on blood before moving?
slip = getslipperyness(lf->cell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
// don't move
reason = E_OK;
return B_FALSE;
if (!isairborne(lf)) {
slip = getslipperyness(lf->cell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
// don't move
reason = E_OK;
return B_FALSE;
}
}
// move to new cell
@ -1043,12 +1068,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
taketime(lf, getmovespeed(lf));
// slip on blood in new cell?
slip = getslipperyness(cell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
// don't move
reason = E_OK;
return B_FALSE;
if (!isairborne(lf)) {
slip = getslipperyness(cell, &slipob);
if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) {
slipon(lf, slipob);
// don't move
reason = E_OK;
return B_FALSE;
}
}
} else {
object_t *inway;

1
move.h
View File

@ -12,6 +12,7 @@ int getdiraway(cell_t *src, cell_t *dst, int wantcheck);
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck);
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher);
int moveawayfrom(lifeform_t *lf, cell_t *dst);
void moveeffects(lifeform_t *lf);
int movelf(lifeform_t *lf, cell_t *newcell);
int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose);
int movetowards(lifeform_t *lf, cell_t *dst);

18
nexus.c
View File

@ -120,6 +120,10 @@ int main(int argc, char **argv) {
// find staircase
where = findobinmap(firstmap, OT_STAIRSUP);
assert(where);
// make sure no lifeforms are there
if (where->lf) {
killlf(where->lf);
}
// add player
real_addlf(where, R_HUMAN, 1, C_PLAYER); // this will assign 'player'
@ -583,6 +587,16 @@ int rnd(int min, int max) {
res = (rand() % (max - min + 1)) + min;
return res;
}
int roll(char *string) {
int ndice,nsides,bonus;
int roll;
texttodice(string, &ndice,&nsides,&bonus);
roll = rolldie(ndice, nsides) + bonus;
return roll;
}
// get a random number
int rolldie(int ndice, int sides) {
int i;
@ -883,10 +897,6 @@ void timeeffectsworld(map_t *map) {
// now handle effects on lifeforms and/or their objects
for (l = map->lf ; l ; l = l->next) {
timeeffectslf(l);
for (o = l->pack->first ; o ; o = nexto) {
nexto = o->next;
timeeffectsob(o);
}
}
//dblog("AFTER SORT AND ADJUST.....");

View File

@ -15,6 +15,7 @@ int isplayerturn(void);
int limit(int *what, int min, int max);
float pctof(float pct, float num);
int rnd(int min, int max);
int roll(char *string);
int rolldie(int ndice, int sides);
int rollhitdice(lifeform_t *lf);
int rollmpdice(lifeform_t *lf);

653
objects.c

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@ void appendinscription(object_t *o, char *text);
void applyobmod(object_t *o, obmod_t *om);
int blessob(object_t *o);
void brightflash(cell_t *centre, int range, lifeform_t *immunelf);
int canbepoisoned(enum OBTYPE oid);
object_t *canstackob(obpile_t *op, object_t *match);
object_t *canstacknewot(obpile_t *op, objecttype_t *match);
int changemat(object_t *o, enum MATERIAL mat);
@ -140,6 +141,7 @@ void killob(object_t *o);
void killobpile(obpile_t *o);
void killoc(objectclass_t *oc);
void killot(objecttype_t *ot);
int knockbackob(object_t *o, int dir, int howfar, int power, lifeform_t *pusher);
lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level);
void makeduller(object_t *o, int howmuch);
void makeknown(enum OBTYPE otid);
@ -170,7 +172,7 @@ void setinscription(object_t *o, char *text);
void shufflehiddennames(void);
object_t *splitob(object_t *o);
int takedamage(object_t *o, unsigned int howmuch, int damtype);
int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t *firearm);
int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm);
void timeeffectsob(object_t *o);
void turnoff(lifeform_t *lf, object_t *o);
void turnon(lifeform_t *lf, object_t *o);

686
spell.c

File diff suppressed because it is too large Load Diff

View File

@ -2,11 +2,11 @@
#define __SPELLS_H
#include "defs.h"
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target);
int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifeform_t *target, flag_t *cwflag);
int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_t *target, object_t *targob, cell_t *targcell, int blessed, int *seenbyplayer);
void fizzle(lifeform_t *caster);
//int getiqreq(enum OBTYPE oid);
int getmpcost(enum OBTYPE oid);
int getmpcost(lifeform_t *lf, enum OBTYPE oid);
enum SKILL getschoolskill(enum SPELLSCHOOL ss);
int getspellduration(int min,int max,int blessed);
int getspelllevel(enum OBTYPE spellid);
@ -16,6 +16,9 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid);
enum SPELLSCHOOL getspellschool(enum OBTYPE spellid);
int getspellrange(enum OBTYPE spellid, int power);
void pullobto(object_t *o, lifeform_t *lf);
void stopspell(lifeform_t *caster, enum OBTYPE spellid);
void stopallspells(lifeform_t *lf);
lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target);
cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, int needlof, enum OBTYPE spellid, int power);
lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf);
#endif

55
text.c
View File

@ -444,6 +444,61 @@ int texttodice(char *text, int *ndice, int *nsides, int *bonus) {
return B_FALSE;
}
void texttospellopts(char *text, int *power, char *damstr, int *needgrab) {
char *p;
int n;
char *argname[] = {
"pw:",
"dam:",
"needgrab:",
NULL,
};
void *argval[] = {
power,
damstr,
needgrab,
NULL,
};
char argtype[] = {
'i',
's',
'b',
'\0',
};
// defaults
if (power) *power = 0;
if (damstr) strcpy(damstr, "");
if (needgrab) *needgrab = B_FALSE;
// for each arg
for (n = 0; argname[n]; n++) {
// search for it in text...
for (p = text ; *p ; p++) {
if (!strncmp(p, argname[n], strlen(argname[n])) ) {
char localval[BUFLEN];
char *valfull;
strcpy(localval, p + strlen(argname[n]));
valfull = strtok(localval, ";");
if (valfull) {
if (argval[n]) {
if (argtype[n] == 'i') {
*((int *)argval[n]) = atoi(valfull);
} else if (argtype[n] == 'b') {
*((int *)argval[n]) = atoi(valfull) ? B_TRUE : B_FALSE;
} else if (argtype[n] == 's') {
strcpy((char *)argval[n], valfull);
}
}
break;
}
}
}
}
}
char *you(lifeform_t *lf) {
if (isplayer(lf)) {
return "You";

1
text.h
View File

@ -18,6 +18,7 @@ char *strrep(char *text, char *oldtok, char *newtok, int *rv);
char *dostrrep(char* in, char** out, char* oldtok, char* newtok, int *rv);
int strpixmatch(char *haystack, char *needle);
int texttodice(char *text, int *ndice, int *nsides, int *bonus);
void texttospellopts(char *text, int *power, char *damstr, int *needgrab);
char *you(lifeform_t *lf);
char *you_l(lifeform_t *lf);
char *your(lifeform_t *lf);