- [+] display cell wall types in askcoords()

- [+] sort OC_ in defs.h
- [+] when a monster UNHIDES, need to redraw!!!
* [+] chain lightning
- [+] teleportation trap
- [+] wish bug with invalid strings: The xxx's strong scent leading
      east appears on the ground!
- [+] bug: animals ggetting extra attacks due to unarmed skill.
- [+] change melee attack with 2nd hand to happen at SKILLED level, not
      adept.
* [+] infinite loops during creation
- [+] make javelins weigh more
- [+] potions still cost too much.. should be at least 1/3 the cost
- [+] "you feel footprints here".  need F_nofeel
This commit is contained in:
Rob Pearce 2011-06-05 09:21:21 +00:00
parent b6c2fb818c
commit 3442dc293d
14 changed files with 343 additions and 237 deletions

View File

@ -28,7 +28,6 @@ int applyarmourdamage(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damty
object_t *o;
o = getequippedob(lf->pack, BP_BODY);
if (o && (o->type->id == OT_FLAKJACKET)) {
// stop ALL missile damage
armour = o;
}
}
@ -1001,14 +1000,14 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
// returns the amount of damage the armour blocked...
int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE damtype) {
int reduceamt = 0;
float reducepct;
int ar;
object_t *o;
ar = getarmourrating(lf);
reducepct = getdamreducepct(ar);
reduceamt = (int) ceil((reducepct / 100.0) * (float)dam);
//reducepct = getdamreducepct(ar);
//reduceamt = (int) ceil((reducepct / 100.0) * (float)dam);
reduceamt = ar/2;
// special case
if (damtype == DT_PROJECTILE) {
@ -1455,11 +1454,13 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) {
return dam;
}
/*
float getdamreducepct(float armourrating) {
float reducepct;
reducepct = (armourrating * 1.5);
return reducepct;
}
*/
/*
int getunarmeddamroll(flag_t *f) {
@ -1659,7 +1660,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
}
// victim immobile or asleep?
if (isimmobile(victim)) {
if (isimmobile(victim) || lfhasflag(victim, F_EATING)) {
acc += 50;
}

View File

@ -15,7 +15,7 @@ int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam);
char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
void getdamrange(flag_t *f, int *min, int *max);
//void getdamrangeunarmed(flag_t *f, int *min, int *max);
float getdamreducepct(float armourrating);
//float getdamreducepct(float armourrating);
int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag);
//int getunarmeddamroll(flag_t *f);
float getstrdammod(lifeform_t *lf);

193
defs.h
View File

@ -534,27 +534,28 @@ enum DAMTYPE {
// Object Classes
enum OBCLASS {
OC_TERRAIN,
OC_MONEY,
OC_WEAPON,
OC_ARMOUR,
OC_MISSILE,
OC_RING,
OC_SCROLL,
OC_POTION,
OC_WAND,
OC_FOOD,
OC_CORPSE,
OC_ROCK,
OC_TOOLS,
OC_TECH,
OC_MISC,
OC_FLORA,
OC_SPELL,
OC_ABILITY,
OC_EFFECT,
OC_DFEATURE,
OC_ARMOUR,
OC_BOOK,
OC_CORPSE,
OC_DFEATURE,
OC_EFFECT,
OC_FLORA,
OC_FOOD,
OC_MISC,
OC_MISSILE,
OC_MONEY,
OC_POTION,
OC_RING,
OC_ROCK,
OC_SCROLL,
OC_TECH,
OC_TERRAIN,
OC_TOOLS,
OC_TRAP,
OC_SPELL,
OC_WAND,
OC_WEAPON,
OC_NULL = -999
};
@ -782,12 +783,13 @@ enum OBTYPE {
OT_WATERSHALLOW,
OT_WATERDEEP,
// traps
OT_TRAPROCK,
OT_TRAPARROW,
OT_TRAPARROWP,
OT_TRAPGAS,
OT_TRAPFIRE,
OT_TRAPGAS,
OT_TRAPMINE,
OT_TRAPROCK,
OT_TRAPTELEPORT,
OT_TRAPTRIP,
// rocks / plants
OT_GOLD,
@ -874,147 +876,6 @@ enum OBTYPE {
// BOOKS
OT_MANUAL,
OT_SPELLBOOK,
/*
OT_MAN_ARMOUR,
OT_MAN_ATHLETICS,
OT_MAN_BACKSTAB,
OT_MAN_COOKING,
OT_MAN_FIRSTAID,
OT_MAN_LISTEN,
OT_MAN_LOCKPICKING,
OT_MAN_MAGITEMUSAGE,
OT_MAN_RANGED,
OT_MAN_SHIELDS,
OT_MAN_SPELLCASTING,
OT_MAN_SPOTHIDDEN,
OT_MAN_STEALTH,
OT_MAN_TECHUSAGE,
OT_MAN_TRAPS,
OT_MAN_TWOWEAPON,
// manuals of knowledge
OT_MAN_LORE_ARCANA,
OT_MAN_LORE_DEMONS,
OT_MAN_LORE_HUMANOID,
OT_MAN_LORE_NATURE,
OT_MAN_LORE_UNDEAD,
// manuals of weaponry
OT_MAN_AXES,
OT_MAN_CLUBS,
OT_MAN_LONGBLADES,
OT_MAN_POLEARMS,
OT_MAN_SHORTBLADES,
OT_MAN_STAVES,
OT_MAN_UNARMED,
// manuals of spells
OT_MAN_SS_ALLOMANCY,
OT_MAN_SS_AIR,
OT_MAN_SS_DEATH,
OT_MAN_SS_DIVINATION,
OT_MAN_SS_NATURE,
OT_MAN_SS_FIRE,
OT_MAN_SS_COLD,
OT_MAN_SS_GRAVITY,
OT_MAN_SS_LIFE,
OT_MAN_SS_MODIFICATION,
OT_MAN_SS_MENTAL,
OT_MAN_SS_SUMMONING,
OT_MAN_SS_TRANSLOCATION,
OT_MAN_SS_WILD,
// SPELLBOOKS
// allomancy can't be learned from books
// -- death
OT_SB_ANIMATEDEAD,
OT_SB_DRAINLIFE,
OT_SB_FEAR,
OT_SB_PAIN,
OT_SB_PARALYZE,
OT_SB_POISONBOLT,
OT_SB_INFINITEDEATH,
OT_SB_WEAKEN,
OT_SB_FEEBLEMIND,
OT_SB_BLINDNESS,
OT_SB_POSSESSION,
OT_SB_STENCH,
// -- divination
OT_SB_DETECTAURA,
OT_SB_DETECTLIFE,
OT_SB_DETECTOBS,
OT_SB_LOCATEOBJECT,
OT_SB_LORE,
OT_SB_REVEALHIDDEN,
OT_SB_IDENTIFY,
OT_SB_MAPPING,
OT_SB_SEEINVIS,
// -- elemental - air
OT_SB_AIRBLAST,
OT_SB_CALLLIGHTNING,
OT_SB_CLOUDKILL,
OT_SB_GUSTOFWIND,
OT_SB_LIGHTNINGSTORM,
OT_SB_WINDSHIELD,
// -- elemental - fire
OT_SB_BLADEBURN,
OT_SB_BURNINGWAVE,
OT_SB_FIREDART,
OT_SB_FIREBALL,
OT_SB_FLAMEPILLAR,
OT_SB_FLAMEBURST,
OT_SB_SPARK,
// -- elemental - ice
OT_SB_CHILL,
OT_SB_CONECOLD,
OT_SB_COLDBURST,
OT_SB_FREEZEOB,
OT_SB_FROSTBITE,
OT_SB_ICEEDGE,
OT_SB_ICICLE,
OT_SB_WALLOFICE,
// -- elemental - earth
OT_SB_DIG,
// -- gravity
OT_SB_GRAVLOWER,
OT_SB_GRAVBOOST,
OT_SB_HASTE,
OT_SB_FLIGHT,
OT_SB_SLOW,
OT_SB_LEVITATION,
// -- life
OT_SB_HEALING,
OT_SB_HEALINGMIN,
OT_SB_HEALINGMAJ,
OT_SB_TURNUNDEAD,
// -- mental / psionic
OT_SB_MINDSCAN,
OT_SB_SLEEP,
OT_SB_TELEKINESIS,
OT_SB_PACIFY,
OT_SB_PSYARMOUR,
OT_SB_CHARM,
// -- modification
OT_SB_GASEOUSFORM,
OT_SB_GREASE,
OT_SB_KNOCK,
OT_SB_HOLDPORTAL,
OT_SB_INSCRIBE,
OT_SB_INVISIBILITY,
OT_SB_LIGHT,
OT_SB_DARKNESS,
OT_SB_MENDING,
OT_SB_PASSWALL,
OT_SB_PETRIFY,
OT_SB_POLYMORPH,
OT_SB_STICKTOSNAKE,
// -- summoning
OT_SB_CREATEMONSTER,
OT_SB_SUMMONWEAPON,
// -- translocation
OT_SB_BLINK,
OT_SB_DISPERSAL,
OT_SB_GATE,
OT_SB_TELEPORT,
OT_SB_TWIDDLE,
// -- wild can't be learned from books
*/
// spells
// -- allomancy
OT_S_ABSORBMETAL,
@ -1051,6 +912,7 @@ enum OBTYPE {
// -- elemental - air
OT_S_JOLT,
OT_S_AIRBLAST,
OT_S_CHAINLIGHTNING,
OT_S_CLOUDKILL,
OT_S_GUSTOFWIND,
OT_S_MIST,
@ -1506,6 +1368,7 @@ enum FLAG {
F_NONE, // dummy flag
// map flags
F_MAPCOORDS, // v0+v1 are x/y coords for this map area
F_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2
// object flags
F_DEAD, // object will be removed
F_CREATEDBY, // object was made by lf id v0, text=real lfname
@ -1525,6 +1388,7 @@ enum FLAG {
// v2 = enum sense used to see this (ie. s_smell, s_sight)
// (optional) text = lfid of lf who left this.
// should only be used for SCENT, not footprints.
F_NOFEEL, // when blind, don't show "you can feel xxx"
// 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)
@ -1946,7 +1810,8 @@ enum FLAG {
// next to the attacker
F_PHALANX, // gain v0 AR if v2 or more adj monsters matching f->text
F_MORALE, // gain +v0 in morale checks.
F_SPOTTED, // you have spotted hiding lf id v0
F_SPOTTED, // you have spotted hiding lf id v0. you lsoe this if they
// go out of sight.
// INTRINSICS
F_MAGICARMOUR,// armour is magically boosted. f->text is the description
// ie 'magic armour', 'force field'
@ -2107,6 +1972,7 @@ enum FLAG {
F_VAULTATLF, // v0/1=x/y, v1=pctchance, text=lfname
F_VAULTATCELL, // v0/1=x/y, v1=pctchance, text=cellname
F_VAULTBOX, // v0=thingtype, v1=pctchance, v2=fill?, text=x1,y1,x2,y2,thingname
F_VAULTEXIT, // v0/1=x,y for exit.
F_VAULTSCATTER, // v0=thingtype, v1=pctchance
// text=x1,y1,x2,y2,mincount-maxcount,thingname
// if maxcount is PCT, mincount is a percentage
@ -2363,6 +2229,7 @@ enum VAULTSTATE {
enum VAULTTHING {
VT_NONE,
VT_EXIT,
VT_OB,
VT_LF,
VT_CELL,

View File

@ -38,3 +38,13 @@ Z = undead
---
C
hybrid human animal?
----------
~ = deep liquid (water / lava)
[ = tool
] = armour
} = gas
, = small puddle
{ = large puddle/pool
( = barrel
\ = furniture

View File

@ -17,6 +17,9 @@ General format:
Legend is:
c:type:what[:pct]
OR
c:exit
c = any letter
type = ob, mon or cell
@ -28,6 +31,8 @@ Flags can be:
'type' can be: ob, mon, cell
coords can be negative ("count back from right/bottom")
exitat(x,y) // vault exit is at position x,y
box(x,y,x2,y2) type:what[:pct] // outline box with what
fill(x,y,x2,y2) type:what[:pct] // filled box with what
coords can be negative ("count back from right/bottom")

58
io.c
View File

@ -285,6 +285,59 @@ void animcells(cell_t *src, cell_t **dst, int ndst, int gradual, char ch, char c
needredraw = B_TRUE;
}
void animline(cell_t *src, cell_t *dst, int gradual, char ch, char ch2, int colour) {
glyph_t gl;
int i;
cell_t *retcell[MAXRETCELLS];
int ndst;
calcbresnham(src->map, src->x, src->y, dst->x, dst->y, retcell, &ndst);
gl.ch = ch;
gl.colour = colour;
// hide cursor
curs_set(0);
for (i = 0; i < ndst; i++) {
int n;
if ((i % 2) == 0) {
gl.ch = ch;
} else {
gl.ch = ch2;
}
if (gradual) {
// update screen each time
updateviewfor(src);
drawlevelfor(player);
}
if (gradual) {
// draw one at a time
for (n = 0; n <= i; n++) {
drawglyph(&gl, retcell[n]->x - viewx, retcell[n]->y - viewy);
}
} else {
drawglyph(&gl, retcell[i]->x - viewx, retcell[i]->y - viewy);
}
if (gradual) {
wrefresh(gamewin);
usleep(ANIMDELAY);
}
}
if (!gradual) {
wrefresh(gamewin);
usleep(ANIMDELAY);
}
// show cursor
curs_set(1);
needredraw = B_TRUE;
}
void animradial(cell_t *src, int radius, char ch, int colour) {
glyph_t gl;
int i;
@ -759,7 +812,7 @@ cell_t *askcoords(char *prompt, int targettype, lifeform_t *srclf, int maxrange,
gettopobname(c, buf);
}
} else {
// can't see objects or lf there
// can't see this cell
void *thing;
char desc[BUFLEN];
switch (isinscanrange(c, &thing, desc, NULL)) {
@ -7106,11 +7159,14 @@ void showlfstats(lifeform_t *lf, int showall) {
if (lorelev >= PR_NOVICE) setcol(mainwin, lorecol);
mvwprintw(mainwin, y2, x2, ftext, "Armour Rating");
/*
if (arating > 0) {
wprintw(mainwin, "%d (-%0.0f%% dmg)", arating, getdamreducepct(arating)); y2++;
} else {
wprintw(mainwin, "%d", arating); y2++;
}
*/
wprintw(mainwin, "%d", arating); y2++;
if (lorelev >= PR_NOVICE) unsetcol(mainwin, lorecol);
}

1
io.h
View File

@ -5,6 +5,7 @@ void addheading(prompt_t *p, char *text);
void addmsghist(char *text);
void addpromptq(prompt_t *p, char *q);
void anim(cell_t *src, cell_t *dst, char ch, int colour);
void animline(cell_t *src, cell_t *dst, int gradual, char ch, char ch2, int colour);
void animcells(cell_t *src, cell_t **dst, int ndst, int gradual, char ch, char ch2, int colour);
void animradial(cell_t *src, int radius, char ch, int colour);
void animradialorth(cell_t *src, int radius, char ch, int colour);

33
lf.c
View File

@ -4005,9 +4005,11 @@ int getmaxattacks(lifeform_t *lf) {
// if we have high unarmed skill and our second hand is free,
// we get one more attack
if (getskill(lf, SK_UNARMED) >= PR_ADEPT) {
if (!getequippedob(lf->pack, BP_SECWEAPON)) {
maxattacks++;
if (lfhasflag(lf, F_HUMANOID)) {
if (getskill(lf, SK_UNARMED) >= PR_SKILLED) {
if (hasbp(lf, BP_SECWEAPON) && !getequippedob(lf->pack, BP_SECWEAPON)) {
maxattacks++;
}
}
}
@ -5504,6 +5506,14 @@ int giveskill(lifeform_t *lf, enum SKILL id) {
msg("You can now deflect attacks with your second weapon.");
}
}
} else if (id == SK_UNARMED) {
if ((gamemode == GM_GAMESTARTED) && isplayer(lf)) {
if (f->val[1] == PR_SKILLED) {
if (hasbp(lf, BP_SECWEAPON)) {
msg("You can now make melee attacks with your off-hand.");
}
}
}
} else if (id == SK_SS_ALLOMANCY) {
// give all allomantic spells
mayusespellschool(lf->flags, SS_ALLOMANCY, F_CANCAST);
@ -7268,7 +7278,6 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-3 darts");
addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "javelin");
addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "leather armour");
addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "buckler");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-10 gold coins");
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
@ -10089,12 +10098,9 @@ flag_t *levelabilityready(lifeform_t *lf) {
}
void loseconcentration(lifeform_t *lf) {
flag_t *f;
// stop sprinting
f = lfhasflag(lf, F_SPRINTING);
if (f && f->val[0]) {
killflag(f);
}
stopsprinting(lf);
// boost spells end
stopallspells(lf);
@ -12393,6 +12399,11 @@ void stoprunning(lifeform_t *lf) {
if (f) {
killflag(f);
}
}
void stopsprinting(lifeform_t *lf) {
flag_t *f;
f = lfhasflag(lf, F_SPRINTING);
if (f && f->val[0]) {
killflag(f);
@ -12863,7 +12874,7 @@ void turneffectslf(lifeform_t *lf) {
}
// secret doors, traps, etc?
if (isplayer(lf) && !isinbattle(lf) && !isblind(lf)) {
if (isplayer(lf) && !isinbattle(lf) && !isblind(lf) && !lfhasflag(lf, F_TRAINING)) {
for (i = 0; i < lf->nlos; i++) {
if (!lf->los[i]->lf) {
object_t *o;
@ -13548,6 +13559,7 @@ int usestairs(lifeform_t *lf, object_t *o) {
// move player to new map
moveto(lf, newcell, B_TRUE, B_TRUE);
if ((dir == D_UP) && !isairborne(lf)) {
stopsprinting(adjally[n]); // you can sprint down stairs, but not up
taketime(lf, getmovespeed(lf)*2); // takes longer to climb
} else {
taketime(lf, getmovespeed(lf));
@ -13559,6 +13571,7 @@ int usestairs(lifeform_t *lf, object_t *o) {
c = getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) {
if (!initiatemove(adjally[n], NULL, NULL)) {
stopsprinting(adjally[n]);
movelf(adjally[n], c);
if ((dir == D_UP) && !isairborne(adjally[n])) {
taketime(adjally[n], getmovespeed(adjally[n])*2); // takes longer to climb

1
lf.h
View File

@ -281,6 +281,7 @@ int stone(lifeform_t *lf);
void stopeating(lifeform_t *lf);
void stopresting(lifeform_t *lf);
void stoprunning(lifeform_t *lf);
void stopsprinting(lifeform_t *lf);
int testammo(lifeform_t *lf, object_t *o);
int takeoff(lifeform_t *lf, object_t *o);
void taketime(lifeform_t *lf, long howlong);

44
map.c
View File

@ -1213,7 +1213,9 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
if (rnd(1,100) <= getvaultchance(map)) {
vault_t *v;
v = getvaulttype(map);
if (!createvault(map, i, v, &roomw[i],&roomh[i])) {
if (createvault(map, i, v, &roomw[i],&roomh[i])) {
// failed
} else {
// success
roomvault[i] = v;
}
@ -1309,7 +1311,9 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
while (!done) {
c = getrandomroomcell(map, i);
// if nothing there
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
//if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) {
if (c && cellwalkable(NULL, c, NULL)) {
int obchance;
int nadded = 0;
@ -1330,6 +1334,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir) {
}
if (ntries >= numobs) {
done = B_TRUE;
break;
}
}
@ -1654,6 +1659,11 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
int w,h,x,y;
int minx,miny,maxx,maxy;
flag_t *f;
// default
if (retw) *retw = -1;
if (reth) *reth = -1;
if (!v) {
return B_TRUE;
}
@ -1670,8 +1680,6 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
// get width/height from vault
w = v->w;
h = v->h;
if (retw) *retw = w;
if (reth) *reth = h;
// find vault position
if (calcroompos(map, w, h, &minx, &miny)) {
dblog("** couldn't make vault room!\n");
@ -1698,6 +1706,9 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
}
}
if (retw) *retw = w;
if (reth) *reth = h;
// add other stuff to the vault
addvaultcontents(map, v, minx, miny, maxx, maxy);
@ -1706,19 +1717,19 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth) {
autodoors(map, roomid, minx, miny, maxx, maxy);
}
linkdoors(map, roomid, minx, miny, maxx,maxy);
linkexits(map, roomid, minx, miny, maxx,maxy);
return B_FALSE;
}
// make sure doors in a given room link up to the rest of the map.
void linkdoors(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
// make sure exits/doors in a given room link up to the rest of the map.
void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
int x,y,i;
cell_t *poss[MAXCANDIDATES],*c;
int nposs = 0;
int db = B_FALSE;
if (db) dblog("linkdoors for roomid %d", roomid);
if (db) dblog("linkexits for roomid %d", roomid);
// find all doors // TODO: ...or "exits"
for (y = miny; y <= maxy; y++) {
@ -1726,14 +1737,14 @@ void linkdoors(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
c = getcellat(m, x, y);
if (!c) continue;
if (hasobwithflag(c->obpile, F_DOOR)) {
if (db) dblog("found door at %d,%d",x,y);
if (hasobwithflag(c->obpile, F_DOOR) || hasflagval(m->flags, F_ROOMEXIT, roomid, x, y, NULL)) {
if (db) dblog("found door/exit at %d,%d",x,y);
poss[nposs++] = c;
}
}
}
if (db) dblog("%d doors found.",nposs);
if (db) dblog("%d doors/exits found.",nposs);
// for each door, make sure it links to at least one cell which isn't
// part of this room
@ -1794,12 +1805,12 @@ void linkdoors(map_t *m, int roomid, int minx, int miny, int maxx, int maxy) {
c = getcellindir(poss[i], whichway);
while (c && !cellwalkable(NULL, c, NULL)) {
setcelltype(c, getemptycelltype(c->map->habitat));
c = getcellindir(poss[i], whichway);
c = getcellindir(c, whichway);
}
}
} // end if ncorridors = 0
} // end for each door
if (db) dblog("linkdoors complete.");
if (db) dblog("linkexits complete.");
}
// room w/h are returned in *w and *h if given.
@ -2459,7 +2470,7 @@ cell_t *getrandomcell(map_t *map) {
return cell;
}
cell_t *getrandomcelloftype(map_t *map, int id) {
cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id) {
cell_t *cell;
cell = getrandomcell(map);
while (cell->type->id != id) {
@ -2491,7 +2502,10 @@ cell_t *getrandomroomcell(map_t *map, int roomid) {
for (x = 0; x < map->w; x++) {
c = getcellat(map, x, y);
// is this cell in the correct room and not a wall?
if (c && isempty(c)) {
// using c->type->solid in case we have a room
// filled with boulders
//if (c && cellwalkable(NULL, c, NULL)) {
if (c && !c->type->solid) {
int ok = B_FALSE;
if (c->roomid == roomid) {
ok = B_TRUE;

4
map.h
View File

@ -53,7 +53,7 @@ int getthingchance(int habitat);
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob);
cell_t *getrandomcell(map_t *map);
cell_t *getrandomcelloftype(map_t *map, int id);
cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id);
int getrandomdir(int dirtype);
cell_t *getrandomroomcell(map_t *map, int roomid);
void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells);
@ -76,7 +76,7 @@ int isnewcellok(cell_t *cell, char *err);
int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m);
int iswallindir(cell_t *cell, int dir);
void linkdoors(map_t *m, int roomid, int minx, int miny, int maxx, int maxy);
void linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy);
int linkstairs(object_t *o);
void makedoor(cell_t *cell);
void makelit(cell_t *c, enum LIGHTLEV how, int howlong);

6
move.c
View File

@ -917,7 +917,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
didmsg = B_TRUE;
}
// stop sprinting
stoprunning(lf);
stopsprinting(lf);
}
}
}
@ -1295,7 +1295,7 @@ int opendoor(lifeform_t *lf, object_t *o) {
touch(lf, o);
// stop sprinting
stoprunning(lf);
stopsprinting(lf);
/*
sf = lfhasflag(lf, F_SPRINTING);
if (sf && sf->val[0]) {
@ -1455,7 +1455,7 @@ int closedoor(lifeform_t *lf, object_t *o) {
if (lf) {
// stop sprinting
stoprunning(lf);
stopsprinting(lf);
if (isplayer(lf)) {
msg("You close %s.", obname);

102
objects.c
View File

@ -427,7 +427,10 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
enum FLAG doorflag[5];
int ndoorflags = 0;
addedob[0] = NULL; // just in case we don't add any
// just in case we don't add any
addedob[0] = NULL;
nadded = 0;
nretobs = 0;
localname = strdup(name);
@ -686,6 +689,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack) {
if (!ot) {
//if (gamestarted) msg("DB: No match for object name '%s'", p );
if (db) dblog("DB: No match for object name '%s'", p );
nretobs = 0;
return NULL;
}
}
@ -2046,6 +2050,10 @@ int canseeob(lifeform_t *lf, object_t *o) {
}
}
}
if (isblind(player) && hasflag(o->flags, F_NOFEEL)) {
return B_FALSE;
}
return B_TRUE;
}
@ -2939,9 +2947,9 @@ int getobvalue(object_t *o) {
// do nothing
price += (pow(getspelllevel(f->val[0]), 2) * 2);
} else if (o->type->obclass->id == OC_POTION) {
price += (pow(getspelllevel(f->val[0]), 2) * 15);
price += (pow(getspelllevel(f->val[0]), 2) * 5);
} else if (o->type->obclass->id == OC_WAND) {
price += (pow(getspelllevel(f->val[0]), 2) * 22);
price += (pow(getspelllevel(f->val[0]), 2) * 15);
}
} else if (f->id == F_MANUALOF) {
price *= 124;
@ -4554,21 +4562,32 @@ int getthrowdam(object_t *o) {
return (int)dam;
}
// get either name of top object, or cell type if solid
char *gettopobname(cell_t *c, char *retbuf) {
char buf[BUFLEN];
object_t *o;
o = gettopobject(c);
if (o) {
int nother;
getobname(o, buf, o->amt);
strcat(retbuf, buf);
// other obs here too?
nother = countnoncosmeticobs(c->obpile, B_TRUE) - 1;
if (nother >= 1) {
int nother;
if (c->type->solid) {
strcpy(retbuf, c->type->name);
nother = countnoncosmeticobs(c->obpile, B_TRUE);
if (nother) {
sprintf(buf, " (+%d other thing%s)", nother, (nother == 1) ? "" : "s");
strcat(retbuf, buf);
}
return retbuf;
} else {
object_t *o;
o = gettopobject(c);
if (o) {
getobname(o, buf, o->amt);
strcat(retbuf, buf);
// other obs here too?
nother = countnoncosmeticobs(c->obpile, B_TRUE) - 1;
if (nother >= 1) {
sprintf(buf, " (+%d other thing%s)", nother, (nother == 1) ? "" : "s");
strcat(retbuf, buf);
}
return retbuf;
}
}
return NULL;
}
@ -5074,7 +5093,7 @@ void initobjects(void) {
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_OBHP, 50, 50, NA, NULL);
addflag(lastobjectclass->flags, F_OBHPDRAIN, 1, DT_DECAY, NA, NULL); // ie. corpses last for 50 turns
addoc(OC_TECH, "Technology", "A strange piece of futuristic technology.", '~', C_GREY);
addoc(OC_TECH, "Technology", "A strange piece of futuristic technology.", '[', C_GREY);
addocnoun(lastobjectclass, "technology");
addocnoun(lastobjectclass, "tech");
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -5208,7 +5227,7 @@ void initobjects(void) {
addot(OT_WATERSHALLOW, "shallow water", "Waist-deep water.", MT_WATER, 150, OC_TERRAIN);
addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "{");
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "~");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DEEPWATER, DP_WAIST, NA, NA, NULL);
addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice");
@ -5220,7 +5239,7 @@ void initobjects(void) {
addot(OT_WATERDEEP, "deep water", "Very deep water.", MT_WATER, 300, OC_TERRAIN);
addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BOLDBLUE, NA, NA, "{");
addflag(lastot->flags, F_GLYPH, C_BOLDBLUE, NA, NA, "~");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice");
addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 1, DT_COMPASS, "cloud of steam");
@ -5246,9 +5265,16 @@ void initobjects(void) {
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
addflag(lastot->flags, F_SECRET, 25, NA, NA, NULL);
addot(OT_TRAPTELEPORT, "teleportation trap", "A magical dispersal field.", MT_NOTHING, 0, OC_TRAP);
addflag(lastot->flags, F_TRAP, NA, B_TRUE, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_MAGENTA, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
addot(OT_TRAPARROW, "arrow trap", "A pressure plate which causes arrows to shoot at you.", MT_NOTHING, 0, OC_TRAP);
addflag(lastot->flags, F_TRAP, 25, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 76, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -5257,7 +5283,6 @@ void initobjects(void) {
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
addot(OT_TRAPARROWP, "poison arrow trap", "A pressure plate which causes poisoned arrows to shoot at you.", MT_NOTHING, 0, OC_TRAP);
addflag(lastot->flags, F_TRAP, 25, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -5266,7 +5291,6 @@ void initobjects(void) {
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
addot(OT_TRAPGAS, "gas trap", "A pressure plate which releases poisonous gas.", MT_NOTHING, 0, OC_TRAP);
addflag(lastot->flags, F_TRAP, 27, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -5275,7 +5299,6 @@ void initobjects(void) {
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
addot(OT_TRAPFIRE, "fire trap", "A pressure plate which fires a pillar of flame.", MT_NOTHING, 0, OC_TRAP);
addflag(lastot->flags, F_TRAP, 30, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 59, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -5284,7 +5307,6 @@ void initobjects(void) {
addflag(lastot->flags, F_SECRET, 30, NA, NA, NULL);
addot(OT_TRAPMINE, "landmine trap", "A buried, pressure-sensitive explosive device.", MT_NOTHING, 0, OC_TRAP);
addflag(lastot->flags, F_TRAP, 30, B_TRUE, NA, NULL);
addflag(lastot->flags, F_TRAP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 20, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "^");
@ -5846,6 +5868,12 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
// l5
addot(OT_S_CHAINLIGHTNING, "chain lightning", "Electricity arcs between all nearby enemies.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
///////////////////
// elemental - fire
///////////////////
@ -6080,13 +6108,12 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
// l5
// l6
addot(OT_S_LIGHTNINGSTORM, "lightning storm", "Blasts all visible enemies bolts of lightning from the sky.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
// l6
addot(OT_S_SUMMONANIMALSLG, "summon large animals", "Summons 2-3 large animals.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
@ -7153,7 +7180,7 @@ void initobjects(void) {
addot(OT_ACIDSPLASH, "splash of acid", "A splash corrosive acid.", MT_ACID, 0, OC_MISC);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates");
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
@ -7204,7 +7231,7 @@ void initobjects(void) {
addot(OT_MUDPOOL, "pool of mud", "A large puddle of wet mud.", MT_WATER, 0, OC_MISC);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, ",");
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "{");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -7231,7 +7258,7 @@ void initobjects(void) {
addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool of water.", MT_WATER, 0, OC_MISC);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, ",");
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "{");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 85, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -7249,6 +7276,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_COSMETIC, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addot(OT_BLOODCSPLASH, "splash of cockatrice blood", "A small pool of cockatrice blood.", MT_BLOOD, 0, OC_MISC);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
@ -7280,23 +7308,24 @@ void initobjects(void) {
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL);
addflag(lastot->flags, F_COSMETIC, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SLIPPERY, 3, NA, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "blood stain");
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dries up");
addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "dry up");
addflag(lastot->flags, F_OBHP, 60, 60, NA, NULL);
addflag(lastot->flags, F_OBHP, 45, 45, NA, NULL);
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DRINKABLE, B_TRUE, 0, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addot(OT_WOODENBARREL, "wooden barrel", "A solid wooden barrel.", MT_WOOD, 20, OC_MISC);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
@ -7341,6 +7370,7 @@ void initobjects(void) {
addot(OT_FOOTPRINT, "footprints", "Footprints which show the passage of some kind of creature.", MT_NOTHING, 0, OC_MISC);
addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NO_PLURAL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOGLYPH, NA, NA, NA, NULL);
@ -8003,7 +8033,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL);
addot(OT_JAVELIN, "javelin", "A long, sharp missile weapon.", MT_METAL, 1.5, OC_MISSILE);
addot(OT_JAVELIN, "javelin", "A long, sharp missile weapon.", MT_METAL, 6.5, OC_MISSILE);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_MISSILEDAM, 3, NA, NA, "");
@ -12560,9 +12590,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
throwdam = getthrowdam(o);
dam = (int)((float)throwdam * multiplier);
takedamage(shield, dam, DT_PROJECTILE);
youhit = B_FALSE;
}
}
}
@ -12832,7 +12860,7 @@ void timeeffectsob(object_t *o) {
if (haslos(player, location)) {
getobname(sg, sgname, sg->amt);
canseeloc = B_FALSE;
canseeloc = B_TRUE;
msg("The %s pulses %s!", noprefix(sgname),
(o->blessed == B_CURSED) ? "white" : "black");
}
@ -13177,6 +13205,14 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, lifeform_t *lf) {
losehp(lf, roll("1d4"), DT_BASH, NULL, "a falling rock trap");
}
addob(lf->cell->obpile, "stone");
} else if (oid == OT_TRAPTELEPORT) {
cell_t *newc;
// move somewhere else!
newc = getrandomcelloftype(lf->cell->map, getemptycelltype(lf->cell->map->habitat));
if (newc) {
teleportto(lf, newc, B_TRUE);
}
} else if ((oid == OT_TRAPARROW) || (oid == OT_TRAPARROWP)) {
int dir,bestdir = D_NONE;
cell_t *src;

106
spell.c
View File

@ -1766,6 +1766,92 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster)) {
msg("A relaxing aroma surrounds you.");
}
} else if (spellid == OT_S_CHAINLIGHTNING) {
cell_t *hitcell[MAXRETCELLS]; // all cells which have been hit in total
cell_t *arccell[MAXRETCELLS]; // cells hit this time
cell_t *arccell2[MAXRETCELLS]; // cells hit this time
int nhitcells = 0, narccells,narccells2;
int i;
int range;
int nsides = 6;
range = getspellrange(spellid, power);
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
// create a line of fire towards the target cell
animline(caster->cell, targcell, B_FALSE, '/', '\\', C_WHITE);
if (cansee(player, caster)) {
msg("%s shoot%s a bolt of electricity!",castername, isplayer(caster) ? "" : "s");
}
if (targcell->lf) {
arccell[0] = targcell;
narccells = 1;
} else {
fizzle(caster);
}
nhitcells = 0;
while (narccells) {
int stillseen = B_FALSE;
// everyone takes damage, and mark cells as hit
for (i = 0; i < narccells; i++) {
losehp(arccell[i]->lf, rolldie(2,nsides), DT_ELECTRIC, caster, "an electricity bolt");
hitcell[nhitcells++] = arccell[i];
if (haslos(player, arccell[i])) {
stillseen = B_TRUE;
needredraw = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
}
// now range gets halved and damage lowered
range /= 2;
if (range <= 0) break;
if (--nsides <= 0) break; // ie. max of 5 arcs
// now arc to other cells with lfs still within range
narccells2 = 0;
for (i = 0; i < narccells; i++) {
int x,y;
cell_t *c;
for (y = arccell[i]->y - range ; y <= arccell[i]->y + range; y++) {
for (x = arccell[i]->x - range ; x <= arccell[i]->x + range; x++) {
c = getcellat(targcell->map, x, y);
if (c && c->lf && (c->lf != caster)
&& haslof(arccell[i], c, LOF_NEED, NULL)) {
int n,found = B_FALSE;
// if this cell hasn't been hit...
for (n = 0; n < nhitcells; n++) {
if (hitcell[n] == c) {
found = B_TRUE;
break;
}
}
if (!found) {
// will arc to here
arccell2[narccells2++] = c;
animline(arccell[i], c, B_FALSE, '/', '\\', C_WHITE);
}
}
}
}
}
// replace arccells
for (i = 0; i < narccells2; i++) {
arccell[i] = arccell2[i];
}
narccells = narccells2;
if (narccells && stillseen) {
msg("The electricity arcs!");
}
} // end while narccells
} else if (spellid == OT_S_CLOUDKILL) {
int radius;
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power)) return B_TRUE;
@ -5062,7 +5148,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = targcell->obpile->first ; o ; o = o->next) {
flag_t *f;
f = hasflag(o->flags, F_SECRET);
if (f) {
if (f && (f->val[0] != NA)) {
char obname[BUFLEN];
getobname(o, obname, o->amt);
msg("%s is magically revealed!", obname);
@ -5072,7 +5158,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
}
// remove invisibility
// remove invisibility/hiding
if (targcell->lf) {
flag_t *f, *nextf;
for (f = targcell->lf->flags->first ; f ; f = nextf) {
@ -5082,9 +5168,22 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
killflag(f);
// player can see whoever just appeared, and the caster?
if (cansee(player, targcell->lf) && cansee(player, caster)) {
char tname[BUFLEN];
seen = B_TRUE;
getlfname(targcell->lf, tname);
msg("%s becomes visible!", tname);
}
}
} else if ( (f->id == F_HIDING) &&
!lfhasflagval(caster, F_SPOTTED, targcell->lf->id, NA, NA, NULL)) {
addflag(caster->flags, F_SPOTTED, targcell->lf->id, NA, NA, NULL);
// player can see whoever just appeared, and the caster?
if (cansee(player, targcell->lf) && cansee(player, caster)) {
char tname[BUFLEN];
seen = B_TRUE;
getlfname(targcell->lf, tname);
msg("A hiding %s is revealed!", noprefix(tname));
}
}
}
}
@ -6574,6 +6673,9 @@ int getspellrange(enum OBTYPE spellid, int power) {
case OT_S_LIGHTNINGBOLT:
range = (power*3);
break;
case OT_S_CHAINLIGHTNING:
range = (power*3);
break;
default:
break;
}