* [+] always add webs if there are randomly generated spiders on a level

- [+] non-wood doors
    - [+] iron
- [+] only interrupt rest for hunger if it's 'starving' or 'vhungry'
- [+] limit the amount of jumping we can do from athletics skill.
- [+] no message when i lockpick with a -6 combat knife.
- [+] make small corpses give much less nutrition!
- [+] high unarmed skill should give you unarmed attacks with a
      1-handed weapon.
- [+] dual weild
    - [+] if you have twoweapon skill, when you weild a weapon, say
          "weild as secondary weapon? y/n"
    - [+] in attackcell(), check if we have a weapon in our second hand
          AND are skilled in twoweaponing
    - [+] if so, get an attack with both, but with an accuracy penalty
          (until adept level)
    - [+] make sure shiedl code doesn't accept weapons!
- [+] knockback() can now knock back other lfs that you hit on the way
* [+] faster resting obs (only via R)
- [+] replace F_RESTING with F_ASLEEP. v0 = onpurpose. if v0, you wake
      up when at full hp/mp/etc
- [+] implement F_TRAINING with traincounter
- [+] don't say 'rest until nearby allies ar eheald' if they aren't
      damaged
- [+] make listen dififculty check dependant on distance to noise
- [+] doesn't make sense for druid to be a vegetarian. use "can only
      eat meat when hungry"
- [+] @@ - combine acc+dmg.  ie.  "weapon: mace (63%,2-9dmg)
- [+] @@ - show both weapons if dualweilding.
- [+] porcupine shoudl have F_SHARP corpse.  implement F_CORPSEFLAGS
- [+] create monster - "giant ant" making "giant antlion"!
- [+] giant porcupine
    - [+] implement
    - [+] should attack ants on sight - f_hatesrace
        - [+] if race=hatesrace or baserace = hatesrace, will attack it.
- [+] gust of wind - blow obs away!
- [+] thorns (grow spikes, attackers take dmg)
    - [+] f_retaliate, v0=ndice,v1=dsides, v2=damype, text=obname
- [+] major healing (new spell)
This commit is contained in:
Rob Pearce 2011-05-05 03:12:52 +00:00
parent 7099d01164
commit 810ab99662
17 changed files with 1360 additions and 1358 deletions

138
ai.c
View File

@ -392,11 +392,12 @@ void aiturn(lifeform_t *lf) {
flag_t *mf;
//flag_t *nextf;
// lifeform_t *fleefrom = NULL;
lifeform_t *target;
lifeform_t *target,*newtarget;
enum BODYPART bp;
cell_t *c;
//cell_t *c;
lifeform_t *master = NULL;
enum IQBRACKET iqb;
int n;
/*
@ -601,9 +602,6 @@ void aiturn(lifeform_t *lf) {
return;
}
if (goingtomove && (getcelldist(lf->cell, target->cell) == 1)) {
}
if (!lfhasflag(lf, F_HIDING)) {
objecttype_t *st;
// can we attack with spells (ie. ones which target the victim)?
@ -711,7 +709,7 @@ void aiturn(lifeform_t *lf) {
// try to throw it!
if (!throwat(lf, o, target->cell)) {
// succesful
goingtomove = B_FALSE;
return;
} else {
if (db) dblog(".oO { throw failed! }");
}
@ -748,7 +746,7 @@ void aiturn(lifeform_t *lf) {
if (!operate(lf, o, zapcell)) {
// succesful
goingtomove = B_FALSE;
return;
} else {
if (db) dblog(".oO { zap failed! }");
}
@ -861,8 +859,51 @@ void aiturn(lifeform_t *lf) {
// not attacking anyone in particular
if (db) dblog(".oO { i do not have a target or can't move towards it. }");
// are we hostile? if so, look for a target
if (db) dblog(".oO { i do not have a target or can't move towards it. looking for one. }");
// look for any race which we hate
newtarget = NULL;
for (n = 0; n < lf->nlos; n++) {
lifeform_t *who;
who = lf->los[n]->lf;
if (who && cansee(lf, who)) {
if (lfhasflagval(lf, F_HATESRACE, who->race->id, NA, NA, NULL) ||
lfhasflagval(lf, F_HATESRACE, who->race->baseid, NA, NA, NULL) ) {
if (db) dblog(".oO { found a hated target - lfid %d (%s) ! }",who->id, who->race->name);
newtarget = who;
break;
}
}
}
if (!newtarget) {
// now look for enemies
for (n = 0; n < lf->nlos; n++) {
lifeform_t *who;
who = lf->los[n]->lf;
if (who && cansee(lf, who)) {
if (areenemies(lf, who)) {
if (db) dblog(".oO { found an enemy target - lfid %d (%s) ! }",who->id, who->race->name);
newtarget = who;
break;
}
}
}
}
if (newtarget) {
aiattack(lf, newtarget, AI_FOLLOWTIME);
// then move towards them...
if (db) dblog(".oO { moving towards my new target }");
if (icanattack) {
if (!movetowards(lf, newtarget->cell, DT_ORTH)) return;
} else {
if (db) dblog(".oO { won't move towards target - i have no weapon. }");
}
}
/*
// look for a target to attack based on our allegiance
switch (getallegiance(lf)) {
int i;
int x,y;
@ -918,6 +959,8 @@ void aiturn(lifeform_t *lf) {
default:
break;
}
*/
///////////////////////////////////////////////
// training
@ -941,7 +984,7 @@ void aiturn(lifeform_t *lf) {
master = findlf(lf->cell->map, mf->val[0]);
if (master && cansee(lf, master)) {
// can see my master
if (lfhasflag(master, F_RESTING)) {
if (isresting(master)) {
// rest as well.
rest(lf, B_TRUE);
return;
@ -1143,11 +1186,11 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
case ST_VICTIM:
case ST_ADJVICTIM:
if (needlos && (!victim || !cansee(lf, victim)) ) {
dblog(".oO { cant cast %s - no LOS to victim }", ot ? ot->name : "?unkownspell?");
if (db) dblog(".oO { cant cast %s - no LOS to victim }", ot ? ot->name : "?unkownspell?");
return B_FALSE;
}
if (needlof && !haslof(lf->cell, victim->cell, needlof, NULL) ) {
dblog(".oO { cant cast %s - no LOF to victim }", ot ? ot->name : "?unkownspell?");
if (db) dblog(".oO { cant cast %s - no LOF to victim }", ot ? ot->name : "?unkownspell?");
return B_FALSE;
}
break;
@ -1157,7 +1200,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
} else {
// invalid spell for this purpose
dblog(".oO { cant cast %s - not valid for given purpose }", ot ? ot->name : "?unkownspell?");
if (db) dblog(".oO { cant cast %s - not valid for given purpose }", ot ? ot->name : "?unkownspell?");
return B_FALSE;
}
@ -1197,6 +1240,15 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
// now check whether it meets specific spell conditions
specificcheckok = B_TRUE;
if (ot->id == OT_S_AIRBLAST) {
// target must be in a straight compass dir from us
if ((victim->x != lf->x) ||
(victim->y != lf->y) ||
(abs(victim->x - lf->x) != abs(victim->y - lf->y)) ) {
} else {
specificcheckok = B_FALSE;
}
}
if (ot->id == OT_S_ANIMATEMETAL) {
object_t *wep;
wep = getweapon(lf);
@ -1210,37 +1262,19 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if ((ot->id == OT_S_DRAINLIFE) && isimmuneto(victim->flags, DT_NECROTIC)) {
specificcheckok = B_FALSE;
}
if ((ot->id == OT_A_SWOOP) || (ot->id == OT_A_CHARGE)) {
flag_t *willflag;
flag_t *srflag;
int srange = 5;
srflag = lfhasflag(lf, F_SWOOPRANGE);
if (srflag) {
srange = srflag->val[0];
}
willflag = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (willflag) {
texttospellopts(f->text, NULL, NULL, NULL, &srange);
if (!srange) srange = 5;
}
if (!haslof(lf->cell, victim->cell, LOF_NEED,NULL)) {
specificcheckok = B_FALSE;
} else if (isimmobile(lf)) {
specificcheckok = B_FALSE;
} else if ((ot->id == OT_A_SWOOP) && !lfhasflag(lf, F_FLYING)) {
specificcheckok = B_FALSE;
} else if (getcelldist(lf->cell, victim->cell) > srange) {
specificcheckok = B_FALSE;
} else if (getcelldist(lf->cell, victim->cell) == 1) { // ie already adjacent
if (ot->id == OT_A_FLURRY) {
if (!isdualweilding(lf)) {
specificcheckok = B_FALSE;
}
}
if ((ot->id == OT_S_HASTE) && (lfhasflag(victim, F_FASTACT) || lfhasflag(victim, F_FASTACTMOVE)) ) {
specificcheckok = B_FALSE;
}
if (ot->id == OT_A_HEAVYBLOW) {
if (!getweapon(lf)) {
specificcheckok = B_FALSE;
}
}
if (ot->id == OT_A_HIDE) {
if (lfhasflag(victim, F_HIDING)) {
specificcheckok = B_FALSE;
@ -1272,6 +1306,34 @@ 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_SWOOP) || (ot->id == OT_A_CHARGE)) {
flag_t *willflag;
flag_t *srflag;
int srange = 5;
srflag = lfhasflag(lf, F_SWOOPRANGE);
if (srflag) {
srange = srflag->val[0];
}
willflag = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (willflag) {
texttospellopts(f->text, NULL, NULL, NULL, &srange);
if (!srange) srange = 5;
}
if (!haslof(lf->cell, victim->cell, LOF_NEED,NULL)) {
specificcheckok = B_FALSE;
} else if (isimmobile(lf)) {
specificcheckok = B_FALSE;
} else if ((ot->id == OT_A_SWOOP) && !lfhasflag(lf, F_FLYING)) {
specificcheckok = B_FALSE;
} else if (getcelldist(lf->cell, victim->cell) > srange) {
specificcheckok = B_FALSE;
} else if (getcelldist(lf->cell, victim->cell) == 1) { // ie already adjacent
specificcheckok = B_FALSE;
}
}
if ((ot->id == OT_S_WARPWOOD)) {
specificcheckok = B_FALSE;
if (victim) {

148
attack.c
View File

@ -113,6 +113,7 @@ int attackcell(lifeform_t *lf, cell_t *c) {
int attacktime;
int gotweapon = B_FALSE;
int maxattacks = ALL;
int lastweaponidx = -1;
// anyone there? if so just attack.
if (c->lf) {
@ -155,14 +156,29 @@ int attackcell(lifeform_t *lf, cell_t *c) {
}
// first use our weapon...
wep[0] = getweapon(lf);
if (wep[0]) {
damflag[0] = hasflag(wep[0]->flags, F_DAM);
validwep[0] = B_TRUE;
nweps = 0;
wep[nweps] = getweapon(lf);
if (wep[nweps]) {
damflag[nweps] = hasflag(wep[nweps]->flags, F_DAM);
validwep[nweps] = B_TRUE;
lastweaponidx = 0;
nweps++;
gotweapon = B_TRUE;
}
// if we are skilled at twoweaponing, we can attack with our second weapon
// as well, with a possible accuracy penalty depending on our skill level.
if (getskill(lf, SK_TWOWEAPON)) {
wep[nweps] = getsecmeleeweapon(lf);
if (wep[nweps]) {
damflag[nweps] = hasflag(wep[nweps]->flags, F_DAM);
validwep[nweps] = B_TRUE;
lastweaponidx = nweps;
nweps++;
gotweapon = B_TRUE;
}
}
// then use all our innate attacks..
for (f = lf->flags->first ; f; f = f->next) {
if (f->id == F_HASATTACK) {
@ -178,11 +194,12 @@ int attackcell(lifeform_t *lf, cell_t *c) {
validwep[nweps] = B_TRUE;
damflag[nweps] = f;
nweps++;
innateattacks++;
}
}
}
innateattacks = countinnateattacks(lf);
// stop sprinting
f = lfhasflag(lf, F_SPRINTING);
if (f && f->val[0]) {
@ -200,36 +217,26 @@ int attackcell(lifeform_t *lf, cell_t *c) {
return B_TRUE;
}
maxattacks = nweps; // ie. all
f = lfhasflag(lf, F_MAXATTACKS);
if (f) {
maxattacks = f->val[0];
} else {
maxattacks = innateattacks;
}
//maxattacks = nweps; // ie. all
maxattacks = getmaxattacks(lf);
/*
// if we have a weapon, this takes the place of one of our
// attacks.
// for monsters, pick which one to replace randomly.
// for players, never pick the weapon to replace randomly.
if (gotweapon && (nweps >= 2)) {
if (isplayer(lf)) {
validwep[rnd(1,nweps-1)] = B_FALSE;
} else {
validwep[rnd(0,nweps-1)] = B_FALSE;
}
}
// - for monsters, pick which one to replace randomly.
// - for players, never pick the weapon to replace randomly.
*/
// # valid attacks higher than our allowed attacks?
if (nweps > maxattacks) {
int nvalid;
int first;
// player never invalidates their weapon
// player never invalidates their equipped weapons
if (isplayer(lf) && gotweapon) {
first = 1;
first = lastweaponidx+1;
} else {
first = 0;
}
@ -256,6 +263,7 @@ int attackcell(lifeform_t *lf, cell_t *c) {
}
}
// remember initial cells
for (i = 0; i < nweps; i++) {
if (validwep[i]) {
if (attacktype == AT_LF) {
@ -266,6 +274,14 @@ int attackcell(lifeform_t *lf, cell_t *c) {
if (attackob(lf, (object_t *)attacktarget, wep[i], damflag[i])) 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) {
break;
}
}
}
// now kill all temp obs
@ -286,6 +302,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
char attackername[BUFLEN];
char victimname[BUFLEN];
int fatal = B_FALSE;
int deflected = B_FALSE;
int firstisbackstab = B_FALSE;
int hit = B_FALSE;
int critical = 0;
@ -347,8 +364,21 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// did you hit?
ndam = 0;
if (rolltohit(lf, victim, wep, &critical)) {
hit = B_TRUE;
hit = rolltohit(lf, victim, wep, &critical);
// deflection?
if (hit) {
object_t *dwep;
dwep = isdualweilding(victim);
if (dwep && (getskill(victim, SK_TWOWEAPON) >= PR_MASTER)) {
if (onein(4)) {
deflected = B_TRUE;
hit = B_FALSE;
}
}
}
if (hit) {
if (aidb) dblog(".oO { i hit! }");
// special case
@ -454,8 +484,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
ndam = 0;
}
if (ndam > 0) {
flag_t *f;
for (i = 0; i < ndam; i++) {
@ -464,11 +492,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
flag_t *rust;
if (firstisbackstab && (i == 0)) backstab = B_TRUE;
dblog("initial dam[%d] = %d",i,dam[i]);
//dblog("initial dam[%d] = %d",i,dam[i]);
if (lfhasflag(lf, F_HEAVYBLOW) || hasflag(wep->flags, F_HEAVYBLOW)) {
dam[i] = (int)pctof(110,dam[i]);
dblog("heavy blow makes dam[%d] = %d",i,dam[i]);
//dblog("heavy blow makes dam[%d] = %d",i,dam[i]);
}
// modify for rust
@ -492,7 +520,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
// modify based on resistances
adjustdamlf(victim, &dam[i], damtype[i]);
dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
//dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
if (!backstab) {
// modify for defender's armour
@ -500,7 +528,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
applyarmourdamreduction(victim, wep, reduceamt, &dam[i], damtype[i]);
dblog("reduced by armour to dam[%d] = %d",i,dam[i]);
//dblog("reduced by armour to dam[%d] = %d",i,dam[i]);
}
// will this hit be fatal?
@ -703,12 +731,33 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
addflag(lf->flags, F_ATTACHEDTO, victim->id, NA, NA, NULL);
}
}
}
// retaliation happens even if victim died
for (f = victim->flags->first ; f ; f = f->next) {
if (f->id == F_RETALIATE) {
int rdam;
char damstring[BUFLEN];
rdam = rolldie(f->val[0], f->val[1]);
if (cansee(player, victim)) {
msg("%s%s %s %s %s!", victimname, getpossessive(victimname),
noprefix(f->text),
getattackverb(victim, NULL, f->val[2], rdam, lf->maxhp),
attackername);
}
sprintf(damstring, "%s%s %s", victimname, getpossessive(victimname), noprefix(f->text));
losehp(lf, rdam, f->val[2], victim, damstring);
}
}
} else { // miss!
if (aidb) dblog(".oO { i missed! }");
// announce it
if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
if (deflected) {
if (cansee(player, lf)) {
msg("%s deflect%s %s%s attack.", victimname, isplayer(victim) ? "" : "s",attackername, getpossessive(attackername));
}
} else if (lfhasflag(victim, F_MAGSHIELD) && ismetal(wep->material->id)) {
if (isplayer(lf) || cansee(player, lf)) {
sprintf(buf, "%s",attackername);
@ -763,6 +812,32 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
}
}
// twoweapon?
if (hit) {
enum SKILLLEVEL slev;
slev = getskill(lf, SK_TWOWEAPON);
if (slev >= PR_SKILLED) {
object_t *secwep;
secwep = getsecmeleeweapon(lf);
// ie. if we are using two weapons, and the current one
// is the first...
if (secwep && (secwep != wep)) {
int bonus = 0;
// next hit will have enhanced accuracy
if (slev == PR_SKILLED) {
bonus = 10;
} else if (slev == PR_EXPERT) {
bonus = 25;
} else if (slev == PR_MASTER) {
bonus = 40;
}
if (bonus) {
addtempflag(lf->flags, F_ACCURACYMOD, bonus, NA, NA, NULL, 1);
}
}
}
}
if (aidb) dblog(".oO { doattack about to return B_FALSE }");
return B_FALSE;
}
@ -1473,6 +1548,7 @@ int isphysicaldam(enum DAMTYPE damtype) {
return B_FALSE;
}
// returns true if we hit
int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) {
int acc,ev;
int gothit;
@ -1540,7 +1616,6 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
acc += 50;
}
// base 5% critical chance
if (critical) {
int critroll;
@ -1555,10 +1630,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
if (critroll >= 95) *critical = 1;
}
if (acc < 0) acc = 0;
if (acc > 100) acc = 100;
limit(&acc, 0, 100);
//if (aidb) dblog(".oO { my modified chance to hit is %d %% }", acc);
myroll = rnd(1,100);

78
defs.h
View File

@ -4,7 +4,7 @@
// MACROS
#define MAXOF(a,b) (a > b ? a : b)
#define PRACTICETIME 50 // #attempts it takes to learn new skill
#define PRACTICETIME 15 // #attempts it takes to learn new weapon skill
#define WETTIME 10 // how long it takes for things to dry
#define DRUNKTIME 10 // how long it takes for alcohol to wear off
@ -48,6 +48,7 @@ enum SKILL {
SK_SPOTHIDDEN,
SK_STEALTH,
SK_TECHUSAGE,
SK_TWOWEAPON,
// knowledge
SK_LORE_ARCANA,
SK_LORE_DEMONS,
@ -68,7 +69,7 @@ enum SKILL {
SK_SS_DEATH,
SK_SS_DIVINATION,
SK_SS_FIRE,
SK_SS_ICE,
SK_SS_COLD,
SK_SS_GRAVITY,
SK_SS_LIFE,
SK_SS_MODIFICATION,
@ -78,7 +79,7 @@ enum SKILL {
SK_SS_TRANSLOCATION,
SK_SS_WILD,
};
#define MAXSKILLS 39
#define MAXSKILLS 40
// proficiency levels
enum SKILLLEVEL {
@ -166,6 +167,8 @@ enum LFCONDITION {
// if target lf is out of view for this many turns, abandon chase
#define AI_FOLLOWTIME (10)
#define DEFAULTRESTHEALTIME (3)
// object confitions for random objects
#define RO_NONE 0
@ -209,8 +212,9 @@ enum LFCONDITION {
#define MORESTRING "--More--"
#define SOLDOUTSTRING "--SOLD OUT--"
// hunger constant
#define HUNGERCONST 10000
// hunger constant - this is how many turns
// it will take to go from 'normal' to 'hungry' etc
#define HUNGERCONST 200
// LIMITS
@ -392,7 +396,7 @@ enum SPELLSCHOOL {
SS_DEATH,
SS_DIVINATION,
SS_FIRE,
SS_ICE,
SS_COLD,
SS_GRAVITY,
SS_LIFE,
SS_MODIFICATION,
@ -609,6 +613,7 @@ enum RACE {
R_HAWKFROST,
R_LEECH,
R_NEWT,
R_PORCUPINE,
R_RAT,
R_SNAKE,
R_SNAKECARPET,
@ -696,7 +701,8 @@ enum OBTYPE {
// dungeon features
OT_BOULDER,
OT_STATUE,
OT_WOODENDOOR,
OT_DOORWOOD,
OT_DOORIRON,
OT_WOODENTABLE,
OT_WOODENBARREL,
OT_WOODENSTOOL,
@ -727,20 +733,6 @@ enum OBTYPE {
// corpses
OT_CORPSE,
OT_HEAD,
/*
OT_CORPSEEYEBAT,
OT_CORPSEBAT,
OT_CORPSEFLY,
OT_CORPSEGLOWBUG,
OT_CORPSEGOBLIN,
OT_CORPSEHUMAN,
OT_CORPSELIZARD,
OT_CORPSEOGRE,
OT_CORPSEORK,
OT_CORPSERODENT,
OT_CORPSETROLL,
OT_CORPSEWOLF,
*/
// potions
OT_POT_ACID,
OT_POT_ACROBATICS,
@ -754,6 +746,7 @@ enum OBTYPE {
OT_POT_GASEOUSFORM,
OT_POT_HEALING,
OT_POT_HEALINGMIN,
OT_POT_HEALINGMAJ,
OT_POT_INVIS,
OT_POT_INVULN,
OT_POT_MAGIC,
@ -802,6 +795,7 @@ enum OBTYPE {
OT_MAN_SPOTHIDDEN,
OT_MAN_STEALTH,
OT_MAN_TECHUSAGE,
OT_MAN_TWOWEAPON,
// manuals of knowledge
OT_MAN_LORE_ARCANA,
OT_MAN_LORE_DEMONS,
@ -823,7 +817,7 @@ enum OBTYPE {
OT_MAN_SS_DIVINATION,
OT_MAN_SS_NATURE,
OT_MAN_SS_FIRE,
OT_MAN_SS_ICE,
OT_MAN_SS_COLD,
OT_MAN_SS_GRAVITY,
OT_MAN_SS_LIFE,
OT_MAN_SS_MODIFICATION,
@ -881,6 +875,7 @@ enum OBTYPE {
// -- life
OT_SB_HEALING,
OT_SB_HEALINGMIN,
OT_SB_HEALINGMAJ,
OT_SB_TURNUNDEAD,
// -- mental / psionic
OT_SB_MINDSCAN,
@ -964,6 +959,7 @@ enum OBTYPE {
// -- life
OT_S_HEALING,
OT_S_HEALINGMIN,
OT_S_HEALINGMAJ,
OT_S_TURNUNDEAD,
// -- mental / psionic
OT_S_MINDSCAN,
@ -1009,6 +1005,7 @@ enum OBTYPE {
OT_S_SUMMONANIMALSSM,
OT_S_SUMMONANIMALSMD,
OT_S_SUMMONANIMALSLG,
OT_S_THORNS,
OT_S_WARPWOOD,
OT_S_WATERJET,
// -- summoning
@ -1033,7 +1030,7 @@ enum OBTYPE {
OT_A_LEARN,
OT_A_LEVELUP,
// abilities
OT_A_SUCKBLOOD,
OT_A_FLURRY,
OT_A_GRAB,
OT_A_CHARGE,
OT_A_CRUSH,
@ -1041,6 +1038,7 @@ enum OBTYPE {
OT_A_RAGE,
OT_A_SPRINT,
OT_A_STINGACID, // need to define dam in f_canwill
OT_A_SUCKBLOOD,
OT_A_SWOOP,
OT_A_EMPLOY,
OT_A_HEAVYBLOW,
@ -1067,6 +1065,7 @@ enum OBTYPE {
OT_WAND_WEAKNESS,
OT_WAND_WONDER,
// tools
OT_BLANKET,
OT_BLINDFOLD,
OT_BUGLAMP,
OT_CANDLE,
@ -1092,7 +1091,9 @@ enum OBTYPE {
OT_MOTIONSCANNER,
OT_NVGOGGLES,
OT_PAPERCLIP,
OT_SLEEPINGBAG,
OT_TELEPAD,
OT_TENT,
OT_XRAYGOGGLES,
// misc objects
OT_BONE,
@ -1507,7 +1508,7 @@ enum FLAG {
//F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod
F_DAM, // v0 = damtype, text = 1d1+1
F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier)
F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better)
F_ACCURACY, // 100 - val0 = modify to tohit% (ie. higher is better)
F_UNARMEDWEP, // this is not a real weapon, ie. claws, teeth etc
F_ARMOURPIERCE, // goes through armour
F_TWOHANDED, // weapon uses two hands to weild
@ -1520,6 +1521,11 @@ enum FLAG {
F_FLAMESTRIKE, // causes fires where you hit
F_BALANCE, // heals target if their maxhp < your maxhp
F_REVENGE, // causes damage based on your hp
F_HELPSREST, // makes you heal mp/hp faster when using 'R'
// reduces skillcheck difficulty by v0.
// optional v1 = how many less turns between
// skillchecks. should not go more than
// DEFAULTRESTHEALTIME.
// tech flags
F_RNDCHARGES, // ob starts with between val0 and val1 charges
// this will cause F_CHARGES to be filled in
@ -1588,6 +1594,7 @@ enum FLAG {
F_DEBUG, // debugging enabled
F_ACCURACYMOD, // modify your accuracy by val0
F_VEGETARIAN, // this lf will not eat meat.
F_PARTVEGETARIAN,// this lf will only eat if hunger >= 'hungry'
F_SHIELDPENALTY, // lower your accuracy by val0 due to a cumbersome
// shield
F_LEVRACE, // at level v0, this race is promoted to race v1
@ -1599,6 +1606,12 @@ enum FLAG {
F_RESTHEALTIME, // val0 = how long to rest before healing hp
F_RESTHEALAMT, // val0 = how many hp to gain after resting x turns
F_RESTHEALMPAMT, // val0 = how many MP to gain after resting x turns
F_HOMEOB, // when this monster is auto generated on a level, place
// this object underneath them.
// text = object name
F_HOMELEVOB, // when this monster is auto generated on a level, place
// between v0 and v1 objects of type 'text' somewhere on
// the level.
F_AUTOCMD, // val0 = how many times to repeat this
F_LASTCMD, // text[0] = last command performed, v0/1 = x/y of cell, v2=various
F_CANLEARN, // lf is able to learn skill val0
@ -1612,6 +1625,8 @@ enum FLAG {
F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will
// start off hidden
F_CORPSETYPE, // text field specifies what corpse obtype to leave
F_CORPSEFLAG, // add flag v0 to our corpse.
// v1->v0, v2->v1, text->text
F_MYCORPSE, // text field contains obid of my corpse.
// (for ghosts)
F_NOCORPSE, // monster's body crumbles to dust after death
@ -1644,6 +1659,8 @@ enum FLAG {
// vanish.
// v1 is lifetime left. this decrements each turn.
// when at zero, lf vanishes.
F_HATESRACE, // lf will attack lfs with race=v0 or baseid=v0 on
// sight
F_HOSTILE, // lf will attack the player if in sight
F_FRIENDLY, // lf will attack all non-players if in sight
F_WANTS, // lf will try to pick up object type val0. if
@ -1722,7 +1739,8 @@ enum FLAG {
F_MAGICARMOUR,// armour is magically boosted. f->text is the description
// ie 'magic armour', 'force field'
// v0 is power left.
F_ASLEEP, // is asleep
F_ASLEEP, // is asleep. if v2 is set, means we are sleeping on
// purpose and will wake up when at full hp/mp/etc.
F_ATTACHEDTO, // you are attached to lf id v0, and will move with it
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
F_BLIND, // cannot see anything
@ -1795,6 +1813,9 @@ enum FLAG {
F_RESISTMAG, // immunity to magic effects. v0=amt (1-20)
F_MPREGEN, // regenerate MP at val0 per turn
F_RAGE, // you are enraged. v0/v1 will be set to player's old hp/maxhp
F_RETALIATE, // deal damage to anyone who hits you
// v0=ndice, v1=dsides, v2=damtype, text=obname
// text must have at least TWO words
F_RISEASGHOST, // become a ghost when you die.
F_SEEINDARK, // nightvis range is val0
F_TREMORSENSE, // doesn't need eyes to see, can see in dark with v0
@ -1831,8 +1852,8 @@ enum FLAG {
F_STATGAINREADY, // ready to increase str/int etc. v2 is how many times
// we can do it.
F_INTERRUPTED, // somethign interrupted our rest. stop!
F_RESTING, // are we resting? cleared on any action other than rest.
// v2 = if not, NA it is the training counter.
F_TRAINING, // are we training? 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
@ -2018,7 +2039,8 @@ enum ERROR {
//
E_NOBP = 48,
E_VEGETARIAN = 49,
E_NOOB = 50,
E_PARTVEGETARIAN= 50,
E_NOOB = 51,
};

37
doc/glyphs.txt Normal file
View File

@ -0,0 +1,37 @@
@ = human
: = timid animal
} = gas cloud
) = dancing weapon
A = avian / bird
a = ant
B = bat
C = celestial / divine ?
d = canine/dog
e = eye
f = feline/cat
g = goblin
i = insect
j = jelly/ooze/leech
k = kobold
G = large goblin
n = small humanoid / nymph / sprite
o = orc
O = ogre
p = sPirit
c = cockatricoe
x = small creature/monster
q = quadraped
Q = large quadraped
r = rodent
s = snake
S = spider
h = humanoid
H = large humanoid
U = unearthly/demonic/horrific creature
w = worm
z = lizard-like creature
Z = undead
---
C
hybrid human animal?

34
flag.c
View File

@ -105,7 +105,22 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
if ((gamemode == GM_GAMESTARTED)) {
if (f->pile->owner) {
if (announceflaggain(f->pile->owner, f)) {
addflag(f->pile, F_INTERRUPTED, B_TRUE, NA, NA, NULL); // note: recursive call!
// don't include flags which interrupt will kill!
switch (f->id) {
case F_RUNNING:
case F_TRAINING:
case F_AUTOCMD:
break;
case F_ASLEEP:
if (f->val[2] == NA) { // ie. sleeping, not resting
addflag(f->pile, F_INTERRUPTED, B_TRUE, NA, NA, NULL);
}
break;
default:
addflag(f->pile, F_INTERRUPTED, B_TRUE, NA, NA, NULL);
break;
}
f->known = B_TRUE;
if (f->obfrom) {
object_t *ob;
@ -198,6 +213,15 @@ void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {
}
}
int countflags(flagpile_t *fp) {
flag_t *f;
int count = 0;
for (f = fp->first ; f ; f = f->next) {
count++;
}
return count;
}
int flagcausesredraw(lifeform_t *lf, enum FLAG fid) {
if (!lf) return B_FALSE;
@ -334,6 +358,7 @@ void killflag(flag_t *f) {
lifeform_t *lf;
int doredraw = B_FALSE;
lf = f->pile->owner;
// flags which cause a redraw
@ -364,10 +389,15 @@ void killflag(flag_t *f) {
if (announceflagloss(lf, f)) {
// don't include flags which interrupt will kill!
switch (f->id) {
case F_RESTING:
case F_RUNNING:
case F_TRAINING:
case F_AUTOCMD:
break;
case F_ASLEEP:
if (f->val[2] != NA) { // ie. resting
addflag(lf->flags, F_INTERRUPTED, B_TRUE, NA, NA, NULL);
}
break;
default:
addflag(lf->flags, F_INTERRUPTED, B_TRUE, NA, NA, NULL);
break;

1
flag.h
View File

@ -8,6 +8,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int countflags(flagpile_t *fp);
int flagcausesredraw(lifeform_t *lf, enum FLAG fid);
int flagstacks(enum FLAG fid);
int modcounter(flagpile_t *fp, int amt);

183
io.c
View File

@ -62,6 +62,8 @@ extern lifeform_t *player;
extern map_t *firstmap;
int gettinginput = B_FALSE;
int viewx = -9999,viewy = -9999;
int vieww,viewh;
@ -516,18 +518,20 @@ cell_t *askcoords(char *prompt, int targettype) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "fleeing");
}
if (lfhasflag(c->lf, F_PRONE)) {
f = lfhasflag(c->lf, F_ASLEEP);
if (f) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
if (f->val[2] == NA) {
strcat(extrainfo, "sleeping");
} else {
strcat(extrainfo, "resting");
}
} else if (lfhasflag(c->lf, F_PRONE)) {
// prevent showing 'prone' AND 'asleep'
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "prone");
}
if (lfhasflag(c->lf, F_RESTING)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "resting");
}
if (lfhasflag(c->lf, F_ASLEEP)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "asleep");
}
f = lfhasflag(c->lf, F_ATTACHEDTO);
if (lfhasflag(c->lf, F_ATTACHEDTO)) {
lifeform_t *alf;
@ -603,6 +607,13 @@ cell_t *askcoords(char *prompt, int targettype) {
strcat(extrainfo, "enraged");
}
for (f = c->lf->flags->first ; f ; f = f->next) {
if (f->id == F_RETALIATE) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, f->text);
}
}
wep = getweapon(c->lf);
if (wep && (c->lf->race->id != R_DANCINGWEAPON)) {
object_t *secwep;
@ -859,7 +870,19 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE;
break;
case F_ASLEEP:
if (isplayer(lf) && (f->val[2] != NA)) { // ie. resting
object_t *restob;
restob = getrestob(lf);
if (restob) {
char restobname[BUFLEN];
getobname(restob, restobname, 1);
msg("You start resting (in your %s)...",noprefix(restobname));
} else {
msg("You start resting (on the ground)...");
}
} else {
msg("%s fall%s asleep.",lfname, isplayer(lf) ? "" : "s");
}
donesomething = B_TRUE;
break;
case F_ATTACHEDTO:
@ -1146,6 +1169,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
msg("%s enter%s a berzerker rage!", lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
break;
case F_RETALIATE:
msg("%s appear%s from %s%s skin.", noprefix(f->text),
(f->text[strlen(f->text)-1] == 's') ? "" : "s",
lfname, getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_REGENERATES:
if (isplayer(lf)) { // don't know if monsters get it
msg("Your body's healing rate is enhanced!");
@ -1584,6 +1613,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("%s %s less angry now.", lfname, isplayer(lf) ? "feel" : "seems");
donesomething = B_TRUE;
break;
case F_RETALIATE:
msg("%s disappear%s from %s%s skin.", noprefix(f->text),
(f->text[strlen(f->text)-1] == 's') ? "" : "s",
lfname, getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_REGENERATES:
if (isplayer(lf)) { // don't know if monsters lose it
msg("Your healing rate is no longer enhanced.");
@ -1931,7 +1966,7 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, long opts, ...) {
wantflag[nwantflags] = va_arg(flags, enum FLAG);
}
va_end(flags);
dblog("nwantflags is %d",nwantflags);
//dblog("nwantflags is %d",nwantflags);
// remember player's current ammo
if (op->owner) {
@ -2883,6 +2918,9 @@ void describeob(object_t *o) {
case F_PRODUCESLIGHT:
mvwprintw(mainwin, y, 0, "%s produces light.", buf); y++;
break;
case F_RETALIATE:
mvwprintw(mainwin, y, 0, "%s protects you with %s.", buf, f->text); y++;
break;
case F_RAGE:
mvwprintw(mainwin, y, 0, "%s makes you enraged.", buf); y++;
break;
@ -3171,6 +3209,7 @@ void docomms(void) {
char buf[BUFLEN];
char lfname[BUFLEN];
char ch;
flag_t *f;
where = askcoords("Talk to who?", TT_MONSTER);
if (where && where->lf && cansee(player, where->lf)) {
@ -3194,7 +3233,9 @@ void docomms(void) {
if (isadjacent(lf->cell, player->cell) && !lfhasflag(lf, F_NOPACK)) {
addchoice(&prompt, 't', "Trade items with me", NULL, NULL);
}
if (lfhasflag(lf, F_RESTING)) {
f = isresting(lf);
if (f) {
addchoice(&prompt, 'r', "Stop resting.", NULL, NULL);
} else {
addchoice(&prompt, 'r', "Rest until you are healed.", NULL, NULL);
@ -3240,7 +3281,8 @@ void docomms(void) {
msg("Cancelled.");
return;
case 'r':
if (lfhasflag(lf, F_RESTING)) {
f = isresting(lf);
if (f) {
stopresting(lf);
} else {
if (needstorest(lf, NULL)) {
@ -4465,7 +4507,7 @@ void dorest(void) {
}
}
} else {
if (countnearbyallies(player)) {
if (countnearbyhurtallies(player)) {
strcpy(ques, "Rest until nearby allies are healed?");
ch = askchar(ques, "yn", "y", B_TRUE);
if (ch == 'y') {
@ -5252,12 +5294,14 @@ int getkey(void) {
key_code = getch();
// XXX NEW CODE:
if (gettinginput) {
if (strcmp(msgbuf, "")) {
clearmsg();
//strcpy(msgbuf, "");
//drawmsg();
//drawcursor();
}
}
return keycodetokey(key_code);
}
@ -5347,7 +5391,9 @@ void handleinput(void) {
f->val[0]--;
}
} else {
gettinginput = B_TRUE;
ch = getkey();
gettinginput = B_FALSE;
}
gotcmd = B_TRUE;
@ -5823,7 +5869,7 @@ void drawstatus(void) {
wprintw(statwin, " Next:%ld",xpleft);
}
// blinded?
if (isblind(player)) {
if (isblind(player) && !lfhasflag(player, F_ASLEEP)) {
setcol(statwin, C_RED);
wprintw(statwin, " Blind");
unsetcol(statwin, C_RED);
@ -5836,7 +5882,15 @@ void drawstatus(void) {
}
// paralysed somehow?
if (isimmobile(player)) {
if (isresting(player)) {
setcol(statwin, C_CYAN);
wprintw(statwin, " Resting");
unsetcol(statwin, C_CYAN);
} else if (lfhasflag(player, F_ASLEEP)) {
setcol(statwin, C_BLUE);
wprintw(statwin, " Asleep");
unsetcol(statwin, C_BLUE);
} else if (isimmobile(player)) {
setcol(statwin, C_RED);
wprintw(statwin, " Immobile");
unsetcol(statwin, C_RED);
@ -6283,14 +6337,17 @@ void showlfstats(lifeform_t *lf, int showall) {
int y = 0, y2 = 0, x2 = 40;
int x;
int arating, evasion;
int speed,acc;
int acc;
char actbuf[BUFLEN],movebuf[BUFLEN];
int h;
char buf[BUFLEN],buf2[BUFLEN];
job_t *j;
flag_t *f;
char *ftext= "%12s: ";
long xpneeded;
object_t *w;
object_t *o;
object_t *w[2];
int nweps = 0;
objecttype_t *ot;
int first;
int i;
@ -6552,21 +6609,36 @@ void showlfstats(lifeform_t *lf, int showall) {
// now go to second column
mvwprintw(mainwin, y2, x2, ftext, "# Attacks");
wprintw(mainwin, "%d", getmaxattacks(lf)); y2++;
y2++;
// current weapon + dam
w = getweapon(lf);
if (w) {
nweps = 0;
o = getweapon(lf);
if (o) w[nweps++] = o;
o = getsecmeleeweapon(lf);
if (o) {
// can't be the same as the first one!
if ((nweps == 1) && (o == w[0])) {
} else {
w[nweps++] = o;
}
}
for (i = 0; i < nweps; i++) {
if (w[i]) {
int mindam,maxdam;
int bonus;
int bonus,speed;
// weapon
sprintf(buf, "%s", w->type->name);
mvwprintw(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
if (showall) {
// damage
f = hasflag(w->flags, F_BONUS);
char buf2[BUFLEN];
// calculate damage
f = hasflag(w[i]->flags, F_BONUS);
if (f && f->known) {
// only tell player about bonuses if they are known.!
bonus = f->val[0];
@ -6574,7 +6646,7 @@ void showlfstats(lifeform_t *lf, int showall) {
bonus = 0;
}
f = hasflag(w->flags, F_DAM);
f = hasflag(w[i]->flags, F_DAM);
if (f) {
getdamrange(f, &mindam, &maxdam);
} else {
@ -6586,7 +6658,7 @@ void showlfstats(lifeform_t *lf, int showall) {
maxdam += bonus;
// apply damage mod for strength
if (!hasflag(w->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
if (!hasflag(w[i]->flags, F_NOSTRDAMMOD) && !lfhasflag(lf, F_NOSTRDAMMOD)) {
mindam = (int)((float)mindam * dammod);
maxdam = (int)((float)maxdam * dammod);
}
@ -6594,30 +6666,33 @@ void showlfstats(lifeform_t *lf, int showall) {
if (mindam < 0) mindam = 0;
if (maxdam < 0) maxdam = 0;
sprintf(buf, "%d-%d",(int)mindam,(int)maxdam);
mvwprintw(mainwin, y2, x2, ftext, "Weapon Dmg");
sprintf(buf, "%s (%d-%d dmg)", w[i]->type->name,(int)mindam,(int)maxdam);
mvwprintw(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
// chance to hit
acc = getlfaccuracy(lf, w);
mvwprintw(mainwin, y2, x2, ftext, "Wep.Accuracy");
wprintw(mainwin, "%d%%", acc); y2++;
// attack speed
acc = getlfaccuracy(lf, w[i]);
speed = getattackspeed(lf);
getspeedname(speed, buf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Attack Speed");
getspeedname(speed, buf2);
capitalise(buf2);
sprintf(buf, "%s, %d%%",buf2,acc);
mvwprintw(mainwin, y2, x2, ftext, "Speed/Acc");
wprintw(mainwin, "%-20s", buf); y2++;
} else {
// just show weapon name
sprintf(buf, "%s", w[i]->type->name);
mvwprintw(mainwin, y2, x2, ftext, "Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
}
} else {
// no damage
// no weapon
sprintf(buf, "N/A");
mvwprintw(mainwin, y2, x2, ftext, "Current Weapon");
wprintw(mainwin, "%-20s", buf); y2++;
}
} // end for each weapon
// skip a line
y2++;
@ -6675,7 +6750,7 @@ void showlfstats(lifeform_t *lf, int showall) {
// no attacks at all?
if (!w && !op->first) {
if ((nweps == 0) && !op->first) {
sprintf(buf, "N/A");
mvwprintw(mainwin, y2, x2, ftext, "Attack");
wprintw(mainwin, "%-20s", buf); y2++;
@ -6709,19 +6784,18 @@ void showlfstats(lifeform_t *lf, int showall) {
y2++; // skip line
}
speed = getactspeed(lf);
getspeedname(speed, buf);
getspeednameshort(getactspeed(player), actbuf);
getspeednameshort(getmovespeed(player), movebuf);
if (!strcmp(actbuf, movebuf)) {
sprintf(buf, "%s", actbuf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Action Speed");
wprintw(mainwin, "%-20s", buf); y2++;
} else {
sprintf(buf, "Mv:%s Act:%s", movebuf,actbuf);
}
speed = getmovespeed(lf);
getspeedname(speed, buf);
capitalise(buf);
mvwprintw(mainwin, y2, x2, ftext, "Move Speed");
mvwprintw(mainwin, y2, x2, ftext, "Speed");
wprintw(mainwin, "%-20s", buf); y2++;
y2++; // skip line
@ -6993,6 +7067,17 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
f = lfhasflag(lf, F_RETALIATE);
if (f && (f->known)) {
if (showall || (lorelev >= PR_BEGINNER)) {
mvwprintw(mainwin, y, 0, "%s %s covered by %s (%dd%d %s dmg to attackers).", you(lf), is(lf), f->text,
f->val[0], f->val[1], getdamname(f->val[2]));
} else {
mvwprintw(mainwin, y, 0, "%s %s covered by %s", you(lf), is(lf), f->text);
}
y++;
}
// fleeing?
if (showall) {
for (f = lf->flags->first ; f ; f = f->next) {

595
lf.c

File diff suppressed because it is too large Load Diff

9
lf.h
View File

@ -34,8 +34,10 @@ int cantakeoff(lifeform_t *lf, object_t *o);
int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *targob, cell_t *targcell);
void checkxp(enum RACE rid);
float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
int countinnateattacks(lifeform_t *lf);
int countmoney(lifeform_t *lf);
int countnearbyallies(lifeform_t *lf);
int countnearbyhurtallies(lifeform_t *lf);
void debug(lifeform_t *lf);
void die(lifeform_t *lf);
void dumplev(void);
@ -45,6 +47,7 @@ int eat(lifeform_t *lf, object_t *o);
void enhanceskills(lifeform_t *lf);
object_t *eyesshaded(lifeform_t *lf);
int fall(lifeform_t *lf, lifeform_t *fromlf, int announce);
int fallasleep(lifeform_t *lf, int howlong);
void fightback(lifeform_t *lf, lifeform_t *attacker);
job_t *findjob(enum JOB jobid);
job_t *findjobbyname(char *name);
@ -105,6 +108,7 @@ char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer);
glyph_t *getlfglyph(lifeform_t *lf);
enum MATERIAL getlfmaterial(lifeform_t *lf);
enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid);
int getmaxattacks(lifeform_t *lf);
float getmaxcarryweight(lifeform_t *lf);
float getmaxliftweight(lifeform_t *lf);
int getmaxmp(lifeform_t *lf);
@ -121,6 +125,8 @@ char *getlfnamea(lifeform_t *lf, char *buf);
char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis);
enum LFSIZE getlfsize(lifeform_t *lf);
float getlfweight(lifeform_t *lf, int withobs);
object_t *getsecmeleeweapon(lifeform_t *lf);
object_t *getshield(lifeform_t *lf);
int getspellspeed(lifeform_t *lf);
char *getplayername(char *buf);
char *getplayernamefull(char *buf);
@ -133,6 +139,7 @@ object_t *getrandomarmour(lifeform_t *lf);
//int getrandommonlevel(int depth);
race_t *getrandomrace(map_t *map, int forcedepth);
race_t *getreallyrandomrace(void);
object_t *getrestob(lifeform_t *lf);
enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id);
char *getspeedname(int speed, char *buf);
char *getspeednameshort(int speed, char *buf);
@ -177,6 +184,7 @@ enum BURDENED isburdened(lifeform_t *lf);
int ischarmable(lifeform_t *lf);
int isdead(lifeform_t *lf);
flag_t *isdrunk(lifeform_t *lf);
object_t *isdualweilding(lifeform_t *lf);
int isfleeing(lifeform_t *lf);
int isfreebp(lifeform_t *lf, enum BODYPART bp);
int isfriendly(lifeform_t *lf);
@ -193,6 +201,7 @@ flag_t *ispoisoned(lifeform_t *lf);
int ispolymorphed(lifeform_t *lf);
int isprone(lifeform_t *lf);
flag_t *isresistantto(flagpile_t *fp, enum DAMTYPE dt);
flag_t *isresting(lifeform_t *lf);
object_t *isstuck(lifeform_t *lf);
flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt);
void killjob(job_t *job);

607
log.txt
View File

@ -2,612 +2,5 @@
====== NEW LOGFILE ====
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
finding random lf with rarity val 92-100
-> possibility: kobold, rarity=95
-> possibility: xat, rarity=95
-> possibility: giant bat, rarity=95
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=95
got 5 possibilities.
rollhitdice() - rolling 2d4 + 2
rollhitdice() - mod is +44%
rollhitdice() ---- die 1/2 == 4
rollhitdice() ---- die 2/2 == 4
TOTAL: 8
-> modified to: 11
test
givejob() starting.
processing normal flag: 228
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 174
processing normal flag: 175
processing normal flag: 175
processing normal flag: 175
processing normal flag: 175
processing normal flag: 175
processing normal flag: 175
processing normal flag: 175
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 173
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 263
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 175
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 260
processing normal flag: 338
test
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { cannot see my master - adding F_TARGETCELL for last known loc }
.oO { something going to targecell: 1, 2 }
.oO { walking from 1,4 towards f_targetcell (1,2) ... }
.oO { successfully walked towards f_targetcell. arrived at 1,3 }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving randomly }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { cannot see my master - adding F_TARGETCELL for last known loc }
.oO { your young wolf going to targecell: 1, 1 }
.oO { walking from 1,3 towards f_targetcell (1,1) ... }
.oO { successfully walked towards f_targetcell. arrived at 1,2 }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { didn't find any obs i want }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving randomly }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { cannot see my master - adding F_TARGETCELL for last known loc }
.oO { something going to targecell: 1, 1 }
.oO { walking from 3,1 towards f_targetcell (1,1) ... }
.oO { successfully walked towards f_targetcell. arrived at 2,1 }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { didn't find any obs i want }
.oO { walking from 2,1 towards f_targetcell (1,1) ... }
.oO { successfully walked towards f_targetcell. arrived at 1,1 }
.oO { arrived at f_targetcell. removing. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { i can see my master - moving towards them }
.oO { success. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { cannot see my master - adding F_TARGETCELL for last known loc }
.oO { something going to targecell: 1, 13 }
.oO { walking from 1,10 towards f_targetcell (1,13) ... }
.oO { successfully walked towards f_targetcell. arrived at 1,11 }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { didn't find any obs i want }
.oO { walking from 1,11 towards f_targetcell (1,13) ... }
.oO { successfully walked towards f_targetcell. arrived at 1,12 }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { didn't find any obs i want }
.oO { walking from 1,12 towards f_targetcell (1,13) ... }
.oO { successfully walked towards f_targetcell. arrived at 1,13 }
.oO { arrived at f_targetcell. removing. }
AIMOVE: your young wolf
.oO { looking for covetted objects... }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { looking for any ob which i want. }
.oO { no targetcell, so looking for remote objects }
.oO { didn't find any obs i want }
.oO { i do not have a target or can't move towards it. }
.oO { i am friendly to the player. looking for a target. }
.oO { cannot see my master and am at last known loc. trying last known dir (Southeast) }
.oO { ...successfully }

184
map.c
View File

@ -45,6 +45,27 @@ cell_t *addcell(map_t *m, int x, int y) {
return cell;
}
void addhomeobs(lifeform_t *lf) {
flag_t *f;
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_HOMEOB) {
addob(lf->cell->obpile, f->text);
} else if (f->id == F_HOMELEVOB) {
int i,amt;
amt = rnd(f->val[0],f->val[1]);
for (i = 0; i < amt; i++) {
cell_t *c;
// pick new EMPTY random spot
c = getrandomcell(lf->cell->map);
while (!cellwalkable(NULL, c, NULL)) {
c = getrandomcell(lf->cell->map);
}
addob(c->obpile, f->text);
}
}
}
}
map_t *addmap(void) {
map_t *a;
int id;
@ -166,7 +187,6 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int auto
newlf->born = B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, B_TRUE, NA, NA, NULL);
newlf->born = B_TRUE;
}
}
}
@ -735,6 +755,7 @@ void createmap(map_t *map, int depth, int habitat) {
cell_t *cell, *c;
object_t *o;
int db = B_FALSE;
lifeform_t *lf;
// parameters
int turnpct = DEF_TURNPCT;
@ -1240,33 +1261,11 @@ void createmap(map_t *map, int depth, int habitat) {
c = getrandomroomcell(map, i);
// if nothing there
if (c && isempty(c) && !countobs(c->obpile)) {
/*
if (roomspecial[i]) {
if (getrand(1,4) == 1) { // less chance of monster
addlifeform(x, y, curz,getrandommonster(curz),
getrand(1,curz+1), C_AI, B_FALSE, B_TRUE);
} else {
//add objects based on room type
if (roomspecial[i] == SP_MEDLAB) {
addspecialroomob(x, y, curz, SP_MEDLAB,
OR, 3, OP_AI_HEALS, OP_REVIVES);
} else if (roomspecial[i] == SP_COMPLAB) {
addspecialroomob(x, y, curz, SP_COMPLAB,
OR, 0);
} else if (roomspecial[i] == SP_ALIENNEST) {
addspecialroomob(x, y, curz, SP_ALIENNEST,
OR, 0);
}
}
} else {
*/
// slightly more chance of objects in rooms
addrandomthing(c,60);
done = B_TRUE;
//dblog("----> Success ob at (%d,%d).",c->x,c->y);
} else {
ntries++;
//dblog("----> Failed, now at retry #%d/%d",ntries, numobs);
}
if (ntries >= numobs) {
@ -1280,132 +1279,11 @@ void createmap(map_t *map, int depth, int habitat) {
if (db) dblog("Finished adding objects.");
/*
// some extra monsters in corridors
for (i = 0; i < getrand(3,8); i++) {
int x,y;
lifeform_t *lf;
lf = addlifeform(rand() % MAZEW, rand() % MAZEH,curz,getrandommonster(curz), getrand(1,curz+1), C_AI, B_FALSE, B_TRUE);
done = B_FALSE;
while (!done) {
getrandomcell(&x, &y, curz,C_EMPTY );
if (isempty(x,y,curz)) {
lf->x = x;
lf->y = y;
lf->z = curz;
done = B_TRUE;
}
}
}
*/
/*
// add a fixed revival booth
done = B_FALSE;
while (!done) {
getrandomcell(&x,&y, curz,C_ROOM); // get a random cell in a room
if (isempty(x,y,curz)) {
if (!cellhasobject(x,y,curz)) {
done = B_TRUE;
// add home objects
for (lf = map->lf ; lf ; lf = lf->next) {
addhomeobs(lf);
}
}
}
addobject(&wreck->mazelev[curz].maze[y*MAZEW+x].floorobs, O_REVIVAL);
// emergency lighting
for (y = 0; y < MAZEH; y++) {
for (x = 0; x < MAZEW; x++) {
if (getfloor(x,y,curz) == C_EMPTY) {
if (isempty(x,y,curz) && !hasdangerousobject(NULL,x,y,curz)) {
// chance of a light...
int lightchance = 5;
int roll = getrand(1,100);
if (roll <= lightchance) {
addobject(&wreck->mazelev[curz].maze[y*MAZEW+x].floorobs, O_EMERGLIGHT);
}
}
}
}
}
// add the reactor
done = B_FALSE;
while (!done) {
getrandomcell(&x,&y, curz,C_ROOM); // get a random cell in a room
if (getdistance(x,y,wreck->dockpos.x,wreck->dockpos.y) >= 20) {
if (isempty(x,y,curz)) {
if (!cellhasobject(x,y,curz)) {
done = B_TRUE;
}
}
}
}
wreck->mazelev[curz].reactorpos.x = x;
wreck->mazelev[curz].reactorpos.y = y;
addobject(&wreck->mazelev[curz].maze[y*MAZEW+x].floorobs, O_REACTOR);
wreck->mazelev[curz].powered = B_TRUE;
wreck->mazelev[curz].lightlevel = getrand(50,100);
//printf("reactor at %d,%d,%d\n",x,y,curz);
// all empty cells around it change
for (cury = y-2 ; cury <= y+2; cury++) {
for (curx = x-2 ; curx <= x+2; curx++) {
if (isonmap(curx,cury,curz)) {
if (!issolid(curx,cury,curz)) {
wreck->mazelev[curz].maze[cury*MAZEW+curx].floor = C_EMPTYHAZARD;
}
}
}
}
// calculate level difficulty
wreck->mazelev[curz].mondifficulty = 0;
wreck->mazelev[curz].mapdifficulty = 0;
// monsters
for (lf = wreck->mazelev[curz].lifeform ; lf ; lf = lf->next) {
if (lf->controller != C_HUMAN) {
wreck->mazelev[curz].mondifficulty += (getrdifficulty(lf->race));
}
}
// maze layout & objects
for (y = 0; y < MAZEH; y++) {
for (x = 0; x < MAZEW; x++) {
switch (numexits(x,y,curz)) {
case 2: // corner
wreck->mazelev[curz].mapdifficulty += 0.5;
break;
case 1: // dead end
wreck->mazelev[curz].mapdifficulty += 1;
break;
}
if (containerhasobject(&wreck->mazelev[curz].maze[y*MAZEW+x].floorobs, O_SPAWNPIT)) {
wreck->mazelev[curz].mondifficulty += DF_SPAWNPIT;
}
}
}
// fix exithp
for (y = 0; y < MAZEH; y++) {
for (x = 0; x < MAZEW; x++) {
int d;
for (d = D_NORTH ; d <= D_WEST; d++) {
int extype = getexit(x,y,curz,d);
if (isbreakableexit(getexit(x,y,curz,d))) {
// using setexit will make sure the hp is right
setexit(x,y,curz,d,extype);
}
}
}
}
*/
//printf("*** Level difficulty is %0.2f\n", getmazedifficulty(curz));
map->beingcreated = B_FALSE;
}
@ -2499,11 +2377,19 @@ int linkstairs(object_t *o) {
void makedoor(cell_t *cell) {
object_t *o;
map_t *m;
char doorbuf[BUFLEN];
m = cell->map;
setcelltype(cell, getemptycelltype(cell->map->habitat));
o = addob(cell->obpile, "wooden door");
setcelltype(cell, getemptycelltype(m->habitat));
if ((rnd(1,100) + m->depth) >= 66) {
strcpy(doorbuf, "iron door");
} else {
strcpy(doorbuf, "wooden door");
}
o = addob(cell->obpile, doorbuf);
if (o && (rnd(1,2) == 1)) {
opendoor(NULL, o);
} else {

1
map.h
View File

@ -1,6 +1,7 @@
#include "defs.h"
cell_t *addcell(map_t *map, int x, int y);
void addhomeobs(lifeform_t *lf);
map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen);
void addrandomob(cell_t *c);

66
move.c
View File

@ -484,11 +484,22 @@ int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, in
return bestdir;
}
// use 'n/a' for zero chance of falling. 0 means 'calculate based on distance'
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff) {
int i;
char lfname[BUFLEN];
char newlfname[BUFLEN];
int seen;
int hitwall = B_FALSE;
int mightfall = B_TRUE;
cell_t *newcell;
lifeform_t *newlf;
// calculate chance of falling
if (fallcheckdiff == 0) {
// chance based on distance
fallcheckdiff = howfar*10;
}
getlfname(lf,lfname);
if (cansee(player, lf)) {
@ -519,11 +530,31 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
switch (reason) {
case E_WALLINWAY:
case E_OFFMAP:
msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s");
if (seen) msg("%s slam%s into a wall!",lfname,isplayer(lf) ? "" : "s");
losehp(lf, rnd(1,6), DT_BASH, pusher, "slamming into a wall");
hitwall = B_TRUE;
// stop moving
i = howfar;
// don't fall
mightfall = B_FALSE;
break;
case E_LFINWAY:
newcell = getcellindir(lf->cell, dir);
newlf = newcell->lf;
if (newlf) { // should always be true
int momentumleft;
getlfname(newlf, newlfname);
if (seen) msg("%s slam%s into %s!",lfname,isplayer(lf) ? "" : "s",newlfname);
// remember our momentum
momentumleft = howfar - i;
// stop moving
i = howfar;
// higher chance of both falling
if (fallcheckdiff != NA) {
fallcheckdiff += (momentumleft*5);
}
// confer our remaining momentum on to them
knockback(newcell->lf, dir, momentumleft, lf, fallcheckdiff); // NOTE: recursive call
}
break;
default:
break;
@ -531,16 +562,13 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
}
}
// if you ran into a wall, it will prevent you from falling back.
if (!hitwall) {
int diff;
if (fallcheckdiff) {
diff = fallcheckdiff;
} else {
diff = howfar*10;
if (fallcheckdiff == NA) {
mightfall = B_FALSE;
}
if (mightfall) {
// save to avoid falling
if (!skillcheck(lf, SC_FALL, howfar*10, 0)) {
if (!skillcheck(lf, SC_FALL, fallcheckdiff, 0)) {
fall(lf, NULL, B_TRUE);
}
}
@ -622,6 +650,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
int preroom = -1, postroom = -1;
int prespeed = B_FALSE, postspeed = B_FALSE;
assert(newcell);
getlfname(lf, lfname);
if (newcell->map != lf->cell->map) {
@ -748,7 +778,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
}
} // end if crushable
if (o->type->id == OT_VINE) {
if ((o->type->id == OT_VINE) && !hasjob(lf, J_DRUID)) {
char obname[BUFLEN];
getobname(o,obname,o->amt);
if (isplayer(lf)) {
@ -807,7 +837,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if (isplayer(l)) {
if (cansee(l, lf) && areenemies(lf, l)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_RESTING)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_TRAINING)) {
// TODO: also check for isresting(l), if we have allies standing watch
char lfname2[BUFLEN];
getlfname(lf, lfname);
sprintf(lfname2, "%s",noprefix(lfname));
@ -924,7 +955,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
// see objects on ground
if (isplayer(lf)) {
int numobs;
numobs = countobs(newcell->obpile);
numobs = countnoncosmeticobs(newcell->obpile);
if ((numobs == 0) && !newcell->writing) {
// just clear the message buffer
if (!didmsg) clearmsg();
@ -964,10 +995,10 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
// measure distance when determining which way is "towards"
//
// in general:
// use orthogonal for voluntary movement (eg. monster moving
// use orthogonal/dt_orth for voluntary movement (eg. monster moving
// towards player), compass
//
// use compass for involuntary movement (eg. being knocked back by
// use compass/dt_compass for involuntary movement (eg. being knocked back by
// an explosion)
//
int movetowards(lifeform_t *lf, cell_t *dst, int dirtype) {
@ -1284,6 +1315,9 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
if ((o->type->id == OT_WEB) && (lf->race->baseid == R_SPIDER)) {
continue;
}
if ((o->type->id == OT_VINE) && hasjob(lf, J_DRUID)) {
continue;
}
f = hasflag(o->flags, F_RESTRICTMOVEMENT);
if (f) {

34
nexus.c
View File

@ -192,7 +192,7 @@ int main(int argc, char **argv) {
skill_t *sk;
initprompt(&prompt, "Select your spell specialty:");
addchoice(&prompt, 'a', getskillname(SK_SS_AIR), NULL, findskill(SK_SS_AIR));
addchoice(&prompt, 'i', getskillname(SK_SS_ICE), NULL, findskill(SK_SS_ICE));
addchoice(&prompt, 'i', getskillname(SK_SS_COLD), NULL, findskill(SK_SS_COLD));
addchoice(&prompt, 'f', getskillname(SK_SS_FIRE), NULL, findskill(SK_SS_FIRE));
getchoice(&prompt);
sk = (skill_t *) prompt.result;
@ -491,21 +491,16 @@ void donextturn(map_t *map) {
int donormalmove = B_TRUE;
flag_t *f;
if (donormalmove) {
// paralyzed etc?
if (isimmobile(who)) {
rest(who, B_FALSE);
donormalmove = B_FALSE;
}
}
// resting?
if (donormalmove) {
f = hasflag(who->flags, F_RESTING);
f = isresting(who);
if (!f) {
f = lfhasflag(who, F_TRAINING);
}
if (f) {
// check for interrupt of resting...
if (isplayer(who) && checkforkey()) {
msg("Stopped resting.");
msg("Stopped %s.",(f->id == F_TRAINING) ? "training" : "resting");
killflag(f);
} else {
rest(who, B_TRUE);
@ -514,6 +509,15 @@ void donextturn(map_t *map) {
}
}
if (donormalmove) {
// paralyzed etc?
if (isimmobile(who)) {
rest(who, B_FALSE);
donormalmove = B_FALSE;
}
}
if (donormalmove) {
if (isplayer(who)) {
drawcursor();
@ -528,7 +532,7 @@ void donextturn(map_t *map) {
}
}
if (hasflag(player->flags, F_RESTING)) {
if (hasflag(player->flags, F_ASLEEP)) {
// ooo is this right ?
needredraw = B_FALSE;
} else if (isdead(who) || cansee(player, who)) {
@ -782,14 +786,18 @@ int isplayerturn(void) {
int limit(int *what, int min, int max) {
int limited = B_FALSE;
if (min != NA) {
if (*what < min) {
*what = min;
limited = B_TRUE;
}
}
if (max != NA) {
if (*what > max) {
*what = max;
limited = B_TRUE;
}
}
return limited;
}
@ -887,7 +895,7 @@ int rollhitdice(lifeform_t *lf) {
int roll = 0;
int i;
float mod;
int db = B_TRUE;
int db = B_FALSE;
f = hasflag(lf->flags, F_HITDICE);
if (f) {

127
objects.c
View File

@ -78,6 +78,7 @@ enum OBCLASS sortorder[] = {
char *techadjective[] = {
"crazy",
"mysterious",
"odd",
"strange",
"weird",
@ -539,9 +540,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
}
}
if (db) dblog("DB: FOUND: ot->name = '%s'", ot->name );
if (ot->id == OT_WOODENDOOR) {
dblog("xxx");
}
// override blessed status from flags...
f = hasflag(ot->flags, F_STARTBLESSED);
@ -721,19 +719,19 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
if (cf) {
switch (rf->val[0]) {
case SZ_MINI:
cf->val[1] = 5;
cf->val[1] = 1;
break;
case SZ_TINY:
cf->val[1] = 25;
cf->val[1] = 10;
break;
case SZ_SMALL:
cf->val[1] = 55;
cf->val[1] = 25;
break;
case SZ_MEDIUM:
cf->val[1] = 90;
cf->val[1] = 75;
break;
case SZ_HUMAN:
cf->val[1] = 100;
cf->val[1] = 120;
break;
case SZ_LARGE:
cf->val[1] = 150;
@ -1849,6 +1847,18 @@ int countobs(obpile_t *op) {
return count;
}
int countnoncosmeticobs(obpile_t *op) {
object_t *o;
int count = 0;
for (o = op->first ; o ; o = o->next) {
if (!hasflag(o->flags, F_COSMETIC)) {
count++;
}
}
return count;
}
int curseob(object_t *o) {
int rv = B_FALSE;
lifeform_t *lf;
@ -2972,6 +2982,16 @@ char *getobequipinfo(object_t *o, char *buf) {
} else {
strcat(buf, " (weapon)");
}
} else if (f->val[0] == BP_SECWEAPON) {
if (isshield(o)) {
strcat(buf, " (shield)");
} else if (ismeleeweapon(o)) {
strcat(buf, " (second weapon)");
} else if (isfirearm(o)) {
strcat(buf, " (firearm)");
} else {
strcat(buf, " (in left hand)");
}
} else {
strcat(buf, " (");
strcat(buf, getbodypartequipname(f->val[0]));
@ -3771,7 +3791,7 @@ char *getschoolname(enum SPELLSCHOOL sch) {
case SS_MENTAL: return "Psionic Powers";
case SS_AIR: return "Elemental/Air Magic";
case SS_FIRE: return "Elemental/Fire Magic";
case SS_ICE: return "Elemental/Ice Magic";
case SS_COLD: return "Elemental/Cold Magic";
case SS_MODIFICATION: return "Modification Magic";
case SS_DEATH: return "Necromancy";
case SS_NATURE: return "Nature";
@ -3795,7 +3815,7 @@ char *getschoolnameshort(enum SPELLSCHOOL sch) {
case SS_WILD: return "Wild Magic";
case SS_AIR: return "Air Magic";
case SS_FIRE: return "Fire Magic";
case SS_ICE: return "Ice Magic";
case SS_COLD: return "Cold Magic";
case SS_DEATH: return "Necromancy";
case SS_LIFE: return "Life Magic";
case SS_MENTAL: return "Psionic Powers";
@ -4358,7 +4378,7 @@ void initobjects(void) {
// object types
// dungeon features
addot(OT_WOODENDOOR, "wooden door", "A sturdy wooden door.", MT_WOOD, 150, OC_DFEATURE);
addot(OT_DOORWOOD, "wooden door", "A sturdy wooden door.", MT_WOOD, 150, OC_DFEATURE);
// GLYPH here is a special case in getglyph
addflag(lastot->flags, F_DOOR, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL);
@ -4371,6 +4391,20 @@ void initobjects(void) {
addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
addot(OT_DOORIRON, "iron door", "A strong iron door.", MT_METAL, 300, OC_DFEATURE);
// GLYPH here is a special case in getglyph
addflag(lastot->flags, F_DOOR, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MAX, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 60, 60, NA, NULL);
addflag(lastot->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL);
addot(OT_WOODENTABLE, "wooden table", "A waist-height wooden table.", MT_WOOD, 25, OC_DFEATURE);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "\\");
@ -4546,7 +4580,7 @@ void initobjects(void) {
// potions (sorted by rarity)
addot(OT_POT_JUICE, "potion of fruit juice", "Tasty (but not very fresh) fruit juice!", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-8 health to whoever drinks it.", MT_GLASS, 1, OC_POTION);
addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-10 health to whoever drinks it.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL);
addot(OT_POT_WATER, "potion of water", "Plain, regular water.", MT_GLASS, 1, OC_POTION);
@ -4555,6 +4589,9 @@ void initobjects(void) {
addot(OT_POT_HEALING, "potion of healing", "Restores 10-20 health to whoever drinks it.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL);
addot(OT_POT_HEALINGMAJ, "potion of major healing", "Restores 20-30 health to whoever drinks it.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 72, NA, NULL);
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL);
addot(OT_POT_OIL, "potion of oil", "A bottle of cooking oil.", MT_GLASS, 1, OC_POTION);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 83, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of oil");
@ -4918,7 +4955,7 @@ void initobjects(void) {
///////////////////
// l2
addot(OT_S_CONECOLD, "cone of cold", "Shoots a blast of ice cold air, dealing 2-6 cold damage.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ICE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
@ -4927,7 +4964,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
// l3
addot(OT_S_COLDBURST, "cold burst", "Creates a radial blast of coldness out from the caster.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ICE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL);
///////////////////
@ -5013,6 +5050,13 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 4, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_THORNS, "thorns", "Sharp thorns grow from your skin, dealing 1d4 damage to attackers.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_WEB, "web", "Slows down pursuers with a burst of sticky spider web.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
@ -5042,6 +5086,7 @@ void initobjects(void) {
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_HAILSTORM, "hail storm", "Creates an intense storm of hail, causing damage to all within.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
@ -5157,6 +5202,12 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_HEALINGMAJ, "major healing", "Restores 20-30 health to the caster.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
///////////////////
// modification
///////////////////
@ -5313,6 +5364,9 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addflag(lastot->flags, F_NEEDSGRAB, B_TRUE, NA, NA, NULL);
addot(OT_A_FLURRY, "flurry", "Perform a flurry of attacks, forcing your opponent backwards.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
@ -5379,6 +5433,8 @@ void initobjects(void) {
addflag(lastot->flags, F_MANUALOF, SK_STEALTH, NA, NA, NULL);
addot(OT_MAN_TECHUSAGE, "manual of technology", "Teaches you the skill 'technology'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_TECHUSAGE, NA, NA, NULL);
addot(OT_MAN_TWOWEAPON, "manual of dual weilding", "Teaches you the skill 'dual weilding'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_TWOWEAPON, NA, NA, NULL);
// knowledge manuals
addot(OT_MAN_LORE_ARCANA, "tome of arcane lore", "Teaches you the skill 'lore:arcana'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_LORE_ARCANA, NA, NA, NULL);
@ -5418,8 +5474,8 @@ void initobjects(void) {
addflag(lastot->flags, F_MANUALOF, SK_SS_NATURE, NA, NA, NULL);
addot(OT_MAN_SS_FIRE, "manual of fire magic", "Teaches you the skill 'fire magic'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SS_FIRE, NA, NA, NULL);
addot(OT_MAN_SS_ICE, "manual of ice magic", "Teaches you the skill 'ice magic'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SS_ICE, NA, NA, NULL);
addot(OT_MAN_SS_COLD, "manual of ice magic", "Teaches you the skill 'ice magic'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SS_COLD, NA, NA, NULL);
addot(OT_MAN_SS_GRAVITY, "manual of gravitation magic", "Teaches you the skill 'gravitation magic'.", MT_PAPER, 3, OC_BOOK);
addflag(lastot->flags, F_MANUALOF, SK_SS_GRAVITY, NA, NA, NULL);
addot(OT_MAN_SS_LIFE, "manual of life magic", "Teaches you the skill 'life magic'.", MT_PAPER, 3, OC_BOOK);
@ -5680,6 +5736,10 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
// tools
addot(OT_BLANKET, "wool blanket", "A warm wool blanket for those cold winter nights.", MT_CLOTH, 2, OC_ARMOUR);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 10, NA, NA, NULL);
addot(OT_BLINDFOLD, "blindfold", "Short length of wide cloth, used for blocking eyesight.", MT_CLOTH, 0.01, OC_TOOLS);
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_BLIND, B_TRUE, NA, NULL);
@ -5789,6 +5849,10 @@ void initobjects(void) {
addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d1");
addflag(lastot->flags, F_ACCURACY, 50, NA, NA, NULL);
addot(OT_SLEEPINGBAG, "sleeping bag", "An insulated bag for sleeping in. Very comfortable.", MT_CLOTH, 4, OC_TECH);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 15, NA, NA, NULL);
// tech - l1
addot(OT_POCKETWATCH, "pocket watch", "A portable timekeeping device made to be carried in a pocket.", MT_METAL, 0.1, OC_TECH);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
@ -5817,6 +5881,11 @@ void initobjects(void) {
addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, IFACTIVE, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_TENT, "tent", "A easy to use, portable shelter made of fabric.", MT_CLOTH, 10, OC_TECH);
addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 15, 1, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
// tech - l2
addot(OT_FLASHBANG, "flashbang", "A stun grenade which temporarily blinds all within sight.", MT_METAL, 1, OC_TECH);
@ -6439,6 +6508,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 6, 6, NA, NULL);
addflag(lastot->flags, F_WATERPROOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 5, NA, NA, NULL);
// armour - waist
addot(OT_BELTLEATHER, "leather belt", "A plain leather belt.", MT_LEATHER, 0.2, OC_ARMOUR);
addflag(lastot->flags, F_RARITY, H_ALL, 85, NA, NULL);
@ -6941,7 +7011,7 @@ void initobjects(void) {
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 6, NA, NULL);
addot(OT_SAI, "sai", "A dagger with two long prongs on either side, made to trap opponents' weapons.", MT_METAL, 1, OC_WEAPON);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 81, NA, NULL);
addflag(lastot->flags, F_DAM, DT_PIERCE, NA, NA, "1d4");
addflag(lastot->flags, F_DISARMATTACK, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
@ -7998,9 +8068,11 @@ lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level) {
return newlf;
}
void makeduller(object_t *o, int howmuch) {
// returns true if something hapepned
int makeduller(object_t *o, int howmuch) {
char obname[BUFLEN];
int oldbonus,newbonus;
int rv = B_FALSE;
// get object name before changing the bonus
getobname(o,obname, 1);
@ -8025,7 +8097,11 @@ void makeduller(object_t *o, int howmuch) {
msg("%s seems duller!",obname);
}
}
rv = B_TRUE;
} else {
rv = B_FALSE;
}
return rv;
}
void makeknown(enum OBTYPE otid) {
@ -9835,13 +9911,6 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i
break;
case OT_POT_RESTORATION:
failed = B_TRUE;
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
if (isplayer(lf)) {
msg("You feel momentarily restored.");
}
break;
}
if (getattr(lf,A_STR) < lf->baseatt[A_STR]) {
setattr(lf, A_STR, lf->baseatt[A_STR]);
failed = B_FALSE;
@ -9978,7 +10047,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE potblessed, i
if (seen) *seen = B_TRUE;
}
if (potblessed != B_CURSED) {
modhunger(lf, -pctof(10, (float)HUNGERCONST));
modhunger(lf, -pctof(25, (float)HUNGERCONST));
}
break;
default: // nothing happens
@ -10114,7 +10183,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
if (isblessed(o)) power += 4;
// enforce maximum
if (power > 10) power = 10;
limit(&power, NA, 10);
// for unidentified scrolls which target an object,
// let player select ANY object (even if it won't
@ -11128,8 +11197,8 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
}
}
// an actual physical shield?
shield = getequippedob(target->pack, BP_SECWEAPON);
if (shield && isshield(shield)) {
shield = getshield(target);
if (shield) {
// block chance based on shield skill
// ie. ST_AVERAGE = speed3 = 18
// ie. gun = speed10 = 60 = basically impossible

View File

@ -33,6 +33,7 @@ void colourmatchob(object_t *o, lifeform_t *lf);
void copyobprops(object_t *dst, object_t *src);
int countnames(char **list);
int countobs(obpile_t *op);
int countnoncosmeticobs(obpile_t *op);
int curseob(object_t *o);
void damageallobs(object_t *exception, obpile_t *op, int howmuch, int damtype);
void dumprandomobs(int amt);
@ -161,7 +162,7 @@ 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);
int makeduller(object_t *o, int howmuch);
void makeknown(enum OBTYPE otid);
void maketried(enum OBTYPE otid);
void makewet(object_t *o, int amt);

209
spell.c
View File

@ -184,6 +184,50 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// attack
attackcell(user, targcell);
}
} else if (abilid == OT_A_FLURRY) {
int dir;
int dirch;
if (!isdualweilding(user)) {
if (isplayer(user)) msg("You need two be dual-weilding to perform an attack flurry!");
return B_TRUE;
}
// ask for direction
if (targcell) {
dir = getdirtowards(user->cell, targcell, NULL, B_FALSE, DT_ORTH);
} else {
dirch = askchar("Flurry in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
dir = chartodir(dirch);
if (dir == D_NONE) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE ;
} else {
targcell = getcellindir(user->cell, dir);
}
}
target = targcell->lf;
if (!target) {
if (isplayer(user)) msg("There is nobody there to attack!");
return B_TRUE;
}
getlfname(target, targetname);
// announce
if (!isplayer(user) && cansee(player, user)) {
msg("%s performs a flurry of fast attacks!", username);
}
// push them back
knockback(target, dir, 1, user, 5);
// if we succeeded in pushing them...
if (target->cell != targcell) {
movelf(user, targcell);
}
// now attack them
attackcell(user, target->cell);
} else if (abilid == OT_A_GRAB) {
char dirch;
flag_t *f;
@ -1089,23 +1133,56 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_AIRBLAST) {
int dir;
object_t *o,*nexto;
cell_t *firstobcell = NULL;
cell_t *nextc;
if (targcell) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
target = targcell->lf;
dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS);
} else {
int dirch;
dirch = askchar("Airblast in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE);
if ((dirch == '.') || (dir == '-')) {
fizzle(caster);
return B_TRUE;
}
dir = chartodir(dirch);
}
// keep going that dir until the next cell is a wall/lf/impassable ob
targcell = caster->cell;
nextc = getcellindir(targcell, dir);
while (nextc && cellwalkable(NULL, nextc, NULL)) {
targcell = nextc;
if (!firstobcell) {
// obs here?
for (o = targcell->obpile->first ;o ; o = o->next) {
if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_COSMETIC)) {
firstobcell = targcell;
break;
}
}
}
nextc = getcellindir(targcell, dir);
}
if (cansee(player, caster)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
msg("%s emit%s a powerful blast of air!", castername, isplayer(caster) ? "" : "s");
}
dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS);
// lfs
if (target) {
// if it was a lifeform which stopped us...
if (nextc->lf) {
targcell = nextc;
target = targcell->lf;
knockback(target, dir, power, caster, 0);
} else {
} else if (firstobcell) {
// objects
for (o = targcell->obpile->first ;o ; o = nexto) {
for (o = firstobcell->obpile->first ;o ; o = nexto) {
nexto = o->next;
if (!hasflag(o->flags, F_NOPICKUP)) knockbackob(o, dir, power, power, caster);
if (!hasflag(o->flags, F_NOPICKUP) && !hasflag(o->flags, F_COSMETIC)) {
knockbackob(o, dir, power, power, caster);
}
}
}
} else if (spellid == OT_S_ANIMATEDEAD) {
@ -2628,7 +2705,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
howlong = getspellduration(5,25,blessed) + power;
addtempflag(target->flags, F_FASTACTMOVE, 10, NA, NA, NULL, howlong);
}
} else if (spellid == OT_S_HEALING) {
} else if ((spellid == OT_S_HEALING) || (spellid == OT_S_HEALINGMIN) || (spellid == OT_S_HEALINGMAJ)) {
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE;
target = targcell->lf;
@ -2641,24 +2718,59 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (killflagsofid(target->flags, F_PAIN)) {
donesomething = B_TRUE;
}
if (killflagsofid(target->flags, F_POISONED)) {
donesomething = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if ((spellid == OT_S_HEALINGMIN) && donesomething) {
// minor healing will stop here
return B_FALSE;
}
if (target->hp < target->maxhp) {
switch (blessed) {
case B_BLESSED:
gainhp(target, 20 + (power*2));
int min,max;
switch (spellid) {
case OT_S_HEALINGMIN:
default:
min = 1; max = 10;
break;
case B_UNCURSED:
gainhp(target, rnd(10,20) + (power*2));
case OT_S_HEALING:
min = 10; max = 20;
break;
case B_CURSED:
gainhp(target, 10);
case OT_S_HEALINGMAJ:
min = 20; max = 30;
break;
}
gainhp(target, getspellduration(min,max,blessed) + (power*2));
if (isplayer(target)) {
if (target->hp >= target->maxhp) {
switch (spellid) {
case OT_S_HEALINGMIN:
msg("All of your scrapes and bruises are healed!");
break;
case OT_S_HEALING:
default:
msg("Your wounds close themselves!");
break;
case OT_S_HEALINGMAJ:
msg("Your injuries are healed!");
break;
}
} else {
switch (spellid) {
case OT_S_HEALINGMIN:
msg("Some of your scrapes and bruises are healed!");
break;
case OT_S_HEALING:
default:
msg("Some of your wounds close themselves!");
break;
case OT_S_HEALINGMAJ:
msg("Your injuries are partially healed!");
break;
}
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, target->cell)) {
@ -2668,57 +2780,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
donesomething = B_TRUE;
}
if (killflagsofid(target->flags, F_POISONED)) {
donesomething = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if (!donesomething) {
if (isplayer(target)) {
nothinghappens();
}
}
} else if (spellid == OT_S_HEALINGMIN) {
int donesomething = B_FALSE;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power)) return B_TRUE;
target = targcell->lf;
if (!target) {
fizzle(caster);
return B_FALSE;
}
// cure bad effects instead of healing
if (killflagsofid(target->flags, F_PAIN)) {
return B_FALSE;
}
if (target->hp < target->maxhp) {
switch (blessed) {
case B_BLESSED:
gainhp(target, 8 + power);
break;
case B_UNCURSED:
gainhp(target, rnd(1,8) + power);
break;
case B_CURSED:
gainhp(target, 1);
break;
}
if (isplayer(target)) {
msg("%s of your scrapes and bruises are healed!",
(target->hp >= target->maxhp) ? "All" : "Some");
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, target->cell)) {
getlfname(target, buf);
msg("%s looks a little healthier!", buf);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
donesomething = B_TRUE;
}
if (killflagsofid(target->flags, F_POISONED)) {
donesomething = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if (!donesomething) {
if (isplayer(target)) {
@ -4233,7 +4294,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE;
}
howlong = getspellduration(5,10,blessed) + (power/2);
addtempflag(target->flags, F_ASLEEP, B_TRUE, NA, NA, NULL, howlong);
fallasleep(target, F_ASLEEP);
if (isplayer(target) || haslos(player, target->cell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
@ -4747,6 +4808,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (failed) {
fizzle(caster);
}
} else if (spellid == OT_S_THORNS) {
flag_t *f;
// always targetted at caster
targcell = caster->cell;
target = caster;
f = addtempflag(caster->flags, F_RETALIATE, 1, 4, DT_PIERCE, "sharp thorns", FROMSPELL);
f->obfrom = spellid;
} else if (spellid == OT_S_TURNUNDEAD) {
int i;
// works on all undead in sight
@ -5079,8 +5148,8 @@ enum SKILL getschoolskill(enum SPELLSCHOOL ss) {
return SK_SS_NATURE;
case SS_FIRE:
return SK_SS_FIRE;
case SS_ICE:
return SK_SS_ICE;
case SS_COLD:
return SK_SS_COLD;
case SS_GRAVITY:
return SK_SS_GRAVITY;
case SS_LIFE: