- [+] bug: "10 flaming arrows ##########\n are no longer on fire"

- [+] bug:  when wearing no boots: "A small puddle of water hits you!"
- [+] animated zombie keeps changing colour
* [+] wizard special case:
* [+] bug - walked down stiars on top of a monster
- [+] change "haslof" to come from a cell
- [+] replace WE_NOTSOLID with WE_WALKABLE
- [+] show hp/mp in colour
- [+] invis potion should always traget user
- [+] generic functions to curse/uncurse an object
- [+] not prompting for statgain after training properly. fixed.
* [+] pressing a key should interrupt resting
* [+] implement doublebuffering for screen
- [+] don't show attack dmg for mosnters
- [+] reduce sprint time
- [+] if a monster is chasing someone (ie has F_TARGET), then don't
      consider cursed ob ells as valid
- [+] don't hear noises when in battle
- [+] colourise attribs on status bar
* [+] askob/askobmulti
- [+] "lockpick with what" showing too much
* [+] inventoy colours
- [+] "masterwork stick" ?!
- [+] poison:  save to get rid of poison should be HARDER than save to
      prevent getting it
* [+] why are xats starting off carrying objects ?
* [+] small chance of catching a thrown missile if you have very high
      dex
* [+] if you polymorphed on purpose, have a "revert to original form"
      ability
- [+] nausea should only affect humanoids
- [+] BUG displaying knowledge when it goes longer than 1 screen.
- [+] monsters are attacking each other again! fixed?
* [+] BUG: when i load a game, i gain all knowledge!
- [+] more pole weapons
* [+] disarming weapons
* [+] tripping weapons
* [+] MORE ISSUES with askobject
* [+] validatelf
- [+] fix bug with poison triggering too often
- [+] chance of retching when nauseated. no hp loss, but takes time.
- [+] monsters shouldn't throw stuff if they don't have lof.
- [+] fix crash in knockbackob->fireat, caused by thrower == null
- [+] let high powered KNOCK knockback creatures again ?
- [+] test function to dump out:  dungeonlev   
      which_monsters_can_appear
- [+] firstaid tells you how long poison will last and whether it's
      lifethreatenting?
* [+] high level listen gives more info
- [+] wind shield spell
    - [+] repels all missiles of speed <= power 
- [+] variable level spells
    - [+] F_VARLEVEL
    - [+] when you cast, say "cast at how much power" with choices
          "Power II (5 MP)"
    - [+] show in spell list:  "5-10 MP"
- [+] replace ARBOOST with MAGICARMOUR
- [+] needan()
* [+] move psychic shield check into losehp
- [+] high level detectlife should show actual lf glyphs
- [+] control which jobs can learn which new skills.
    - [+] F_CANLEARN xxx
- [+] remember last target from spells
    - [+] askcoords = does lf for lastlftarg exist? if not, set it to
          null
    - [+] if so, start with it
    - [+] when you pick one, set it.
- [+] F_SHIELDPENALTY - modifies accuracy.
* [+] stop wizards from using shields
This commit is contained in:
Rob Pearce 2011-04-06 07:27:55 +00:00
parent 69d14c05fe
commit 7e8aecf958
22 changed files with 2496 additions and 1197 deletions

5
ai.c
View File

@ -488,7 +488,7 @@ void aimove(lifeform_t *lf) {
} }
// if not adjacent, check for guns, wands, throwing // if not adjacent, check for guns, wands, throwing
if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf, target->cell, B_FALSE, NULL)) { if (goingtomove && (getcelldist(lf->cell, target->cell) > 1) && haslof(lf->cell, target->cell, LOF_NEED, NULL)) {
// can we attack by firing a weapon? // can we attack by firing a weapon?
gun = getfirearm(lf); gun = getfirearm(lf);
if (goingtomove && gun && getammo(lf)) { if (goingtomove && gun && getammo(lf)) {
@ -609,6 +609,7 @@ void aimove(lifeform_t *lf) {
if (db) dblog(".oO { walking from %d,%d towards f_targetcell (%d,%d) ... }", lf->cell->x, lf->cell->y, x, y); if (db) dblog(".oO { walking from %d,%d towards f_targetcell (%d,%d) ... }", lf->cell->x, lf->cell->y, x, y);
c = getcellat(lf->cell->map, x, y); c = getcellat(lf->cell->map, x, y);
if (c) { if (c) {
// target cell adjacent and something in the way?
if (movetowards(lf, c, DT_ORTH)) { if (movetowards(lf, c, DT_ORTH)) {
// couldn't move towards it for some reason. // couldn't move towards it for some reason.
// so stop trying. // so stop trying.
@ -929,7 +930,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
srange = srflag->val[0]; srange = srflag->val[0];
} }
if (!haslof(lf, victim->cell, LOF_NEED,NULL)) { if (!haslof(lf->cell, victim->cell, LOF_NEED,NULL)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} else if (isimmobile(lf) || !lfhasflag(lf, F_FLYING)) { } else if (isimmobile(lf) || !lfhasflag(lf, F_FLYING)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;

View File

@ -23,7 +23,7 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty
// figure out what bit of armour was hit // figure out what bit of armour was hit
// special case - missiles against flak jacket // special case - missiles always hit flak jacket
if (damtype == DT_PROJECTILE) { if (damtype == DT_PROJECTILE) {
object_t *o; object_t *o;
o = getequippedob(lf->pack, BP_BODY); o = getequippedob(lf->pack, BP_BODY);
@ -38,8 +38,6 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty
armour = getrandomarmour(lf); armour = getrandomarmour(lf);
} }
if (armour) { if (armour) {
int actualdam; int actualdam;
flag_t *rust; flag_t *rust;
@ -573,7 +571,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
if (lfhasflag(victim, F_DODGES)) { if (lfhasflag(victim, F_DODGES)) {
cell_t *adj; cell_t *adj;
adj = getrandomadjcell(victim->cell, WE_NOTSOLID); adj = getrandomadjcell(victim->cell, WE_WALKABLE, B_NOEXPAND);
if (adj) { if (adj) {
flag_t *f; flag_t *f;
f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL); f = addflag(victim->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
@ -827,8 +825,10 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
} else { } else {
return "bash"; return "bash";
} }
} else { } else if (pct <= 30) {
return "pummel"; return "pummel";
} else {
return "slam";
} }
} else if (damtype == DT_BITE) { } else if (damtype == DT_BITE) {
if (lf && (ownersize <= SZ_SMALL)) { if (lf && (ownersize <= SZ_SMALL)) {
@ -1332,6 +1332,30 @@ obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) {
return op; return op;
} }
int isphysicaldam(enum DAMTYPE damtype) {
switch (damtype) {
case DT_BASH:
case DT_BITE:
case DT_CHOP:
case DT_CLAW:
case DT_COLD:
case DT_CRUSH:
case DT_ELECTRIC:
case DT_EXPLOSIVE:
case DT_FALL:
case DT_FIRE:
case DT_MAGIC:
case DT_PIERCE:
case DT_PROJECTILE:
case DT_SLASH:
case DT_UNARMED:
return B_TRUE;
default:
break;
}
return B_FALSE;
}
int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) { int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical) {
int acc,ev; int acc,ev;
object_t *wep; object_t *wep;
@ -1475,6 +1499,53 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
} // end if dampct > 50 } // end if dampct > 50
} }
} }
} else if ((f->id == F_DISARMATTACK) && victim && owner && !isdead(victim)) {
object_t *victimwep;
skill_t *sk;
int skillmod;
victimwep = getweapon(victim);
if (victimwep) {
sk = getobskill(wep);
if (sk) {
skillmod = getskill(owner, sk->id);
if (skillmod == 0) skillmod = -5;
} else {
skillmod = 0;
}
if (skillcheckvs(owner, SC_DEX, skillmod, victim, SC_SLIP, 0)) {
char lfname[BUFLEN];
char victimname[BUFLEN];
getlfname(owner,lfname);
getlfname(victim, victimname);
if (cansee(player, owner)) {
msg("%s disarm%s %s!",lfname, isplayer(owner) ? "" : "s", victimname);
}
drop(victimwep, ALL);
}
}
} else if ((f->id == F_TRIPATTACK) && victim && owner && !isdead(victim)) {
skill_t *sk;
int skillmod;
sk = getobskill(wep);
if (sk) {
skillmod = getskill(owner, sk->id);
if (skillmod == 0) skillmod = -5;
} else {
skillmod = 0;
}
if (skillcheckvs(owner, SC_DEX, skillmod, victim, SC_SLIP, 0)) {
char lfname[BUFLEN];
char victimname[BUFLEN];
getlfname(owner,lfname);
getlfname(victim, victimname);
if (cansee(player, owner)) {
msg("%s trip%s %s.",lfname, isplayer(owner) ? "" : "s", victimname);
}
fall(victim, B_TRUE);
}
} else if ((f->id == F_HEAVYBLOW) && victim && owner) { } else if ((f->id == F_HEAVYBLOW) && victim && owner) {
int dir; int dir;
// knock back victim // knock back victim
@ -1487,7 +1558,8 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
enum FLAG fid; enum FLAG fid;
int min,max,howlong; int min,max,howlong;
fid = f->val[0]; fid = f->val[0];
if (!lfhasflag(victim, fid)) { // the f_poisoned flag stacks, others don't.
if (!lfhasflag(victim, fid) || (fid == F_POISONED)) {
int passedcheck = B_FALSE; int passedcheck = B_FALSE;
// do they get a saving throw? // do they get a saving throw?
if (f->val[1] != NA) { if (f->val[1] != NA) {
@ -1544,7 +1616,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
} else { } else {
strcpy(frombuf, "something unknown"); strcpy(frombuf, "something unknown");
} }
addtempflag(victim->flags, fid, NA, NA, NA, frombuf, howlong); poison(victim, howlong, frombuf);
} else { } else {
addtempflag(victim->flags, fid, NA, NA, NA, NULL, howlong); addtempflag(victim->flags, fid, NA, NA, NA, NULL, howlong);
} }

View File

@ -20,5 +20,6 @@ int getdamroll(object_t *o, lifeform_t *victim);
int getdamrollfromflag(flag_t *f); int getdamrollfromflag(flag_t *f);
float getstrdammod(lifeform_t *lf); float getstrdammod(lifeform_t *lf);
obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag); obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
int isphysicaldam(enum DAMTYPE damtype);
int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical); int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical);
void wepeffects(flagpile_t *fp, cell_t *where, int dam); void wepeffects(flagpile_t *fp, cell_t *where, int dam);

100
defs.h
View File

@ -8,6 +8,9 @@
#define WETTIME 10 // how long it takes for things to dry #define WETTIME 10 // how long it takes for things to dry
#define POISONDAMCHANCE 33 // chance of vomitting when poisoned
#define POISONDAM 2 // damage taken from vomiting when poisoned
// ncurses colours // ncurses colours
enum COLOUR { enum COLOUR {
C_BLACK = 0, C_BLACK = 0,
@ -607,6 +610,7 @@ enum OBTYPE {
OT_ROASTMEAT, OT_ROASTMEAT,
OT_BREADFRESH, OT_BREADFRESH,
OT_CHOCOLATE, OT_CHOCOLATE,
OT_CLOVER,
// corpses // corpses
OT_CORPSE, OT_CORPSE,
OT_HEAD, OT_HEAD,
@ -642,6 +646,7 @@ enum OBTYPE {
OT_POT_INVULN, OT_POT_INVULN,
OT_POT_MAGIC, OT_POT_MAGIC,
OT_POT_OIL, OT_POT_OIL,
OT_POT_POISON,
OT_POT_POLYMORPH, OT_POT_POLYMORPH,
OT_POT_RESTORATION, OT_POT_RESTORATION,
OT_POT_SANCTUARY, OT_POT_SANCTUARY,
@ -678,6 +683,7 @@ enum OBTYPE {
OT_MAN_LOCKPICKING, OT_MAN_LOCKPICKING,
OT_MAN_MAGITEMUSAGE, OT_MAN_MAGITEMUSAGE,
OT_MAN_RESEARCH, OT_MAN_RESEARCH,
OT_MAN_SHIELDS,
OT_MAN_SPELLCASTING, OT_MAN_SPELLCASTING,
OT_MAN_STEALTH, OT_MAN_STEALTH,
OT_MAN_TECHUSAGE, OT_MAN_TECHUSAGE,
@ -798,6 +804,7 @@ enum OBTYPE {
// -- elemental - air // -- elemental - air
OT_S_AIRBLAST, OT_S_AIRBLAST,
OT_S_CLOUDKILL, OT_S_CLOUDKILL,
OT_S_WINDSHIELD,
// -- elemental - fire // -- elemental - fire
OT_S_SPARK, OT_S_SPARK,
OT_S_FIREDART, OT_S_FIREDART,
@ -869,6 +876,7 @@ enum OBTYPE {
OT_A_EMPLOY, OT_A_EMPLOY,
OT_A_HEAVYBLOW, OT_A_HEAVYBLOW,
OT_A_INSPECT, OT_A_INSPECT,
OT_A_POLYREVERT,
OT_A_STINGACID, // need to define dam in f_canwill OT_A_STINGACID, // need to define dam in f_canwill
// wands // wands
OT_WAND_COLD, OT_WAND_COLD,
@ -989,16 +997,23 @@ enum OBTYPE {
OT_BUCKLER, OT_BUCKLER,
OT_SHIELD, OT_SHIELD,
OT_SHIELDLARGE, OT_SHIELDLARGE,
OT_SHIELDTOWER,
// rings // rings
OT_RING_INVIS, OT_RING_INVIS,
OT_RING_INVULN, OT_RING_INVULN,
OT_RING_LUCK, OT_RING_LUCK,
OT_RING_CONTROL,
OT_RING_CON,
OT_RING_DEX,
OT_RING_IQ,
OT_RING_STR,
OT_RING_MANA, OT_RING_MANA,
OT_RING_MIRACLES,
OT_RING_MPREGEN, OT_RING_MPREGEN,
OT_RING_PROTFIRE, OT_RING_PROTFIRE,
OT_RING_REGENERATION, OT_RING_REGENERATION,
OT_RING_RESISTMAG, OT_RING_RESISTMAG,
OT_RING_SEEINVIS, OT_RING_SIGHT,
OT_RING_WOUNDING, OT_RING_WOUNDING,
// animal weapons // animal weapons
OT_CLAWS, OT_CLAWS,
@ -1021,48 +1036,57 @@ enum OBTYPE {
OT_JAVELIN, OT_JAVELIN,
OT_BULLET, OT_BULLET,
OT_RUBBERBULLET, OT_RUBBERBULLET,
// stabbing weapons // axes
OT_DAGGER,
OT_COMBATKNIFE,
OT_ORNDAGGER,
OT_RAPIER,
OT_TRIDENT,
OT_QUICKBLADE,
// chopping weapons
OT_AXE, OT_AXE,
OT_HANDAXE, OT_HANDAXE,
OT_BATTLEAXE, OT_BATTLEAXE,
OT_GREATAXE, OT_GREATAXE,
// slashing weapons // short blades
OT_COMBATKNIFE,
OT_DAGGER,
OT_KNIFE, OT_KNIFE,
OT_STEAKKNIFE, OT_ORNDAGGER,
OT_SCYTHE, OT_QUICKBLADE,
OT_RAPIER,
OT_SAI,
OT_SHORTSWORD, OT_SHORTSWORD,
OT_SCIMITAR, OT_STEAKKNIFE,
OT_LONGSWORD, OT_SICKLE,
// long swords
OT_FALCHION,
OT_GREATSWORD, OT_GREATSWORD,
OT_LONGSWORD,
OT_ORNSWORD, OT_ORNSWORD,
OT_SCIMITAR,
// polearms // polearms
OT_GLAIVE,
OT_GUISARME,
OT_HALBERD,
OT_LANCE,
OT_RANSEUR,
OT_SCYTHE,
OT_SPEAR, OT_SPEAR,
OT_TRIDENT,
// staves
OT_QUARTERSTAFF, OT_QUARTERSTAFF,
// bashing weapons // clubs
OT_STICK,
OT_SPANNER,
OT_CLUB, OT_CLUB,
OT_FLAIL, OT_FLAIL,
OT_FLAILHEAVY, OT_FLAILHEAVY,
OT_GREATCLUB,
OT_MACE, OT_MACE,
OT_MORNINGSTAR, OT_MORNINGSTAR,
OT_GREATCLUB, OT_NUNCHAKU,
OT_SICKLE, OT_SPANNER,
OT_STICK,
// projectile weapons // projectile weapons
OT_REVOLVER,
OT_SLING,
OT_BOW, OT_BOW,
OT_LONGBOW,
OT_CROSSBOW, OT_CROSSBOW,
OT_CROSSBOWHAND, OT_CROSSBOWHAND,
// holy weapons OT_LONGBOW,
OT_REVOLVER,
OT_SLING,
// special weapons
OT_HANDOFGOD, OT_HANDOFGOD,
@ -1087,7 +1111,7 @@ enum BODYPART {
#define MAXBODYPARTS (12) #define MAXBODYPARTS (12)
// empty types // empty types
#define WE_NOTSOLID 1 #define WE_WALKABLE 1
#define WE_EMPTY 2 #define WE_EMPTY 2
#define WE_PORTAL 3 #define WE_PORTAL 3
@ -1126,6 +1150,7 @@ enum FLAG {
F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold) F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold)
F_CONTAINSOB, // for vending machiens. v0 is ob letter F_CONTAINSOB, // for vending machiens. v0 is ob letter
// text is an object it contains. // text is an object it contains.
F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc
// for items in shops // for items in shops
F_SHOPITEM, // causes shops to show this item as identified F_SHOPITEM, // causes shops to show this item as identified
F_VALUE, // how much an item is worth (over its base weight+material) F_VALUE, // how much an item is worth (over its base weight+material)
@ -1148,6 +1173,7 @@ enum FLAG {
F_DIECONVERTTEXTPL, // text when the object converts, if there are more than 1. eg. "melt" F_DIECONVERTTEXTPL, // text when the object converts, if there are more than 1. eg. "melt"
F_DIECONVERT, // val0 = what this turns into when dying F_DIECONVERT, // val0 = what this turns into when dying
F_NOBLESS, // can't be blessed or cursed F_NOBLESS, // can't be blessed or cursed
F_NOQUALITY, // can't be masterwork / shoddy
F_CORPSEOF, // this is a corpse of montype val0. F_CORPSEOF, // this is a corpse of montype val0.
F_DTCONVERT, // damtype val0 converts this to f->text F_DTCONVERT, // damtype val0 converts this to f->text
F_NODTCONVERT, // overrides DTCONVERT . F_NODTCONVERT, // overrides DTCONVERT .
@ -1245,6 +1271,8 @@ enum FLAG {
F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better) F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better)
F_ARMOURPIERCE, // goes through armour F_ARMOURPIERCE, // goes through armour
F_TWOHANDED, // weapon uses two hands to weild F_TWOHANDED, // weapon uses two hands to weild
F_TRIPATTACK, // weapon can trip the victim
F_DISARMATTACK, // weapon can disarm the victim
F_FIREARM, // this weapon is equipped in bp_secweapon, not _weapon. F_FIREARM, // this weapon is equipped in bp_secweapon, not _weapon.
F_FIRESPEED, // how fast this weapon shoots projectiles F_FIRESPEED, // how fast this weapon shoots projectiles
F_AMMOOB, // what object this weapon fires F_AMMOOB, // what object this weapon fires
@ -1286,9 +1314,13 @@ enum FLAG {
F_WALKDAM, // val0 = damtype, text = dam per sec F_WALKDAM, // val0 = damtype, text = dam per sec
// abilities // abilities
F_NEEDSGRAB, // this ability needs to to grab someone first. F_NEEDSGRAB, // this ability needs to to grab someone first.
F_NOANNOUNCE, // don't announce when you gain/lose this ability
// magic // magic
F_SPELLSCHOOL, // val0 = SPELLSCHOOL enum F_SPELLSCHOOL, // val0 = SPELLSCHOOL enum
F_SPELLLEVEL, // val0 = difficulty level of spell F_SPELLLEVEL, // val0 = difficulty level of spell
F_VARPOWER, // can cast this spell at variable power level
// for spells with this flag, the MP cost goes up
// based on the power level.
F_MAXPOWER, // val0 = max power of this spell (1-10) F_MAXPOWER, // val0 = max power of this spell (1-10)
F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2 F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2
F_ONGOING, // this spell has an ongoing cost F_ONGOING, // this spell has an ongoing cost
@ -1309,6 +1341,8 @@ enum FLAG {
F_DONEDARKMSG, // tells the game not to say 'it is very dark here' F_DONEDARKMSG, // tells the game not to say 'it is very dark here'
// lifeform flags / lf flags // lifeform flags / lf flags
F_DEBUG, // debugging enabled F_DEBUG, // debugging enabled
F_SHIELDPENALTY, // modify your accuracy by val0 due to a cumbersome
// shield
F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3 F_ATTRMOD, // modify attribute val0 by val1. ie. 0=A_STR,1=-3
F_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18 F_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18
F_SIZE, // val0 = lf size (enum LFSIZE) F_SIZE, // val0 = lf size (enum LFSIZE)
@ -1318,6 +1352,7 @@ enum FLAG {
F_RESTHEALMPAMT, // val0 = how many MP to gain after resting x turns F_RESTHEALMPAMT, // val0 = how many MP to gain after resting x turns
F_AUTOCMD, // val0 = how many times to repeat this 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_LASTCMD, // text[0] = last command performed, v0/1 = x/y of cell, v2=various
F_CANLEARN, // lf is able to learn skill val0
F_STARTOB, // val0 = %chance of starting with it, text = ob name F_STARTOB, // val0 = %chance of starting with it, text = ob name
// val1,2 = min/max amounts. if NA, min=max=1. // val1,2 = min/max amounts. if NA, min=max=1.
F_STARTSKILL, // val0 = skill id F_STARTSKILL, // val0 = skill id
@ -1333,6 +1368,8 @@ enum FLAG {
F_GUNTARGET, // current projectile weapon target F_GUNTARGET, // current projectile weapon target
F_CASTINGSPELL, // set while the player is casting a spell F_CASTINGSPELL, // set while the player is casting a spell
// v0 is spell id // v0 is spell id
F_AVOIDCURSEDOB, // for AI animals - they will avoid walking on obid 'text'
// (text is a long)
// ABILITY/SPELL FLAGS / ability flags / spell flags // ABILITY/SPELL FLAGS / ability flags / spell flags
F_FAILEDINSPECT, // lf has failed an inspect check for item id v0 F_FAILEDINSPECT, // lf has failed an inspect check for item id v0
F_BOOSTSPELL, // v0 is active boost spell F_BOOSTSPELL, // v0 is active boost spell
@ -1402,11 +1439,14 @@ enum FLAG {
// to the victim // to the victim
F_PHALANX, // gain v0 AR if v2 or more adj monsters matching f->text F_PHALANX, // gain v0 AR if v2 or more adj monsters matching f->text
// INTRINSICS // INTRINSICS
F_ARBOOST,// armour is magically boosted F_MAGICARMOUR,// armour is magically boosted. f->text is the description
// ie 'magic armour', 'force field'
F_ASLEEP, // is asleep F_ASLEEP, // is asleep
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn) F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
F_BLIND, // cannot see anything F_BLIND, // cannot see anything
F_CANCAST, // can cast the spell val0 (need MP) F_CANCAST, // can cast the spell val0 (need MP)
F_CANHEARLF, // you can hear lifeform id v0 (show their glyph)
// this flag does not get announced.
F_CANWILL, // can cast the spell/ability val0 without using MP F_CANWILL, // can cast the spell/ability val0 without using MP
// v1 is counter untiluse // v1 is counter untiluse
// v2 is what you need to use it // v2 is what you need to use it
@ -1416,8 +1456,11 @@ enum FLAG {
// dam:xdy+b; damage // dam:xdy+b; damage
// needgrab:xx; do you need to grab first? // needgrab:xx; do you need to grab first?
F_CHARMEDBY,// you've been charmed by lf id v0 F_CHARMEDBY,// you've been charmed by lf id v0
F_CONTROL,// you control polymorphs, teleports and createmonsters
F_DETECTAURAS, // autodetect bless/curse F_DETECTAURAS, // autodetect bless/curse
F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0 F_DETECTLIFE, // autodetect nearby lifeforms in orthogonal dist v0
// if v1 is true, actual lf glyphs are shown.
// otherwise just an indicative size is shown
F_DETECTMAGIC, // autodetect magic/special objects F_DETECTMAGIC, // autodetect magic/special objects
F_DETECTMETAL, // autodetect nearby metal F_DETECTMETAL, // autodetect nearby metal
F_DETECTOBS, // autodetect nearby obs in orthog dist v0 F_DETECTOBS, // autodetect nearby obs in orthog dist v0
@ -1467,6 +1510,8 @@ enum FLAG {
F_CANSEETHROUGHMAT, //val0=kind of material you can see through F_CANSEETHROUGHMAT, //val0=kind of material you can see through
F_SPRINTING, // v0=true: you are sprinting. false=you are tired F_SPRINTING, // v0=true: you are sprinting. false=you are tired
F_TIRED, // you are too tired to sprint F_TIRED, // you are too tired to sprint
F_WINDSHIELD,// has a windshield protecting against missiles of speed
// v0 or lower.
F_DODGES, // you dodge missed attacks F_DODGES, // you dodge missed attacks
F_NOTIME, // this lf's actions don't take time F_NOTIME, // this lf's actions don't take time
F_PERCEPTION, // v0 = 0-20. perception level. F_PERCEPTION, // v0 = 0-20. perception level.
@ -1584,6 +1629,8 @@ enum SPELLTARGET {
#define B_TRANSPARENT (-1) #define B_TRANSPARENT (-1)
#define B_TRANS (-1) #define B_TRANS (-1)
#define B_ALLOWEXPAND (-1)
#define B_NOEXPAND (0)
#define B_IFACTIVATED (-1) #define B_IFACTIVATED (-1)
@ -1857,6 +1904,7 @@ enum SKILL {
SK_LOCKPICKING, SK_LOCKPICKING,
SK_MAGITEMUSAGE, SK_MAGITEMUSAGE,
SK_RESEARCH, SK_RESEARCH,
SK_SHIELDS,
SK_SPELLCASTING, SK_SPELLCASTING,
SK_STEALTH, SK_STEALTH,
SK_TECHUSAGE, SK_TECHUSAGE,
@ -1883,7 +1931,7 @@ enum SKILL {
SK_SS_TRANSLOCATION, SK_SS_TRANSLOCATION,
SK_SS_WILD, SK_SS_WILD,
}; };
#define MAXSKILLS 31 #define MAXSKILLS 32
// proficiency levels // proficiency levels
enum SKILLLEVEL { enum SKILLLEVEL {

View File

@ -6,6 +6,8 @@ in objcets.c:
update getdamnamenoun() - eg. you are immune to "electricity" update getdamnamenoun() - eg. you are immune to "electricity"
in attack.c in attack.c
update isphysicaldam()
update getattackverb if required update getattackverb if required
update getkillverb if required update getkillverb if required
@ -14,3 +16,4 @@ in attack.c
ie. hitting a door with DT_CHOP won't damage the weapon ie. hitting a door with DT_CHOP won't damage the weapon
ie. hitting a door with DT_SLASH _will_ damage the weapon ie. hitting a door with DT_SLASH _will_ damage the weapon

4
flag.c
View File

@ -342,7 +342,9 @@ void killflag(flag_t *f) {
// we will revert to our original form at the end of timeeffectslf(). // we will revert to our original form at the end of timeeffectslf().
if (lf && (f->id == F_POLYMORPHED)) { if (lf && (f->id == F_POLYMORPHED)) {
lf->polyrevert = B_TRUE; if (lfhasflag(lf, F_ORIGRACE)) {
lf->polyrevert = B_TRUE;
}
} }
// free mem // free mem

662
io.c

File diff suppressed because it is too large Load Diff

11
io.h
View File

@ -14,14 +14,14 @@ int announceobflaggain(object_t *o, flag_t *f);
void announceobflagloss(object_t *o, flag_t *f); void announceobflagloss(object_t *o, flag_t *f);
object_t *askobject(obpile_t *op, char *title, int *count, long opts); object_t *askobject(obpile_t *op, char *title, int *count, long opts);
object_t *askobjectwithflag(obpile_t *op, char *title, int *count, long opts, enum FLAG withflag); object_t *askobjectwithflag(obpile_t *op, char *title, int *count, long opts, enum FLAG withflag);
object_t *askobjectofclass(obpile_t *op, char *title, int *count, long opts, enum OBCLASS obclass); object_t *doaskobject(obpile_t *op, char *title, int *count, long opts, ...);
object_t *doaskobject(obpile_t *op, char *title, int *count, long opts, enum FLAG withflag, ...);
int askobjectmulti(obpile_t *op, char *prompt, long opts); int askobjectmulti(obpile_t *op, char *prompt, long opts);
char askchar(char *prompt, char *validchars, char *def, int showchars); char askchar(char *prompt, char *validchars, char *def, int showchars);
cell_t *askcoords(char *prompt, int targettype); cell_t *askcoords(char *prompt, int targettype);
char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def); char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def);
void centre(WINDOW *win, int y, char *format, ... ); void centre(WINDOW *win, int y, char *format, ... );
int chartodir(char ch); int chartodir(char ch);
char checkforkey(void);
int cleanupgfx(void); int cleanupgfx(void);
void clearmsg(void); void clearmsg(void);
void real_clearmsg(int force); void real_clearmsg(int force);
@ -35,7 +35,7 @@ void docomms(void);
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst); void dodrop(obpile_t *op, int wantmulti, obpile_t *dst);
void doeat(obpile_t *op); void doeat(obpile_t *op);
void doenter(lifeform_t *lf); void doenter(lifeform_t *lf);
void doexplain(void); void doexplain(char *question);
void dofinaloblist(obpile_t *op); void dofinaloblist(obpile_t *op);
void dofire(void); void dofire(void);
void dohelp(void); void dohelp(void);
@ -63,8 +63,8 @@ int dowear(obpile_t *op);
int doweild(obpile_t *op); int doweild(obpile_t *op);
int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar); int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar);
void drawglyph(glyph_t *g, int x, int y); void drawglyph(glyph_t *g, int x, int y);
void drawunviscell(cell_t *cell, int x, int y); //void drawunviscell(cell_t *cell, int x, int y);
void drawcellwithcontents(cell_t *cell, int x, int y); //void drawcellwithcontents(cell_t *cell, int x, int y);
void drawcursor(void); void drawcursor(void);
void drawlevelfor(lifeform_t *lf); void drawlevelfor(lifeform_t *lf);
void drawmsg(void); void drawmsg(void);
@ -79,6 +79,7 @@ void doheading(WINDOW *win, int *y, int x, char *what);
void initgfx(void); void initgfx(void);
void initprompt(prompt_t *p, char *q1); void initprompt(prompt_t *p, char *q1);
int keycodetokey(int keycode); int keycodetokey(int keycode);
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters);
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2); void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2);
void more(void); void more(void);
void warn(char *format, ... ); void warn(char *format, ... );

931
lf.c

File diff suppressed because it is too large Load Diff

12
lf.h
View File

@ -19,6 +19,7 @@ int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost);
int candrink(lifeform_t *lf, object_t *o); int candrink(lifeform_t *lf, object_t *o);
int caneat(lifeform_t *lf, object_t *o); int caneat(lifeform_t *lf, object_t *o);
int canhear(lifeform_t *lf, cell_t *c); int canhear(lifeform_t *lf, cell_t *c);
int canlearn(lifeform_t *lf, enum SKILL skid);
int canpickup(lifeform_t *lf, object_t *o, int amt); int canpickup(lifeform_t *lf, object_t *o, int amt);
int canpush(lifeform_t *lf, object_t *o, int dir); int canpush(lifeform_t *lf, object_t *o, int dir);
int canquaff(lifeform_t *lf, object_t *o); int canquaff(lifeform_t *lf, object_t *o);
@ -35,6 +36,7 @@ void dumpxp(void);
int eat(lifeform_t *lf, object_t *o); int eat(lifeform_t *lf, object_t *o);
void enhanceskills(lifeform_t *lf); void enhanceskills(lifeform_t *lf);
object_t *eyesshaded(lifeform_t *lf); object_t *eyesshaded(lifeform_t *lf);
int fall(lifeform_t *lf, int announce);
void fightback(lifeform_t *lf, lifeform_t *attacker); void fightback(lifeform_t *lf, lifeform_t *attacker);
job_t *findjob(enum JOB jobid); job_t *findjob(enum JOB jobid);
job_t *findjobbyname(char *name); job_t *findjobbyname(char *name);
@ -104,7 +106,7 @@ char *getplayernamefull(char *buf);
int getracerarity(enum RACE rid); int getracerarity(enum RACE rid);
object_t *getrandomarmour(lifeform_t *lf); object_t *getrandomarmour(lifeform_t *lf);
//int getrandommonlevel(int depth); //int getrandommonlevel(int depth);
race_t *getrandomrace(map_t *map); race_t *getrandomrace(map_t *map, int forcedepth);
race_t *getreallyrandomrace(void); race_t *getreallyrandomrace(void);
enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id); enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id);
char *getspeedname(int speed, char *buf); char *getspeedname(int speed, char *buf);
@ -135,7 +137,8 @@ flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int
int lockpick(lifeform_t *lf, object_t *target, object_t *device); int lockpick(lifeform_t *lf, object_t *target, object_t *device);
void loseobflags(lifeform_t *lf, object_t *o, int kind); void loseobflags(lifeform_t *lf, object_t *o, int kind);
int hasbp(lifeform_t *lf, enum BODYPART bp); int hasbp(lifeform_t *lf, enum BODYPART bp);
int haslof(lifeform_t *viewer, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest); flag_t *hasactivespell(lifeform_t *lf, enum OBTYPE sid);
int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest);
int haslos(lifeform_t *viewer, cell_t *dest); int haslos(lifeform_t *viewer, cell_t *dest);
void initjobs(void); void initjobs(void);
void initrace(void); void initrace(void);
@ -162,8 +165,10 @@ flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt);
void killjob(job_t *job); void killjob(job_t *job);
void killlf(lifeform_t *lf); void killlf(lifeform_t *lf);
void killrace(race_t *race); void killrace(race_t *race);
void loseconcentration(lifeform_t *lf);
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc); int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc);
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam); int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam);
void losemp(lifeform_t *lf, int amt);
void makefriendly(lifeform_t *lf, int howlong); void makefriendly(lifeform_t *lf, int howlong);
void makenauseated(lifeform_t *lf, int amt, int howlong); void makenauseated(lifeform_t *lf, int amt, int howlong);
void makenoise(lifeform_t *lf, enum NOISETYPE nid); void makenoise(lifeform_t *lf, enum NOISETYPE nid);
@ -175,6 +180,8 @@ float modifybystat(float num, lifeform_t *lf, enum ATTRIB att);
void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext); void noise(cell_t *c, lifeform_t *noisemaker, char *text, char *seetext);
void outfitlf(lifeform_t *lf); void outfitlf(lifeform_t *lf);
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground); int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground);
void poison(lifeform_t *lf, int howlong, char *fromwhat);
int poisonthreatenslife(lifeform_t *lf);
void practice(lifeform_t *lf, enum SKILL skid); void practice(lifeform_t *lf, enum SKILL skid);
void precalclos(lifeform_t *lf); void precalclos(lifeform_t *lf);
int push(lifeform_t *lf, object_t *o, int dir); int push(lifeform_t *lf, object_t *o, int dir);
@ -211,6 +218,7 @@ void turneffectslf(lifeform_t *lf);
int touch(lifeform_t *lf, object_t *o); int touch(lifeform_t *lf, object_t *o);
int unweild(lifeform_t *lf, object_t *o); int unweild(lifeform_t *lf, object_t *o);
int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where); int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where);
int useringofmiracles(lifeform_t *lf, int charges);
int usestairs(lifeform_t *lf, object_t *o); int usestairs(lifeform_t *lf, object_t *o);
int validateraces(void); int validateraces(void);
int wear(lifeform_t *lf, object_t *o); int wear(lifeform_t *lf, object_t *o);

525
log.txt
View File

@ -8,190 +8,6 @@ xxx
xxx xxx
xxx xxx
xxx xxx
xxx
xxx
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85
-> possibility: troglodyte, rarity=85
-> possibility: xat, rarity=90
-> possibility: giant bat, rarity=90
-> possibility: giant worker ant, rarity=85
-> possibility: giant newt, rarity=100
-> possibility: giant rat, rarity=90
-> possibility: brown snake, rarity=85
-> possibility: giant fly, rarity=85
-> possibility: glowbug, rarity=85
got 10 possibilities.
finding random lf with rarity val 85-100 finding random lf with rarity val 85-100
-> possibility: goblin, rarity=85 -> possibility: goblin, rarity=85
@ -388,239 +204,118 @@ finding random lf with rarity val 85-100
-> possibility: glowbug, rarity=85 -> possibility: glowbug, rarity=85
got 10 possibilities. got 10 possibilities.
rollhitdice() - rolling 2d4 + 2 rollhitdice() - rolling 2d4 + 2
rollhitdice() - mod is +-5% rollhitdice() - mod is +32%
rollhitdice() ---- die 1/2 == 4 rollhitdice() ---- die 1/2 == 4
rollhitdice() ---- die 2/2 == 4 rollhitdice() ---- die 2/2 == 4
TOTAL: 8 TOTAL: 8
-> modified to: 8 -> modified to: 10
givejob() starting. givejob() starting.
processing normal flag: 191 processing normal flag: 200
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 149 processing normal flag: 157
processing normal flag: 150 processing normal flag: 158
processing normal flag: 150 processing normal flag: 158
processing normal flag: 150 processing normal flag: 158
processing normal flag: 150 processing normal flag: 158
processing normal flag: 150 processing normal flag: 158
processing normal flag: 150 processing normal flag: 158
processing normal flag: 219 processing normal flag: 156
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 219 processing normal flag: 229
processing normal flag: 218 processing normal flag: 229
processing normal flag: 218 processing normal flag: 229
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
processing normal flag: 218 processing normal flag: 227
nclasses is 0 processing normal flag: 227
nclasses is 0 processing normal flag: 227
nclasses is 0 processing normal flag: 227
nclasses is 0 nwantflags is 1
nclasses is 0 nwantflags is 0
nclasses is 0
initial dam[0] = 1
adjusted for lf to dam[0] = 1
reduced by armour to dam[0] = 0
initial dam[0] = 1
adjusted for lf to dam[0] = 1
reduced by armour to dam[0] = 0
initial dam[0] = 26
heavy blow makes dam[0] = 39
adjusted for lf to dam[0] = 39
reduced by armour to dam[0] = 39
initial dam[1] = 10
heavy blow makes dam[1] = 15
adjusted for lf to dam[1] = 15
reduced by armour to dam[1] = 15
nclasses is 0
nclasses is 0
initial dam[0] = 19
heavy blow makes dam[0] = 28
adjusted for lf to dam[0] = 28
reduced by armour to dam[0] = 23
initial dam[1] = 6
heavy blow makes dam[1] = 9
adjusted for lf to dam[1] = 4
reduced by armour to dam[1] = 3
nclasses is 0
nclasses is 0
initial dam[0] = 2
adjusted for lf to dam[0] = 2
reduced by armour to dam[0] = 1
initial dam[0] = 0
adjusted for lf to dam[0] = 0
reduced by armour to dam[0] = 0
initial dam[0] = 2
adjusted for lf to dam[0] = 2
reduced by armour to dam[0] = 1
initial dam[0] = 4
adjusted for lf to dam[0] = 4
reduced by armour to dam[0] = 2
initial dam[0] = 1
adjusted for lf to dam[0] = 1
reduced by armour to dam[0] = 0
initial dam[0] = 2
adjusted for lf to dam[0] = 2
reduced by armour to dam[0] = 1
initial dam[0] = 2
adjusted for lf to dam[0] = 2
reduced by armour to dam[0] = 1
initial dam[0] = 30
heavy blow makes dam[0] = 45
adjusted for lf to dam[0] = 45
reduced by armour to dam[0] = 45
initial dam[1] = 3
heavy blow makes dam[1] = 4
adjusted for lf to dam[1] = 4
reduced by armour to dam[1] = 4
rollhitdice() - rolling 49d4 + 0
rollhitdice() - mod is +22%
rollhitdice() ---- die 1/49 == 1
rollhitdice() ---- die 2/49 == 1
rollhitdice() ---- die 3/49 == 2
rollhitdice() ---- die 4/49 == 2
rollhitdice() ---- die 5/49 == 4
rollhitdice() ---- die 6/49 == 2
rollhitdice() ---- die 7/49 == 3
rollhitdice() ---- die 8/49 == 4
rollhitdice() ---- die 9/49 == 4
rollhitdice() ---- die 10/49 == 2
rollhitdice() ---- die 11/49 == 1
rollhitdice() ---- die 12/49 == 3
rollhitdice() ---- die 13/49 == 1
rollhitdice() ---- die 14/49 == 1
rollhitdice() ---- die 15/49 == 4
rollhitdice() ---- die 16/49 == 1
rollhitdice() ---- die 17/49 == 3
rollhitdice() ---- die 18/49 == 3
rollhitdice() ---- die 19/49 == 4
rollhitdice() ---- die 20/49 == 4
rollhitdice() ---- die 21/49 == 1
rollhitdice() ---- die 22/49 == 4
rollhitdice() ---- die 23/49 == 1
rollhitdice() ---- die 24/49 == 3
rollhitdice() ---- die 25/49 == 3
rollhitdice() ---- die 26/49 == 1
rollhitdice() ---- die 27/49 == 2
rollhitdice() ---- die 28/49 == 2
rollhitdice() ---- die 29/49 == 4
rollhitdice() ---- die 30/49 == 1
rollhitdice() ---- die 31/49 == 1
rollhitdice() ---- die 32/49 == 1
rollhitdice() ---- die 33/49 == 3
rollhitdice() ---- die 34/49 == 1
rollhitdice() ---- die 35/49 == 4
rollhitdice() ---- die 36/49 == 3
rollhitdice() ---- die 37/49 == 2
rollhitdice() ---- die 38/49 == 3
rollhitdice() ---- die 39/49 == 3
rollhitdice() ---- die 40/49 == 3
rollhitdice() ---- die 41/49 == 4
rollhitdice() ---- die 42/49 == 1
rollhitdice() ---- die 43/49 == 2
rollhitdice() ---- die 44/49 == 2
rollhitdice() ---- die 45/49 == 1
rollhitdice() ---- die 46/49 == 3
rollhitdice() ---- die 47/49 == 3
rollhitdice() ---- die 48/49 == 1
rollhitdice() ---- die 49/49 == 2
TOTAL: 115
-> modified to: 140
initial dam[0] = 0
adjusted for lf to dam[0] = 0
reduced by armour to dam[0] = 0
initial dam[0] = 19
heavy blow makes dam[0] = 28
adjusted for lf to dam[0] = 28
reduced by armour to dam[0] = 28
initial dam[1] = 11
heavy blow makes dam[1] = 16
adjusted for lf to dam[1] = 16
reduced by armour to dam[1] = 16
nclasses is 1

209
map.c
View File

@ -90,7 +90,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
} }
if ((raceid == R_NONE) || (raceid == R_RANDOM)) { if ((raceid == R_NONE) || (raceid == R_RANDOM)) {
r = getrandomrace(c->map); r = getrandomrace(c->map, 0);
} else { } else {
r = findrace(raceid); r = findrace(raceid);
} }
@ -147,7 +147,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
// starting with the first one // starting with the first one
adjcell = NULL; adjcell = NULL;
for (n = 0; n < nmoncells; n++) { for (n = 0; n < nmoncells; n++) {
adjcell = getrandomadjcell(moncell[n], WE_NOTSOLID); adjcell = getrandomadjcell(moncell[n], WE_WALKABLE, B_ALLOWEXPAND);
if (adjcell) break; if (adjcell) break;
} }
// did we find one? // did we find one?
@ -172,7 +172,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt) {
// sometimes give the lf random objects (extra monsters through // sometimes give the lf random objects (extra monsters through
// 'numappears' don't get them. // 'numappears' don't get them.
if (!lfhasflag(lf, F_NOPACK)) { if (lfhasflag(lf, F_HUMANOID) && !lfhasflag(lf, F_NOPACK)) {
if (rnd(1,3) == 1) { if (rnd(1,3) == 1) {
int nobs = rnd(1,3); int nobs = rnd(1,3);
char buf[BUFLEN]; char buf[BUFLEN];
@ -360,6 +360,89 @@ int getcelldistorth(cell_t *src, cell_t *dst) { // add x/y
return abs(dst->x - src->x) + abs(dst->y - src->y); return abs(dst->x - src->x) + abs(dst->y - src->y);
} }
//populates 'g' with the contects of cell 'c', as seen by 'viewer'
// if we can't see anything there, set g->ch to NUL.
void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
glyph_t tempgl;
// default
g->ch = '\0';
if (haslos(viewer, c)) {
// show cell contents
//drawcellwithcontents(cell, x-viewx, y-viewy);
if (c->lf && cansee(viewer, c->lf)) { // lifeform here which we can see
// draw the lf's race glyph
*g = *(getlfglyph(c->lf));
return;
} else { // we can see the floor here
void *thing;
// scanned lf here?
if (isinscanrange(c, &thing, NULL, &tempgl) == TT_MONSTER) {
*g = tempgl;
//mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph);
//drawglyph(&glyph, x, y);
return;
}
}
// objects here?
if ((countobs(c->obpile) > 0)) {
object_t *o;
// draw highest object in sort order
o = gettopobject(c);
if (o) {
*g = *(getglyph(o));
} else {
// should never happen. if it does, just show the
// first object
dblog("Warn: sorted object glyph drawing matching nothing!");
//mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph);
//drawglyph(&cell->obpile->first->type->obclass->glyph, x, y);
*g = c->obpile->first->type->obclass->glyph;
}
} else {
// draw cell normally
//drawcell(cell, x, y);
*g = c->type->glyph;
}
} else { // can't see the cell
void *thing;
//drawscannedcell(cell, x-viewx, y-viewy);
switch (isinscanrange(c, &thing, NULL, &tempgl)) {
case TT_MONSTER:
case TT_OBJECT:
*g = tempgl;
break;
default:
if (c->known) {
//drawunviscell(cell, x-viewx, y-viewy);
object_t *o;
// copy from cell
*g = c->type->glyph;
if (g->ch == '.') {
g->ch = ' ';
}
// show staircases...
o = hasobwithflag(c->obpile, F_CLIMBABLE);
if (o) {
*g = *(getglyph(o));
}
// show dungeon features
o = hasobofclass(c->obpile, OC_DFEATURE);
if (o) {
*g = *(getglyph(o));
}
}
break;
}
}
}
enum CELLTYPE getemptycelltype(enum HABITAT hab) { enum CELLTYPE getemptycelltype(enum HABITAT hab) {
switch (hab) { switch (hab) {
case H_DUNGEON: case H_DUNGEON:
@ -1785,41 +1868,62 @@ int getobchance(int habitat) {
return 0; return 0;
} }
cell_t *getrandomadjcell(cell_t *c, int wantempty) { cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) {
int dir; int radius = 1;
int ntries = 0; int x,y;
cell_t *poss[MAXCANDIDATES];
int nposs = 0;
cell_t *new; cell_t *new;
dir = getrandomdir(DT_COMPASS); int done = B_FALSE;
while (ntries < 8) {
new = getcellindir(c, dir); while (!done) {
if (new) { int numwithlof = 0;
if (wantempty == WE_EMPTY) { for (y = c->y - radius ; y <= c->y + radius ; y++) {
// make sure it's empty for (x = c->x - radius ; x <= c->x + radius ; x++) {
if (isempty(new)) { new = getcellat(c->map, x, y);
return new; if (new && (getcelldist(c,new) == radius) && haslof(c, new, LOF_WALLSTOP, NULL)) {
} numwithlof++;
} else if (wantempty == WE_NOTSOLID) { if (wantempty == WE_EMPTY) {
if (cellwalkable(NULL, new, NULL)) { // make sure it's empty
return new; if (isempty(new)) {
} poss[nposs++] = new;
} else if (wantempty == WE_PORTAL) { }
if (cellwalkable(NULL, new, NULL) && !hasenterableobject(new) ) { } else if (wantempty == WE_WALKABLE) {
if (!hasobwithflag(new->obpile, F_DOOR)) { if (cellwalkable(NULL, new, NULL)) {
return new; poss[nposs++] = new;
}
} else if (wantempty == WE_PORTAL) {
if (cellwalkable(NULL, new, NULL) && !hasenterableobject(new) ) {
if (!hasobwithflag(new->obpile, F_DOOR)) {
poss[nposs++] = new;
}
}
} else {
// always ok
poss[nposs++] = new;
} }
} }
} else {
// always ok
return new;
} }
} }
// not found yet...
dir++; // found any possibilities ?
if (dir > DC_NW) dir = DC_N; if (nposs) {
ntries++; done = B_TRUE;
} else {
if (allowexpand) {
if (numwithlof) {
// increment radius
radius++;
} else {
return NULL;
}
} else {
return NULL;
}
}
} }
return NULL; return poss[rnd(0,nposs-1)];
} }
cell_t *getrandomcell(map_t *map) { cell_t *getrandomcell(map_t *map) {
@ -1985,15 +2089,25 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
if (c->lf) { if (c->lf) {
if (getcelldistorth(player->cell, c) <= f->val[0]) { if (getcelldistorth(player->cell, c) <= f->val[0]) {
*thing = c->lf; *thing = c->lf;
if (desc) { if (f->val[1] == B_TRUE) {
char *p; if (desc) {
p = getsizetext(getlfsize(c->lf)); real_getlfnamea(c->lf, desc, B_FALSE);
sprintf(desc, "%s %s monster", isvowel(*p) ? "an" : "a", p); strcat(desc, " (detected)");
} }
if (glyph) { if (glyph) {
// select glyph based on size *glyph = *(getlfglyph(c->lf));
glyph->ch = '0' + ((int) getlfsize(c->lf)); }
glyph->colour = C_GREY; } else {
if (desc) {
char *p;
p = getsizetext(getlfsize(c->lf));
sprintf(desc, "%s %s monster", isvowel(*p) ? "an" : "a", p);
}
if (glyph) {
// select glyph based on size
glyph->ch = '0' + ((int) getlfsize(c->lf));
glyph->colour = C_GREY;
}
} }
return TT_MONSTER; return TT_MONSTER;
} }
@ -2026,6 +2140,21 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
} }
} }
} }
// can hear them using master level listen skill?
if (c->lf && lfhasflagval(player, F_CANHEARLF, c->lf->id, NA, NA, NULL)) {
if (glyph) {
*glyph = *(getlfglyph(c->lf));
}
if (desc) {
real_getlfnamea(c->lf, desc, B_FALSE);
strcat(desc, " (heard)");
}
*thing = c->lf;
return TT_MONSTER;
}
f = lfhasflag(player, F_DETECTOBS); f = lfhasflag(player, F_DETECTOBS);
if (f) { if (f) {
if (getcelldistorth(player->cell, c) <= f->val[0]) { if (getcelldistorth(player->cell, c) <= f->val[0]) {

3
map.h
View File

@ -9,6 +9,7 @@ int cellhaslos(cell_t *c1, cell_t *dest);
cell_t *getcellat(map_t *map, int x, int y); cell_t *getcellat(map_t *map, int x, int y);
int getcelldist(cell_t *src, cell_t *dst); int getcelldist(cell_t *src, cell_t *dst);
int getcelldistorth(cell_t *src, cell_t *dst); int getcelldistorth(cell_t *src, cell_t *dst);
void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer);
enum CELLTYPE getemptycelltype(enum HABITAT hab); enum CELLTYPE getemptycelltype(enum HABITAT hab);
object_t *gettopobject(cell_t *where); object_t *gettopobject(cell_t *where);
void calclight(map_t *map); void calclight(map_t *map);
@ -30,7 +31,7 @@ void forgetcells(map_t *map, int amt);
cell_t *getcellindir(cell_t *cell, int dir); cell_t *getcellindir(cell_t *cell, int dir);
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved); int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
int getobchance(int habitat); int getobchance(int habitat);
cell_t *getrandomadjcell(cell_t *c, int wantempty); cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
cell_t *getrandomcell(map_t *map); cell_t *getrandomcell(map_t *map);
cell_t *getrandomcelloftype(map_t *map, int id); cell_t *getrandomcelloftype(map_t *map, int id);
int getrandomdir(int dirtype); int getrandomdir(int dirtype);

41
move.c
View File

@ -1093,7 +1093,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
return B_TRUE; return B_TRUE;
} }
if (!haslof(lf, dst, B_FALSE, &newdst)) { if (!haslof(lf->cell, dst, B_FALSE, &newdst)) {
if (newdst) { if (newdst) {
// update destination // update destination
dst = newdst; dst = newdst;
@ -1170,6 +1170,13 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
int slip; int slip;
// check for cursed objects + animals // check for cursed objects + animals
// do this AFTER checking if we will move, so that
// they will actually try the move and fail (this lets
// the player find out about the cursed object).
//
// note however that if a monster is chasing a player (ie
// has F_TARGET,player) then they will simply avoid the cursed
// object rather than failing the movement.
for (o = cell->obpile->first ; o ; o = o->next) { for (o = cell->obpile->first ; o ; o = o->next) {
if (!isplayer(lf)) { if (!isplayer(lf)) {
if (o->blessed == B_CURSED) { if (o->blessed == B_CURSED) {
@ -1184,6 +1191,9 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} }
taketime(lf, getmovespeed(lf)); taketime(lf, getmovespeed(lf));
reason = E_OK; reason = E_OK;
// avoid this object in future
sprintf(buf, "%ld",o->id);
addflag(lf->flags, F_AVOIDCURSEDOB, NA, NA, NA, buf);
return B_FALSE; return B_FALSE;
} }
} }
@ -1225,7 +1235,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
moveto(lf, cell, onpurpose); moveto(lf, cell, onpurpose);
taketime(lf, getmovespeed(lf)); taketime(lf, getmovespeed(lf));
} else { } else {
object_t *inway; object_t *inway = NULL;
int door, dooropen; int door, dooropen;
reason = errcode; reason = errcode;
switch (errcode) { switch (errcode) {
@ -1313,8 +1323,8 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} }
} }
} }
} else { // object is in the way } else { // somethign random is in the way
if (lf->controller == C_PLAYER) { if (isplayer(lf) && inway) {
char obname[BUFLEN]; char obname[BUFLEN];
getobname(inway, obname, 1); getobname(inway, obname, 1);
msg("There is %s in your way.",obname); msg("There is %s in your way.",obname);
@ -1406,6 +1416,8 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
int willmove(lifeform_t *lf, int dir, enum ERROR *error) { int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
cell_t *cell; cell_t *cell;
enum IQBRACKET iq; enum IQBRACKET iq;
object_t *o;
char buf[BUFLEN];
//object_t *o; //object_t *o;
iq = getiqname(getattr(lf, A_IQ), NULL); iq = getiqname(getattr(lf, A_IQ), NULL);
@ -1417,6 +1429,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
cell = getcellindir(lf->cell, dir); cell = getcellindir(lf->cell, dir);
if (celldangerous(lf, cell, B_TRUE, error)) { if (celldangerous(lf, cell, B_TRUE, error)) {
if (error) *error = E_WONT;
return B_FALSE; return B_FALSE;
} }
@ -1429,6 +1442,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
if (canswapwith(lf, cell->lf)) { if (canswapwith(lf, cell->lf)) {
return B_TRUE; return B_TRUE;
} }
if (error) *error = E_WONT;
return B_FALSE; return B_FALSE;
} }
} }
@ -1438,9 +1452,28 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
if (iq >= IQ_AVERAGE) { if (iq >= IQ_AVERAGE) {
// don't move if in pain // don't move if in pain
if (lfhasflag(lf, F_PAIN)) { if (lfhasflag(lf, F_PAIN)) {
if (error) *error = E_WONT;
return B_FALSE; return B_FALSE;
} }
} }
// look for avoided objects (because they are cursed).
for (o = cell->obpile->first ; o ; o = o->next) {
flag_t *f;
sprintf(buf, "%ld",o->id);
f = lfhasflagval(lf, F_AVOIDCURSEDOB, NA, NA, NA, buf);
if (f) {
// still cursed?
if (iscursed(o)) {
if (error) *error = E_WONT;
return B_FALSE;
} else {
// remove the flag.
killflag(f);
}
}
}
return B_TRUE; return B_TRUE;
} }

32
nexus.c
View File

@ -433,8 +433,14 @@ void donextturn(map_t *map) {
if (donormalmove) { if (donormalmove) {
f = hasflag(who->flags, F_RESTING); f = hasflag(who->flags, F_RESTING);
if (f) { if (f) {
rest(who, B_TRUE); // check for interrupt of resting...
donormalmove = B_FALSE; if (isplayer(who) && checkforkey()) {
msg("Stopped resting.");
killflag(f);
} else {
rest(who, B_TRUE);
donormalmove = B_FALSE;
}
} }
} }
@ -523,6 +529,25 @@ char *getdirname(int dir) {
return "?errordir?"; return "?errordir?";
} }
enum COLOUR getpctcol(float num, float max) {
float pct;
pct = (num / max) * 100;
if (pct > 100) {
return C_BOLDBLUE;
} else if (pct == 100) {
return C_BOLDGREEN;
} else if (pct >= 75) {
return C_GREEN;
} else if (pct >= 50) {
return C_BROWN;
} else if (pct >= 25) {
return C_RED;
} else { // ie. < 25%
return C_ORANGE;
}
return C_ORANGE;
}
void getrarity(int depth, int *min, int *max, int range) { void getrarity(int depth, int *min, int *max, int range) {
int mid; int mid;
mid = 100 - (depth * 3); mid = 100 - (depth * 3);
@ -752,6 +777,7 @@ float pctof(float pct, float num) {
return ((pct / 100.0) * num); return ((pct / 100.0) * num);
} }
// get a random number between min and max // get a random number between min and max
int rnd(int min, int max) { int rnd(int min, int max) {
int res; int res;
@ -1024,9 +1050,11 @@ void timeeffectsworld(map_t *map) {
//dblog("shuffling id %d %s timespent=%d -> %d",l->id,l->race->name, l->timespent, l->timespent - firstlftime); //dblog("shuffling id %d %s timespent=%d -> %d",l->id,l->race->name, l->timespent, l->timespent - firstlftime);
l->timespent -= firstlftime; l->timespent -= firstlftime;
assert(l->timespent >= 0); assert(l->timespent >= 0);
/*
if (isplayer(l)) { if (isplayer(l)) {
statdirty = B_TRUE; statdirty = B_TRUE;
} }
*/
} }
//dblog("after shuffle:"); //dblog("after shuffle:");

View File

@ -9,6 +9,7 @@ void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, in
void donextturn(map_t *map); void donextturn(map_t *map);
celltype_t *findcelltype(int id); celltype_t *findcelltype(int id);
char *getdirname(int dir); char *getdirname(int dir);
enum COLOUR getpctcol(float num, float max);
void getrarity(int depth, int *min, int *max, int range); void getrarity(int depth, int *min, int *max, int range);
int init(void); int init(void);
void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels); void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels);

817
objects.c

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@ obpile_t *addobpile(lifeform_t *owner, cell_t *where);
objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid); objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid);
void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat); void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat);
void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype); void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype);
int adjustshieldpenalty(lifeform_t *lf, float amt);
//void adjustprice(objecttype_t *ot, float *price ); //void adjustprice(objecttype_t *ot, float *price );
void appendinscription(object_t *o, char *text); void appendinscription(object_t *o, char *text);
void applyobmod(object_t *o, obmod_t *om); void applyobmod(object_t *o, obmod_t *om);
@ -77,6 +78,7 @@ int getnumshards(object_t *o);
int getnutritionbase(object_t *o); int getnutritionbase(object_t *o);
int getnutrition(object_t *o); int getnutrition(object_t *o);
char *getobdesc(object_t *o, char *buf); char *getobdesc(object_t *o, char *buf);
char *getobequipinfo(object_t *o, char *buf);
char *getobextrainfo(object_t *o, char *buf); char *getobextrainfo(object_t *o, char *buf);
cell_t *getoblocation(object_t *o); cell_t *getoblocation(object_t *o);
char *getobname(object_t *o, char *buf, int count); char *getobname(object_t *o, char *buf, int count);
@ -137,6 +139,7 @@ int ispourable(object_t *o);
int ispushable(object_t *o); int ispushable(object_t *o);
int isreadable(object_t *o); int isreadable(object_t *o);
int isrotting(object_t *o); int isrotting(object_t *o);
int isthrownmissile(object_t *o);
int isweapon(object_t *o); int isweapon(object_t *o);
int iswearable(object_t *o); int iswearable(object_t *o);
void killmaterial(material_t *m); void killmaterial(material_t *m);
@ -181,6 +184,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
void timeeffectsob(object_t *o); void timeeffectsob(object_t *o);
void turnoff(lifeform_t *lf, object_t *o); void turnoff(lifeform_t *lf, object_t *o);
void turnon(lifeform_t *lf, object_t *o); void turnon(lifeform_t *lf, object_t *o);
int uncurseob(object_t *o, int *seen);
int usecharge(object_t *o); int usecharge(object_t *o);
int validateobs(void); int validateobs(void);
int willshatter(enum MATERIAL mat); int willshatter(enum MATERIAL mat);

11
save.c
View File

@ -93,8 +93,10 @@ int loadflagpile(FILE *f, flagpile_t *fp) {
int loadknowledge(FILE *f) { int loadknowledge(FILE *f) {
int db = B_FALSE; int db = B_FALSE;
char buf[BUFLEN]; char buf[BUFLEN];
char line[BUFLEN];
int otid,known; int otid,known;
char hiddenname[BUFLEN]; char hiddenname[BUFLEN];
char *p,*dummy;
if (db) dblog("--> Loading knowledge...\n"); if (db) dblog("--> Loading knowledge...\n");
fscanf(f, "startknowledge\n"); fscanf(f, "startknowledge\n");
@ -102,7 +104,14 @@ int loadknowledge(FILE *f) {
buf[strlen(buf)-1] = '\0'; // strip newline buf[strlen(buf)-1] = '\0'; // strip newline
while (strcmp(buf, "endknowledge")) { while (strcmp(buf, "endknowledge")) {
sscanf(buf, "%d^%s^%d",&otid, hiddenname, &known); //sscanf(buf, "%d^%s^%d",&otid, hiddenname, &known);
strcpy(line, buf);
p = strtok_r(line, "^", &dummy);
otid = atoi(p);
p = strtok_r(NULL, "^", &dummy);
strcpy(hiddenname, p);
p = strtok_r(NULL, "^", &dummy);
known = atoi(p);
addknowledge(otid, hiddenname, known); addknowledge(otid, hiddenname, known);
// get next line // get next line
fgets(buf, BUFLEN, f); fgets(buf, BUFLEN, f);

210
spell.c
View File

@ -120,7 +120,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (!target) { if (!target) {
if (isplayer(user)) msg("There is nobody there!"); if (isplayer(user)) msg("There is nobody there!");
return TRUE; return TRUE;
} else if (!haslof(user, targcell, LOF_NEED, NULL)) { } else if (!haslof(user->cell, targcell, LOF_NEED, NULL)) {
if (isplayer(user)) msg("Your path there is blocked!"); if (isplayer(user)) msg("Your path there is blocked!");
return TRUE; return TRUE;
} }
@ -319,7 +319,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// TODO: if jumper is smaller, move them out of the way instead // TODO: if jumper is smaller, move them out of the way instead
// move them out of the way // move them out of the way
c = getrandomadjcell(victim->cell, WE_EMPTY); c = getrandomadjcell(victim->cell, WE_EMPTY, B_NOEXPAND);
// nowhere to move? move to player's cell! // nowhere to move? move to player's cell!
if (!c) { if (!c) {
c = user->cell; c = user->cell;
@ -405,7 +405,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
return B_TRUE; return B_TRUE;
} }
howlong = 5; howlong = 2;
// +2 for each athletics skill level // +2 for each athletics skill level
slev = getskill(user, SK_ATHLETICS); slev = getskill(user, SK_ATHLETICS);
if (slev > PR_INEPT) { if (slev > PR_INEPT) {
@ -436,6 +436,22 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// cause ongoing pain for 2 turns // cause ongoing pain for 2 turns
addtempflag(target->flags, F_PAIN, DT_ACID, NA, NA, damstr, 2); addtempflag(target->flags, F_PAIN, DT_ACID, NA, NA, damstr, 2);
taketime(user, getactspeed(user)); taketime(user, getactspeed(user));
} else if (abilid == OT_A_POLYREVERT) {
flag_t *f;
if (!target) target = user;
// take time
taketime(user, getactspeed(user));
f = lfhasflag(target, F_ORIGRACE);
if (!f) {
if (isplayer(user)) nothinghappens();
return B_FALSE;
}
// this call will also remove this ability...
setrace(user, f->val[0]);
} else if (abilid == OT_A_LEARN) { } else if (abilid == OT_A_LEARN) {
skill_t *sk; skill_t *sk;
char ch = 'a'; char ch = 'a';
@ -456,6 +472,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
sprintf(buf, "%s",getskilllevelname(i)); sprintf(buf, "%s",getskilllevelname(i));
addchoice(&prompt, ch++, buf, buf, NULL); addchoice(&prompt, ch++, buf, buf, NULL);
} }
if (prompt.nchoices <= 0) {
msg("You have already mastered this skill!");
return B_TRUE;
}
getchoice(&prompt); getchoice(&prompt);
while (strcmp(getskilllevelname(getskill(user, sk->id)), prompt.choice[prompt.selection].text)) { while (strcmp(getskilllevelname(getskill(user, sk->id)), prompt.choice[prompt.selection].text)) {
@ -1067,7 +1087,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y); targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) { if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell, B_FALSE, NULL)) { if (targcell->lf && (targcell->lf != caster) && haslof(caster->cell, targcell, B_FALSE, NULL)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
// automatic hit // automatic hit
getlfname(targcell->lf, lfname); getlfname(targcell->lf, lfname);
@ -1130,7 +1150,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else { } else {
// get random adjacent cell // get random adjacent cell
targcell = getrandomadjcell(caster->cell, WE_EMPTY); targcell = getrandomadjcell(caster->cell, WE_EMPTY, B_ALLOWEXPAND);
} }
} }
@ -1278,7 +1298,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int howlong,radius; int howlong,radius;
howlong = getspellduration(10,20,blessed) + (power*2); howlong = getspellduration(10,20,blessed) + (power*2);
radius = power * 10; radius = power * 10;
addtempflag(target->flags, F_DETECTLIFE, 10, NA, NA, NULL, howlong); addtempflag(target->flags, F_DETECTLIFE, 10, (power >= 5) ? B_TRUE : NA, NA, NULL, howlong);
} else { } else {
// monsters can't use this // monsters can't use this
} }
@ -1492,7 +1512,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y); targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldist(caster->cell, targcell) <= range)) { if (targcell && (getcelldist(caster->cell, targcell) <= range)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell, B_FALSE, NULL)) { if (targcell->lf && (targcell->lf != caster) && haslof(caster->cell, targcell, B_FALSE, NULL)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
// automatic hit // automatic hit
getlfname(targcell->lf, lfname); getlfname(targcell->lf, lfname);
@ -1578,6 +1598,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (o) { if (o) {
setobcreatedby(o, caster); setobcreatedby(o, caster);
} }
if (c->lf) {
losehp(c->lf, rolldie(power,4), DT_FIRE, caster, "a fireball");
}
} }
} }
for (dir = DC_NE; dir <= DC_NW; dir += 2) { for (dir = DC_NE; dir <= DC_NW; dir += 2) {
@ -1588,6 +1611,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (o) { if (o) {
setobcreatedby(o, caster); setobcreatedby(o, caster);
} }
if (c->lf) {
int ndice;
ndice = power / 2; if (ndice < 1) ndice = 1;
losehp(c->lf, rolldie(ndice,4), DT_FIRE, caster, "a fireball");
}
} }
} }
for (dir = D_N; dir <= D_W; dir++) { for (dir = D_N; dir <= D_W; dir++) {
@ -1600,6 +1628,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (o) { if (o) {
setobcreatedby(o, caster); setobcreatedby(o, caster);
} }
if (c->lf) {
int ndice;
ndice = power / 2; if (ndice < 1) ndice = 1;
losehp(c->lf, rolldie(ndice,2), DT_FIRE, caster, "a fireball");
}
} }
} }
} }
@ -1657,7 +1690,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// announce // announce
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
msg("%s emit%s a blast of fire!",castername,isplayer(caster) ? "" : "s"); msg("%s emit%s a %sblast of fire!",castername,isplayer(caster) ? "" : "s",
(power >= 5) ? "huge " : "");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
@ -1667,7 +1701,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) { for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y); targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) { if (targcell && (getcelldistorth(caster->cell, targcell) <= range)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster, targcell, B_FALSE, NULL)) { if (targcell->lf && (targcell->lf != caster) && haslof(caster->cell, targcell, B_FALSE, NULL)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
// automatic hit // automatic hit
getlfname(targcell->lf, lfname); getlfname(targcell->lf, lfname);
@ -1862,9 +1896,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster) || haslos(player, target->cell)) { if (isplayer(caster) || haslos(player, target->cell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
// if this is the player, remember the original race and job... // remember the original race
addflag(target->flags, F_ORIGRACE, target->race->id, NA, NA, NULL); addflag(target->flags, F_ORIGRACE, target->race->id, NA, NA, NULL);
// polymorph will be temporary... // polymorph is always will be temporary
addtempflag(target->flags, F_POLYMORPHED, B_TRUE, NA, NA, NULL, 10); addtempflag(target->flags, F_POLYMORPHED, B_TRUE, NA, NA, NULL, 10);
setrace(target, R_GASCLOUD); setrace(target, R_GASCLOUD);
} }
@ -2244,7 +2278,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
sprintf(buf, "Whose mind will you scan?"); sprintf(buf, "Whose mind will you scan?");
where = askcoords(buf, TT_MONSTER); where = askcoords(buf, TT_MONSTER);
if (where && haslos(caster, where) && haslf(where)) { if (where && haslos(caster, where) && haslf(where)) {
showlfstats(where->lf, B_TRUE); char targname[BUFLEN];
lifeform_t *oldplayer;
// temporarily change player pointer...
oldplayer = player;
player = where->lf;
//
getlfname(where->lf, targname);
sprintf(buf, "Mindscanning %s, ESC to quit.", targname);
doexplain(buf);
// restore player pointer
player = oldplayer;
//showlfstats(where->lf, B_TRUE);
} else { } else {
failed = B_TRUE; failed = B_TRUE;
} }
@ -2419,6 +2466,27 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
getlfname(target, targname); getlfname(target, targname);
// warn if it can't do magic
if (lfhasflag(target, F_NOSPELLS)) {
int cancel = B_FALSE;
if (isplayer(caster)) {
char buf[BUFLEN];
char ch;
sprintf(buf, "You may be stuck in %s%s body - proceed?", targname,
getpossessive(targname));
ch = askchar(buf, "yn", "n", B_TRUE);
if (ch != 'y') {
cancel = B_TRUE;
}
} else {
cancel = B_TRUE;
}
if (cancel) {
if (isplayer(caster)) msg("Cancelled.");
return B_TRUE;
}
}
// saving throw.... // saving throw....
if (skillcheck(target, SC_RESISTMAG, 20 + power*2, 0)) { if (skillcheck(target, SC_RESISTMAG, 20 + power*2, 0)) {
if (isplayer(caster) && cansee(player, target)) { if (isplayer(caster) && cansee(player, target)) {
@ -2473,7 +2541,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
targcell = caster->cell; targcell = caster->cell;
target = caster; target = caster;
f = addtempflag(caster->flags, F_ARBOOST, power*3, NA, NA, NULL, FROMSPELL); f = addtempflag(caster->flags, F_MAGICARMOUR, power*4, NA, NA, "psychic barrier", FROMSPELL);
f->obfrom = spellid; f->obfrom = spellid;
} else if (spellid == OT_S_PULL) { } else if (spellid == OT_S_PULL) {
if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_WALLSTOP, spellid, power)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_MONSTER, B_TRUE, LOF_WALLSTOP, spellid, power)) return B_TRUE;
@ -2628,7 +2696,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *srcportal,*dstportal; object_t *srcportal,*dstportal;
// find adjacent cell for portal // find adjacent cell for portal
srccell = getrandomadjcell(caster->cell, WE_NOTSOLID); srccell = getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND);
if (!srccell) { if (!srccell) {
fizzle(caster); fizzle(caster);
return B_FALSE; return B_FALSE;
@ -2752,22 +2820,32 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_KNOCK) { } else if (spellid == OT_S_KNOCK) {
object_t *o; object_t *o;
if (!validatespellcell(caster, &targcell,TT_DOOR, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_DOOR, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
o = hasobwithflag(targcell->obpile, F_DOOR);
if (o) { target = targcell->lf;
int dooropen;
isdoor(o, &dooropen); // just check whether it's open, we know it's a door // high powered knock can knock back monsters
if (dooropen) { if (target && (power >= 7)) {
fizzle(caster); int dir;
} else { dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS);
if (haslos(player, targcell)) { knockback(target, dir, 2, caster);
getobname(o, buf, o->amt);
msg("%s %s!",isplayer(caster) ? "You blast" : "Something blasts", buf);
}
takedamage(o, 999, DT_DIRECT);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else { } else {
fizzle(caster); o = hasobwithflag(targcell->obpile, F_DOOR);
if (o) {
int dooropen;
isdoor(o, &dooropen); // just check whether it's open, we know it's a door
if (dooropen) {
fizzle(caster);
} else {
if (haslos(player, targcell)) {
getobname(o, buf, o->amt);
msg("%s %s!",isplayer(caster) ? "You blast" : "Something blasts", buf);
}
takedamage(o, 999, DT_DIRECT);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
fizzle(caster);
}
} }
} else if (spellid == OT_S_LEVITATION) { } else if (spellid == OT_S_LEVITATION) {
flag_t *f; flag_t *f;
@ -2965,6 +3043,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE; return B_FALSE;
} }
if (lfhasflag(caster, F_CONTROL)) {
if (power < 5) {
power = 5;
}
}
if (isplayer(caster) && (power >= 5)) { if (isplayer(caster) && (power >= 5)) {
if (isplayer(target)) { if (isplayer(target)) {
askstring("What will you become", '?', buf, BUFLEN, NULL); askstring("What will you become", '?', buf, BUFLEN, NULL);
@ -2987,7 +3071,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// random race, but not the same! // random race, but not the same!
r = target->race; r = target->race;
while (r == target->race) { while (r == target->race) {
r = getrandomrace(NULL); r = getrandomrace(NULL, 0);
} }
} }
@ -2997,20 +3081,34 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
if (r) { if (r) {
//int rememberorig = B_FALSE;
getlfname(target, buf); getlfname(target, buf);
// if this is the player, remember the original race and job... // if this is the player, remember the original race and job...
if (isplayer(target) && !hasflag(target->flags, F_ORIGRACE)) { if (!hasflag(target->flags, F_ORIGRACE)) {
int howlong; // remember the original race
addflag(target->flags, F_ORIGRACE, target->race->id, NA, NA, NULL); addflag(target->flags, F_ORIGRACE, target->race->id, NA, NA, NULL);
}
if (isplayer(target)) {
int howlong;
// polymorph will be temporary... // polymorph will be temporary...
howlong = rnd(20,50); howlong = rnd(20,50);
addtempflag(target->flags, F_POLYMORPHED, B_TRUE, NA, NA, NULL, howlong); addtempflag(target->flags, F_POLYMORPHED, B_TRUE, NA, NA, NULL, howlong);
} else {
// permenant
addflag(target->flags, F_POLYMORPHED, B_TRUE, NA, NA, NULL);
} }
// become the new race! // become the new race!
setrace(target, r->id); setrace(target, r->id);
// if someone cast the spell at themself, they can change back at will.
if (target == caster) {
addflag(target->flags, F_CANWILL, OT_A_POLYREVERT, NA, NA, NULL);
}
if (haslos(player, target->cell)) { if (haslos(player, target->cell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
@ -3092,7 +3190,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
target = caster; target = caster;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (getmr(target) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You flicker."); msg("You flicker.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -3105,6 +3203,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
if (lfhasflag(caster, F_CONTROL)) {
if (power < 5) {
power = 5;
} else if (power < 8) {
power = 8;
}
}
if ((power < 5) || !isplayer(caster)) { if ((power < 5) || !isplayer(caster)) {
// random // random
while (!c || c->type->solid || haslf(c)) { while (!c || c->type->solid || haslf(c)) {
@ -3386,6 +3492,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else { } else {
fizzle(caster); fizzle(caster);
} }
} else if (spellid == OT_S_WINDSHIELD) {
flag_t *f;
// always targetted at caster
targcell = caster->cell;
target = caster;
f = addtempflag(caster->flags, F_WINDSHIELD, power, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid;
} else if ((spellid == OT_S_WISH) || (spellid == OT_S_GIFT)) { } else if ((spellid == OT_S_WISH) || (spellid == OT_S_GIFT)) {
object_t *o; object_t *o;
if (isplayer(caster)) { if (isplayer(caster)) {
@ -3424,7 +3538,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (hasflag(o->flags, F_IMPASSABLE)) { if (hasflag(o->flags, F_IMPASSABLE)) {
cell_t *newloc; cell_t *newloc;
// if so, don't put it where the player is! // if so, don't put it where the player is!
newloc = getrandomadjcell(target->cell, WE_NOTSOLID); newloc = getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND);
o = relinkob(o, newloc->obpile); o = relinkob(o, newloc->obpile);
} }
if (o) { if (o) {
@ -3561,15 +3675,9 @@ char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf) {
strcat(buf, roman(power)); strcat(buf, roman(power));
} }
if (spellid == OT_S_TELEPORT) { if (spellid == OT_S_DETECTLIFE) {
if (power >= 8) {
strcat(buf, "(fullctrl)");
} else if (power >= 5) {
strcat(buf, "(semictrl)");
}
} else if (spellid == OT_S_POLYMORPH) {
if (power >= 5) { if (power >= 5) {
strcat(buf, "(ctrl)"); strcat(buf, "(enhanced)");
} }
} else if (spellid == OT_S_CREATEMONSTER) { } else if (spellid == OT_S_CREATEMONSTER) {
if (power >= 7) { if (power >= 7) {
@ -3577,12 +3685,26 @@ char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf) {
} else if (power >= 5) { } else if (power >= 5) {
strcat(buf, "(semictrl)"); strcat(buf, "(semictrl)");
} }
} else if (spellid == OT_S_KNOCK) {
if (power >= 7) {
strcat(buf, "(enhanced)");
}
} else if (spellid == OT_S_LIGHT) { } else if (spellid == OT_S_LIGHT) {
if (power >= 8) { if (power >= 8) {
strcat(buf, "(perm,ctrl)"); strcat(buf, "(perm,ctrl)");
} else if (power >= 3) { } else if (power >= 3) {
strcat(buf, "(ctrl)"); strcat(buf, "(ctrl)");
} }
} else if (spellid == OT_S_POLYMORPH) {
if (power >= 5) {
strcat(buf, "(ctrl)");
}
} else if (spellid == OT_S_TELEPORT) {
if (power >= 8) {
strcat(buf, "(fullctrl)");
} else if (power >= 5) {
strcat(buf, "(semictrl)");
}
} }
return buf; return buf;
} }
@ -3661,7 +3783,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
// specialised school skill - apply this AFTER dividing by spell level // specialised school skill - apply this AFTER dividing by spell level
schoolskill = getskill(lf, getschoolskill(getspellschool(spellid))); schoolskill = getskill(lf, getschoolskill(getspellschool(spellid)));
if (schoolskill != PR_INEPT) { if (schoolskill != PR_INEPT) {
power += schoolskill; power += ((float)schoolskill * 1.5);
} }
// enforce maximum // enforce maximum
@ -3850,7 +3972,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i
} }
// line of fire interrupted? // line of fire interrupted?
if (where && needlof && !haslof(caster, where, needlof, &newwhere)) { if (where && needlof && !haslof(caster->cell, where, needlof, &newwhere)) {
if (newwhere) { if (newwhere) {
if (isplayer(caster)) { if (isplayer(caster)) {
// warn! // warn!

23
text.c
View File

@ -9,6 +9,14 @@
extern long curtime; extern long curtime;
int needan(char *text) {
if (isvowel(tolower(text[0]))) {
return B_TRUE;
}
return B_FALSE;
}
char *capitalise(char *text) { char *capitalise(char *text) {
if (strlen(text) > 0) { if (strlen(text) > 0) {
text[0] = toupper(text[0]); text[0] = toupper(text[0]);
@ -72,6 +80,21 @@ char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dic
return dicebuf; return dicebuf;
} }
char *getattrabbrev(enum ATTRIB att) {
switch (att) {
case A_NONE:
return "??";
case A_STR:
return "St";
case A_IQ:
return "Iq";
case A_DEX:
return "Dx";
case A_CON:
return "Cn";
}
return "??";
}
char *getattrname(enum ATTRIB att) { char *getattrname(enum ATTRIB att) {
switch (att) { switch (att) {

2
text.h
View File

@ -1,8 +1,10 @@
#include "defs.h" #include "defs.h"
int needan(char *text);
char *capitalise(char *text); char *capitalise(char *text);
char *capitaliseall(char *text); char *capitaliseall(char *text);
char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf); char *dicetotext(int ndice, int nsides, int bonus, int *min, int *max, char *dicebuf, char *minmaxbuf);
char *getattrabbrev(enum ATTRIB att);
char *getattrname(enum ATTRIB att); char *getattrname(enum ATTRIB att);
char *getpossessive(char *text); char *getpossessive(char *text);
char *getsizetext(enum LFSIZE sz); char *getsizetext(enum LFSIZE sz);