- [+] job abilities can now generally happen as often as you like,
since they're ilmited by stamina. - [+] rename dexterity to agility - [+] The leprechaun steals an uncursed ring of miracles from you! The leprechaun cowers away from you! - [+] should FLEE , not cower! - [+] should set blessknown after reading a scroll - [+] cursed mending scroll not working on non-damaged objects - [+] spanner helps metal repair - [+] needle boosts sewing ability - [+] when resting in a tent, monstesr have very low chance of noticing you (5%) - [+] move display of resistances to 'effects' section. - [+] show what a mosnter wants in effects (if you have >= beginner knowledge) - [+] prevent running into monsters with shift+dir - [+] infinite loop when creating a map, constant getrandomroomcell() calls failing - [+] monstesr will steal objects they WANT rather than always random - [+] monster: - [+] leprechaun - [+] lucky - [+] covets gold - [+] shillelagh ? or just a club? - [+] blink - [+] steal - [+] dodge - [+] at the moment attack doesn't seem to be draining stamina... - [+] it is, but i'm getting it right back due to attack speed. - [+] make stamina take longer to regen. - 1 per 3 turns rather than 1 per 2. - [+] stamina loss must be MORE than basic regen rate (0.3) - [+] make stamina loss for attack depend on atatck speed! - [+] instead of "you feel sick", say "you have contracted weakening poison" or "you have been infected with xxx" - [+] store stamina as a float, but getstamina() should return an int. - [+] sprinting - use 1.5 stamina per cell instead of 1? - [+] modify accuracy text - [+] fork - [+] showing f_entertext should set didmsg - [+] instead of printing 100% accuracy, show "Acc:0" (ie 100), "Acc:-1" (ie -10) etc - [+] do this in @@ - [+] do this in describeob - [+] nocturnal monsters - [+] base monsters initially being asleep on time and whether mosnter is nocturnal - [+] also during aiturn(), if they have nothing to do and it's their sleeping time, goto sleep - [+] add flags - [+] flies should always move towards corpses if possible - [+] maybe F_WANTSOB corpse, covet? - [+] but thye can't pick it up so they'll just hover nearby? - [+] now they can be hostile too - [+] when we're picking a random corpse, try again if we get something with nocorpse like a ghost - [+] getrandomcorpserace() - [+] lower stamina max - currently at lv1+ft:11 i have 7 stam. should be more like 5 - [+] severed finger shoudn't count as making you bleed when you attack - [+] in askcoords, always show cell name - [+] monsters with no melee attacks can always cast spells while adjacent - [+] resting issues - [+] having a temporary injury means oyu need to rest, so don't say "you don't need to rest"! - [+] also don't stop resting until all temporary injuries are healed - [+] show comparative weights / armour ratings - [+] make price for npcs to join be lower - [+] assertion failure with who->timespent == 0 when a mosnter falls through a hole - [+] (after I follow by falling down the pit) - [+] make taketime() not work when not on the player's map - [+] bug - monsters never waking up - [+] "tailwind" spell (fast movement speed but forwards only) - [+] now that i have Hardness, _all_ reduced damage should go towards armour. - [+] earthquake - pits open up around you (but not under you) - [+] force sphere - radial blast outwards, knocks back lfs + obs + doors etc
This commit is contained in:
parent
ad18cf2398
commit
25db5b0da7
70
ai.c
70
ai.c
|
@ -68,7 +68,7 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
|
|||
penalty = (getcelldist(lf->cell, victim->cell)-1);
|
||||
if (penalty < 0) penalty = 0;
|
||||
penalty *= 3;
|
||||
if (!skillcheckvs(lf, SC_WILL, -penalty, victim, SC_WILL, 5)) {
|
||||
if (!skillcheckvs(lf, SC_WILL, -penalty, victim, SC_WILL, 5+gethitdice(victim))) {
|
||||
dblog(".oO { attempted target fooled me with feign death. ignoring. }");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -602,6 +602,8 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
|
|||
if ( (spell != OT_NONE) && // found a valid spell/ability to use
|
||||
((dist != 1) || // there is distance between us and target
|
||||
(st->obclass->id == OC_ABILITY) || // OR this works from adjacent
|
||||
(st->obclass->id == OC_ABILITY) || // OR we have no melee attack
|
||||
!countinnateattacks(lf) ||
|
||||
(rnd(1,3) == 1)) // OR random chance of using anyway...
|
||||
) {
|
||||
int spellfailed = B_FALSE;
|
||||
|
@ -669,8 +671,8 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
|
|||
// spell succesful
|
||||
|
||||
if ((spell == OT_A_STEAL) && !lfhasflag(lf, F_NOFLEE)) {
|
||||
// run away for a few turns
|
||||
fleefrom(lf, spelllf, rnd(3,7), B_TRUE);
|
||||
// run away for a while
|
||||
fleefrom(lf, spelllf, rnd(10,20), B_TRUE);
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -1031,7 +1033,6 @@ void aiturn(lifeform_t *lf) {
|
|||
// housekeeping - weapon changes, drop/pickup,
|
||||
// use items, talk,etc
|
||||
///////////////////////////////////////////////
|
||||
|
||||
if (lfhasflag(lf, F_ISPRISONER) && master && isplayer(master) && cansee(lf, master)) {
|
||||
if (isoutdoors(lf->cell->map) && pctchance(20)) {
|
||||
object_t *o;
|
||||
|
@ -1096,10 +1097,14 @@ void aiturn(lifeform_t *lf) {
|
|||
int vol;
|
||||
f = poss[rnd(0,nposs-1)];
|
||||
vol = rnd(f->val[1], f->val[2]);
|
||||
if (f->text) {
|
||||
say(lf, f->text, vol);
|
||||
} else {
|
||||
sayphrase(lf, f->val[0], vol, NA, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// healing
|
||||
|
@ -1144,6 +1149,17 @@ void aiturn(lifeform_t *lf) {
|
|||
if (lf->hp < (lf->maxhp/2)) {
|
||||
if (!useitemwithflag(lf, F_AIHEALITEM)) {
|
||||
return;
|
||||
} else {
|
||||
// don't have or can't use our healing items
|
||||
// no enemies in sight?
|
||||
if (safetorest(lf)) {
|
||||
// if it's "night time" for us, sleep forever.
|
||||
// otehrwise just sleep until we're healed
|
||||
if (!gotosleep(lf, issleepingtimefor(lf) ? B_TRUE : B_FALSE)) {
|
||||
taketime(lf, getactspeed(lf)); // to make sure our turn ends
|
||||
return; // success
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1393,40 +1409,50 @@ void aiturn(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
if (!lfhasflag(lf, F_STUNNED)) {
|
||||
lifeform_t *hateposs[MAXCANDIDATES],*poss[MAXCANDIDATES];
|
||||
int nposs = 0, nhateposs = 0;
|
||||
if (db) dblog(".oO { looking for a target . }");
|
||||
// look for any race which we hate
|
||||
|
||||
// look for any hated lfs or enemies
|
||||
newtarget = NULL;
|
||||
for (n = 0; n < lf->nlos; n++) {
|
||||
lifeform_t *who;
|
||||
if (lf->los[n] != lf->cell) {
|
||||
if (lf->los[n] != lf->cell) { // not ourself
|
||||
who = lf->los[n]->lf;
|
||||
if (who && !isdead(who) && !isunconscious(who) && cansee(lf, who)) {
|
||||
int chance = 100;
|
||||
// targets sleeping in a tent will probably be ignored
|
||||
if (isresting(lf)) {
|
||||
object_t *restob;
|
||||
restob = getrestob(who);
|
||||
if (restob && (restob->type->id == OT_TENT)) {
|
||||
chance = 5;
|
||||
}
|
||||
}
|
||||
if (pctchance(chance)) {
|
||||
if (lfhasflagval(lf, F_HATESRACE, who->race->id, NA, NA, NULL) ||
|
||||
lfhasflagval(lf, F_HATESRACE, who->race->baseid, NA, NA, NULL) ) {
|
||||
if (nhateposs < MAXCANDIDATES) {
|
||||
if (db) dblog(".oO { found a hated target - lfid %d (%s) ! }",who->id, who->race->name);
|
||||
newtarget = who;
|
||||
hateposs[nhateposs++] = who;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!newtarget) {
|
||||
// now look for enemies
|
||||
for (n = 0; n < lf->nlos; n++) {
|
||||
if (lf->los[n] != lf->cell) {
|
||||
lifeform_t *who;
|
||||
who = lf->los[n]->lf;
|
||||
if (who && cansee(lf, who) && !isdead(who) && !isunconscious(who)) {
|
||||
if (areenemies(lf, who)) {
|
||||
} else if (!nhateposs && areenemies(lf, who)) { // dont check if we've already found a hated target
|
||||
if (nposs < MAXCANDIDATES) {
|
||||
if (db) dblog(".oO { found an enemy target - lfid %d (%s) ! }",who->id, who->race->name);
|
||||
newtarget = who;
|
||||
break;
|
||||
poss[nposs++] = who;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nhateposs) {
|
||||
newtarget = hateposs[rnd(0,nhateposs-1)];
|
||||
} else if (nposs) {
|
||||
newtarget = poss[rnd(0,nposs-1)];
|
||||
}
|
||||
}
|
||||
|
||||
if (newtarget) {
|
||||
if (aiattack(lf, newtarget, DEF_AIFOLLOWTIME)) {
|
||||
|
@ -1788,7 +1814,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
|
|||
if ((ot->id == OT_S_SMITEEVIL) && (getalignment(victim) != AL_EVIL)) {
|
||||
specificcheckok = B_FALSE;
|
||||
}
|
||||
if ((ot->id == OT_A_SPRINT) && (lfhasflag(lf, F_SPRINTING) || !lf->stamina)) {
|
||||
if ((ot->id == OT_A_SPRINT) && (lfhasflag(lf, F_SPRINTING) || !getstamina(lf))) {
|
||||
specificcheckok = B_FALSE;
|
||||
}
|
||||
if ((ot->id == OT_A_STEAL) || (ot->id == OT_S_CONFISCATE)) {
|
||||
|
|
30
attack.c
30
attack.c
|
@ -175,7 +175,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
int attackedpeaceful = B_FALSE;
|
||||
|
||||
// warn if attacking will cause injury
|
||||
if (!force && isplayer(lf)) {
|
||||
if (!force && isplayer(lf) && haslos(lf, c)) {
|
||||
if (!confirm_injury_action(BP_HANDS, DT_SLASH, "attack")) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -268,12 +268,6 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
// lose a tiny bit of stamina
|
||||
modstamina(lf, -0.2);
|
||||
|
||||
// stop sprinting
|
||||
stopsprinting(lf);
|
||||
|
||||
// ai code...
|
||||
if (lfhasflag(lf, F_DEMANDSBRIBE)) {
|
||||
if (!isplayer(lf) && (attacktype == AT_LF) && isplayer((lifeform_t *)attacktarget)) {
|
||||
|
@ -336,9 +330,6 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
|
||||
innateattacks = countinnateattacks(lf);
|
||||
|
||||
// stop sprinting
|
||||
stopsprinting(lf);
|
||||
|
||||
// take time
|
||||
attacktime = getattackspeed(lf);
|
||||
|
||||
|
@ -467,7 +458,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
sayphrase(lf, SP_SORRY, -1, NA, NULL);
|
||||
}
|
||||
|
||||
if (lfhasflagval(lf, F_INJURY, NA, BP_HANDS, DT_SLASH, NULL)) {
|
||||
if (hasbleedinginjury(lf, BP_HANDS)) {
|
||||
if (!bleedfrom(lf, BP_HANDS, B_FALSE)) {
|
||||
losehp(lf, 1, DT_DIRECT, NULL, "blood loss");
|
||||
}
|
||||
|
@ -517,6 +508,11 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
|
|||
}
|
||||
}
|
||||
|
||||
// lose a bit of stamina
|
||||
modstamina(lf, -getattackstamloss(lf));
|
||||
|
||||
// stop sprinting
|
||||
stopsprinting(lf);
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -2070,7 +2066,7 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) {
|
|||
}
|
||||
|
||||
if (victim) {
|
||||
if (lfhasflagval(victim, F_INJURY, NA, BP_BODY, DT_SLASH, NULL)) {
|
||||
if (hasbleedinginjury(victim, BP_BODY)) {
|
||||
if (willbleedfrom(victim, BP_BODY)) {
|
||||
// extra damage
|
||||
dam += rnd(1,2);
|
||||
|
@ -2236,7 +2232,7 @@ void modifyforsize(int *val, lifeform_t *lf, lifeform_t *victim, int howmuch, en
|
|||
}
|
||||
}
|
||||
|
||||
// returns true if we hit
|
||||
// returns true if we hit. also sets 'critical' if passed
|
||||
int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) {
|
||||
int acc,ev;
|
||||
int gothit = B_FALSE;
|
||||
|
@ -2286,6 +2282,10 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
|
|||
acc += 30;
|
||||
}
|
||||
|
||||
if (lfhasflag(lf, F_AIMEDSTRIKE)) {
|
||||
acc -= 50;
|
||||
}
|
||||
|
||||
// modify for defender's evasion
|
||||
if (isprone(victim) || !cansee(victim, lf)) {
|
||||
ev = 0;
|
||||
|
@ -2310,6 +2310,10 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
|
|||
if (pctchance(acc)) gothit = B_TRUE;
|
||||
}
|
||||
|
||||
if (gothit && lfhasflag(lf, F_AIMEDSTRIKE) && critical) {
|
||||
*critical = 1;
|
||||
}
|
||||
|
||||
return gothit;
|
||||
}
|
||||
|
||||
|
|
BIN
data/hiscores.db
BIN
data/hiscores.db
Binary file not shown.
41
defs.h
41
defs.h
|
@ -294,6 +294,8 @@ enum RELATIVEDIR {
|
|||
// ... try to make this roughly 4 hours (check TIMECONST.
|
||||
#define HUNGERCONST 500
|
||||
|
||||
#define STAMREGEN (0.3) // base amount of stamina to regain each turn
|
||||
|
||||
// Time periods
|
||||
#define TM_DRUNKTIME (10) // how long it takes for alcohol to wear off
|
||||
#define TM_WETTIME (10) // how long it takes for things to dry
|
||||
|
@ -497,7 +499,7 @@ enum GAMEMODE {
|
|||
enum ATTRIB {
|
||||
A_NONE = -1,
|
||||
A_STR = 0,
|
||||
A_DEX = 1,
|
||||
A_AGI = 1,
|
||||
A_WIS = 2,
|
||||
A_IQ = 3,
|
||||
A_CON = 4,
|
||||
|
@ -802,6 +804,7 @@ enum RACE {
|
|||
R_HOBGOBLIN,
|
||||
R_HOBGOBLINWAR,
|
||||
R_KOBOLD,
|
||||
R_LEPRECHAUN,
|
||||
R_LIZARDMAN,
|
||||
R_MINOTAUR,
|
||||
R_OGRE,
|
||||
|
@ -1157,13 +1160,14 @@ enum OBTYPE {
|
|||
OT_S_SNOWBALL,
|
||||
OT_S_WALLOFICE,
|
||||
// -- gravity
|
||||
OT_S_TRUESTRIKE,
|
||||
OT_S_FLIGHT,
|
||||
OT_S_FORCESPHERE,
|
||||
OT_S_GRAVLOWER,
|
||||
OT_S_GRAVBOOST,
|
||||
OT_S_HASTE,
|
||||
OT_S_SLOW,
|
||||
OT_S_LEVITATION,
|
||||
OT_S_FLIGHT,
|
||||
OT_S_SLOW,
|
||||
OT_S_TRUESTRIKE,
|
||||
// -- life / cleric
|
||||
OT_S_HEALING,
|
||||
OT_S_HEALINGMIN,
|
||||
|
@ -1201,7 +1205,7 @@ enum OBTYPE {
|
|||
OT_S_PETRIFY,
|
||||
OT_S_POLYMORPH,
|
||||
OT_S_POLYMORPHRND,
|
||||
// nature
|
||||
// nature / enviromancy
|
||||
OT_S_BARKSKIN,
|
||||
OT_S_CALLLIGHTNING,
|
||||
OT_S_CALLWIND,
|
||||
|
@ -1211,6 +1215,7 @@ enum OBTYPE {
|
|||
OT_S_CUREPOISON,
|
||||
OT_S_DETECTPOISON,
|
||||
OT_S_DIG,
|
||||
OT_S_EARTHQUAKE,
|
||||
OT_S_EVAPORATE,
|
||||
OT_S_WEB,
|
||||
OT_S_ENDUREELEMENTS,
|
||||
|
@ -1268,6 +1273,7 @@ enum OBTYPE {
|
|||
OT_A_LEARN,
|
||||
OT_A_LEVELUP,
|
||||
// abilities
|
||||
OT_A_AIMEDSTRIKE,
|
||||
OT_A_COOK,
|
||||
OT_A_DARKWALK,
|
||||
OT_A_DISARM,
|
||||
|
@ -1407,6 +1413,8 @@ enum OBTYPE {
|
|||
OT_FOOTPRINT,
|
||||
OT_SCENT,
|
||||
// effects
|
||||
OT_DUSTCLOUD,
|
||||
OT_DUSTPUFF,
|
||||
OT_FIRELARGE,
|
||||
OT_FIREMED,
|
||||
OT_FIRESMALL,
|
||||
|
@ -1532,6 +1540,7 @@ enum OBTYPE {
|
|||
// short blades
|
||||
OT_COMBATKNIFE,
|
||||
OT_DAGGER,
|
||||
OT_FORK,
|
||||
OT_KNIFE,
|
||||
OT_ORNDAGGER,
|
||||
OT_QUICKBLADE,
|
||||
|
@ -1569,6 +1578,7 @@ enum OBTYPE {
|
|||
OT_MACE,
|
||||
OT_MORNINGSTAR,
|
||||
OT_NUNCHAKU,
|
||||
OT_SHILLELAGH,
|
||||
OT_SPANNER,
|
||||
OT_STICK,
|
||||
// projectile weapons
|
||||
|
@ -2049,7 +2059,7 @@ enum FLAG {
|
|||
// player only flags
|
||||
F_DONEDARKMSG, // tells the game not to say 'it is very dark here'
|
||||
F_DONELISTEN, // supress further 'you hear xx' messages this turn.
|
||||
// lifeform flags / lf flags
|
||||
// lifeform flags / lf flags / monster flags
|
||||
F_ALIGNMENT, // v0 = al_good, al_neutral, al_evil. default neutral.
|
||||
F_PIETY, // for god lifeforms - tracks player's piety with them
|
||||
F_PRAYEDTO, // player has prayed to this god before.
|
||||
|
@ -2077,10 +2087,15 @@ enum FLAG {
|
|||
F_SIZE, // val0 = lf size (enum LFSIZE)
|
||||
F_USEDPOISON, // this lf used a poisoned weapon to attack
|
||||
F_RANDOMTALKPCT, // v0 = chance of randomly saying something each turn
|
||||
F_RANDOMTALK, // v0 = sp_xxx for what to say when we randomly talk.
|
||||
F_RANDOMTALK, // EITHER:
|
||||
// v0 = sp_xxx for what to say when we randomly talk.
|
||||
// v1/v2 are min/max volume
|
||||
// OR
|
||||
// text = what to say
|
||||
// v1/v2 are min/max volume
|
||||
//
|
||||
// can have multiple of these flags, if so then
|
||||
// randomly eslect one each time.
|
||||
// randomly select one each time.
|
||||
F_RESTCOUNT, // val0 = how long you've been resting for
|
||||
F_RESTHEALTIME, // val0 = how long to rest before healing hp
|
||||
F_RESTHEALAMT, // val0 = how many hp to gain after resting x turns
|
||||
|
@ -2124,6 +2139,8 @@ enum FLAG {
|
|||
F_MYCORPSE, // text field contains obid of my corpse.
|
||||
// (for ghosts)
|
||||
F_NOCORPSE, // monster's body crumbles to dust after death
|
||||
F_NOCTURNAL, // monster sleeps during the day
|
||||
F_DIURNAL, // monster sleeps at night
|
||||
F_LFSUFFIX, // text = suffix. eg. "skeleton"
|
||||
F_VISRANGE, // how far you can see (in the light)
|
||||
F_VISRANGEMOD, // modifications to visrange
|
||||
|
@ -2231,6 +2248,8 @@ enum FLAG {
|
|||
// val1 is the volume of the noise
|
||||
// text is "verb^noun"
|
||||
// eg. "shouts^a shout"
|
||||
// if this flag occurs more than once with
|
||||
// the same v0, a random one is selected.
|
||||
F_SPELLCASTTEXT, // text is announcement for spellcast
|
||||
// if text is empty, then don't announce
|
||||
// this lf's spell casting at all.
|
||||
|
@ -2311,9 +2330,12 @@ enum FLAG {
|
|||
F_SPOTTED, // you have spotted hiding lf id v0. you lsoe this if they
|
||||
// go out of sight.
|
||||
// special attack flags
|
||||
F_AIMEDSTRIKE, // next attack is an aimed strike
|
||||
F_COMBOSTRIKE, // lf is performing a combination strike
|
||||
F_HEAVYBLOW, // next attack is a heavy blow
|
||||
F_QUIVERINGPALM, // your next strike will be a quivpalm attack
|
||||
F_TRUESTRIKE, // your attacks ALWAYS hit. turnsleft=v0
|
||||
F_HURRICANESTRIKE, // lf is performing a hurricane strike
|
||||
// INTRINSICS
|
||||
F_MAGICARMOUR,// armour is magically boosted. f->text is the description
|
||||
// ie 'magic armour', 'force field'
|
||||
|
@ -2322,6 +2344,7 @@ enum FLAG {
|
|||
// v1 is enum sleeptype st_xxx
|
||||
// if v2 is set, means we are sleeping on
|
||||
// purpose and will wake up when at full hp/mp/etc.
|
||||
// ie. "resting"
|
||||
F_ATTACHEDTO, // you are attached to lf id v0, and will move with it
|
||||
F_AWARENESS, // you can see 360 degrees around yourself
|
||||
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
|
||||
|
@ -2383,7 +2406,6 @@ enum FLAG {
|
|||
// v2 is save difficulty
|
||||
F_GRABBEDBY,// you've been grabbed by lf id v0
|
||||
F_GRABBING, // you are grabbing lf id v0
|
||||
F_HURRICANESTRIKE, // lf is performing a hurricane strike
|
||||
F_HIDING, // lifeform is hiding. v0 is modifier to stealth checks.
|
||||
F_ICESLIDE, // lf has "slide" spell active.
|
||||
// v0 = timeleft (since 'lifetime' is used for FROMSPELL)
|
||||
|
@ -2428,7 +2450,6 @@ enum FLAG {
|
|||
F_STENCH, // creatures within v0 gain f_nauseated = v1
|
||||
F_STUNNED, // cannot attack or cast spells
|
||||
F_TREMORSENSE, // doesn't need eyes to see, can see in dark with v0
|
||||
F_TRUESTRIKE, // your attacks ALWAYS hit. turnsleft=v0
|
||||
F_PRODUCESLIGHT, // produces light of val0 radius.
|
||||
// (but not for obs in pack)
|
||||
// if val2 is true, will only make light if ob
|
||||
|
|
327
lf.c
327
lf.c
|
@ -492,7 +492,7 @@ void callguards(lifeform_t *caller, lifeform_t *victim) {
|
|||
}
|
||||
|
||||
int canattack(lifeform_t *lf) {
|
||||
if (!lf->stamina) {
|
||||
if (!getstamina(lf)) {
|
||||
reason = E_NOSTAM;
|
||||
return B_FALSE;
|
||||
} else if (lfhasflag(lf, F_STUNNED)) {
|
||||
|
@ -583,7 +583,7 @@ int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) {
|
|||
}
|
||||
|
||||
f = hasflag(ot->flags, F_STAMCOST);
|
||||
if (f && (lf->stamina < f->val[0])) {
|
||||
if (f && (getstamina(lf) < f->val[0])) {
|
||||
reason = E_NOSTAM;
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -696,12 +696,13 @@ int canhear(lifeform_t *lf, cell_t *dest, int volume) {
|
|||
// can't hear noises from other maps
|
||||
if (lf->cell->map != dest->map) return B_FALSE;
|
||||
|
||||
celldist = getcelldist(lf->cell, dest);
|
||||
|
||||
// for player only:
|
||||
// can't hear if you have a hostile mosnter next to you
|
||||
// and you're not blind.
|
||||
// (you're too engrossed in the battle)
|
||||
/*
|
||||
celldist = getcelldist(lf->cell, dest);
|
||||
if (isplayer(lf) && isinbattle(lf)) {
|
||||
if (celldist != 1) return B_FALSE;
|
||||
}
|
||||
|
@ -1300,7 +1301,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
losemp(lf, cost);
|
||||
|
||||
// miscast chance?
|
||||
if (isplayer(lf)) {
|
||||
if (isplayer(lf) && !hasjob(lf, J_GOD)) {
|
||||
if (pctchance(getmiscastchance(lf))) {
|
||||
msg("^WYour cumbersome armour makes you miscast your spell!");
|
||||
return B_FALSE;
|
||||
|
@ -1353,10 +1354,12 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
}
|
||||
} else { // player can't see them
|
||||
if ((targlf == player) || (targcell = player->cell)) {
|
||||
if (!lfhasflag(player, F_ASLEEP)) {
|
||||
msg("Something casts a spell at you.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// boost power?
|
||||
if (hasjob(lf, J_DRUID)) {
|
||||
|
@ -1576,7 +1579,7 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
losehp(lf, roll("6d6"), DT_DIRECT, NULL, "running water");
|
||||
}
|
||||
if ((!slev || !lf->stamina) && !lfhasflag(lf, F_BREATHWATER) ) {
|
||||
if ((!slev || !getstamina(lf)) && !lfhasflag(lf, F_BREATHWATER) ) {
|
||||
int damamt;
|
||||
|
||||
// take drowning damage. generally you'll die
|
||||
|
@ -1707,17 +1710,6 @@ int countinnateattacks(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
|
||||
int countmoney(lifeform_t *lf) {
|
||||
object_t *o;
|
||||
int amt = 0;
|
||||
for (o = lf->pack->first ; o ; o = o->next) {
|
||||
if (o->type->id == OT_GOLD) {
|
||||
amt += o->amt;
|
||||
}
|
||||
}
|
||||
return amt;
|
||||
}
|
||||
|
||||
int countnearbyallies(lifeform_t *lf) {
|
||||
lifeform_t *l;
|
||||
int count = 0;
|
||||
|
@ -1785,7 +1777,7 @@ int demandbribe(lifeform_t *lf) {
|
|||
hd = gethitdice(lf);
|
||||
gold = hasob(player->pack, OT_GOLD);
|
||||
if (gold) {
|
||||
totmoney = countmoney(player);
|
||||
totmoney = countmoney(player->pack);
|
||||
} else {
|
||||
totmoney = 0;
|
||||
}
|
||||
|
@ -2737,6 +2729,14 @@ int eat(lifeform_t *lf, object_t *o) {
|
|||
|
||||
// announce
|
||||
if (turnstoeat <= 1) {
|
||||
char taste[BUFLEN];
|
||||
if (hasflagval(o->flags, F_CORPSEOF, R_CHICKEN, NA, NA, NULL)) {
|
||||
sprintf(taste, " Tastes like chicken!");
|
||||
} else if (f->val[1] >= 20) {
|
||||
sprintf(taste, " Yum!");
|
||||
} else {
|
||||
strcpy(taste, "");
|
||||
}
|
||||
if (alreadyeating) {
|
||||
if (isplayer(lf)) {
|
||||
msg("You finish %s.%s", drinking ? "drinking" : "eating",
|
||||
|
@ -2988,10 +2988,10 @@ void enhanceskills(lifeform_t *lf) {
|
|||
if (isplayer(lf)) {
|
||||
char ch;
|
||||
more();
|
||||
ch = askchar("Increase your Strength, Dexterity, Fitness, IQ or Wisdom?", "sdfiw",NULL, B_TRUE);
|
||||
ch = askchar("Increase your Strength, Agility, Fitness, IQ or Wisdom?", "safiw",NULL, B_TRUE);
|
||||
switch (ch) {
|
||||
case 's': att = A_STR; break;
|
||||
case 'd': att = A_DEX; break;
|
||||
case 'a': att = A_AGI; break;
|
||||
case 'f': att = A_CON; break;
|
||||
case 'i': att = A_IQ; break;
|
||||
case 'w': att = A_WIS; break;
|
||||
|
@ -4512,7 +4512,7 @@ int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, int *narms
|
|||
|
||||
ar += thisar;
|
||||
|
||||
ar += getobbonus(o);
|
||||
ar += getobbonus(o, B_FALSE);
|
||||
if (hitob) {
|
||||
hitob[*narms] = o;
|
||||
hitchance[*narms] = getbodyparthitchance(isshield ? BP_BODY : eqflag->val[0]);
|
||||
|
@ -4526,7 +4526,6 @@ int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, int *narms
|
|||
}
|
||||
|
||||
// how far away should we be before attacking?
|
||||
|
||||
int getattackspeed(lifeform_t *lf) {
|
||||
object_t *w;
|
||||
float speed;
|
||||
|
@ -4542,6 +4541,22 @@ int getattackspeed(lifeform_t *lf) {
|
|||
return (int)speed;
|
||||
}
|
||||
|
||||
float getattackstamloss(lifeform_t *lf) {
|
||||
object_t *w;
|
||||
float loss;
|
||||
loss = ((float)STAMREGEN+0.2);
|
||||
|
||||
w = getweapon(lf);
|
||||
if (w) {
|
||||
int del;
|
||||
del = getobattackdelay(w);
|
||||
loss = pctof(del, loss);
|
||||
}
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
|
||||
int getattpoints(lifeform_t *lf) {
|
||||
flag_t *f;
|
||||
int attpoints = 0;
|
||||
|
@ -4583,7 +4598,7 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) {
|
|||
val += f->val[1];
|
||||
}
|
||||
if (f->id == F_DRUNK) {
|
||||
if (attr == A_DEX) {
|
||||
if (attr == A_AGI) {
|
||||
if (hasjob(lf, J_PIRATE)) {
|
||||
val += f->val[0];
|
||||
} else {
|
||||
|
@ -4807,7 +4822,7 @@ int getevasion(lifeform_t *lf) {
|
|||
ev += level_ev;
|
||||
|
||||
// dexterity mod
|
||||
ev += getattr(lf, A_DEX);
|
||||
ev += getattr(lf, A_AGI);
|
||||
|
||||
// you are easier to hit if you're glowing
|
||||
if (hasflag(lf->flags, F_PRODUCESLIGHT)) {
|
||||
|
@ -5318,7 +5333,7 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
|
|||
} else {
|
||||
int dexmod;
|
||||
// modify with dexterity
|
||||
dexmod = getstatmod(lf, A_DEX);
|
||||
dexmod = getstatmod(lf, A_AGI);
|
||||
// double dex penalties when dual weilding
|
||||
if (isdualweilding(lf) && (dexmod < 0)) {
|
||||
dexmod *= 2;
|
||||
|
@ -5369,7 +5384,7 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
|
|||
}
|
||||
}
|
||||
|
||||
if (acc < 0) acc = 0;
|
||||
//if (acc < 0) acc = 0;
|
||||
return acc;
|
||||
}
|
||||
|
||||
|
@ -5772,7 +5787,7 @@ float getmaxstamina(lifeform_t *lf) {
|
|||
if (lfhasflagval(lf, F_INJURY, IJ_LUNGCOLLAPSED, NA, NA, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
stam = (getattr(lf, A_CON) / 2);
|
||||
stam = (getattr(lf, A_CON) / 3);
|
||||
stam += (getskill(lf, SK_ATHLETICS)*2);
|
||||
return stam;
|
||||
}
|
||||
|
@ -6174,6 +6189,11 @@ int getspellspeed(lifeform_t *lf) {
|
|||
return speed;
|
||||
}
|
||||
|
||||
// note: stamina is stored as a float, but we treat it as an int.
|
||||
int getstamina(lifeform_t *lf) {
|
||||
return (int)floor(lf->stamina);
|
||||
}
|
||||
|
||||
char *getplayername(char *buf) {
|
||||
flag_t *f;
|
||||
f = hasflag(player->flags, F_NAME);
|
||||
|
@ -6219,52 +6239,6 @@ int getpoisondamchance(enum POISONTYPE ptype) {
|
|||
return chance;
|
||||
}
|
||||
|
||||
char *getpoisondamverb(enum POISONTYPE ptype) {
|
||||
switch (ptype) {
|
||||
case P_FOOD:
|
||||
case P_VENOM:
|
||||
return "vomit";
|
||||
case P_GAS:
|
||||
case P_COLD:
|
||||
return "cough";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
char *getpoisondesc(enum POISONTYPE ptype) {
|
||||
switch (ptype) {
|
||||
case P_FOOD:
|
||||
case P_VENOM:
|
||||
case P_GAS:
|
||||
case P_WEAKNESS:
|
||||
return "Poisoned";
|
||||
case P_COLD:
|
||||
return "Sick";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Poisoned";
|
||||
}
|
||||
|
||||
char *getpoisonname(enum POISONTYPE ptype) {
|
||||
switch (ptype) {
|
||||
case P_COLD:
|
||||
return "hypothermia";
|
||||
case P_FOOD:
|
||||
return "food poisoning";
|
||||
case P_GAS:
|
||||
return "gas inhalation";
|
||||
case P_VENOM:
|
||||
return "venom poisoning";
|
||||
case P_WEAKNESS:
|
||||
return "weakening poison";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
enum POISONSEVERITY getpoisonseverity(enum POISONTYPE ptype) {
|
||||
switch (ptype) {
|
||||
|
@ -6374,6 +6348,16 @@ enum BODYPART getrandomcorebp(lifeform_t *lf) {
|
|||
return selbp;
|
||||
}
|
||||
|
||||
race_t *getrandomcorpserace(cell_t *c) {
|
||||
race_t *r;
|
||||
r = getrandomrace(c, NA);
|
||||
while (hasflag(r->flags, F_NOCORPSE)) {
|
||||
r = getrandomrace(c, NA);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
job_t *getrandomjob(int onlyplayerjobs) {
|
||||
job_t *j;
|
||||
int njobs = 0;
|
||||
|
@ -6687,7 +6671,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
strcpy(buf, "hideous"); break;
|
||||
case A_CON:
|
||||
strcpy(buf, "frail"); break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(buf, "uncoordinated"); break;
|
||||
case A_IQ:
|
||||
strcpy(buf, "vegetable"); break;
|
||||
|
@ -6707,7 +6691,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
strcpy(buf, "repulsive"); break;
|
||||
case A_CON:
|
||||
strcpy(buf, "sickly"); break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(buf, "oafish"); break;
|
||||
case A_IQ:
|
||||
strcpy(buf, "animal"); break;
|
||||
|
@ -6727,7 +6711,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
strcpy(buf, "ugly"); break;
|
||||
case A_CON:
|
||||
strcpy(buf, "unhealthy"); break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(buf, "clumsy"); break;
|
||||
case A_IQ:
|
||||
strcpy(buf, "dim-witted"); break;
|
||||
|
@ -6747,7 +6731,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
strcpy(buf, "unattractive"); break;
|
||||
case A_CON:
|
||||
strcpy(buf, "unfit"); break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(buf, "awkward"); break;
|
||||
case A_IQ:
|
||||
strcpy(buf, "dopey"); break;
|
||||
|
@ -6765,7 +6749,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
switch (whichatt) {
|
||||
case A_CHA:
|
||||
case A_CON:
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
case A_STR:
|
||||
case A_IQ:
|
||||
case A_WIS:
|
||||
|
@ -6782,7 +6766,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
strcpy(buf, "attractive"); break;
|
||||
case A_CON:
|
||||
strcpy(buf, "healthy"); break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(buf, "dextrous"); break;
|
||||
case A_IQ:
|
||||
strcpy(buf, "smart"); break;
|
||||
|
@ -6802,7 +6786,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
strcpy(buf, "alluring"); break;
|
||||
case A_CON:
|
||||
strcpy(buf, "very fit"); break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(buf, "nimble"); break;
|
||||
case A_IQ:
|
||||
strcpy(buf, "enlightened"); break;
|
||||
|
@ -6822,7 +6806,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
strcpy(buf, "beautiful"); break;
|
||||
case A_CON:
|
||||
strcpy(buf, "hardy"); break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(buf, "agile"); break;
|
||||
case A_IQ:
|
||||
strcpy(buf, "genius"); break;
|
||||
|
@ -6842,7 +6826,7 @@ enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, char *buf) {
|
|||
strcpy(buf, "stunning"); break;
|
||||
case A_CON:
|
||||
strcpy(buf, "very hardy"); break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(buf, "very agile"); break;
|
||||
case A_IQ:
|
||||
strcpy(buf, "supergenius"); break;
|
||||
|
@ -7786,8 +7770,22 @@ int gotosleep(lifeform_t *lf, int onpurpose) {
|
|||
return B_FALSE;
|
||||
}
|
||||
|
||||
flag_t *hasbleedinginjury(lifeform_t *lf, enum BODYPART bp) {
|
||||
flag_t *f, *retflag[MAXCANDIDATES];
|
||||
int nretflags,i;
|
||||
getflags(player->flags, retflag, &nretflags, F_INJURY, F_NONE);
|
||||
for (i = 0;i < nretflags; i++) {
|
||||
f = retflag[i];
|
||||
// only temporary flags count - not permenant ones
|
||||
if ((f->lifetime > 0) && (f->val[1] == bp) && (f->val[2] == DT_SLASH)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int hasfreeaction(lifeform_t *lf) {
|
||||
if (isdead(lf)) return B_FALSE;
|
||||
if (isimmobile(lf)) return B_FALSE;
|
||||
if (lfhasflag(lf, F_CASTINGSPELL)) return B_FALSE;
|
||||
if (lfhasflag(lf, F_EATING)) return B_FALSE;
|
||||
|
@ -7802,6 +7800,17 @@ job_t *hasjob(lifeform_t *lf, enum JOB job) {
|
|||
return j;
|
||||
}
|
||||
|
||||
int hastempinjuries(lifeform_t *lf) {
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags,i,count = 0;
|
||||
|
||||
getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
if (retflag[i]->lifetime > 0) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch) {
|
||||
int i;
|
||||
for (i = 0; i < abs(howmuch); i++) {
|
||||
|
@ -9005,6 +9014,16 @@ flag_t *isresting(lifeform_t *lf) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int issleepingtimefor(lifeform_t *lf) {
|
||||
if (lfhasflag(lf, F_NOCTURNAL) && !isnighttime()) {
|
||||
return B_TRUE;
|
||||
} else if (lfhasflag(lf, F_DIURNAL) && isnighttime()) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
object_t *isstuck(lifeform_t *lf) {
|
||||
object_t *o;
|
||||
|
||||
|
@ -10306,6 +10325,22 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
|
|||
snprintf(buf2, BUFLEN, "^%d damage",amt);
|
||||
strcat(buf, buf2);
|
||||
|
||||
// unseen?
|
||||
if (fromlf && !cansee(lf, fromlf)) {
|
||||
strcat(buf2, "^unseen");
|
||||
}
|
||||
|
||||
// "while xxx"
|
||||
strcpy(buf2, "");
|
||||
if ((countcellexits(lf->cell) == 1) && fromlf && (getcelldist(fromlf->cell, lf->cell) == 1)) {
|
||||
strcat(buf2, "^while cornered");
|
||||
}
|
||||
if (!hasfreeaction(lf)) {
|
||||
if (strlen(buf2)) strcat(buf2, " and helpless");
|
||||
else strcat(buf2, "^while helpless");
|
||||
}
|
||||
if (strlen(buf2)) strcat(buf, buf2);
|
||||
|
||||
setlastdam(lf, buf);
|
||||
|
||||
|
||||
|
@ -10459,19 +10494,28 @@ int makenauseated(lifeform_t *lf, int amt, int howlong) {
|
|||
}
|
||||
|
||||
void makenoise(lifeform_t *lf, enum NOISETYPE nid) {
|
||||
flag_t *f;
|
||||
flag_t *retflag[MAXCANDIDATES],*nflag[MAXCANDIDATES];
|
||||
int nretflags, volume = 1, i,nnflags = 0;
|
||||
char *verb = NULL, *noun = NULL;
|
||||
int volume = 1;
|
||||
|
||||
if (lfhasflag(lf, F_FROZEN)) {
|
||||
// can't make noise if frozen!
|
||||
return;
|
||||
}
|
||||
|
||||
f = hasflagval(lf->flags, F_NOISETEXT, nid, NA, NA, NULL);
|
||||
if (f) {
|
||||
|
||||
getflags(lf->flags, retflag, &nretflags, F_NOISETEXT, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
if (retflag[i]->id == nid) {
|
||||
nflag[nnflags++] = retflag[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (nnflags) {
|
||||
flag_t *f;
|
||||
char *dummy;
|
||||
char noisetext[BUFLEN];
|
||||
f = nflag[rnd(0,nnflags-1)];
|
||||
|
||||
volume = f->val[1];
|
||||
|
||||
|
@ -10585,7 +10629,7 @@ int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o) {
|
|||
|
||||
if (myval < valneeded) {
|
||||
switch (att) {
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
reason = E_LOWDEX;
|
||||
break;
|
||||
case A_CHA:
|
||||
|
@ -10651,7 +10695,7 @@ int modattr(lifeform_t *lf, enum ATTRIB attr, int amt) {
|
|||
case A_CON:
|
||||
strcpy(adverb, "healthier");
|
||||
break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(adverb, "more agile");
|
||||
break;
|
||||
case A_IQ:
|
||||
|
@ -10674,7 +10718,7 @@ int modattr(lifeform_t *lf, enum ATTRIB attr, int amt) {
|
|||
case A_CON:
|
||||
strcpy(adverb, "frail");
|
||||
break;
|
||||
case A_DEX:
|
||||
case A_AGI:
|
||||
strcpy(adverb, "sluggish");
|
||||
break;
|
||||
case A_IQ:
|
||||
|
@ -10800,17 +10844,17 @@ float modifybystat(float num, lifeform_t *lf, enum ATTRIB att) {
|
|||
|
||||
void modstamina(lifeform_t *lf, float howmuch) {
|
||||
float orig;
|
||||
orig = lf->stamina;
|
||||
orig = getstamina(lf);
|
||||
lf->stamina += howmuch;
|
||||
limitf(&(lf->stamina), 0, getmaxstamina(lf));
|
||||
if (lf->stamina != orig) {
|
||||
if (getstamina(lf) != orig) {
|
||||
if (isplayer(lf)) {
|
||||
statdirty = B_TRUE;
|
||||
drawstatus();
|
||||
updatestatus();
|
||||
if (lf->stamina == 0) msg("You are exhausted.");
|
||||
if (getstamina(lf) == 0) msg("You are exhausted.");
|
||||
} else if (cansee(player, lf)) {
|
||||
if (lf->stamina == 0) {
|
||||
if (getstamina(lf) == 0) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(lf, lfname);
|
||||
msg("%s looks exhausted.", lfname);
|
||||
|
@ -10818,7 +10862,7 @@ void modstamina(lifeform_t *lf, float howmuch) {
|
|||
}
|
||||
}
|
||||
|
||||
if (lf->stamina == 0) {
|
||||
if (getstamina(lf) == 0) {
|
||||
stopsprinting(lf);
|
||||
}
|
||||
}
|
||||
|
@ -10832,6 +10876,9 @@ int needstorest(lifeform_t *lf, char *validchars) {
|
|||
if (lf->hp < lf->maxhp) {
|
||||
if (validchars) strcat(validchars, "h");
|
||||
need = B_TRUE;
|
||||
} else if (hastempinjuries(lf)) {
|
||||
if (validchars) strcat(validchars, "h");
|
||||
need = B_TRUE;
|
||||
}
|
||||
if ((getmaxmp(lf) > 0) && (lf->mp < getmaxmp(lf))) {
|
||||
if (validchars) strcat(validchars, "m");
|
||||
|
@ -11589,16 +11636,16 @@ int recruit(lifeform_t *lf) {
|
|||
difficulty = 20 + ((gethitdice(player) - gethitdice(lf))*2);
|
||||
if (real_skillcheck(player, A_CHA, difficulty, 0, &result)) {
|
||||
// passed
|
||||
askingprice = rnd(gethitdice(lf)*50, gethitdice(lf)*100 );
|
||||
askingprice = rnd(gethitdice(lf)*5, gethitdice(lf)*20 );
|
||||
addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL);
|
||||
} else {
|
||||
if (difficulty - result >= 10) {
|
||||
// very expensive
|
||||
askingprice = rnd(gethitdice(lf)*250, gethitdice(lf)*300 );
|
||||
askingprice = rnd(gethitdice(lf)*20, gethitdice(lf)*30 );
|
||||
addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL);
|
||||
} else {
|
||||
// expensive
|
||||
askingprice = rnd(gethitdice(lf)*100, gethitdice(lf)*200 );
|
||||
askingprice = rnd(gethitdice(lf)*10, gethitdice(lf)*25 );
|
||||
addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -11606,12 +11653,15 @@ int recruit(lifeform_t *lf) {
|
|||
|
||||
if (askingprice != 0) {
|
||||
// modify by charisma
|
||||
askingprice = pctof(100 + getstatmod(player, A_CHA), askingprice);
|
||||
askingprice = pctof(100 - getstatmod(player, A_CHA), askingprice);
|
||||
limit(&askingprice, 0, NA);
|
||||
}
|
||||
|
||||
if (askingprice > 0) {
|
||||
sayphrase(lf, SP_RECRUIT_ASKPRICE, SV_TALK, askingprice, NULL);
|
||||
more();
|
||||
|
||||
if (askingprice > countmoney(player)) {
|
||||
if (askingprice > countmoney(player->pack)) {
|
||||
} else {
|
||||
char ch;
|
||||
snprintf(buf, BUFLEN, "Pay $%d to hire %s", askingprice, lfname);
|
||||
|
@ -11635,7 +11685,7 @@ int recruit(lifeform_t *lf) {
|
|||
}
|
||||
sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p);
|
||||
} else {
|
||||
if (askingprice > countmoney(player)) {
|
||||
if (askingprice > countmoney(player->pack)) {
|
||||
sayphrase(lf, SP_RECRUIT_DECLINE_CANTPAY, SV_TALK, askingprice, NULL);
|
||||
} else {
|
||||
sayphrase(lf, SP_RECRUIT_DECLINE_WONTPAY, SV_TALK, askingprice, NULL);
|
||||
|
@ -12499,7 +12549,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
|
|||
attrib = getattr(lf, A_CON);
|
||||
break;
|
||||
case SC_DEX:
|
||||
attrib = getattr(lf, A_DEX);
|
||||
attrib = getattr(lf, A_AGI);
|
||||
break;
|
||||
case SC_IQ:
|
||||
attrib = getattr(lf, A_IQ);
|
||||
|
@ -12516,7 +12566,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
|
|||
break;
|
||||
///////////////
|
||||
case SC_OPENLOCKS:
|
||||
attrib = getattr(lf, A_DEX);
|
||||
attrib = getattr(lf, A_AGI);
|
||||
break;
|
||||
case SC_WILL:
|
||||
attrib = getattr(lf, A_WIS);
|
||||
|
@ -12535,10 +12585,10 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
|
|||
break;
|
||||
case SC_SLIP:
|
||||
case SC_FALL:
|
||||
attrib = getattr(lf, A_DEX);
|
||||
attrib = getattr(lf, A_AGI);
|
||||
break;
|
||||
case SC_SHIELDBLOCK:
|
||||
attrib = (getattr(lf, A_DEX) / 4);
|
||||
attrib = (getattr(lf, A_AGI) / 4);
|
||||
break;
|
||||
case SC_POISON:
|
||||
attrib = getattr(lf, A_CON);
|
||||
|
@ -12546,7 +12596,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
|
|||
case SC_DISARM:
|
||||
attrib = (getskill(lf, SK_TRAPS)*3);
|
||||
if (attrib) {
|
||||
attrib += (getattr(lf, A_DEX)/4);
|
||||
attrib += (getattr(lf, A_AGI)/4);
|
||||
}
|
||||
break;
|
||||
case SC_CLIMB:
|
||||
|
@ -12628,14 +12678,14 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
|
|||
slev = PR_INEPT;
|
||||
}
|
||||
switch (slev) {
|
||||
case PR_NOVICE: othermod = 4; break;
|
||||
case PR_BEGINNER: othermod = 7; break;
|
||||
case PR_ADEPT: othermod = 10; break;
|
||||
case PR_SKILLED: othermod = 13; break;
|
||||
case PR_EXPERT: othermod = 16; break;
|
||||
case PR_MASTER: othermod = 20; break;
|
||||
case PR_NOVICE: othermod = 0; break;
|
||||
case PR_BEGINNER: othermod = 4; break;
|
||||
case PR_ADEPT: othermod = 7; break;
|
||||
case PR_SKILLED: othermod = 10; break;
|
||||
case PR_EXPERT: othermod = 13; break;
|
||||
case PR_MASTER: othermod = 16; break;
|
||||
default:
|
||||
othermod = 0;
|
||||
othermod = -4;
|
||||
break;
|
||||
}
|
||||
} else if (ct == SC_MORALE) {
|
||||
|
@ -12664,7 +12714,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
|
|||
} else if (ct == SC_STEAL) {
|
||||
if (attrib > 0) {
|
||||
// ie. -3 to 3
|
||||
othermod += (getstatmod(lf, A_DEX) / 15);
|
||||
othermod += (getstatmod(lf, A_AGI) / 15);
|
||||
}
|
||||
} else if (ct == SC_STEALTH) {
|
||||
if (attrib > 0) {
|
||||
|
@ -12680,7 +12730,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
|
|||
levmod *= 2;
|
||||
} else if (ct == SC_TUMBLE) {
|
||||
// ie. -3 to 3
|
||||
othermod += (getstatmod(lf, A_DEX) / 15);
|
||||
othermod += (getstatmod(lf, A_AGI) / 15);
|
||||
}
|
||||
|
||||
|
||||
|
@ -13044,7 +13094,7 @@ void startlfturn(lifeform_t *lf) {
|
|||
|
||||
// either use up stamina, or gain it
|
||||
if (lfhasflag(lf, F_SPRINTING)) {
|
||||
modstamina(lf, -1);
|
||||
modstamina(lf, -1.5);
|
||||
} else if (isswimming(lf)) {
|
||||
int lossamt;
|
||||
// lose stamina based on swimming skill
|
||||
|
@ -13059,8 +13109,8 @@ void startlfturn(lifeform_t *lf) {
|
|||
}
|
||||
if (lossamt) modstamina(lf, -lossamt);
|
||||
} else {
|
||||
if (lf->stamina < getmaxstamina(lf)) {
|
||||
float regenrate = 0.5;
|
||||
if (getstamina(lf) < getmaxstamina(lf)) {
|
||||
float regenrate = STAMREGEN;
|
||||
if (lfhasflagval(lf, F_INJURY, IJ_WINDPIPECRUSHED, NA, NA, NULL)) {
|
||||
regenrate = 0.2; // override everything else
|
||||
} else {
|
||||
|
@ -13094,7 +13144,7 @@ void startlfturn(lifeform_t *lf) {
|
|||
if (f) {
|
||||
cell_t *retcell[MAXCANDIDATES];
|
||||
int nretcells;
|
||||
getradiuscells(lf->cell, 2, DT_COMPASS, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 0);
|
||||
getradiuscells(lf->cell, 2, DT_COMPASS, B_FALSE, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 0);
|
||||
for (i = 0; i < nretcells; i++) {
|
||||
if (retcell[i]->lf && areenemies(lf, retcell[i]->lf)) {
|
||||
int dir,reldir;
|
||||
|
@ -13752,11 +13802,33 @@ int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag) {
|
|||
}
|
||||
}
|
||||
if (prompt.nchoices > 1) {
|
||||
if (isplayer(lf) && (slev >= PR_ADEPT)) {
|
||||
if (slev >= PR_ADEPT) {
|
||||
if (isplayer(lf)) {
|
||||
addchoice(&prompt, '-', "Nothing", NULL, NULL, NULL);
|
||||
// pick what you want
|
||||
getchoice(&prompt);
|
||||
o = (object_t *)prompt.result;
|
||||
} else {
|
||||
int nn,nposs = 0;
|
||||
object_t *poss[MAXCHOICES*2];
|
||||
// get something we want
|
||||
for (nn = 0; nn < prompt.nchoices; nn++) {
|
||||
int cov;
|
||||
if (aiwants(lf, (object_t *)prompt.choice[nn].data, &cov)) {
|
||||
if (cov) { // add twice
|
||||
poss[nposs++] = o;
|
||||
poss[nposs++] = o;
|
||||
} else {
|
||||
poss[nposs++] = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nposs) {
|
||||
o = poss[rnd(0,nposs-1)];
|
||||
} else {
|
||||
o = (object_t *)prompt.choice[rnd(0,prompt.nchoices-1)].data;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// random
|
||||
o = (object_t *)prompt.choice[rnd(0,prompt.nchoices-1)].data;
|
||||
|
@ -14016,11 +14088,20 @@ void taketime(lifeform_t *lf, long howlong) {
|
|||
|
||||
map = lf->cell->map;
|
||||
|
||||
assert(howlong > 0);
|
||||
|
||||
if (db && (gamemode == GM_GAMESTARTED) && cansee(player, lf)) {
|
||||
if (gamemode == GM_GAMESTARTED) {
|
||||
if (map != player->cell->map) {
|
||||
// lfs not on the player's map don't take time.
|
||||
// this avoids the assertion below failing when
|
||||
// (for example) a monster falls through a pit.
|
||||
return;
|
||||
}
|
||||
if (db && cansee(player, lf)) {
|
||||
dblog("lfid %d (%s) spending %d time\n",lf->id,lf->race->name, howlong);
|
||||
}
|
||||
}
|
||||
|
||||
assert(howlong > 0);
|
||||
|
||||
// inc timespent
|
||||
lf->timespent += howlong;
|
||||
assert(lf->timespent >= 0);
|
||||
|
@ -15082,7 +15163,7 @@ int rest(lifeform_t *lf, int onpurpose) {
|
|||
|
||||
wantclearmsg = B_FALSE;
|
||||
// resting
|
||||
if (lf->hp >= lf->maxhp) {
|
||||
if ((lf->hp >= lf->maxhp) && !hastempinjuries(lf)) {
|
||||
hf = lfhasflag(lf, F_RESTUNTILHP);
|
||||
if (hf) killflag(hf);
|
||||
}
|
||||
|
|
9
lf.h
9
lf.h
|
@ -54,7 +54,6 @@ int check_rest_ok(lifeform_t *lf);
|
|||
float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
|
||||
int confuse(lifeform_t *lf, int howlong);
|
||||
int countinnateattacks(lifeform_t *lf);
|
||||
int countmoney(lifeform_t *lf);
|
||||
int countnearbyallies(lifeform_t *lf);
|
||||
int countnearbyhurtallies(lifeform_t *lf);
|
||||
int countplantsinsight(lifeform_t *lf);
|
||||
|
@ -110,6 +109,8 @@ object_t *getarmour(lifeform_t *lf, enum BODYPART bp);
|
|||
int getarmournoise(lifeform_t *lf);
|
||||
int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, int *narms);
|
||||
int getattackspeed(lifeform_t *lf);
|
||||
float getattackstamloss(lifeform_t *lf);
|
||||
float getattackstamloss(lifeform_t *lf);
|
||||
int getattpoints(lifeform_t *lf);
|
||||
int getattr(lifeform_t *lf, enum ATTRIB attr);
|
||||
enum ATTRBRACKET getattrbracket(int attrval, enum ATTRIB whichatt, /*@null@*/char *buf);
|
||||
|
@ -182,6 +183,7 @@ float getlfweight(lifeform_t *lf, int withobs);
|
|||
object_t *getsecmeleeweapon(lifeform_t *lf);
|
||||
object_t *getshield(lifeform_t *lf);
|
||||
int getspellspeed(lifeform_t *lf);
|
||||
int getstamina(lifeform_t *lf);
|
||||
char *getplayername(char *buf);
|
||||
char *getplayernamefull(char *buf);
|
||||
int getpoisondamchance(enum POISONTYPE ptype);
|
||||
|
@ -193,6 +195,7 @@ int getraceclass(lifeform_t *lf);
|
|||
int getracerarity(map_t *map, enum RACE rid);
|
||||
object_t *getrandomarmour(lifeform_t *lf);
|
||||
enum BODYPART getrandomcorebp(lifeform_t *lf);
|
||||
race_t *getrandomcorpserace(cell_t *c);
|
||||
job_t *getrandomjob(int onlyplayerjobs);
|
||||
int getrandommonlevel(race_t *r, map_t *m);
|
||||
race_t *getrandomrace(cell_t *c, int forcedepth);
|
||||
|
@ -224,13 +227,14 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp);
|
|||
void givestartskills(lifeform_t *lf, flagpile_t *fp);
|
||||
map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs);
|
||||
int gotosleep(lifeform_t *lf, int onpurpose);
|
||||
flag_t *hasbleedinginjury(lifeform_t *lf, enum BODYPART bp);
|
||||
int hasfreeaction(lifeform_t *lf);
|
||||
job_t *hasjob(lifeform_t *lf, enum JOB job);
|
||||
void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch);
|
||||
int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype);
|
||||
int lfcanbestoned(lifeform_t *lf);
|
||||
flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid);
|
||||
flag_t *lfhasflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, /*@null@*/ char *text);
|
||||
flag_t *lfhasflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, char *text);
|
||||
flag_t *lfhasknownflag(lifeform_t *lf, enum FLAG fid);
|
||||
flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, /*@null@*/ char *text);
|
||||
int lfproduceslight(lifeform_t *lf);
|
||||
|
@ -274,6 +278,7 @@ 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);
|
||||
int issleepingtimefor(lifeform_t *lf);
|
||||
object_t *isstuck(lifeform_t *lf);
|
||||
int issmellablelf(lifeform_t *lf);
|
||||
int isswimming(lifeform_t *lf);
|
||||
|
|
36
map.c
36
map.c
|
@ -285,6 +285,11 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
|
|||
// TODO: base this on the time, and whether monster is nocturnal
|
||||
if (pctchance(asleepchance)) {
|
||||
addflag(lf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
|
||||
} else {
|
||||
// might be asleep based on time.
|
||||
if (issleepingtimefor(lf)) {
|
||||
addflag(lf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
// monsters who on dark levels can always see in the dark
|
||||
|
@ -535,7 +540,7 @@ int getmapmaxvisrange(map_t *m) {
|
|||
// populates retcell[] with all cells within given radius of centre
|
||||
// if 'scatter' is >0, then not all cells will be returned - as you approach the edge of the radius,
|
||||
// chances of getting the cells are lowered
|
||||
void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells, int scatterdensity) {
|
||||
void getradiuscells(cell_t *centre, int radius, int dirtype, int outsideonly, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells, int scatterdensity) {
|
||||
int (*distfunc)(cell_t *, cell_t *);
|
||||
int x,y;
|
||||
cell_t *c;
|
||||
|
@ -554,10 +559,14 @@ void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlo
|
|||
for (x = centre->x - radius; x <= centre->x + radius; x++) {
|
||||
c = getcellat(centre->map, x,y);
|
||||
if (c) {
|
||||
int distance;
|
||||
int distance,distmatch = B_FALSE;
|
||||
distance = distfunc(centre, c);
|
||||
if (haslof(centre, c, needlof, NULL) && (distance <= radius) &&
|
||||
(wantcentre || (c != centre)) ) {
|
||||
if (outsideonly) {
|
||||
if (distance == radius) distmatch = B_TRUE;
|
||||
} else {
|
||||
if (distance <= radius) distmatch = B_TRUE;
|
||||
}
|
||||
if (distmatch && haslof(centre, c, needlof, NULL) && (wantcentre || (c != centre)) ) {
|
||||
int chance;
|
||||
if (scatterdensity) {
|
||||
chance = 100 - (((float)distance / (float)radius) * scatterdensity);
|
||||
|
@ -2035,8 +2044,12 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
|
|||
} else {
|
||||
for (i = 0; i < map->region->rtype->stairsperlev; i++) {
|
||||
c = NULL;
|
||||
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) {
|
||||
while (!isempty(c) || countobs(c->obpile, B_TRUE)) {
|
||||
c = getrandomroomcell(map, ANYROOM);
|
||||
if (!c) {
|
||||
// ANY cell at all, doesn't have to be a room.
|
||||
c = getrandomcell(map);
|
||||
}
|
||||
}
|
||||
o = addobfast(c->obpile, OT_STAIRSUP);
|
||||
linkstairs(o, NULL);
|
||||
|
@ -2213,14 +2226,14 @@ void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
|
|||
c = getrandomcell(map);
|
||||
w = rnd(MINCLEARINGRADIUS,MAXCLEARINGRADIUS);
|
||||
// clear obs in all clearing cells
|
||||
getradiuscells(c, w, DT_ORTH, LOF_DONTNEED, B_TRUE, retcell, &nretcells, B_FALSE);
|
||||
getradiuscells(c, w, DT_ORTH, B_FALSE, LOF_DONTNEED, B_TRUE, retcell, &nretcells, B_FALSE);
|
||||
for (n = 0; n < nretcells; n++) {
|
||||
// kill all obs here
|
||||
while (retcell[n]->obpile->first) killob(retcell[n]->obpile->first);
|
||||
}
|
||||
|
||||
// fill some cells with dirt
|
||||
getradiuscells(c, w, DT_ORTH, LOF_DONTNEED, B_TRUE, retcell, &nretcells, 70);
|
||||
getradiuscells(c, w, DT_ORTH,B_FALSE, LOF_DONTNEED, B_TRUE, retcell, &nretcells, 70);
|
||||
for (n = 0; n < nretcells; n++) {
|
||||
setcelltype(retcell[n], CT_DIRT);
|
||||
}
|
||||
|
@ -2235,7 +2248,7 @@ void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
|
|||
|
||||
w = rnd(MINCLEARINGRADIUS,MAXCLEARINGRADIUS);
|
||||
|
||||
getradiuscells(c, w, DT_ORTH, LOF_DONTNEED, B_TRUE, retcell, &nretcells, 80);
|
||||
getradiuscells(c, w, DT_ORTH, B_FALSE, LOF_DONTNEED, B_TRUE, retcell, &nretcells, 80);
|
||||
for (n = 0; n < nretcells; n++) {
|
||||
switch (rnd(0,1)) {
|
||||
default: case 0: strcpy(buf, "tree"); break;
|
||||
|
@ -3280,7 +3293,10 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
|||
}
|
||||
} else {
|
||||
if (db) dblog(" Cannot find a way to link up.");
|
||||
assert(0 == 1); // for debugging
|
||||
// debugging - a failure here during fix_reachability is fatal.
|
||||
if (wantfilled) {
|
||||
assert(0 == 1);
|
||||
}
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -5295,7 +5311,7 @@ void setcellknown(cell_t *cell, int forcelev) {
|
|||
void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype) {
|
||||
cell_t *cell[MAXCANDIDATES];
|
||||
int ncells,i;
|
||||
getradiuscells(centre, radius, dirtype, LOF_DONTNEED, B_TRUE, cell, &ncells, B_FALSE);
|
||||
getradiuscells(centre, radius, dirtype, B_FALSE, LOF_DONTNEED, B_TRUE, cell, &ncells, B_FALSE);
|
||||
for (i = 0; i < ncells; i++) {
|
||||
cell_t *c;
|
||||
c = cell[i];
|
||||
|
|
2
map.h
2
map.h
|
@ -32,7 +32,7 @@ flag_t *getmapcoords(map_t *m, int *x, int *y);
|
|||
int getmapdifficulty(map_t *m);
|
||||
map_t *getmapindir(map_t *src, int dir);
|
||||
int getmapmaxvisrange(map_t *m);
|
||||
void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells, int scatterdensity);
|
||||
void getradiuscells(cell_t *centre, int radius, int dirtype, int outsideonly, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells, int scatterdensity);
|
||||
int getroomid(cell_t *c);
|
||||
void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid);
|
||||
object_t *gettopobject(cell_t *where, int forglyph);
|
||||
|
|
47
move.c
47
move.c
|
@ -7,6 +7,7 @@
|
|||
#include "attack.h"
|
||||
#include "defs.h"
|
||||
#include "flag.h"
|
||||
#include "god.h"
|
||||
#include "io.h"
|
||||
#include "lf.h"
|
||||
#include "map.h"
|
||||
|
@ -476,6 +477,7 @@ int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) {
|
|||
|
||||
// src is where something is
|
||||
// dst is what we are going away from
|
||||
// if srclf is set, it is used for cellwalkable() checks. ie. if move will be involuntary, don't set this!
|
||||
// wantcheck is whether to check for dangerous things before considering a direction valid
|
||||
int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype, int keepinlof) {
|
||||
int d;
|
||||
|
@ -931,7 +933,7 @@ int moveeffects(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
if (isbleeding(lf)) {
|
||||
if (lfhasflagval(lf, F_INJURY, NA, BP_LEGS, DT_SLASH, NULL)) {
|
||||
if (hasbleedinginjury(lf, BP_LEGS)) {
|
||||
if (!bleedfrom(lf, BP_LEGS, B_FALSE)) {
|
||||
losehp(lf, 1, DT_DIRECT, NULL, "blood loss");
|
||||
}
|
||||
|
@ -1265,6 +1267,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
f = hasflag(postroom->vault->flags, F_VAULTENTERTEXT);
|
||||
if (f) {
|
||||
msg("%s", f->text);
|
||||
didmsg = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1530,9 +1533,6 @@ int move_will_hurt(lifeform_t *lf) {
|
|||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags,i;
|
||||
|
||||
if (lfhasflag(lf, F_PAIN)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
getflags(lf->flags, retflag, &nretflags, F_INJURY, F_PAIN, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
flag_t *f;
|
||||
|
@ -1547,6 +1547,10 @@ int move_will_hurt(lifeform_t *lf) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasbleedinginjury(lf, BP_LEGS)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1819,11 +1823,17 @@ int closedoor(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
|
||||
int tryrun(lifeform_t *lf, int dir) {
|
||||
if (!trymove(lf, dir, B_TRUE, B_TRUE)) {
|
||||
// success!
|
||||
int willrun = B_TRUE,rv;
|
||||
if (!moveclear(lf, dir, NULL)) {
|
||||
// don't double move into monsters, etc
|
||||
willrun = B_FALSE;
|
||||
}
|
||||
rv = trymove(lf, dir, B_TRUE, B_TRUE);
|
||||
if (!rv && willrun) {
|
||||
// successful move
|
||||
addflag(lf->flags, F_RUNNING, dir, B_FALSE, NA, NULL);
|
||||
}
|
||||
return B_FALSE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
int trysneak(lifeform_t *lf, int dir) {
|
||||
|
@ -2206,13 +2216,18 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
|
|||
int rndmove = B_FALSE;
|
||||
int howlong;
|
||||
int reldir;
|
||||
int srcmoney = 0;
|
||||
flag_t *f;
|
||||
|
||||
howlong = getmovespeed(lf);
|
||||
|
||||
reldir = getrelativedir(lf, dir);
|
||||
|
||||
|
||||
if (onpurpose) {
|
||||
if (isplayer(lf)) {
|
||||
srcmoney = countmoney(lf->cell->obpile);
|
||||
}
|
||||
if ((reldir != RD_FORWARDS) && !lfhasflag(lf, F_AWARENESS)) {
|
||||
// if the given dir is behind us, just turn.
|
||||
if (!strafe) {
|
||||
|
@ -2248,8 +2263,8 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
|
|||
|
||||
cell = getcellindir(lf->cell, dir);
|
||||
|
||||
// warn if moving will cause injury
|
||||
if (onpurpose && isplayer(lf)) {
|
||||
// warn if moving will cause damage
|
||||
if (cell && !cell->lf && onpurpose && isplayer(lf) ) {
|
||||
if (!confirm_injury_action(BP_LEGS, DT_SLASH, "move")) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
@ -2536,6 +2551,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
|
|||
char lfname[BUFLEN];
|
||||
getlfname(lfinway, lfname);
|
||||
msg("You swap places with %s.", lfname);
|
||||
dontclearmsg = B_TRUE;
|
||||
}
|
||||
|
||||
swapplaces(lf, lfinway, B_FALSE, onpurpose);
|
||||
|
@ -2600,11 +2616,16 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if (reason == E_OK) {
|
||||
return B_FALSE;
|
||||
} else {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
// purposely moving away fmor money?
|
||||
if (onpurpose && isplayer(lf) && srcmoney) {
|
||||
angergodmaybe(R_GODTHIEVES, srcmoney);
|
||||
}
|
||||
|
||||
if (reason != E_OK) {
|
||||
return B_TRUE;
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
|
|
105
objects.c
105
objects.c
|
@ -1222,9 +1222,9 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
if (o->type->id == OT_CORPSE) {
|
||||
flag_t *rf, *cf;
|
||||
|
||||
if (!corpserace) {
|
||||
if (!corpserace || hasflag(corpserace->flags, F_NOCORPSE)) {
|
||||
// random one.
|
||||
corpserace = getrandomrace(NULL, NA);
|
||||
corpserace = getrandomcorpserace(NULL);
|
||||
}
|
||||
|
||||
o->weight = corpserace->weight;
|
||||
|
@ -1250,11 +1250,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
where = getoblocation(o);
|
||||
// select random race
|
||||
if (where) {
|
||||
corpserace = getrandomrace(where, NA);
|
||||
corpserace = getrandomcorpserace(where);
|
||||
}
|
||||
if (!corpserace) {
|
||||
// ie. vending machine, or inside another object/fake cell?
|
||||
corpserace = getrandomrace(NULL, NA);
|
||||
corpserace = getrandomcorpserace(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1311,9 +1311,9 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
} else if (o->type->id == OT_ROASTMEAT) {
|
||||
flag_t *rf, *cf;
|
||||
|
||||
if (!corpserace) {
|
||||
if (!corpserace || hasflag(corpserace->flags, F_NOCORPSE)) {
|
||||
// random one.
|
||||
corpserace = getrandomrace(NULL, NA);
|
||||
corpserace = getrandomcorpserace(NULL);
|
||||
}
|
||||
|
||||
o->weight = corpserace->weight / 2;
|
||||
|
@ -1468,7 +1468,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
|
|||
if (o->blessed == B_CURSED) f->val[2] *= -1;
|
||||
} else if (o->type->id == OT_RING_DEX) {
|
||||
flag_t *f;
|
||||
f = hasflagval(o->flags, F_EQUIPCONFER, F_ATTRMOD, A_DEX, NA, NULL);
|
||||
f = hasflagval(o->flags, F_EQUIPCONFER, F_ATTRMOD, A_AGI, NA, NULL);
|
||||
if (f) {
|
||||
if (bonus) f->val[2] = bonus;
|
||||
else f->val[2] = rnd(1,3);
|
||||
|
@ -1592,7 +1592,7 @@ int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fr
|
|||
|
||||
redrawpause();
|
||||
|
||||
getradiuscells(where, range, dirtype, needlof, B_TRUE, cell, &ncells, B_FALSE);
|
||||
getradiuscells(where, range, dirtype, B_FALSE, needlof, B_TRUE, cell, &ncells, B_FALSE);
|
||||
for (i = 0; i < ncells; i++) {
|
||||
cell_t *c;
|
||||
c = cell[i];
|
||||
|
@ -2390,6 +2390,18 @@ void copyobprops(object_t *dst, object_t *src) {
|
|||
|
||||
}
|
||||
|
||||
int countmoney(obpile_t *op) {
|
||||
object_t *o;
|
||||
int amt = 0;
|
||||
for (o = op->first ; o ; o = o->next) {
|
||||
if (o->type->id == OT_GOLD) {
|
||||
amt += o->amt;
|
||||
}
|
||||
}
|
||||
return amt;
|
||||
}
|
||||
|
||||
|
||||
int countnames(char **list) {
|
||||
int count;
|
||||
for (count = 0; list[count]; count++);
|
||||
|
@ -3042,9 +3054,10 @@ int getobaccuracy(object_t *wep, lifeform_t *weilder) {
|
|||
}
|
||||
|
||||
// blessed weapons have better base accuracy
|
||||
if (wep->blessed == B_BLESSED) acc += 50;
|
||||
if (wep->blessed == B_BLESSED) acc += 10;
|
||||
//bonusses?
|
||||
|
||||
acc += (getobbonus(wep)*5);
|
||||
acc += (getobbonus(wep, B_FALSE)*10);
|
||||
|
||||
if (weilder) {
|
||||
enum SKILLLEVEL slev;
|
||||
|
@ -3085,15 +3098,18 @@ int getobaccuracy(object_t *wep, lifeform_t *weilder) {
|
|||
return acc;
|
||||
}
|
||||
|
||||
int getobbonus(object_t *o) {
|
||||
int getobbonus(object_t *o, int onlyknown) {
|
||||
int bonus = 0,i;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags = 0;
|
||||
|
||||
getflags(o->flags, retflag, &nretflags, F_BONUS, F_NONE);
|
||||
for (i = 0; i < nretflags; i++) {
|
||||
if (onlyknown && !retflag[i]->known) {
|
||||
} else {
|
||||
bonus += retflag[i]->val[0];
|
||||
}
|
||||
}
|
||||
return bonus;
|
||||
}
|
||||
|
||||
|
@ -3326,29 +3342,6 @@ object_t *getoutercontainerop(obpile_t *op) {
|
|||
return o;
|
||||
}
|
||||
|
||||
// ie. "it has xxx accuracy"
|
||||
char *getaccuracyname(int accpct) {
|
||||
if (accpct >= 200) {
|
||||
return "godlike";
|
||||
} else if (accpct >= 150) {
|
||||
return "incredible";
|
||||
} else if (accpct >= 100) {
|
||||
return "very good";
|
||||
} else if (accpct >= 70) {
|
||||
return "good";
|
||||
} else if (accpct >= 50) {
|
||||
return "average";
|
||||
} else if (accpct >= 30) {
|
||||
return "poor";
|
||||
} else if (accpct >= 20) {
|
||||
return "very poor";
|
||||
} else if (accpct >= 0) {
|
||||
return "incredibly poor";
|
||||
} else {
|
||||
return "a complete lack of";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object_t *getammo(object_t *gun) {
|
||||
object_t *o;
|
||||
|
@ -4547,7 +4540,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
|
|||
}
|
||||
|
||||
if (hasflag(o->flags, F_KNOWNBAD)) {
|
||||
strcat(localbuf, " [bad]");
|
||||
strcat(localbuf, " [badfeeling]");
|
||||
}
|
||||
|
||||
if (getskill(player, SK_COOKING) >= PR_BEGINNER) {
|
||||
|
@ -5212,12 +5205,15 @@ int getthrowdam(object_t *o) {
|
|||
return (int)dam;
|
||||
}
|
||||
|
||||
// get either name of top object, or cell type if solid
|
||||
// get either name of top object, or cell type
|
||||
char *gettopobname(cell_t *c, char *retbuf) {
|
||||
char buf[BUFLEN];
|
||||
int nother;
|
||||
strcpy(retbuf, "");
|
||||
/*
|
||||
if (c->type->solid) {
|
||||
strcpy(retbuf, c->type->name);
|
||||
|
||||
nother = countnoncosmeticobs(c->obpile, B_TRUE);
|
||||
if (nother) {
|
||||
snprintf(buf, BUFLEN, " (+%d other thing%s)", nother, (nother == 1) ? "" : "s");
|
||||
|
@ -5225,6 +5221,8 @@ char *gettopobname(cell_t *c, char *retbuf) {
|
|||
}
|
||||
return retbuf;
|
||||
} else {
|
||||
}
|
||||
*/
|
||||
object_t *o;
|
||||
o = gettopobject(c, B_FALSE);
|
||||
if (o) {
|
||||
|
@ -5236,10 +5234,11 @@ char *gettopobname(cell_t *c, char *retbuf) {
|
|||
snprintf(buf, BUFLEN, " (+%d other thing%s)", nother, (nother == 1) ? "" : "s");
|
||||
strcat(retbuf, buf);
|
||||
}
|
||||
} else {
|
||||
// just print the cell's name
|
||||
strcat(retbuf, c->type->name);
|
||||
}
|
||||
return retbuf;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum BODYPART getweildloc(object_t *o, enum BODYPART *otherloc, int *twohanded) {
|
||||
|
@ -5825,6 +5824,9 @@ int ismagical(object_t *o) {
|
|||
if (hasflag(o->flags, F_ENCHANTABLE) && hasflag(o->flags, F_BONUS)) {
|
||||
return B_TRUE;
|
||||
}
|
||||
if (o->type->id == OT_SHILLELAGH) {
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
return B_FALSE;
|
||||
}
|
||||
|
@ -6245,9 +6247,9 @@ int makeduller(object_t *o, int howmuch) {
|
|||
// get object name before changing the bonus
|
||||
getobname(o,obname, 1);
|
||||
|
||||
oldbonus = getobbonus(o);
|
||||
oldbonus = getobbonus(o, B_FALSE);
|
||||
modbonus(o, -howmuch);
|
||||
newbonus = getobbonus(o);
|
||||
newbonus = getobbonus(o, B_FALSE);
|
||||
|
||||
if (newbonus < oldbonus) {
|
||||
if (o->pile->owner) {
|
||||
|
@ -7641,7 +7643,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
|
|||
if ((m->region->rtype->id == RG_FIRSTDUNGEON) && (m->depth == 1)) {
|
||||
cell_t *cell[MAXCANDIDATES];
|
||||
int ncells,i;
|
||||
getradiuscells(lf->cell, 1, DT_COMPASS, B_FALSE, B_TRUE, cell, &ncells, B_FALSE);
|
||||
getradiuscells(lf->cell, 1, DT_COMPASS, B_FALSE, LOF_DONTNEED, B_TRUE, cell, &ncells, B_FALSE);
|
||||
for (i = 0; i < ncells; i++) {
|
||||
if (hasob(cell[i]->obpile, OT_STAIRSUP)) {
|
||||
object_t *o;
|
||||
|
@ -8594,8 +8596,8 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
|
|||
setattr(lf, A_STR, lf->baseatt[A_STR]);
|
||||
failed = B_FALSE;
|
||||
}
|
||||
if (getattr(lf,A_DEX) < lf->baseatt[A_DEX]) {
|
||||
setattr(lf, A_DEX, lf->baseatt[A_DEX]);
|
||||
if (getattr(lf,A_AGI) < lf->baseatt[A_AGI]) {
|
||||
setattr(lf, A_AGI, lf->baseatt[A_AGI]);
|
||||
failed = B_FALSE;
|
||||
}
|
||||
if (getattr(lf,A_IQ) < lf->baseatt[A_IQ]) {
|
||||
|
@ -8872,6 +8874,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
|
|||
} else {
|
||||
makeknown(o->type->id);
|
||||
}
|
||||
o->blessknown = B_TRUE;
|
||||
real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_TRUE, B_FALSE); // don't adjust for blindness
|
||||
if (isplayer(lf)) {
|
||||
// tell the player
|
||||
|
@ -8893,7 +8896,9 @@ int readsomething(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (seen) makeknown(o->type->id);
|
||||
if (seen) {
|
||||
makeknown(o->type->id); o->blessknown = B_TRUE;
|
||||
}
|
||||
} else if ((o->type->id == OT_SCR_MENDING) && isblessed(o)) {
|
||||
int seen = B_FALSE;
|
||||
object_t *oo;
|
||||
|
@ -8906,7 +8911,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
|
|||
}
|
||||
}
|
||||
if (seen) {
|
||||
makeknown(o->type->id);
|
||||
makeknown(o->type->id); o->blessknown = B_TRUE;
|
||||
} else {
|
||||
if (isplayer(lf) || cansee(player, lf)) nothinghappens();
|
||||
}
|
||||
|
@ -8936,7 +8941,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
|
|||
dospelleffects(lf, f->val[0], power, NULL, targob, NULL, o->blessed, &seen, B_FALSE);
|
||||
if (seen) {
|
||||
// id the scroll now
|
||||
makeknown(o->type->id);
|
||||
makeknown(o->type->id); o->blessknown = B_TRUE;
|
||||
}
|
||||
|
||||
// removeob one of the object
|
||||
|
@ -9152,7 +9157,7 @@ int readsomething(lifeform_t *lf, object_t *o) {
|
|||
|
||||
if (seen) {
|
||||
// id the scroll now
|
||||
makeknown(o->type->id);
|
||||
makeknown(o->type->id); o->blessknown = B_TRUE;
|
||||
} else {
|
||||
if (isplayer(lf)) {
|
||||
nothinghappens();
|
||||
|
@ -10350,7 +10355,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
|
|||
if (willcatch) {
|
||||
acc = 100;
|
||||
} else {
|
||||
acc = getmissileaccuracy(thrower, where, o, firearm, A_DEX);
|
||||
acc = getmissileaccuracy(thrower, where, o, firearm, A_AGI);
|
||||
}
|
||||
} else {
|
||||
// purely based on saving throw...
|
||||
|
@ -11609,6 +11614,8 @@ int getcritchance(lifeform_t *lf, object_t *o, lifeform_t *victim) {
|
|||
f = hasflag(o->flags, F_CRITCHANCE);
|
||||
if (f) {
|
||||
chance += f->val[0];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lf) {
|
||||
|
|
|
@ -36,6 +36,7 @@ int changemat(object_t *o, enum MATERIAL mat);
|
|||
int checkobnames(char *haystack, char *needle);
|
||||
void colourmatchob(object_t *o, lifeform_t *lf);
|
||||
void copyobprops(object_t *dst, object_t *src);
|
||||
int countmoney(obpile_t *op);
|
||||
int countnames(char **list);
|
||||
int countobs(obpile_t *op, int onlyifknown);
|
||||
int countobsoftype(obpile_t *op, enum OBTYPE oid);
|
||||
|
@ -66,7 +67,7 @@ enum COLOUR getmaterialcolour(enum MATERIAL mat );
|
|||
enum MATSTATE getmaterialstate(enum MATERIAL mat);
|
||||
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt);
|
||||
int getobaccuracy(object_t *wep, lifeform_t *weilder);
|
||||
int getobbonus(object_t *o);
|
||||
int getobbonus(object_t *o, int onlyknown);
|
||||
int getobpoints(object_t *o);
|
||||
skill_t *getobskill(object_t *o);
|
||||
enum LFSIZE getobsize(object_t *o);
|
||||
|
@ -76,7 +77,6 @@ char *getoperateverb(object_t *o);
|
|||
object_t *getoutercontainer(object_t *o);
|
||||
object_t *getoutercontainerop(obpile_t *op);
|
||||
//int getobtypevalue(objecttype_t *ot);
|
||||
char *getaccuracyname(int accpct);
|
||||
object_t *getammo(object_t *gun);
|
||||
objecttype_t *getbasicweaponforskill(enum SKILL skid);
|
||||
object_t *getrandomammo(lifeform_t *lf);
|
||||
|
|
4
save.c
4
save.c
|
@ -196,7 +196,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
|||
|
||||
// load rest of this lf
|
||||
fscanf(f, "str: %d/%d\n",&l->att[A_STR],&l->baseatt[A_STR]);
|
||||
fscanf(f, "dex: %d/%d\n",&l->att[A_DEX],&l->baseatt[A_DEX]);
|
||||
fscanf(f, "dex: %d/%d\n",&l->att[A_AGI],&l->baseatt[A_AGI]);
|
||||
fscanf(f, "int: %d/%d\n",&l->att[A_IQ],&l->baseatt[A_IQ]);
|
||||
fscanf(f, "xp: %ld\n",&l->xp);
|
||||
fscanf(f, "skp: %d\n",&l->skillpoints);
|
||||
|
@ -784,7 +784,7 @@ int savelf(FILE *f, lifeform_t *l) {
|
|||
fprintf(f, "newlevel: %d\n",l->newlevel);
|
||||
// liefform will be created after loading the above.
|
||||
fprintf(f, "str: %d/%d\n",l->att[A_STR],l->baseatt[A_STR]);
|
||||
fprintf(f, "dex: %d/%d\n",l->att[A_DEX],l->baseatt[A_DEX]);
|
||||
fprintf(f, "dex: %d/%d\n",l->att[A_AGI],l->baseatt[A_AGI]);
|
||||
fprintf(f, "int: %d/%d\n",l->att[A_IQ],l->baseatt[A_IQ]);
|
||||
fprintf(f, "xp: %ld\n",l->xp);
|
||||
fprintf(f, "skp: %d\n",l->skillpoints);
|
||||
|
|
164
spell.c
164
spell.c
|
@ -99,7 +99,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
if (f) stamcost = f->val[0];
|
||||
|
||||
if (stamcost) {
|
||||
if (user->stamina < stamcost) {
|
||||
if (getstamina(user) < stamcost) {
|
||||
if (isplayer(user)) {
|
||||
msg("You are too tired to do that right now.");
|
||||
}
|
||||
|
@ -580,7 +580,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
}
|
||||
|
||||
// victim gets a skilcheck to avoid being grabbed
|
||||
if (skillcheck(target, SC_DODGE, getattr(user, A_DEX)+11, 0)) {
|
||||
if (skillcheck(target, SC_DODGE, getattr(user, A_AGI)+11, 0)) {
|
||||
if (cansee(player, user)) {
|
||||
msg("%s evade%s %s%s grasp.", targetname, isplayer(target) ? "" : "s",
|
||||
username, getpossessive(username));
|
||||
|
@ -800,12 +800,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
}
|
||||
} else if (abilid == OT_A_REPAIR) {
|
||||
enum SKILLLEVEL slev;
|
||||
object_t *o;
|
||||
object_t *o,*helpob = NULL;
|
||||
enum MATERIAL repairablemats[MAXCANDIDATES];
|
||||
int repaircutoff = 0;
|
||||
int cutoffpct[MAXCANDIDATES];
|
||||
int nmats = 0;
|
||||
int i;
|
||||
char helpobname[BUFLEN];
|
||||
|
||||
// get list of repairable materials
|
||||
slev = getskill(user, SK_METALWORK);
|
||||
|
@ -820,6 +821,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
case PR_MASTER: cutoff = 100; break;
|
||||
default: cutoff = 0; break;
|
||||
}
|
||||
helpob = hasob(user->pack, OT_SPANNER);
|
||||
if (helpob) cutoff += 15;
|
||||
repairablemats[nmats] = MT_METAL;
|
||||
cutoffpct[nmats] = cutoff;
|
||||
nmats++;
|
||||
|
@ -836,6 +839,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
case PR_MASTER: cutoff = 100; break;
|
||||
default: cutoff = 0; break;
|
||||
}
|
||||
helpob = hasob(user->pack, OT_NEEDLE);
|
||||
if (helpob) cutoff += 15;
|
||||
repairablemats[nmats] = MT_CLOTH;
|
||||
cutoffpct[nmats] = cutoff;
|
||||
nmats++;
|
||||
|
@ -844,6 +849,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
nmats++;
|
||||
}
|
||||
|
||||
if (helpob) {
|
||||
real_getobname(helpob, helpobname, helpob->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE);
|
||||
} else {
|
||||
strcpy(helpobname, "");
|
||||
}
|
||||
|
||||
// 1.compile a list of repairable objects
|
||||
// sk_armour lets you repair armour up to xx% (depends on skill)
|
||||
|
@ -864,10 +874,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
f = hasflag(o->flags, F_OBHP);
|
||||
pct = ((float)f->val[0] /(float) f->val[1]) * 100;
|
||||
if (pct < cutoff) {
|
||||
char buf[BUFLEN];
|
||||
char buf[BUFLEN],desc[BUFLEN];
|
||||
getobname(o, buf, o->amt);
|
||||
sprintf(desc, "%s (-> %d%%)",buf, cutoff);
|
||||
// we can repair this object
|
||||
addchoice(&prompt, o->letter, buf, buf, o, NULL);
|
||||
addchoice(&prompt, o->letter, desc, desc, o, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -909,13 +920,21 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
f = hasflag(o->flags, F_OBHP);
|
||||
f->val[0] = pctof(repaircutoff, f->val[1]);
|
||||
if (isplayer(user)) {
|
||||
char buf[BUFLEN];
|
||||
char buf[BUFLEN],withbuf[BUFLEN];
|
||||
real_getobname(o, buf, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE);
|
||||
msg("You %srepair your %s.", (f->val[0] == f->val[1]) ? "" : "partially ", noprefix(buf));
|
||||
if (helpob) sprintf(withbuf, " (with %s)", helpobname);
|
||||
else strcpy(withbuf, "");
|
||||
|
||||
msg("You %srepair your %s%s.", (f->val[0] == f->val[1]) ? "" : "partially ",
|
||||
noprefix(buf), withbuf);
|
||||
} else {
|
||||
char buf[BUFLEN];
|
||||
char buf[BUFLEN],withbuf[BUFLEN];
|
||||
real_getobname(o, buf, o->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE);
|
||||
msg("%s %s repairs %s.", username, (f->val[0] == f->val[1]) ? "completely" : "partially", buf);
|
||||
if (helpob) sprintf(withbuf, " with %s", helpobname);
|
||||
else strcpy(withbuf, "");
|
||||
|
||||
msg("%s %s repairs %s%s.", username, (f->val[0] == f->val[1]) ? "completely" : "partially",
|
||||
buf, withbuf);
|
||||
}
|
||||
|
||||
// TODO: make this like eating/resting/etc ?
|
||||
|
@ -1416,6 +1435,47 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
}
|
||||
msg("all blinded!");
|
||||
return B_FALSE;
|
||||
} else if (abilid == OT_A_AIMEDSTRIKE) {
|
||||
object_t *wep;
|
||||
char dirch;
|
||||
char targetname[BUFLEN];
|
||||
flag_t *f;
|
||||
|
||||
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
|
||||
if (isplayer(user)) msg("You lack the control for an aimed strike while swimming.");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
wep = getweapon(user);
|
||||
|
||||
// ask for direction
|
||||
if (!targcell) {
|
||||
dirch = askchar("Aimed strike in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE);
|
||||
if (dirch == '.') {
|
||||
// yourself!
|
||||
targcell = user->cell;
|
||||
} else {
|
||||
int dir;
|
||||
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);
|
||||
|
||||
f = addflag(user->flags, F_AIMEDSTRIKE, B_TRUE, NA, NA, NULL);
|
||||
attackcell(user, targcell, B_TRUE);
|
||||
killflag(f);
|
||||
} else if (abilid == OT_A_COMBOSTRIKE) {
|
||||
object_t *wep;
|
||||
skill_t *wepsk = NULL;
|
||||
|
@ -1537,10 +1597,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
if (where && where->lf) {
|
||||
char ch;
|
||||
enum ATTRIB att;
|
||||
ch = askchar("Enhance which stat (n for none)?", "sdcin",NULL, B_TRUE);
|
||||
ch = askchar("Enhance which stat (n for none)?", "sacin",NULL, B_TRUE);
|
||||
switch (ch) {
|
||||
case 's': att = A_STR; break;
|
||||
case 'd': att = A_DEX; break;
|
||||
case 'a': att = A_AGI; break;
|
||||
case 'c': att = A_CON; break;
|
||||
case 'i': att = A_IQ; break;
|
||||
default: att = A_NONE; break;
|
||||
|
@ -2094,7 +2154,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
msg("%s unleashes a freezing blast!", castername, getpossessive(castername));
|
||||
}
|
||||
// freeze lfs, obs in most cells
|
||||
getradiuscells(caster->cell, 7, DT_ORTH, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 90);
|
||||
getradiuscells(caster->cell, 7, DT_ORTH, B_FALSE, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 90);
|
||||
for (i = 0; i < nretcells; i++) {
|
||||
object_t *o, *nexto;
|
||||
if (retcell[i]->lf) {
|
||||
|
@ -3688,7 +3748,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
// don't need line of fire!
|
||||
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE;
|
||||
|
||||
getradiuscells(targcell, power, DT_ORTH, LOF_NEED, B_TRUE, cell, &ncells, B_FALSE);
|
||||
getradiuscells(targcell, power, DT_ORTH, B_FALSE, LOF_NEED, B_TRUE, cell, &ncells, B_FALSE);
|
||||
for (i = 0; i < ncells; i++) {
|
||||
object_t *o,*nexto;
|
||||
for (o = cell[i]->obpile->first ; o ; o = nexto) {
|
||||
|
@ -4051,6 +4111,32 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (failed) {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_FORCESPHERE) {
|
||||
cell_t *retcell[MAXRETCELLS];
|
||||
int radius,nretcells,n,i;
|
||||
if (!target) target = caster;
|
||||
targcell = target->cell;
|
||||
radius = power/3;
|
||||
if (isplayer(target)) {
|
||||
msg("You unleash a mighty shockwave!");
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
} else if (cansee(player, target)) {
|
||||
char tname[BUFLEN];
|
||||
getlfname(target, tname);
|
||||
msg("%s unleashes a mighty shockwave!", tname);
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
}
|
||||
// start at outside.
|
||||
for (n = radius; n >= 1; n--) {
|
||||
getradiuscells(targcell, n, DT_COMPASS, B_TRUE, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 0);
|
||||
for (i = 0; i < nretcells; i++) {
|
||||
if (retcell[i]->lf) {
|
||||
knockback(retcell[i]->lf,
|
||||
getdiraway(retcell[i], targcell, NULL, B_FALSE, DT_COMPASS, B_FALSE),
|
||||
2, target, 27+power);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_ENERGYBOLT) {
|
||||
char lfname[BUFLEN];
|
||||
char numbuf[BUFLEN];
|
||||
|
@ -4265,6 +4351,50 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
if (failed) {
|
||||
fizzle(caster);
|
||||
}
|
||||
} else if (spellid == OT_S_EARTHQUAKE) {
|
||||
cell_t *retcell[MAXRETCELLS],*c;
|
||||
int nretcells,i,radius,seenwalls = 0, seenpits = 0;
|
||||
radius = 3 + power;
|
||||
getradiuscells(caster->cell, radius, DT_ORTH, B_FALSE, LOF_DONTNEED, B_FALSE, retcell, &nretcells, 80);
|
||||
for (i = 0; i < nretcells; i++) {
|
||||
c = retcell[i];
|
||||
if (c->type->solid) {
|
||||
if (haslos(player, c)) seenwalls++;
|
||||
setcelltype(c, c->map->habitat->emptycelltype);
|
||||
addob(c->obpile, "50-100 stones");
|
||||
} else {
|
||||
// it collapses
|
||||
addobfast(c->obpile, OT_HOLEINGROUND);
|
||||
if (haslos(player, c)) seenpits++;
|
||||
}
|
||||
}
|
||||
getradiuscells(caster->cell, radius, DT_ORTH, B_FALSE, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 80);
|
||||
for (i = 0; i < nretcells; i++) {
|
||||
c = retcell[i];
|
||||
if (!c->type->solid) {
|
||||
addobfast(c->obpile, OT_DUSTCLOUD);
|
||||
}
|
||||
}
|
||||
if (seenpits || seenwalls || cansee(player, caster)) {
|
||||
msg("The earth below you shudders and shakes violently!");
|
||||
setlosdirty(player);
|
||||
}
|
||||
if (seenpits) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
if (seenwalls == 1) {
|
||||
msg("A huge rent opens up in the ground!");
|
||||
} else {
|
||||
msg("Huge rents open up in the ground!");
|
||||
}
|
||||
}
|
||||
if (seenwalls) {
|
||||
if (seenbyplayer) *seenbyplayer = B_TRUE;
|
||||
if (seenwalls == 1) {
|
||||
msg("A nearby wall collapse into the ground!");
|
||||
} else {
|
||||
msg("Nearby walls collapse into the ground!");
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_ENCHANT) {
|
||||
object_t *o;
|
||||
|
||||
|
@ -6271,12 +6401,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
|
||||
f = hasflag(o->flags, F_OBHP);
|
||||
if (f && isdamaged(o)) {
|
||||
if (f) {
|
||||
if (blessed == B_CURSED) {
|
||||
if (isplayer(caster) || cansee(player, caster)) msg("%s deteriorates!", fullobname);
|
||||
takedamage(o, rnd(1,6) + power, DT_DIRECT);
|
||||
donesomething = B_TRUE;
|
||||
} else {
|
||||
} else if (isdamaged(o)) {
|
||||
f->val[0] += (rnd(1,6) + power);
|
||||
|
||||
if (f->val[0] >= f->val[1]) {
|
||||
|
@ -6630,7 +6760,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
amttolose = power*2;
|
||||
// only announce if the target will have some stamina left.
|
||||
// if they drop to 0, modstamina will handle the announce.
|
||||
if (target->stamina >= amttolose) {
|
||||
if (getstamina(target) >= amttolose) {
|
||||
if (isplayer(target)) {
|
||||
msg("You suddenly feel very lethargic!");
|
||||
} else if (cansee(player, target)) {
|
||||
|
@ -6804,7 +6934,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
} else {
|
||||
// 2nd one failed - lose all stamina instead
|
||||
modstamina(target, -(target->stamina));
|
||||
modstamina(target, -(getstamina(target)));
|
||||
if (isplayer(target)) {
|
||||
msg("You suddenly feel very lethargic!");
|
||||
} else if (cansee(player, target)) {
|
||||
|
|
82
text.c
82
text.c
|
@ -153,6 +153,33 @@ int flip(int ch) {
|
|||
return ch;
|
||||
}
|
||||
|
||||
// ie. "it has xxx accuracy"
|
||||
char *getaccuracyname(int accpct) {
|
||||
if (accpct >= 200) {
|
||||
return "incredible";
|
||||
} else if (accpct >= 150) {
|
||||
return "very good";
|
||||
} else if (accpct >= 100) {
|
||||
return "good";
|
||||
} else if (accpct >= 70) {
|
||||
return "average";
|
||||
} else if (accpct >= 50) {
|
||||
return "poor";
|
||||
} else if (accpct >= 30) {
|
||||
return "very poor";
|
||||
} else if (accpct >= 20) {
|
||||
return "extremely poor";
|
||||
} else {
|
||||
return "a complete lack of";
|
||||
}
|
||||
}
|
||||
|
||||
int getaccuracynum(int accpct) {
|
||||
int num;
|
||||
num = (accpct - 100) / 5; //
|
||||
return num;
|
||||
}
|
||||
|
||||
char *getattrabbrev(enum ATTRIB att) {
|
||||
switch (att) {
|
||||
case A_NONE:
|
||||
|
@ -161,8 +188,8 @@ char *getattrabbrev(enum ATTRIB att) {
|
|||
return "Ch";
|
||||
case A_CON:
|
||||
return "Ft";
|
||||
case A_DEX:
|
||||
return "Dx";
|
||||
case A_AGI:
|
||||
return "Ag";
|
||||
case A_IQ:
|
||||
return "Iq";
|
||||
case A_STR:
|
||||
|
@ -181,8 +208,8 @@ char *getattrname(enum ATTRIB att) {
|
|||
return "charisma";
|
||||
case A_CON:
|
||||
return "fitness";
|
||||
case A_DEX:
|
||||
return "dexterity";
|
||||
case A_AGI:
|
||||
return "agility";
|
||||
case A_IQ:
|
||||
return "intelligence";
|
||||
case A_STR:
|
||||
|
@ -301,6 +328,53 @@ int gethitconferlifetime(char *text, int *min, int *max) {
|
|||
return howlong;
|
||||
}
|
||||
|
||||
char *getpoisondamverb(enum POISONTYPE ptype) {
|
||||
switch (ptype) {
|
||||
case P_FOOD:
|
||||
case P_VENOM:
|
||||
return "vomit";
|
||||
case P_GAS:
|
||||
case P_COLD:
|
||||
return "cough";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
char *getpoisondesc(enum POISONTYPE ptype) {
|
||||
switch (ptype) {
|
||||
case P_FOOD:
|
||||
case P_VENOM:
|
||||
case P_GAS:
|
||||
case P_WEAKNESS:
|
||||
return "Poisoned";
|
||||
case P_COLD:
|
||||
return "Sick";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Poisoned";
|
||||
}
|
||||
|
||||
char *getpoisonname(enum POISONTYPE ptype) {
|
||||
switch (ptype) {
|
||||
case P_COLD:
|
||||
return "hypothermia";
|
||||
case P_FOOD:
|
||||
return "food poisoning";
|
||||
case P_GAS:
|
||||
return "gas inhalation";
|
||||
case P_VENOM:
|
||||
return "venom poisoning";
|
||||
case P_WEAKNESS:
|
||||
return "weakening poison";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
char *getpossessive(char *text) {
|
||||
char lastchar;
|
||||
// you -> your
|
||||
|
|
5
text.h
5
text.h
|
@ -6,11 +6,16 @@ char *capitaliseall(char *text);
|
|||
enum COLOUR chartocol(char ch);
|
||||
char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf);
|
||||
int flip(int ch);
|
||||
char *getaccuracyname(int accpct);
|
||||
int getaccuracynum(int accpct);
|
||||
char *getattrabbrev(enum ATTRIB att);
|
||||
char *getattrname(enum ATTRIB att);
|
||||
char *getdirname(int dir);
|
||||
char *getdirnameshort(int dir);
|
||||
int gethitconferlifetime(char *text, int *min, int *max);
|
||||
char *getpoisondamverb(enum POISONTYPE ptype);
|
||||
char *getpoisondesc(enum POISONTYPE ptype);
|
||||
char *getpoisonname(enum POISONTYPE ptype);
|
||||
char *getpossessive(char *text);
|
||||
char *getdrunktext(flag_t *drunkflag);
|
||||
char *getinjuredbpname(enum BODYPART bp);
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
@id:playerstart_2
|
||||
@map
|
||||
###x###
|
||||
#m|.|m#
|
||||
#.-.-.#
|
||||
###.###
|
||||
#m|.-p#
|
||||
#.-.-p#
|
||||
###.###
|
||||
#m|.|m#
|
||||
#.-.-.#
|
||||
###.###
|
||||
#m|.|m#
|
||||
#.-.-.#
|
||||
###x###
|
||||
@end
|
||||
@legend
|
||||
#:cell:rock wall
|
||||
|:ob:locked iron gate
|
||||
-:ob:iron gate
|
||||
p:ob:playerstart
|
||||
m:mon:humanoid
|
||||
x:exit
|
||||
@end
|
||||
@flags
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
@id:playerstart_4
|
||||
@map
|
||||
###x###
|
||||
#ww_ww#
|
||||
#ww.ww#
|
||||
x_.p._x
|
||||
#ww.ww#
|
||||
#ww_ww#
|
||||
###x###
|
||||
####x####
|
||||
#.......#
|
||||
#.ww_ww.#
|
||||
#.ww.ww.#
|
||||
x._.p._.x
|
||||
#.ww.ww.#
|
||||
#.ww_ww.#
|
||||
#.......#
|
||||
####x####
|
||||
@end
|
||||
@legend
|
||||
#:cell:rock wall
|
||||
|
|
Loading…
Reference in New Issue