- [+] 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 (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?
gun = getfirearm(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);
c = getcellat(lf->cell->map, x, y);
if (c) {
// target cell adjacent and something in the way?
if (movetowards(lf, c, DT_ORTH)) {
// couldn't move towards it for some reason.
// so stop trying.
@ -929,7 +930,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
srange = srflag->val[0];
}
if (!haslof(lf, victim->cell, LOF_NEED,NULL)) {
if (!haslof(lf->cell, victim->cell, LOF_NEED,NULL)) {
specificcheckok = B_FALSE;
} else if (isimmobile(lf) || !lfhasflag(lf, F_FLYING)) {
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
// special case - missiles against flak jacket
// special case - missiles always hit flak jacket
if (damtype == DT_PROJECTILE) {
object_t *o;
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);
}
if (armour) {
int actualdam;
flag_t *rust;
@ -573,7 +571,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim) {
if (lfhasflag(victim, F_DODGES)) {
cell_t *adj;
adj = getrandomadjcell(victim->cell, WE_NOTSOLID);
adj = getrandomadjcell(victim->cell, WE_WALKABLE, B_NOEXPAND);
if (adj) {
flag_t *f;
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 {
return "bash";
}
} else {
} else if (pct <= 30) {
return "pummel";
} else {
return "slam";
}
} else if (damtype == DT_BITE) {
if (lf && (ownersize <= SZ_SMALL)) {
@ -1332,6 +1332,30 @@ obpile_t *getunarmedweapon(lifeform_t *lf,flag_t **uflag) {
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 acc,ev;
object_t *wep;
@ -1475,6 +1499,53 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
} // 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) {
int dir;
// knock back victim
@ -1487,7 +1558,8 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
enum FLAG fid;
int min,max,howlong;
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;
// do they get a saving throw?
if (f->val[1] != NA) {
@ -1544,7 +1616,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, int dam) {
} else {
strcpy(frombuf, "something unknown");
}
addtempflag(victim->flags, fid, NA, NA, NA, frombuf, howlong);
poison(victim, howlong, frombuf);
} else {
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);
float getstrdammod(lifeform_t *lf);
obpile_t *getunarmedweapon(lifeform_t *lf, flag_t **uflag);
int isphysicaldam(enum DAMTYPE damtype);
int rolltohit(lifeform_t *lf, lifeform_t *victim, int *critical);
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 POISONDAMCHANCE 33 // chance of vomitting when poisoned
#define POISONDAM 2 // damage taken from vomiting when poisoned
// ncurses colours
enum COLOUR {
C_BLACK = 0,
@ -607,6 +610,7 @@ enum OBTYPE {
OT_ROASTMEAT,
OT_BREADFRESH,
OT_CHOCOLATE,
OT_CLOVER,
// corpses
OT_CORPSE,
OT_HEAD,
@ -642,6 +646,7 @@ enum OBTYPE {
OT_POT_INVULN,
OT_POT_MAGIC,
OT_POT_OIL,
OT_POT_POISON,
OT_POT_POLYMORPH,
OT_POT_RESTORATION,
OT_POT_SANCTUARY,
@ -678,6 +683,7 @@ enum OBTYPE {
OT_MAN_LOCKPICKING,
OT_MAN_MAGITEMUSAGE,
OT_MAN_RESEARCH,
OT_MAN_SHIELDS,
OT_MAN_SPELLCASTING,
OT_MAN_STEALTH,
OT_MAN_TECHUSAGE,
@ -798,6 +804,7 @@ enum OBTYPE {
// -- elemental - air
OT_S_AIRBLAST,
OT_S_CLOUDKILL,
OT_S_WINDSHIELD,
// -- elemental - fire
OT_S_SPARK,
OT_S_FIREDART,
@ -869,6 +876,7 @@ enum OBTYPE {
OT_A_EMPLOY,
OT_A_HEAVYBLOW,
OT_A_INSPECT,
OT_A_POLYREVERT,
OT_A_STINGACID, // need to define dam in f_canwill
// wands
OT_WAND_COLD,
@ -989,16 +997,23 @@ enum OBTYPE {
OT_BUCKLER,
OT_SHIELD,
OT_SHIELDLARGE,
OT_SHIELDTOWER,
// rings
OT_RING_INVIS,
OT_RING_INVULN,
OT_RING_LUCK,
OT_RING_CONTROL,
OT_RING_CON,
OT_RING_DEX,
OT_RING_IQ,
OT_RING_STR,
OT_RING_MANA,
OT_RING_MIRACLES,
OT_RING_MPREGEN,
OT_RING_PROTFIRE,
OT_RING_REGENERATION,
OT_RING_RESISTMAG,
OT_RING_SEEINVIS,
OT_RING_SIGHT,
OT_RING_WOUNDING,
// animal weapons
OT_CLAWS,
@ -1021,48 +1036,57 @@ enum OBTYPE {
OT_JAVELIN,
OT_BULLET,
OT_RUBBERBULLET,
// stabbing weapons
OT_DAGGER,
OT_COMBATKNIFE,
OT_ORNDAGGER,
OT_RAPIER,
OT_TRIDENT,
OT_QUICKBLADE,
// chopping weapons
// axes
OT_AXE,
OT_HANDAXE,
OT_BATTLEAXE,
OT_GREATAXE,
// slashing weapons
// short blades
OT_COMBATKNIFE,
OT_DAGGER,
OT_KNIFE,
OT_STEAKKNIFE,
OT_SCYTHE,
OT_ORNDAGGER,
OT_QUICKBLADE,
OT_RAPIER,
OT_SAI,
OT_SHORTSWORD,
OT_SCIMITAR,
OT_LONGSWORD,
OT_STEAKKNIFE,
OT_SICKLE,
// long swords
OT_FALCHION,
OT_GREATSWORD,
OT_LONGSWORD,
OT_ORNSWORD,
OT_SCIMITAR,
// polearms
OT_GLAIVE,
OT_GUISARME,
OT_HALBERD,
OT_LANCE,
OT_RANSEUR,
OT_SCYTHE,
OT_SPEAR,
OT_TRIDENT,
// staves
OT_QUARTERSTAFF,
// bashing weapons
OT_STICK,
OT_SPANNER,
// clubs
OT_CLUB,
OT_FLAIL,
OT_FLAILHEAVY,
OT_GREATCLUB,
OT_MACE,
OT_MORNINGSTAR,
OT_GREATCLUB,
OT_SICKLE,
OT_NUNCHAKU,
OT_SPANNER,
OT_STICK,
// projectile weapons
OT_REVOLVER,
OT_SLING,
OT_BOW,
OT_LONGBOW,
OT_CROSSBOW,
OT_CROSSBOWHAND,
// holy weapons
OT_LONGBOW,
OT_REVOLVER,
OT_SLING,
// special weapons
OT_HANDOFGOD,
@ -1087,7 +1111,7 @@ enum BODYPART {
#define MAXBODYPARTS (12)
// empty types
#define WE_NOTSOLID 1
#define WE_WALKABLE 1
#define WE_EMPTY 2
#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_CONTAINSOB, // for vending machiens. v0 is ob letter
// text is an object it contains.
F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc
// for items in shops
F_SHOPITEM, // causes shops to show this item as identified
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_DIECONVERT, // val0 = what this turns into when dying
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_DTCONVERT, // damtype val0 converts this to f->text
F_NODTCONVERT, // overrides DTCONVERT .
@ -1245,6 +1271,8 @@ enum FLAG {
F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better)
F_ARMOURPIERCE, // goes through armour
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_FIRESPEED, // how fast this weapon shoots projectiles
F_AMMOOB, // what object this weapon fires
@ -1286,9 +1314,13 @@ enum FLAG {
F_WALKDAM, // val0 = damtype, text = dam per sec
// abilities
F_NEEDSGRAB, // this ability needs to to grab someone first.
F_NOANNOUNCE, // don't announce when you gain/lose this ability
// magic
F_SPELLSCHOOL, // val0 = SPELLSCHOOL enum
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_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2
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'
// lifeform flags / lf flags
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_ATTRSET, // forces attribute val0 to be val1. ie. 0=A_STR,1=18
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_AUTOCMD, // val0 = how many times to repeat this
F_LASTCMD, // text[0] = last command performed, v0/1 = x/y of cell, v2=various
F_CANLEARN, // lf is able to learn skill val0
F_STARTOB, // val0 = %chance of starting with it, text = ob name
// val1,2 = min/max amounts. if NA, min=max=1.
F_STARTSKILL, // val0 = skill id
@ -1333,6 +1368,8 @@ enum FLAG {
F_GUNTARGET, // current projectile weapon target
F_CASTINGSPELL, // set while the player is casting a spell
// 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
F_FAILEDINSPECT, // lf has failed an inspect check for item id v0
F_BOOSTSPELL, // v0 is active boost spell
@ -1402,11 +1439,14 @@ enum FLAG {
// to the victim
F_PHALANX, // gain v0 AR if v2 or more adj monsters matching f->text
// INTRINSICS
F_ARBOOST,// armour is magically boosted
F_MAGICARMOUR,// armour is magically boosted. f->text is the description
// ie 'magic armour', 'force field'
F_ASLEEP, // is asleep
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
F_BLIND, // cannot see anything
F_CANCAST, // can cast the spell val0 (need MP)
F_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
// v1 is counter untiluse
// v2 is what you need to use it
@ -1416,8 +1456,11 @@ enum FLAG {
// dam:xdy+b; damage
// needgrab:xx; do you need to grab first?
F_CHARMEDBY,// you've been charmed by lf id v0
F_CONTROL,// you control polymorphs, teleports and createmonsters
F_DETECTAURAS, // autodetect bless/curse
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_DETECTMETAL, // autodetect nearby metal
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_SPRINTING, // v0=true: you are sprinting. false=you are tired
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_NOTIME, // this lf's actions don't take time
F_PERCEPTION, // v0 = 0-20. perception level.
@ -1584,6 +1629,8 @@ enum SPELLTARGET {
#define B_TRANSPARENT (-1)
#define B_TRANS (-1)
#define B_ALLOWEXPAND (-1)
#define B_NOEXPAND (0)
#define B_IFACTIVATED (-1)
@ -1857,6 +1904,7 @@ enum SKILL {
SK_LOCKPICKING,
SK_MAGITEMUSAGE,
SK_RESEARCH,
SK_SHIELDS,
SK_SPELLCASTING,
SK_STEALTH,
SK_TECHUSAGE,
@ -1883,7 +1931,7 @@ enum SKILL {
SK_SS_TRANSLOCATION,
SK_SS_WILD,
};
#define MAXSKILLS 31
#define MAXSKILLS 32
// proficiency levels
enum SKILLLEVEL {

View File

@ -6,6 +6,8 @@ in objcets.c:
update getdamnamenoun() - eg. you are immune to "electricity"
in attack.c
update isphysicaldam()
update getattackverb 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_SLASH _will_ damage the weapon

2
flag.c
View File

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

590
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);
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 *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, enum FLAG withflag, ...);
object_t *doaskobject(obpile_t *op, char *title, int *count, long opts, ...);
int askobjectmulti(obpile_t *op, char *prompt, long opts);
char askchar(char *prompt, char *validchars, char *def, int showchars);
cell_t *askcoords(char *prompt, int targettype);
char *askstring(char *prompt, char punc, char *retbuf, int retbuflen, char *def);
void centre(WINDOW *win, int y, char *format, ... );
int chartodir(char ch);
char checkforkey(void);
int cleanupgfx(void);
void clearmsg(void);
void real_clearmsg(int force);
@ -35,7 +35,7 @@ void docomms(void);
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst);
void doeat(obpile_t *op);
void doenter(lifeform_t *lf);
void doexplain(void);
void doexplain(char *question);
void dofinaloblist(obpile_t *op);
void dofire(void);
void dohelp(void);
@ -63,8 +63,8 @@ int dowear(obpile_t *op);
int doweild(obpile_t *op);
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 drawunviscell(cell_t *cell, int x, int y);
void drawcellwithcontents(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 drawcursor(void);
void drawlevelfor(lifeform_t *lf);
void drawmsg(void);
@ -79,6 +79,7 @@ void doheading(WINDOW *win, int *y, int x, char *what);
void initgfx(void);
void initprompt(prompt_t *p, char *q1);
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 more(void);
void warn(char *format, ... );

771
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 caneat(lifeform_t *lf, object_t *o);
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 canpush(lifeform_t *lf, object_t *o, int dir);
int canquaff(lifeform_t *lf, object_t *o);
@ -35,6 +36,7 @@ void dumpxp(void);
int eat(lifeform_t *lf, object_t *o);
void enhanceskills(lifeform_t *lf);
object_t *eyesshaded(lifeform_t *lf);
int fall(lifeform_t *lf, int announce);
void fightback(lifeform_t *lf, lifeform_t *attacker);
job_t *findjob(enum JOB jobid);
job_t *findjobbyname(char *name);
@ -104,7 +106,7 @@ char *getplayernamefull(char *buf);
int getracerarity(enum RACE rid);
object_t *getrandomarmour(lifeform_t *lf);
//int getrandommonlevel(int depth);
race_t *getrandomrace(map_t *map);
race_t *getrandomrace(map_t *map, int forcedepth);
race_t *getreallyrandomrace(void);
enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id);
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);
void loseobflags(lifeform_t *lf, object_t *o, int kind);
int hasbp(lifeform_t *lf, enum BODYPART bp);
int haslof(lifeform_t *viewer, cell_t *dest, 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);
void initjobs(void);
void initrace(void);
@ -162,8 +165,10 @@ flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt);
void killjob(job_t *job);
void killlf(lifeform_t *lf);
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_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 makenauseated(lifeform_t *lf, int amt, int howlong);
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 outfitlf(lifeform_t *lf);
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 precalclos(lifeform_t *lf);
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 unweild(lifeform_t *lf, object_t *o);
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 validateraces(void);
int wear(lifeform_t *lf, object_t *o);

525
log.txt
View File

@ -8,190 +8,6 @@ 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
-> possibility: goblin, rarity=85
@ -388,239 +204,118 @@ finding random lf with rarity val 85-100
-> possibility: glowbug, rarity=85
got 10 possibilities.
rollhitdice() - rolling 2d4 + 2
rollhitdice() - mod is +-5%
rollhitdice() - mod is +32%
rollhitdice() ---- die 1/2 == 4
rollhitdice() ---- die 2/2 == 4
TOTAL: 8
-> modified to: 8
-> modified to: 10
givejob() starting.
processing normal flag: 191
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 149
processing normal flag: 150
processing normal flag: 150
processing normal flag: 150
processing normal flag: 150
processing normal flag: 150
processing normal flag: 150
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 219
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
processing normal flag: 218
nclasses is 0
nclasses is 0
nclasses is 0
nclasses is 0
nclasses 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
processing normal flag: 200
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 157
processing normal flag: 158
processing normal flag: 158
processing normal flag: 158
processing normal flag: 158
processing normal flag: 158
processing normal flag: 158
processing normal flag: 156
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 229
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
processing normal flag: 227
nwantflags is 1
nwantflags is 0

167
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)) {
r = getrandomrace(c->map);
r = getrandomrace(c->map, 0);
} else {
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
adjcell = NULL;
for (n = 0; n < nmoncells; n++) {
adjcell = getrandomadjcell(moncell[n], WE_NOTSOLID);
adjcell = getrandomadjcell(moncell[n], WE_WALKABLE, B_ALLOWEXPAND);
if (adjcell) break;
}
// 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
// 'numappears' don't get them.
if (!lfhasflag(lf, F_NOPACK)) {
if (lfhasflag(lf, F_HUMANOID) && !lfhasflag(lf, F_NOPACK)) {
if (rnd(1,3) == 1) {
int nobs = rnd(1,3);
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);
}
//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) {
switch (hab) {
case H_DUNGEON:
@ -1785,41 +1868,62 @@ int getobchance(int habitat) {
return 0;
}
cell_t *getrandomadjcell(cell_t *c, int wantempty) {
int dir;
int ntries = 0;
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) {
int radius = 1;
int x,y;
cell_t *poss[MAXCANDIDATES];
int nposs = 0;
cell_t *new;
dir = getrandomdir(DT_COMPASS);
while (ntries < 8) {
new = getcellindir(c, dir);
if (new) {
int done = B_FALSE;
while (!done) {
int numwithlof = 0;
for (y = c->y - radius ; y <= c->y + radius ; y++) {
for (x = c->x - radius ; x <= c->x + radius ; x++) {
new = getcellat(c->map, x, y);
if (new && (getcelldist(c,new) == radius) && haslof(c, new, LOF_WALLSTOP, NULL)) {
numwithlof++;
if (wantempty == WE_EMPTY) {
// make sure it's empty
if (isempty(new)) {
return new;
poss[nposs++] = new;
}
} else if (wantempty == WE_NOTSOLID) {
} else if (wantempty == WE_WALKABLE) {
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)) {
return new;
poss[nposs++] = new;
}
}
} else {
// always ok
return new;
poss[nposs++] = new;
}
}
}
// not found yet...
dir++;
if (dir > DC_NW) dir = DC_N;
ntries++;
}
// found any possibilities ?
if (nposs) {
done = B_TRUE;
} else {
if (allowexpand) {
if (numwithlof) {
// increment radius
radius++;
} else {
return NULL;
}
} else {
return NULL;
}
}
}
return poss[rnd(0,nposs-1)];
}
cell_t *getrandomcell(map_t *map) {
@ -1985,6 +2089,15 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
if (c->lf) {
if (getcelldistorth(player->cell, c) <= f->val[0]) {
*thing = c->lf;
if (f->val[1] == B_TRUE) {
if (desc) {
real_getlfnamea(c->lf, desc, B_FALSE);
strcat(desc, " (detected)");
}
if (glyph) {
*glyph = *(getlfglyph(c->lf));
}
} else {
if (desc) {
char *p;
p = getsizetext(getlfsize(c->lf));
@ -1995,6 +2108,7 @@ int isinscanrange(cell_t *c, void **thing, char *desc, glyph_t *glyph) {
glyph->ch = '0' + ((int) getlfsize(c->lf));
glyph->colour = C_GREY;
}
}
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);
if (f) {
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);
int getcelldist(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);
object_t *gettopobject(cell_t *where);
void calclight(map_t *map);
@ -30,7 +31,7 @@ void forgetcells(map_t *map, int amt);
cell_t *getcellindir(cell_t *cell, int dir);
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
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 *getrandomcelloftype(map_t *map, int id);
int getrandomdir(int dirtype);

41
move.c
View File

@ -1093,7 +1093,7 @@ int pullnextto(lifeform_t *lf, cell_t *c) {
return B_TRUE;
}
if (!haslof(lf, dst, B_FALSE, &newdst)) {
if (!haslof(lf->cell, dst, B_FALSE, &newdst)) {
if (newdst) {
// update destination
dst = newdst;
@ -1170,6 +1170,13 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
int slip;
// 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) {
if (!isplayer(lf)) {
if (o->blessed == B_CURSED) {
@ -1184,6 +1191,9 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
}
taketime(lf, getmovespeed(lf));
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;
}
}
@ -1225,7 +1235,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
moveto(lf, cell, onpurpose);
taketime(lf, getmovespeed(lf));
} else {
object_t *inway;
object_t *inway = NULL;
int door, dooropen;
reason = errcode;
switch (errcode) {
@ -1313,8 +1323,8 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
}
}
}
} else { // object is in the way
if (lf->controller == C_PLAYER) {
} else { // somethign random is in the way
if (isplayer(lf) && inway) {
char obname[BUFLEN];
getobname(inway, obname, 1);
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) {
cell_t *cell;
enum IQBRACKET iq;
object_t *o;
char buf[BUFLEN];
//object_t *o;
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);
if (celldangerous(lf, cell, B_TRUE, error)) {
if (error) *error = E_WONT;
return B_FALSE;
}
@ -1429,6 +1442,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
if (canswapwith(lf, cell->lf)) {
return B_TRUE;
}
if (error) *error = E_WONT;
return B_FALSE;
}
}
@ -1438,9 +1452,28 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
if (iq >= IQ_AVERAGE) {
// don't move if in pain
if (lfhasflag(lf, F_PAIN)) {
if (error) *error = E_WONT;
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;
}

28
nexus.c
View File

@ -433,10 +433,16 @@ void donextturn(map_t *map) {
if (donormalmove) {
f = hasflag(who->flags, F_RESTING);
if (f) {
// check for interrupt of resting...
if (isplayer(who) && checkforkey()) {
msg("Stopped resting.");
killflag(f);
} else {
rest(who, B_TRUE);
donormalmove = B_FALSE;
}
}
}
if (donormalmove) {
if (isplayer(who)) {
@ -523,6 +529,25 @@ char *getdirname(int dir) {
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) {
int mid;
mid = 100 - (depth * 3);
@ -752,6 +777,7 @@ float pctof(float pct, float num) {
return ((pct / 100.0) * num);
}
// get a random number between min and max
int rnd(int min, int max) {
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);
l->timespent -= firstlftime;
assert(l->timespent >= 0);
/*
if (isplayer(l)) {
statdirty = B_TRUE;
}
*/
}
//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);
celltype_t *findcelltype(int id);
char *getdirname(int dir);
enum COLOUR getpctcol(float num, float max);
void getrarity(int depth, int *min, int *max, int range);
int init(void);
void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels);

791
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);
void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat);
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 appendinscription(object_t *o, char *text);
void applyobmod(object_t *o, obmod_t *om);
@ -77,6 +78,7 @@ int getnumshards(object_t *o);
int getnutritionbase(object_t *o);
int getnutrition(object_t *o);
char *getobdesc(object_t *o, char *buf);
char *getobequipinfo(object_t *o, char *buf);
char *getobextrainfo(object_t *o, char *buf);
cell_t *getoblocation(object_t *o);
char *getobname(object_t *o, char *buf, int count);
@ -137,6 +139,7 @@ int ispourable(object_t *o);
int ispushable(object_t *o);
int isreadable(object_t *o);
int isrotting(object_t *o);
int isthrownmissile(object_t *o);
int isweapon(object_t *o);
int iswearable(object_t *o);
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 turnoff(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 validateobs(void);
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 db = B_FALSE;
char buf[BUFLEN];
char line[BUFLEN];
int otid,known;
char hiddenname[BUFLEN];
char *p,*dummy;
if (db) dblog("--> Loading knowledge...\n");
fscanf(f, "startknowledge\n");
@ -102,7 +104,14 @@ int loadknowledge(FILE *f) {
buf[strlen(buf)-1] = '\0'; // strip newline
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);
// get next line
fgets(buf, BUFLEN, f);

180
spell.c
View File

@ -120,7 +120,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (!target) {
if (isplayer(user)) msg("There is nobody there!");
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!");
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
// 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!
if (!c) {
c = user->cell;
@ -405,7 +405,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
return B_TRUE;
}
howlong = 5;
howlong = 2;
// +2 for each athletics skill level
slev = getskill(user, SK_ATHLETICS);
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
addtempflag(target->flags, F_PAIN, DT_ACID, NA, NA, damstr, 2);
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) {
skill_t *sk;
char ch = 'a';
@ -456,6 +472,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
sprintf(buf, "%s",getskilllevelname(i));
addchoice(&prompt, ch++, buf, buf, NULL);
}
if (prompt.nchoices <= 0) {
msg("You have already mastered this skill!");
return B_TRUE;
}
getchoice(&prompt);
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++) {
targcell = getcellat(caster->cell->map, x,y);
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];
// automatic hit
getlfname(targcell->lf, lfname);
@ -1130,7 +1150,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
} else {
// 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;
howlong = getspellduration(10,20,blessed) + (power*2);
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 {
// 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++) {
targcell = getcellat(caster->cell->map, x,y);
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];
// automatic hit
getlfname(targcell->lf, lfname);
@ -1578,6 +1598,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (o) {
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) {
@ -1588,6 +1611,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (o) {
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++) {
@ -1600,6 +1628,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (o) {
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
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;
}
@ -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++) {
targcell = getcellat(caster->cell->map, x,y);
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];
// automatic hit
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 (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);
// polymorph will be temporary...
// polymorph is always will be temporary
addtempflag(target->flags, F_POLYMORPHED, B_TRUE, NA, NA, NULL, 10);
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?");
where = askcoords(buf, TT_MONSTER);
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 {
failed = B_TRUE;
}
@ -2419,6 +2466,27 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
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....
if (skillcheck(target, SC_RESISTMAG, 20 + power*2, 0)) {
if (isplayer(caster) && cansee(player, target)) {
@ -2473,7 +2541,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
targcell = caster->cell;
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;
} else if (spellid == OT_S_PULL) {
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;
// find adjacent cell for portal
srccell = getrandomadjcell(caster->cell, WE_NOTSOLID);
srccell = getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND);
if (!srccell) {
fizzle(caster);
return B_FALSE;
@ -2752,6 +2820,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_KNOCK) {
object_t *o;
if (!validatespellcell(caster, &targcell,TT_DOOR, B_TRUE, LOF_DONTNEED, spellid, power)) return B_TRUE;
target = targcell->lf;
// high powered knock can knock back monsters
if (target && (power >= 7)) {
int dir;
dir = getdirtowards(caster->cell, targcell, target, B_FALSE, DT_COMPASS);
knockback(target, dir, 2, caster);
} else {
o = hasobwithflag(targcell->obpile, F_DOOR);
if (o) {
int dooropen;
@ -2769,6 +2846,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
fizzle(caster);
}
}
} else if (spellid == OT_S_LEVITATION) {
flag_t *f;
// always targetted at caster
@ -2965,6 +3043,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE;
}
if (lfhasflag(caster, F_CONTROL)) {
if (power < 5) {
power = 5;
}
}
if (isplayer(caster) && (power >= 5)) {
if (isplayer(target)) {
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!
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) {
//int rememberorig = B_FALSE;
getlfname(target, buf);
// if this is the player, remember the original race and job...
if (isplayer(target) && !hasflag(target->flags, F_ORIGRACE)) {
int howlong;
if (!hasflag(target->flags, F_ORIGRACE)) {
// remember the original race
addflag(target->flags, F_ORIGRACE, target->race->id, NA, NA, NULL);
}
if (isplayer(target)) {
int howlong;
// polymorph will be temporary...
howlong = rnd(20,50);
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!
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 (seenbyplayer) *seenbyplayer = B_TRUE;
}
@ -3092,7 +3190,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
target = caster;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (getmr(target) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) {
if (isplayer(target)) {
msg("You flicker.");
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)) {
// random
while (!c || c->type->solid || haslf(c)) {
@ -3386,6 +3492,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
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)) {
object_t *o;
if (isplayer(caster)) {
@ -3424,7 +3538,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (hasflag(o->flags, F_IMPASSABLE)) {
cell_t *newloc;
// 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);
}
if (o) {
@ -3561,15 +3675,9 @@ char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf) {
strcat(buf, roman(power));
}
if (spellid == OT_S_TELEPORT) {
if (power >= 8) {
strcat(buf, "(fullctrl)");
} else if (power >= 5) {
strcat(buf, "(semictrl)");
}
} else if (spellid == OT_S_POLYMORPH) {
if (spellid == OT_S_DETECTLIFE) {
if (power >= 5) {
strcat(buf, "(ctrl)");
strcat(buf, "(enhanced)");
}
} else if (spellid == OT_S_CREATEMONSTER) {
if (power >= 7) {
@ -3577,12 +3685,26 @@ char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf) {
} else if (power >= 5) {
strcat(buf, "(semictrl)");
}
} else if (spellid == OT_S_KNOCK) {
if (power >= 7) {
strcat(buf, "(enhanced)");
}
} else if (spellid == OT_S_LIGHT) {
if (power >= 8) {
strcat(buf, "(perm,ctrl)");
} else if (power >= 3) {
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;
}
@ -3661,7 +3783,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
// specialised school skill - apply this AFTER dividing by spell level
schoolskill = getskill(lf, getschoolskill(getspellschool(spellid)));
if (schoolskill != PR_INEPT) {
power += schoolskill;
power += ((float)schoolskill * 1.5);
}
// enforce maximum
@ -3850,7 +3972,7 @@ cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, i
}
// line of fire interrupted?
if (where && needlof && !haslof(caster, where, needlof, &newwhere)) {
if (where && needlof && !haslof(caster->cell, where, needlof, &newwhere)) {
if (newwhere) {
if (isplayer(caster)) {
// warn!

23
text.c
View File

@ -9,6 +9,14 @@
extern long curtime;
int needan(char *text) {
if (isvowel(tolower(text[0]))) {
return B_TRUE;
}
return B_FALSE;
}
char *capitalise(char *text) {
if (strlen(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;
}
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) {
switch (att) {

2
text.h
View File

@ -1,8 +1,10 @@
#include "defs.h"
int needan(char *text);
char *capitalise(char *text);
char *capitaliseall(char *text);
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 *getpossessive(char *text);
char *getsizetext(enum LFSIZE sz);