- [+] new monsters

- [+] creeping coins
        - [+] pretends to be gold
        - [+] poison breath
    - [+] rat swarm
    - [+] locust swarm
    - [+] baby mind leech
        - [+] mind whip
    - [+] adult mind leech
        - [+] mental feedback
        - [+] l5 psionic - drain intellect spell.  3d6 IQ drain.
- [+] summon swarm spell
- [+] ai: only pathfind if we are >= animal intelligence.
- [+] shadow - drain strength
- [+] show: "you swap places with the _sleeping_ lf"
- [+] problem:
    - [+] i have metalwork = beginner, sewing = novice
    - [+] ...but i could resize cloth objects!
- [+] SAVE broken again. fixed? 
- [+] in fixreachability, glass walls count as nonsolid
- [+] aligned temples:
    - [+] detect auras: free
    - [+] curse removal: free
    - [+] blessings: half price
- [+] change surface map.
    - [+] map difficulty should be very high.
This commit is contained in:
Rob Pearce 2012-12-12 01:00:17 +00:00
parent fe41614a1c
commit c1cb8ea62e
17 changed files with 674 additions and 162 deletions

View File

@ -1,62 +1,62 @@
#all: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h data.c data.h flag.c flag.h god.c god.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h shops.c shops.h spell.c spell.h vault.c vault.h #all: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h data.c data.h flag.c flag.h god.c god.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h shops.c shops.h spell.c spell.h vault.c vault.h
# gcc -Wall -g -o nexus nexus.c ai.c attack.c data.c flag.c god.c io.c lf.c map.c move.c objects.c text.c save.c spell.c shops.c vault.c -lncurses -lsqlite3 # gcc -Wall -g -pg -o nexus nexus.c ai.c attack.c data.c flag.c god.c io.c lf.c map.c move.c objects.c text.c save.c spell.c shops.c vault.c -lncurses -lsqlite3
nexus: ai.o astar.o attack.o data.o findleak.o flag.o god.o io.o lf.o map.o move.o nexus.o objects.o save.o shops.o spell.o text.o vault.o ai.h attack.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h nexus.h objects.h save.h shops.h spell.h text.h vault.h nexus: ai.o astar.o attack.o data.o findleak.o flag.o god.o io.o lf.o map.o move.o nexus.o objects.o save.o shops.o spell.o text.o vault.o ai.h attack.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h nexus.h objects.h save.h shops.h spell.h text.h vault.h
gcc -g -Wall -o nexus ai.o astar.o attack.o data.o findleak.o flag.o god.o io.o lf.o map.o move.o nexus.o objects.o save.o shops.o spell.o text.o vault.o -lncurses -lsqlite3 gcc -g -pg -Wall -o nexus ai.o astar.o attack.o data.o findleak.o flag.o god.o io.o lf.o map.o move.o nexus.o objects.o save.o shops.o spell.o text.o vault.o -lncurses -lsqlite3
ai.o: ai.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h ai.h objects.h save.h shops.h spell.h text.h vault.h ai.o: ai.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h ai.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o ai.o ai.c gcc -Wall -c -g -pg -o ai.o ai.c
attack.o: attack.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h attack.h astar.h objects.h save.h shops.h spell.h text.h vault.h attack.o: attack.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h attack.h astar.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o attack.o attack.c gcc -Wall -c -g -pg -o attack.o attack.c
astar.o: astar.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h attack.h astar.h objects.h save.h shops.h spell.h text.h vault.h astar.o: astar.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h attack.h astar.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o astar.o astar.c gcc -Wall -c -g -pg -o astar.o astar.c
data.o: data.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h data.h objects.h save.h shops.h spell.h text.h vault.h data.o: data.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h data.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o data.o data.c gcc -Wall -c -g -pg -o data.o data.c
findleak.o: findleak.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h findleak.h objects.h save.h shops.h spell.h text.h vault.h findleak.o: findleak.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h findleak.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o findleak.o findleak.c gcc -Wall -c -g -pg -o findleak.o findleak.c
flag.o: flag.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h flag.h objects.h save.h shops.h spell.h text.h vault.h flag.o: flag.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h flag.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o flag.o flag.c gcc -Wall -c -g -pg -o flag.o flag.c
god.o: god.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h god.h objects.h save.h shops.h spell.h text.h vault.h god.o: god.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h god.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o god.o god.c gcc -Wall -c -g -pg -o god.o god.c
io.o: io.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h io.h objects.h save.h shops.h spell.h text.h vault.h io.o: io.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h io.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o io.o io.c gcc -Wall -c -g -pg -o io.o io.c
lf.o: lf.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h lf.h objects.h save.h shops.h spell.h text.h vault.h lf.o: lf.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h lf.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o lf.o lf.c gcc -Wall -c -g -pg -o lf.o lf.c
map.o: map.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h map.h objects.h save.h shops.h spell.h text.h vault.h map.o: map.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h map.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o map.o map.c gcc -Wall -c -g -pg -o map.o map.c
move.o: move.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h move.h objects.h save.h shops.h spell.h text.h vault.h move.o: move.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h move.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o move.o move.c gcc -Wall -c -g -pg -o move.o move.c
nexus.o: nexus.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h nexus.h objects.h save.h shops.h spell.h text.h vault.h nexus.o: nexus.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h nexus.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o nexus.o nexus.c gcc -Wall -c -g -pg -o nexus.o nexus.c
objects.o: objects.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h objects.h objects.h save.h shops.h spell.h text.h vault.h objects.o: objects.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h objects.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o objects.o objects.c gcc -Wall -c -g -pg -o objects.o objects.c
save.o: save.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h save.h objects.h save.h shops.h spell.h text.h vault.h save.o: save.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h save.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o save.o save.c gcc -Wall -c -g -pg -o save.o save.c
shops.o: shops.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h shops.h objects.h save.h shops.h spell.h text.h vault.h shops.o: shops.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h shops.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o shops.o shops.c gcc -Wall -c -g -pg -o shops.o shops.c
spell.o: spell.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h spell.h objects.h save.h shops.h spell.h text.h vault.h spell.o: spell.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h spell.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o spell.o spell.c gcc -Wall -c -g -pg -o spell.o spell.c
text.o: text.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h text.h objects.h save.h shops.h spell.h text.h vault.h text.o: text.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h text.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o text.o text.c gcc -Wall -c -g -pg -o text.o text.c
vault.o: vault.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h vault.h objects.h save.h shops.h spell.h text.h vault.h vault.o: vault.c ai.h attack.h astar.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h vault.h objects.h save.h shops.h spell.h text.h vault.h
gcc -Wall -c -g -o vault.o vault.c gcc -Wall -c -g -pg -o vault.o vault.c
###################### ######################

118
ai.c
View File

@ -1596,8 +1596,9 @@ int ai_housekeeping(lifeform_t *lf, lifeform_t *master) {
if (lfhasflag(lf, F_RAGE)) return B_FALSE; if (lfhasflag(lf, F_RAGE)) return B_FALSE;
if (lfhasflag(lf, F_ISPRISONER) && master && isplayer(master) && cansee(lf, master)) { if (lfhasflag(lf, F_ISPRISONER) && master && isplayer(master) &&
if (isoutdoors(lf->cell->map) && pctchance(20)) { (cansee(lf, master) || isadjacent(lf->cell,master->cell))) {
if (isoutdoors(lf->cell->map) && pctchance(85)) {
object_t *o; object_t *o;
say(lf, "Thanks for getting me out!", SV_TALK); say(lf, "Thanks for getting me out!", SV_TALK);
o = addobfast(master->pack, OT_MANUAL); o = addobfast(master->pack, OT_MANUAL);
@ -1680,13 +1681,15 @@ int ai_inventory_mgt(lifeform_t *lf, int *canattack) {
object_t *curgun,*bestgun; object_t *curgun,*bestgun;
enum BODYPART bp; enum BODYPART bp;
int icanattack = B_FALSE; int icanattack = B_FALSE;
enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
if (lfhasflag(lf, F_RAGE)) return B_FALSE; if (lfhasflag(lf, F_RAGE)) return B_FALSE;
// burdened? // burdened?
if (isburdened(lf)) { if (isburdened(lf) && (iqb >= IQ_ANIMAL)) {
object_t *o,*heaviest = NULL; object_t *o,*heaviest = NULL;
float hevweight = 0; float hevweight = 0;
@ -1717,69 +1720,74 @@ int ai_inventory_mgt(lifeform_t *lf, int *canattack) {
if (db) dblog(".oO { couldn't drop anything }"); if (db) dblog(".oO { couldn't drop anything }");
} }
// do we have a better weapon we could use? // do we have a better weapon we could use?
curwep = getweapon(lf);
bestwep = getbestweapon(lf);
if ((curwep != bestwep) && !isfirearm(curwep)) { if (iqb >= AT_AVERAGE) {
if (db) dblog(".oO { i have a better weapon than my current one (%s > %s) }",bestwep->type->name, curwep ? curwep->type->name : "nothing"); curwep = getweapon(lf);
// weild better one bestwep = getbestweapon(lf);
if (!weild(lf, bestwep)) return B_TRUE;
}
// do we have a better firearm ? if ((curwep != bestwep) && !isfirearm(curwep)) {
curgun = getfirearm(lf); if (db) dblog(".oO { i have a better weapon than my current one (%s > %s) }",bestwep->type->name, curwep ? curwep->type->name : "nothing");
if (curwep && istwohandedfor(curwep, lf)) {
// we are using a two handed weapon. don't
// check for guns.
} else {
bestgun = getbestfirearm(lf);
if (curgun != bestgun) {
if (db) dblog(".oO { i have a better gun than my current one (%s > %s) }",bestgun->type->name, curgun ? curgun->type->name : "nothing");
// weild better one // weild better one
if (!weild(lf, bestgun)) return B_TRUE; if (!weild(lf, bestwep)) return B_TRUE;
} }
}
// do we have ammo for an empty gun? // do we have a better firearm ?
if (curgun) { curgun = getfirearm(lf);
object_t *curammo; if (curwep && istwohandedfor(curwep, lf)) {
curammo = getammo(curgun); // we are using a two handed weapon. don't
if (!curammo) { // check for guns.
o = getrandomammo(lf); } else {
if (o && !loadfirearm(lf, curgun, o)) { bestgun = getbestfirearm(lf);
// success
return B_TRUE; if (curgun != bestgun) {
if (db) dblog(".oO { i have a better gun than my current one (%s > %s) }",bestgun->type->name, curgun ? curgun->type->name : "nothing");
// weild better one
if (!weild(lf, bestgun)) return B_TRUE;
} }
} }
}
// do we have better armour? // do we have ammo for an empty gun?
for (i = 0; i < lf->race->nbodyparts; i++) { if (curgun) {
object_t *curarm; object_t *curammo;
bp = lf->race->bodypart[i].id; curammo = getammo(curgun);
curarm = getarmour(lf, bp); if (!curammo) {
// is it red hot? o = getrandomammo(lf);
if (curarm && hasflag(curarm->flags, F_HOT) && !isimmuneto(lf->flags, DT_FIRE, B_FALSE)) { if (o && !loadfirearm(lf, curgun, o)) {
if (db) dblog("%s o O { wearing a red-hot item. will try to remove it. } ", lf->race->name); // success
if (cantakeoff(lf, curarm, NULL)) {
if (!takeoff(lf, curarm)) {
return B_TRUE; return B_TRUE;
} }
} else {
if (db) dblog("%s o O { cannot remove it. maybe cursed? } ", lf->race->name);
}
}
// do we have a better one?
for (o = lf->pack->first ; o ; o = o->next) {
if (!isdangerousob(o, lf, B_TRUE) && canwear(lf, o, bp) && isbetterarmourthan(o, curarm)) {
// wear this armour instead
if (!wear(lf, o)) return B_TRUE;
} }
} }
} }
if (iqb >= AT_GTAVERAGE) {
// do we have better armour?
for (i = 0; i < lf->race->nbodyparts; i++) {
object_t *curarm;
bp = lf->race->bodypart[i].id;
curarm = getarmour(lf, bp);
// is it red hot?
if (curarm && hasflag(curarm->flags, F_HOT) && !isimmuneto(lf->flags, DT_FIRE, B_FALSE)) {
if (db) dblog("%s o O { wearing a red-hot item. will try to remove it. } ", lf->race->name);
if (cantakeoff(lf, curarm, NULL)) {
if (!takeoff(lf, curarm)) {
return B_TRUE;
}
} else {
if (db) dblog("%s o O { cannot remove it. maybe cursed? } ", lf->race->name);
}
}
// do we have a better one?
for (o = lf->pack->first ; o ; o = o->next) {
if (!isdangerousob(o, lf, B_TRUE) && canwear(lf, o, bp) && isbetterarmourthan(o, curarm)) {
// wear this armour instead
if (!wear(lf, o)) return B_TRUE;
}
}
}
}
// now check whetehr we have ANY weapon // now check whetehr we have ANY weapon
@ -2310,6 +2318,8 @@ int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
int x,y; int x,y;
cell_t *c = NULL,*origc,*targetc; cell_t *c = NULL,*origc,*targetc;
int db = B_FALSE; int db = B_FALSE;
enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
if (lfhasflag(lf, F_DEBUG)) { if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE; db = B_TRUE;
@ -2328,8 +2338,10 @@ int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
// do we ahv an existing path? // do we ahv an existing path?
pathf = lfhasflag(lf, F_AIPATH); pathf = lfhasflag(lf, F_AIPATH);
if (!pathf) { if (!pathf) {
// if we DONT have a direct path, then pathfind. if (iqb >= IQ_ANIMAL) {
pathf = ai_createpathto(lf, targetc); // if we DONT have a direct path, then pathfind.
pathf = ai_createpathto(lf, targetc);
}
} }
if (pathf) { if (pathf) {

View File

@ -1636,7 +1636,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
} }
} }
} else if ((lf->race->id == R_STIRGE) || (lf->race->id == R_LEECH)) { } else if ((lf->race->id == R_STIRGE) || (lf->race->baseid == R_LEECH)) {
if (getexposedlimbs(victim)) { if (getexposedlimbs(victim)) {
// automatically latch on // automatically latch on
if (!lfhasflag(victim, F_NONCORPOREAL) && !hasflag(lf->flags, F_ATTACHEDTO)) { if (!lfhasflag(victim, F_NONCORPOREAL) && !hasflag(lf->flags, F_ATTACHEDTO)) {
@ -3296,7 +3296,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam, int isu
} }
} }
getflags(fp, retflag, &nretflags, F_AUTOTANGLE, F_DRAINONHIT, F_FLAMESTRIKE, F_HEAVYBLOW, F_HITCONFER, getflags(fp, retflag, &nretflags, F_AUTOTANGLE, F_DRAINONHIT, F_DRAINATTONHIT, F_FLAMESTRIKE, F_HEAVYBLOW, F_HITCONFER,
F_RACESLAY, F_REVENGE, F_RUSTED, F_NONE); F_RACESLAY, F_REVENGE, F_RUSTED, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
@ -3312,6 +3312,10 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam, int isu
gainhp(owner, roll(f->text)); gainhp(owner, roll(f->text));
} }
} }
} else if ((f->id == F_DRAINATTONHIT) && victim && !isdead(victim)) {
int amt;
amt = roll(f->text);
statdrain(victim, f->val[0], amt, f->val[1], f->val[2], owner);
} else if (f->id == F_FLAMESTRIKE) { } else if (f->id == F_FLAMESTRIKE) {
if (!hasob(where->obpile, OT_FIRESMALL)) { if (!hasob(where->obpile, OT_FIRESMALL)) {
// ignite // ignite

326
data.c
View File

@ -306,8 +306,11 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_COOKING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_COOKING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LOCKPICKING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LOCKPICKING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_TECHUSAGE, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_TECHUSAGE, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_THROWING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_DRAGONS, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_NATURE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_UNDEAD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_LORE_LANGUAGE, PR_NOVICE, NA, NULL);
// learnable skills // learnable skills
@ -2826,12 +2829,18 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
// "traps" - hiding monsters // "traps" - hiding monsters
addot(OT_COINSHIDING, "coins", "A sneaky hidden creeping coins!", MT_GOLD, 0.01, OC_TRAP, SZ_MINI);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '$', NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ISMONSTER, R_COINS, OT_GOLD, 150, "3,5d10+50"); // reveal if within 3 cells
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addot(OT_GARGOYLE, "gargoyle", "A sneaky hidden gargoyle!", MT_STONE, 80, OC_TRAP, SZ_HUMAN); addot(OT_GARGOYLE, "gargoyle", "A sneaky hidden gargoyle!", MT_STONE, 80, OC_TRAP, SZ_HUMAN);
addflag(lastot->flags, F_GLYPH, C_STONE, '\'', NA, NULL); addflag(lastot->flags, F_GLYPH, C_STONE, '\'', NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ISMONSTER, R_GARGOYLE, OT_STATUE, 140, "3"); // reveal if within 3 cells addflag(lastot->flags, F_ISMONSTER, R_GARGOYLE, OT_STATUE, 140, "3,1"); // reveal if within 3 cells
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
// traps - object only // traps - object only
@ -5264,6 +5273,7 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addot(OT_S_MFEEDBACK, "mental feedback", "Assaults the target's brain with a mental feedback loop, dealing damage based on their intelligence.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_MFEEDBACK, "mental feedback", "Assaults the target's brain with a mental feedback loop, dealing damage based on their intelligence.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Damage dealt is between 10% and 20% of target's intelligence.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Creatures with higher intelligence will take more damage."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Creatures with higher intelligence will take more damage.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
@ -5361,6 +5371,15 @@ void initobjects(void) {
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_DRAINIQ, "drain intellect", "Mentally destroys some of the target's brain cells, resulting in a permenant loss of intelligence.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The target loses 2d6 + ^bpower^nd6 points of IQ.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l6 // l6
addot(OT_S_REMOTEKO, "remote ko", "Disable the conscious part of a creature's mind, instantly knocking it unconscious.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_REMOTEKO, "remote ko", "Disable the conscious part of a creature's mind, instantly knocking it unconscious.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
@ -5412,6 +5431,17 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SUMMONSWARM, "summon swarm", "Summons a swarm of small creatures into existence to aid the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level I, a rat swarm is created.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level II, a spider swarm is created.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level III, a locust swarm is created.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_VARPOWER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l3 // l3
addot(OT_S_CREATEMONSTER, "create monster", "Summons a (probably hostile) monster to a nearby location.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_CREATEMONSTER, "create monster", "Summons a (probably hostile) monster to a nearby location.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V you can control where the monster appears."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V you can control where the monster appears.");
@ -12231,6 +12261,38 @@ void initrace(void) {
addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
// weight & hp come from amt of gold held.
addrace(R_COINS, "creeping coin pile", 50, '\'', C_YELLOW, MT_GOLD, RC_MAGIC, "These magically animated gold coins are often used as traps by paranoid wizards.");
addbodypart(lastrace, BP_BODY, "metal");
addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "50-100 gold coins");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_GETKILLEDVERB, NA, NA, NA, "defeat");
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_VERYSLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 6, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOBREATH, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOSTAM, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOTAKECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NONAUSEA, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_CLOUDKILL, NA, NA, "pw:1;range:1;");
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_PRETENDSTOBE, OT_GOLD, NA, NA, NULL);
addrace(R_DARKMANTLE, "darklurk", 70, 'U', C_DARKBLUE, MT_FLESH, RC_MAGIC, "A floating squid-like creature, rarely seen due to its ability to cloak itself in a magical darkness. They use their huge tentacles to grab then crush their unsuspecting prey."); addrace(R_DARKMANTLE, "darklurk", 70, 'U', C_DARKBLUE, MT_FLESH, RC_MAGIC, "A floating squid-like creature, rarely seen due to its ability to cloak itself in a magical darkness. They use their huge tentacles to grab then crush their unsuspecting prey.");
addbodypart(lastrace, BP_BODY, NULL); addbodypart(lastrace, BP_BODY, NULL);
addbodypart(lastrace, BP_LEGS, "tentacles"); addbodypart(lastrace, BP_LEGS, "tentacles");
@ -15638,8 +15700,8 @@ void initrace(void) {
addflag(lastrace->flags, F_EATCONFER, F_MUTABLE, B_TRUE, NA, "100"); addflag(lastrace->flags, F_EATCONFER, F_MUTABLE, B_TRUE, NA, "100");
addrace(R_BATBRAIN, "brain bat", 6, 'B', C_PINK, MT_FLESH, RC_ANIMAL, "Rare bats, said to exhibit strange psionic behaviour."); addrace(R_BATBRAIN, "brain bat", 6, 'B', C_PINK, MT_FLESH, RC_ANIMAL, "Rare bats, said to exhibit strange psionic behaviour.");
setbodytype(lastrace, BT_BIRD); setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_RARE, NULL); addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_RARE, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
@ -15869,7 +15931,7 @@ void initrace(void) {
addflag(lastrace->flags, F_FELINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_FELINE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HATESRACEWITHFLAG, F_CANINE, NA, NA, NULL); addflag(lastrace->flags, F_HATESRACEWITHFLAG, F_CANINE, NA, NA, NULL);
addrace(R_CATSHADOW, "shadowcat", 5, 'f', C_DARKGREY, MT_FLESH, RC_MAGIC, "A huge, feral black cat, surrounded by clouds of black smoke."); addrace(R_CATSHADOW, "shadowcat", 5, 'f', C_VDARKGREY, MT_FLESH, RC_MAGIC, "A huge, feral black cat, surrounded by clouds of black smoke.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
@ -16821,6 +16883,78 @@ void initrace(void) {
addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "slither"); addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "slither");
addrace(R_LEECHMIND, "baby mind leech", 10, 'j', C_PINK, MT_FLESH, RC_ANIMAL, "A mutated form of leech which feeds on one's intellect.");
addbodypart(lastrace, BP_BODY, NULL);
lastrace->baseid = R_LEECH;
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_VULNTOSALT, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_VERYRARE, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_VERYRARE, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL);
addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:2;");
addflag(lastrace->flags, F_CANWILL, OT_S_MINDWHIP, NA, NA, "range:1;pw:1;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_MINDWHIP, NA, NA, "sways");
addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "slither");
addrace(R_LEECHMINDA, "mind leech", 10, 'j', C_LIGHTPINK, MT_FLESH, RC_ANIMAL, "A mutated form of leech which feeds on one's intellect.");
addbodypart(lastrace, BP_BODY, NULL);
lastrace->baseid = R_LEECH;
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_VULNTOSALT, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_VERYRARE, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_VERYRARE, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 6, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL);
addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 3, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:2;");
addflag(lastrace->flags, F_CANWILL, OT_S_MFEEDBACK, NA, NA, "range:1;pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_DRAINIQ, NA, NA, "range:1;pw:2;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_MFEEDBACK, NA, NA, "sways");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_DRAINIQ, NA, NA, "sways");
addflag(lastrace->flags, F_CASTCHANCE, 80, NA, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "slither");
addflag(lastrace->flags, F_FILLPOT, OT_POT_MAGIC, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_ATTRMOD, A_IQ, 10, "75");
addrace(R_MAMMOTH, "mammoth", 6000, 'Q', C_DARKYELLOW, MT_LEATHER, RC_ANIMAL, "A massive ancenstor of the elephant, mammoths are covered with fur, slightly larger and more dangerous."); addrace(R_MAMMOTH, "mammoth", 6000, 'Q', C_DARKYELLOW, MT_LEATHER, RC_ANIMAL, "A massive ancenstor of the elephant, mammoths are covered with fur, slightly larger and more dangerous.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
@ -16973,6 +17107,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^squeaking"); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^squeaking");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 1, NA, "squeaks^squeaking"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 1, NA, "squeaks^squeaking");
addrace(R_RATMIND, "mesmerat", 3, 'r', C_PINK, MT_FLESH, RC_ANIMAL, "Glowing, irradiated rats which have developed amazing intellects and mental powers."); addrace(R_RATMIND, "mesmerat", 3, 'r', C_PINK, MT_FLESH, RC_ANIMAL, "Glowing, irradiated rats which have developed amazing intellects and mental powers.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
@ -17480,6 +17615,36 @@ void initrace(void) {
addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, ""); addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, "");
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep"); addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep");
addrace(R_SPIDERPHASE, "phase spider", 5, 'S', C_PINK, MT_FLESH, RC_DEMON, "A strange eight legged beast which seems to be vaguely translucent.");
setbodytype(lastrace, BT_SPIDER);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_NONAUSEA, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_XRAYVIS, 3, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 1, 4, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL); // don't announce spellcasting
addflag(lastrace->flags, F_SPIDERCLIMB, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, "20-30");
addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL); // weak
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep");
addrace(R_SPIDERFUNNELWEB, "giant funnelweb", 5, 'S', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Like a giant spider... but extremely venomous."); addrace(R_SPIDERFUNNELWEB, "giant funnelweb", 5, 'S', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Like a giant spider... but extremely venomous.");
setbodytype(lastrace, BT_SPIDER); setbodytype(lastrace, BT_SPIDER);
lastrace->baseid = R_SPIDER; lastrace->baseid = R_SPIDER;
@ -17562,33 +17727,6 @@ void initrace(void) {
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep"); addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep");
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL); addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL);
addrace(R_SPIDERSWARM, "swarm of spiders", 10, UNI_SWARM, C_DARKGREY, MT_FLESH, RC_HUMANOID, "A fast-moving swarm of deadly spiders.");
addbodypart(lastrace, BP_BODY, "swarm");
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_GETKILLEDVERB, NA, NA, NA, "disperse");
addflag(lastrace->flags, F_NOTAKECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOGIVECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 6, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 7, 7, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SWARM, NA, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling");
addrace(R_SPIDERTOMB, "tomb spider", 5, 'S', C_DARKBLUE, MT_FLESH, RC_ANIMAL, "Tomb spiders are truly nightmarish beings. Their skin can absorb light itself, and they can boost their own life force by consuming the flesh of their victims."); addrace(R_SPIDERTOMB, "tomb spider", 5, 'S', C_DARKBLUE, MT_FLESH, RC_ANIMAL, "Tomb spiders are truly nightmarish beings. Their skin can absorb light itself, and they can boost their own life force by consuming the flesh of their victims.");
setbodytype(lastrace, BT_SPIDER); setbodytype(lastrace, BT_SPIDER);
@ -17628,6 +17766,95 @@ void initrace(void) {
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep"); addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep");
addrace(R_SWARMLOCUST, "swarm of locusts", 50, UNI_SWARM, C_GREY, MT_FLESH, RC_INSECT, "An enormous swarm of angry locusts.");
addbodypart(lastrace, BP_BODY, "swarm");
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_GETKILLEDVERB, NA, NA, NA, "disperse");
addflag(lastrace->flags, F_NOTAKECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOGIVECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 6, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 8, 8, NA, NULL);
addflag(lastrace->flags, F_STENCH, 1, 2, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOSTAM, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SWARM, NA, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_EXHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_EXLOW, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_FLY, SV_TALK, NA, "^buzzing wings");
addflag(lastrace->flags, F_NATURALFLIGHT, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_A_FLY, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_A_FLY, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_FLIGHT, PR_BEGINNER, NA, NULL);
addrace(R_SWARMRAT, "swarm of rats", 40, UNI_SWARM, C_BROWN, MT_FLESH, RC_ANIMAL, "A large swarm of vile rodents.");
addbodypart(lastrace, BP_BODY, "swarm");
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_GETKILLEDVERB, NA, NA, NA, "disperse");
addflag(lastrace->flags, F_NOTAKECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOGIVECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 3, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 5, 5, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SWARM, NA, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling");
addrace(R_SWARMSPIDER, "swarm of spiders", 10, UNI_SWARM, C_DARKGREY, MT_FLESH, RC_ANIMAL, "A fast-moving swarm of deadly spiders.");
addbodypart(lastrace, BP_BODY, "swarm");
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_GETKILLEDVERB, NA, NA, NA, "disperse");
addflag(lastrace->flags, F_NOTAKECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOGIVECRITS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 7, 7, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SWARM, NA, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling");
addrace(R_SWAN, "swan", 1, 'c', C_WHITE, MT_FLESH, RC_ANIMAL, "A graceful waterbird."); addrace(R_SWAN, "swan", 1, 'c', C_WHITE, MT_FLESH, RC_ANIMAL, "A graceful waterbird.");
setbodytype(lastrace, BT_BIRD); setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
@ -17769,6 +17996,7 @@ void initrace(void) {
addrace(R_WOLFWINTER, "winter wolf", 25, 'd', C_WHITE, MT_FLESH, RC_ANIMAL, "Wolves which have lived in close proximity to the undead sometimes mutate into these frosty beasts. While their claws have become less sharp, they instead deal unnatural cold damage."); addrace(R_WOLFWINTER, "winter wolf", 25, 'd', C_WHITE, MT_FLESH, RC_ANIMAL, "Wolves which have lived in close proximity to the undead sometimes mutate into these frosty beasts. While their claws have become less sharp, they instead deal unnatural cold damage.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_TERRITORIAL, 3, NA , NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
@ -18467,7 +18695,7 @@ void initrace(void) {
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL); addflag(lastrace->flags, F_TR, 4, NA, NA, NULL);
@ -19326,6 +19554,38 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "growls^a growl"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "growls^a growl");
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_SHADOW, "shadow", 0.01, 'Z', C_DARKGREY, MT_FLESH, RC_UNDEAD, "A dark shadowy shape which seems to move on its own...");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_EXLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_VLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_EXLOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_NOSTAIRS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_LEVITATING, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TOUCHNECROTIC, 3, NA, NULL);
addflag(lastrace->flags, F_HITCONFER, F_REVIVETIMER, NA, 0, NULL);
addflag(lastrace->flags, F_HITCONFERVALS, 0, 1, R_SHADOW, "rises up as a shadow");
addflag(lastrace->flags, F_HITCONFERRC, RC_HUMANOID, NA, NA, NULL);
addflag(lastrace->flags, F_HITCONFERDEADONLY, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DRAINATTONHIT, A_STR, SC_NONE, -1, "3d6");
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_SKELETON, "skeleton", 20, 'Z', C_BONE, MT_BONE, RC_UNDEAD, "A walking set of bones, animated through the use of necromancy. Due to their lack of soft flesh, they have little to fear from edged weapons."); addrace(R_SKELETON, "skeleton", 20, 'Z', C_BONE, MT_BONE, RC_UNDEAD, "A walking set of bones, animated through the use of necromancy. Due to their lack of soft flesh, they have little to fear from edged weapons.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
setbodypartname(lastrace, BP_WEAPON, "right metacarpals"); setbodypartname(lastrace, BP_WEAPON, "right metacarpals");
@ -19454,7 +19714,7 @@ void initrace(void) {
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL); addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);

24
defs.h
View File

@ -738,6 +738,7 @@ enum COLOUR {
C_LIGHTMAGENTA, C_LIGHTMAGENTA,
C_LIGHTRED, C_LIGHTRED,
C_LIGHTYELLOW, C_LIGHTYELLOW,
C_LIGHTPINK,
C_LAST C_LAST
}; };
@ -966,6 +967,7 @@ enum ATTRIB {
#define MAXATTS 6 #define MAXATTS 6
enum CHECKTYPE { enum CHECKTYPE {
SC_NONE = 0,
SC_STR, SC_STR,
SC_DEX, SC_DEX,
SC_IQ, SC_IQ,
@ -1297,6 +1299,7 @@ enum RACE {
R_CENTAUR, R_CENTAUR,
R_CHIMERA, R_CHIMERA,
R_COCKATRICE, R_COCKATRICE,
R_COINS,
R_CREEPINGCLAW, R_CREEPINGCLAW,
R_CRYMIDIA, R_CRYMIDIA,
R_DARKMANTLE, R_DARKMANTLE,
@ -1439,6 +1442,8 @@ enum RACE {
R_HORSE, R_HORSE,
R_FROG, R_FROG,
R_LEECH, R_LEECH,
R_LEECHMIND,
R_LEECHMINDA,
R_MAMMOTH, R_MAMMOTH,
R_NEWT, R_NEWT,
R_PORCUPINE, R_PORCUPINE,
@ -1459,11 +1464,14 @@ enum RACE {
R_SNAKETREE, R_SNAKETREE,
R_SNAKEWATER, R_SNAKEWATER,
R_SPIDER, R_SPIDER,
R_SPIDERPHASE,
R_SPIDERFUNNELWEB, R_SPIDERFUNNELWEB,
R_SPIDERREDBACK, R_SPIDERREDBACK,
R_SPIDERSWARM,
R_SPIDERTOMB, R_SPIDERTOMB,
R_SWAN, R_SWAN,
R_SWARMSPIDER,
R_SWARMRAT,
R_SWARMLOCUST,
R_WOLFYOUNG, R_WOLFYOUNG,
R_WOLF, R_WOLF,
R_WOLFDIRE, R_WOLFDIRE,
@ -1521,6 +1529,7 @@ enum RACE {
R_MUMMY, R_MUMMY,
R_MUMMYG, R_MUMMYG,
R_REVENANT, R_REVENANT,
R_SHADOW,
R_SKELETON, R_SKELETON,
R_SKELETONFIRE, R_SKELETONFIRE,
R_SKELLION, R_SKELLION,
@ -1732,6 +1741,7 @@ enum OBTYPE {
OT_TRAPTRIP, OT_TRAPTRIP,
OT_TRAPWIND, OT_TRAPWIND,
// traps - hiding monsters // traps - hiding monsters
OT_COINSHIDING,
OT_GARGOYLE, OT_GARGOYLE,
// rocks // rocks
OT_ASH, OT_ASH,
@ -2030,6 +2040,7 @@ enum OBTYPE {
OT_S_CHISTRIKE, OT_S_CHISTRIKE,
OT_S_DELAYDEATH, OT_S_DELAYDEATH,
OT_S_DISORIENT, OT_S_DISORIENT,
OT_S_DRAINIQ,
OT_S_HUNGER, OT_S_HUNGER,
OT_S_LETHARGY, OT_S_LETHARGY,
OT_S_LOWERMETAB, OT_S_LOWERMETAB,
@ -2101,6 +2112,7 @@ enum OBTYPE {
OT_S_GLYPHWARDING, OT_S_GLYPHWARDING,
OT_S_CLEARLEVEL, OT_S_CLEARLEVEL,
OT_S_CREATEMONSTER, OT_S_CREATEMONSTER,
OT_S_SUMMONSWARM,
OT_S_SUMMONWEAPON, OT_S_SUMMONWEAPON,
// -- translocation // -- translocation
OT_S_APPORTATION, OT_S_APPORTATION,
@ -2995,7 +3007,9 @@ enum FLAG {
// v0 = race id of monster // v0 = race id of monster
// v1 = object id to hide as // v1 = object id to hide as
// v2 = spot check difficulty (or NA) // v2 = spot check difficulty (or NA)
// text = reveal ourselves if prey <= this distance // text = dist,xdy
// dist = reveal ourselves if prey <= dist
// xdy = dice string amount of obs to appear
// //
// Also see: F_PRETENDSTOBE // Also see: F_PRETENDSTOBE
@ -3039,8 +3053,12 @@ enum FLAG {
F_CRITKNOCKDOWN, // lf knocks down victims on a critical hit F_CRITKNOCKDOWN, // lf knocks down victims on a critical hit
F_DRAINONHIT, // victims hit by this lf get v0 xplevs drained unless F_DRAINONHIT, // victims hit by this lf get v0 xplevs drained unless
// they pass a skillcheck of type v1, diff v2. // they pass a skillcheck of type v1, diff v2.
// v1 can be NA. // v1 can be SC_NONE.
// if successful, lf gains 'text' hp (in dice format) // if successful, lf gains 'text' hp (in dice format)
F_DRAINATTONHIT, // victims hit by this lf lose 'text' (dice format)
// from attrib v0, unless they make a skill check
// of type v1, diff v2. v1 can be SC_NONE.
// if ATT drops to zero, target dies.
F_HITCONFER, // hitting with this gives flagid=v0 F_HITCONFER, // hitting with this gives flagid=v0
// with timeleft = text ("min-max" // with timeleft = text ("min-max"
// or NULL for permenant) // or NULL for permenant)

3
god.c
View File

@ -2328,6 +2328,9 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
dospelleffects(god, OT_S_CUREPOISON, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE, NULL); dospelleffects(god, OT_S_CUREPOISON, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE, NULL);
} }
// fix drained stats
restoredrainedstats(lf);
if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) {
int i,nretflags; int i,nretflags;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];

3
io.c
View File

@ -9768,6 +9768,7 @@ void initgfx(void) {
initcol(C_LIGHTGREEN, 500, 1000, 500); initcol(C_LIGHTGREEN, 500, 1000, 500);
initcol(C_LIGHTMAGENTA, 1000, 500, 1000); initcol(C_LIGHTMAGENTA, 1000, 500, 1000);
initcol(C_LIGHTYELLOW, 1000, 1000, 500); initcol(C_LIGHTYELLOW, 1000, 1000, 500);
initcol(C_PINK, 1000, 584, 776);
// placeholder // placeholder
initcol(C_LAST, 0, 0, 0); initcol(C_LAST, 0, 0, 0);
@ -13392,7 +13393,7 @@ void showlfstats(lifeform_t *lf, int showall) {
if (!lfhasflag(lf, F_NOSTAM)) { if (!lfhasflag(lf, F_NOSTAM)) {
pen = gettempstammod(lf, temp); pen = gettempstammod(lf, temp);
if (pen != 100) { if (pen != 100) {
mvwprintw(mainwin, y, 0, " %d%% Stamina usage due to heat.",pen); y++; mvwprintw(mainwin, y, 0, " %d%% stamina usage due to heat.",pen); y++;
} }
} }
if (!lfhasflag(lf, F_NOSLEEP) && (temp >= T_HOT)) { if (!lfhasflag(lf, F_NOSLEEP) && (temp >= T_HOT)) {

82
lf.c
View File

@ -3293,6 +3293,8 @@ void die(lifeform_t *lf) {
if (hunger > 0) { if (hunger > 0) {
modhunger(lf, -hunger); modhunger(lf, -hunger);
} }
// fix drained attribs
restoredrainedstats(lf);
// put out fires // put out fires
extinguishlf(lf); extinguishlf(lf);
if (thisisplayer) { if (thisisplayer) {
@ -5351,6 +5353,9 @@ int eat(lifeform_t *lf, object_t *o) {
// blink! // blink!
dospelleffects(lf, OT_S_BLINK, 1, lf, NULL, NULL, B_UNCURSED, NULL, B_TRUE, NULL); dospelleffects(lf, OT_S_BLINK, 1, lf, NULL, NULL, B_UNCURSED, NULL, B_TRUE, NULL);
stopeating = B_TRUE;
} else if (hasflagval(o->flags, F_CORPSEOF, R_SPIDERPHASE, NA, NA, NULL)) {
addtempflag(lf->flags, F_NONCORPOREAL, B_TRUE, NA, NA, NULL, 15);
stopeating = B_TRUE; stopeating = B_TRUE;
} else if (hasflagval(o->flags, F_CORPSEOF, R_BLASTBUG, NA, NA, NULL)) { } else if (hasflagval(o->flags, F_CORPSEOF, R_BLASTBUG, NA, NA, NULL)) {
dospelleffects(lf, OT_S_DETONATE, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); dospelleffects(lf, OT_S_DETONATE, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL);
@ -13695,7 +13700,6 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJUR
return B_FALSE; return B_FALSE;
} }
// return TRUE on failure // return TRUE on failure
int leveldrain(lifeform_t *lf, int amt, enum CHECKTYPE sctype, int scdiff, lifeform_t *fromlf) { int leveldrain(lifeform_t *lf, int amt, enum CHECKTYPE sctype, int scdiff, lifeform_t *fromlf) {
int resisted = B_FALSE; int resisted = B_FALSE;
@ -14733,6 +14737,7 @@ int isfullyhealed(lifeform_t *lf) {
} }
int isexhausted(lifeform_t *lf) { int isexhausted(lifeform_t *lf) {
if (lfhasflag(lf, F_NOSTAM)) return B_FALSE;
if (!getstamina(lf)) return B_TRUE; if (!getstamina(lf)) return B_TRUE;
return B_FALSE; return B_FALSE;
} }
@ -18228,6 +18233,11 @@ int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o, int *pctmod) {
int mightflee(lifeform_t *lf) { int mightflee(lifeform_t *lf) {
flag_t *f; flag_t *f;
enum ATTRBRACKET iqb; enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
if (iqb < IQ_ANIMAL) {
// too stupid to know to flee
return B_FALSE;
}
if (hasflag(lf->flags, F_NOFLEE)) { if (hasflag(lf->flags, F_NOFLEE)) {
return B_FALSE; return B_FALSE;
@ -22308,6 +22318,8 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
int roll,db = B_FALSE; int roll,db = B_FALSE;
char dbtag[BUFLEN]; char dbtag[BUFLEN];
if (ct == SC_NONE) return B_FALSE;
if (lfhasflag(lf, F_DEBUG)) { if (lfhasflag(lf, F_DEBUG)) {
if (ct != SC_STEALTH) { // dont show debug info for stealth checks if (ct != SC_STEALTH) { // dont show debug info for stealth checks
db = B_TRUE; db = B_TRUE;
@ -22367,6 +22379,18 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
return B_FALSE; return B_FALSE;
} }
int restoredrainedstats(lifeform_t *lf) {
enum ATTRIB a;
int donesomething = B_FALSE;
for (a = 0; a < MAXATTS; a++) {
if ((lf->baseatt[a] > 0) && (getattr(lf, a) <= 0)) {
setattr(lf, a, lf->baseatt[a]);
donesomething = B_TRUE;
}
}
return donesomething;
}
// returns TRUE if lf1 succeeded, FALSE if lf1 failed. // returns TRUE if lf1 succeeded, FALSE if lf1 failed.
int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, enum CHECKTYPE ct2, int mod2) { int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, enum CHECKTYPE ct2, int mod2) {
int roll1,roll2; int roll1,roll2;
@ -22531,6 +22555,44 @@ void sortlf(map_t *map, lifeform_t *lf) {
} }
} }
// return TRUE on failure
int statdrain(lifeform_t *lf, enum ATTRIB attr, int amt, enum CHECKTYPE sctype, int scdiff, lifeform_t *fromlf) {
int resisted = B_FALSE;
if (isimmuneto(lf->flags, DT_NECROTIC, B_FALSE)) resisted = B_TRUE;
if (!resisted && isresistantto(lf->flags, DT_NECROTIC, B_FALSE) && onein(2)) resisted = B_TRUE;
// skill check
if (!resisted && skillcheck(lf, sctype, scdiff, 0 )) {
resisted = B_TRUE;
}
if (resisted) {
if (isplayer(lf)) {
msg("You struggle to retain your %s!", getattrname(attr));
}
return B_TRUE;
}
// announce
if (fromlf) {
char lfname[BUFLEN];
char buf[BUFLEN];
sprintf(buf, "%s-drained",getattrname(attr));
setkillverb(lf, buf);
real_getlfnamea(fromlf, lfname, NULL, B_TRUE, B_TRUE);
setlastdam(lf, lfname);
} else {
char buf[BUFLEN];
sprintf(buf, "%s drain",getattrname(attr));
setkillverb(lf, "Killed");
setlastdam(lf, buf);
}
if (fromlf) {
lf->lastdamlf = fromlf->id;
}
modattr(lf, attr, -amt);
return B_FALSE;
}
////////////////////////////////// //////////////////////////////////
// effects which happen before every TURN // effects which happen before every TURN
// (ie. the faster the player is, the faster they happen) // (ie. the faster the player is, the faster they happen)
@ -22551,6 +22613,7 @@ void startlfturn(lifeform_t *lf) {
int nretflags; int nretflags;
int movedlastturn = B_FALSE; int movedlastturn = B_FALSE;
object_t *bloodamu = NULL; object_t *bloodamu = NULL;
enum ATTRIB a;
enum TIMEPHASE tp; enum TIMEPHASE tp;
enum FLAG inair = F_NONE; enum FLAG inair = F_NONE;
enum TEMPERATURE temp; enum TEMPERATURE temp;
@ -22701,7 +22764,7 @@ void startlfturn(lifeform_t *lf) {
if (!cellwalkable(lf, lf->cell, &error)) { if (!cellwalkable(lf, lf->cell, &error)) {
if ((error == E_WALLINWAY) && !isclimbing(lf)) { if ((error == E_WALLINWAY) && !isclimbing(lf)) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You reintegrate inside a solid object!"); msg("^%cYou reintegrate inside a solid object!",getlfcol(lf, CC_VBAD));
} }
losehp(lf, 9999, DT_DIRECT, NULL, "re-integration inside a solid object"); losehp(lf, 9999, DT_DIRECT, NULL, "re-integration inside a solid object");
//} //}
@ -23497,6 +23560,21 @@ void startlfturn(lifeform_t *lf) {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
for (a = 0; a < MAXATTS; a++) {
if ((lf->baseatt[a] > 0) && (getattr(lf, a) <= 0)) {
char buf[BUFLEN];
sprintf(buf, "%s drain",getattrname(a));
setkillverb(lf, "Killed");
setlastdam(lf, buf);
if (isplayer(lf)) {
msg("^%cThe last of your %s drains away...", getlfcol(lf, CC_VBAD), getattrname(a)); more();
}
lf->hp = 0;
return;
}
}
o = hasequippedobid(lf->pack, OT_AMU_CHOKING); o = hasequippedobid(lf->pack, OT_AMU_CHOKING);
if (o && needstobreath(lf)) { if (o && needstobreath(lf)) {
int seen = B_FALSE; int seen = B_FALSE;

2
lf.h
View File

@ -518,9 +518,11 @@ int shoot(lifeform_t *lf);
int getskillcheckchance(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod) ; int getskillcheckchance(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod) ;
int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod); int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod);
int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *result); int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *result);
int restoredrainedstats(lifeform_t *lf);
int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, enum CHECKTYPE ct2, int mod2); int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, enum CHECKTYPE ct2, int mod2);
int slipon(lifeform_t *lf, object_t *o); int slipon(lifeform_t *lf, object_t *o);
void sortlf(map_t *map, lifeform_t *lf); void sortlf(map_t *map, lifeform_t *lf);
int statdrain(lifeform_t *lf, enum ATTRIB attr, int amt, enum CHECKTYPE sctype, int scdiff, lifeform_t *fromlf);
void startlfturn(lifeform_t *lf); void startlfturn(lifeform_t *lf);
int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag); int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag);
int stir(lifeform_t *lf, int vol, int dist, char *noisetext); int stir(lifeform_t *lf, int vol, int dist, char *noisetext);

4
map.c
View File

@ -2639,7 +2639,7 @@ void floodfill(cell_t *startcell) {
int d; int d;
object_t *o; object_t *o;
if (startcell && // not off the map if (startcell && // not off the map
!startcell->type->solid && // empty cell (!startcell->type->solid || (startcell->type->id == CT_WALLGLASS)) && // empty cell
!startcell->filled) { // not already filled !startcell->filled) { // not already filled
startcell->filled = B_TRUE; startcell->filled = B_TRUE;
} else { } else {
@ -8768,7 +8768,7 @@ void initmap(void) {
addbranch(BH_BABAYAGAHUT, "Baba Yaga's Hut", B_FALSE, H_BYHUT, 0, 0, D_NONE, B_FALSE, 0, B_FALSE); addbranch(BH_BABAYAGAHUT, "Baba Yaga's Hut", B_FALSE, H_BYHUT, 0, 0, D_NONE, B_FALSE, 0, B_FALSE);
addbranch(BH_WORLDMAP, "The Surface", B_FALSE, H_FOREST, 10, 0, D_NONE, B_TRUE, 0, B_FALSE); addbranch(BH_WORLDMAP, "The Surface", B_FALSE, H_FOREST, 10, 0, D_NONE, B_TRUE, 20, B_FALSE);
addbranch(BH_HEAVEN, "The Realm of Gods", B_FALSE, H_HEAVEN, 1, 0, D_NONE, B_FALSE, 0, B_FALSE); addbranch(BH_HEAVEN, "The Realm of Gods", B_FALSE, H_HEAVEN, 1, 0, D_NONE, B_FALSE, 0, B_FALSE);
// main branches // main branches
addbranch(BH_MAINDUNGEON, "The Main Dungeon", B_FALSE, H_DUNGEON, 25, 3, D_DOWN, B_TRUE, 0, B_FALSE); addbranch(BH_MAINDUNGEON, "The Main Dungeon", B_FALSE, H_DUNGEON, 25, 3, D_DOWN, B_TRUE, 0, B_FALSE);

8
move.c
View File

@ -3527,7 +3527,13 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
// act of moving will clear the message line and we'll never // act of moving will clear the message line and we'll never
// see it. // see it.
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You swap places with %s.", lfname); if (isunconscious(lfinway)) {
msg("You swap places with the unconscious %s.", noprefix(lfname));
} else if (isasleep(lfinway)) {
msg("You swap places with the sleeping %s.", noprefix(lfname));
} else {
msg("You swap places with %s.", lfname);
}
dontclearmsg = B_TRUE; dontclearmsg = B_TRUE;
} }

View File

@ -1583,9 +1583,16 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
// hiding monsters? // hiding monsters?
f = hasflag(o->flags, F_ISMONSTER); f = hasflag(o->flags, F_ISMONSTER);
if (f) { if (f) {
char *cp,nbuf[BUFLEN];
int amt;
object_t *oo; object_t *oo;
oo = addobfast(o->contents, f->val[1]); oo = addobfast(o->contents, f->val[1]);
assert(oo); assert(oo);
cp = readuntil(nbuf,f->text, ',');
cp = readuntil(nbuf,cp, '-'); // really eol
amt = roll(nbuf);
if (amt < 0) amt = 1;
oo->amt = amt;
} }
// extra chance of bone items being cursed // extra chance of bone items being cursed
@ -5825,7 +5832,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
cell_t *where; cell_t *where;
int no_a = B_FALSE; int no_a = B_FALSE;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags = 0; int nretflags = 0,i;
// default to normal name // default to normal name
/* /*
@ -5838,7 +5845,11 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
if (hasflag(o->flags, F_ISMONSTER)) { if (hasflag(o->flags, F_ISMONSTER)) {
if (o->contents->first) { if (o->contents->first) {
if ((count == o->amt) || (count == ALL)) {
count = o->contents->first->amt;
}
o = o->contents->first; o = o->contents->first;
limit(&count, 1, o->amt);
} }
} }
@ -5856,8 +5867,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
float pct; float pct;
char dname[BUFLEN]; char dname[BUFLEN];
char adjective[BUFLEN]; char adjective[BUFLEN];
lifeform_t *who = NULL; lifeform_t *who = NULL;
pct = ((float)f->lifetime / (float)TM_SCENT)*100; pct = ((float)f->lifetime / (float)TM_SCENT)*100;
if (pct >= 66) { if (pct >= 66) {
strcpy(adjective, "strong "); strcpy(adjective, "strong ");
@ -6369,29 +6380,31 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
// include mods if identified // include mods if identified
// ie. a blessed flaming +5 silver sword ->of pyromania<- // ie. a blessed flaming +5 silver sword ->of pyromania<-
for (br = firstbrand; br; br = br->next) { getflags(o->flags, retflag, &nretflags, F_HASBRAND, F_NONE);
if (hasflagval(o->flags, F_HASBRAND, br->id, NA, NA, NULL)) { for (i = 0; i < nretflags; i++) {
flag_t *brf; flag_t *brf;
int ok = B_TRUE; int ok = B_TRUE;
// are all of the brand flags known? f = retflag[i];
for (brf = br->flags->first ; brf ; brf = brf->next) { br = findbrand(f->val[0]);
int i; // are all of the brand flags known?
getflags(o->flags, retflag, &nretflags, brf->id, F_NONE); for (brf = br->flags->first ; brf ; brf = brf->next) {
for (i = 0; i < nretflags; i++) { flag_t *retflag2[MAXCANDIDATES],*f2;
f = retflag[i]; int nretflags2 = 0,n;
if (f->lifetime == FROMBRAND) { getflags(o->flags, retflag2, &nretflags2, brf->id, F_NONE);
if (f->known || showall) { for (n = 0; n < nretflags2; n++) {
} else { f2 = retflag2[n];
ok = B_FALSE; if (f2->lifetime == FROMBRAND) {
hasunknownmod = B_TRUE; if (f2->known || showall) {
break; } else {
} ok = B_FALSE;
hasunknownmod = B_TRUE;
break;
} }
} }
} }
if (ok) { }
strcat(localbuf, br->suffix); if (ok) {
} strcat(localbuf, br->suffix);
} }
} }
@ -15467,8 +15480,6 @@ void timeeffectsob(object_t *o) {
if (hasflag(o->flags, F_DEAD)) return; if (hasflag(o->flags, F_DEAD)) return;
getobname(o, obname, o->amt);
location = getoblocation(o); location = getoblocation(o);
if (o->pile->owner) { if (o->pile->owner) {
owner = o->pile->owner; owner = o->pile->owner;
@ -15481,6 +15492,12 @@ void timeeffectsob(object_t *o) {
onground = B_TRUE; onground = B_TRUE;
} }
if (haslos(player, location)) {
getobname(o, obname, o->amt);
} else {
strcpy(obname, "?some_ob?");
}
checkflagpile(o->flags); checkflagpile(o->flags);
// special case for trail flags // special case for trail flags
@ -15555,7 +15572,9 @@ void timeeffectsob(object_t *o) {
f = hasflag(o->flags, F_ISMONSTER); f = hasflag(o->flags, F_ISMONSTER);
if (strlen(f->text)) { if (strlen(f->text)) {
int dist; int dist;
dist = atoi(f->text); char dbuf[BUFLEN];
readuntil(dbuf, f->text, ',');
dist = atoi(dbuf);
// player within reveal distance? // player within reveal distance?
if ((getcelldist(player->cell, location) <= dist) && !haslos(player, location)) { if ((getcelldist(player->cell, location) <= dist) && !haslos(player, location)) {

14
save.c
View File

@ -58,10 +58,11 @@ int loadflagpile(FILE *f, flagpile_t *fp) {
flag_t *fl; flag_t *fl;
char buf[BUFLEN]; char buf[BUFLEN];
int rv; int rv;
int skid;
int db = B_FALSE; int db = B_FALSE;
rv = fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%ld\n", rv = fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%ld,%d\n",
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2],&tempflag.lifetime, &tempflag.known,&tempflag.obfrom); &tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2],&tempflag.lifetime, &tempflag.known,&tempflag.obfrom,&skid);
while (tempflag.id != -1) { while (tempflag.id != -1) {
dblog("got flag id=%d\n",tempflag.id); dblog("got flag id=%d\n",tempflag.id);
@ -73,6 +74,7 @@ int loadflagpile(FILE *f, flagpile_t *fp) {
tempflag.val[0], tempflag.val[0],
tempflag.val[1], tempflag.val[1],
tempflag.val[2], strcmp(buf, "^^^") ? buf : NULL, tempflag.lifetime, tempflag.known, tempflag.obfrom); tempflag.val[2], strcmp(buf, "^^^") ? buf : NULL, tempflag.lifetime, tempflag.known, tempflag.obfrom);
fl->skillfrom = findskill((enum SKILL)skid);
if (db) { if (db) {
@ -363,7 +365,7 @@ map_t *loadmap(FILE *f) {
fgets(line, BUFLEN, f); fgets(line, BUFLEN, f);
//if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; //if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0';
sscanf(line, "%d,%d,%d,%d,%d,%[ a-xA-Z_0-9+'*/-]\n",&m->room[i].id, sscanf(line, "%d,%d,%d,%d,%d,%[ a-zA-Z_0-9+'*/-]\n",&m->room[i].id,
&m->room[i].x1, &m->room[i].y1, &m->room[i].x1, &m->room[i].y1,
&m->room[i].x2, &m->room[i].y2, buf); &m->room[i].x2, &m->room[i].y2, buf);
m->room[i].vault = findvault(buf); m->room[i].vault = findvault(buf);
@ -650,7 +652,7 @@ int loadregions(FILE *f) {
fscanf(f, " thingdepth:%d,%d,%d\n",&depth, &x, &y); fscanf(f, " thingdepth:%d,%d,%d\n",&depth, &x, &y);
fscanf(f, " thingkind:%d\n",(int *)&whatkind); fscanf(f, " thingkind:%d\n",(int *)&whatkind);
fscanf(f, " thingval:%d\n",&val); fscanf(f, " thingval:%d\n",&val);
fscanf(f, " thingwhat:%[ a-xA-Z_0-9+'*/-]\n",buf); fscanf(f, " thingwhat:%[ a-zA-Z_0-9+'*/-]\n",buf);
fscanf(f, "endthing\n"); fscanf(f, "endthing\n");
// replace ^ with ' ' in thingwhat // replace ^ with ' ' in thingwhat
@ -917,8 +919,8 @@ int saveflagpile(FILE *f, flagpile_t *fp) {
flag_t *fl; flag_t *fl;
fprintf(f, "flags:\n"); fprintf(f, "flags:\n");
for (fl = fp->first ; fl ; fl = fl->next) { for (fl = fp->first ; fl ; fl = fl->next) {
fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%ld\n", fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%ld,%d\n",
fl->id, fl->nvals, fl->val[0], fl->val[1], fl->val[2],fl->lifetime,fl->known,fl->obfrom); fl->id, fl->nvals, fl->val[0], fl->val[1], fl->val[2],fl->lifetime,fl->known,fl->obfrom, fl->skillfrom->id);
if (!fl->text || !strcmp(fl->text, "")) { if (!fl->text || !strcmp(fl->text, "")) {
fprintf(f, "%s\n","^^^"); fprintf(f, "%s\n","^^^");
} else { } else {

48
shops.c
View File

@ -133,6 +133,15 @@ int getshopblessprice(object_t *o, object_t *shop) {
return cost; return cost;
} }
int isalignedtemple(object_t *shop) {
flag_t *f;
f = hasflag(shop->flags, F_LINKGOD);
if (f && godprayedto(f->val[0])) {
return B_TRUE;
}
return B_FALSE;
}
int obmatchessellflag(object_t *o, flag_t *f, enum SHOPACTION action) { int obmatchessellflag(object_t *o, flag_t *f, enum SHOPACTION action) {
if ((f->val[0] == F_NONE) || hasflag(o->flags, f->val[0])) { if ((f->val[0] == F_NONE) || hasflag(o->flags, f->val[0])) {
if ((f->val[2] == NA) || (o->type->obclass->id == f->val[2])) { if ((f->val[2] == NA) || (o->type->obclass->id == f->val[2])) {
@ -407,6 +416,7 @@ enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char *
int y; int y;
int cost = 0,possible = B_TRUE; int cost = 0,possible = B_TRUE;
y = starty; y = starty;
// calculate cost // calculate cost
for (o = lf->pack->first ; o; o = o->next) { for (o = lf->pack->first ; o; o = o->next) {
if (!o->blessknown && !hasflag(o->flags, F_NOBLESS)) { if (!o->blessknown && !hasflag(o->flags, F_NOBLESS)) {
@ -414,17 +424,23 @@ enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char *
} }
} }
if (cost) {
cost = applyshoppricemod(cost, lf, vm, SA_BUY);
}
if (!cost) { if (!cost) {
mvwprintw(mainwin, y, 0, "You do not seem to possess anything which merits our services."); mvwprintw(mainwin, y, 0, "You do not seem to possess anything which merits our services.");
y += 2; y += 2;
possible = B_FALSE; possible = B_FALSE;
} else { } else {
// aligned templte?
if (isalignedtemple(vm)) {
cost = 0;
} else {
cost = applyshoppricemod(cost, lf, vm, SA_BUY);
}
// ask what to detect // ask what to detect
mvwprintw(mainwin, y, 0, "It will cost $%d to perform an divination on your items.", cost); if (cost) {
mvwprintw(mainwin, y, 0, "It will cost $%d to perform an divination on your items.", cost);
} else {
mvwprintw(mainwin, y, 0, "For a fellow worshipper, we will perform divinations on your items for free.", cost);
}
y += 2; y += 2;
if (countmoney(lf->pack) < cost) { if (countmoney(lf->pack) < cost) {
mvwprintw(mainwin, y, 0, "Unfortunately, you cannot afford this.", cost); mvwprintw(mainwin, y, 0, "Unfortunately, you cannot afford this.", cost);
@ -434,7 +450,11 @@ enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char *
} }
if (possible){ if (possible){
mvwprintw(mainwin, y, 0, "Pay to detect auras on your items (you have $%d) [yn]? ", countmoney(lf->pack)); if (cost) {
mvwprintw(mainwin, y, 0, "Pay to detect auras on your items (you have $%d) [yn]? ", countmoney(lf->pack));
} else {
mvwprintw(mainwin, y, 0, "Detect auras on your items [yn]? ");
}
} else { } else {
mvwprintw(mainwin, y, 0, "[Press a key to return]"); mvwprintw(mainwin, y, 0, "[Press a key to return]");
} }
@ -629,11 +649,23 @@ enum SHOPRETURN shopbless(lifeform_t *lf, object_t *vm, int starty, char *toptex
blesscost = applyshoppricemod(DEF_BLESSCOST, lf, vm, SA_BUY); blesscost = applyshoppricemod(DEF_BLESSCOST, lf, vm, SA_BUY);
surcharge = applyshoppricemod(DEF_SURCHARGE, lf, vm, SA_BUY); surcharge = applyshoppricemod(DEF_SURCHARGE, lf, vm, SA_BUY);
if (isalignedtemple(vm)) {
blesscost /= 2; limit(&blesscost, 1, NA);
remcursecost = 0;
surcharge = 0;
}
mvwprintw(mainwin, y, 0, "So long as their aura is known, we can bestow a blessing on most items."); y += 2; mvwprintw(mainwin, y, 0, "So long as their aura is known, we can bestow a blessing on most items."); y += 2;
mvwprintw(mainwin, y, 0, "Curse removal - $%d each",remcursecost); y++; if (remcursecost == 0) {
mvwprintw(mainwin, y, 0, "Curse removal - FREE",remcursecost); y++;
} else {
mvwprintw(mainwin, y, 0, "Curse removal - $%d each",remcursecost); y++;
}
mvwprintw(mainwin, y, 0, "Blessings - $%d each",blesscost); y += 2; mvwprintw(mainwin, y, 0, "Blessings - $%d each",blesscost); y += 2;
mvwprintw(mainwin, y, 0, "(there is a $%d surcharge for uncursing an equipped item)",surcharge); y += 2; if (surcharge != 0) {
mvwprintw(mainwin, y, 0, "(there is a $%d surcharge for uncursing an equipped item)",surcharge); y += 2;
}
mvwprintw(mainwin, y, 0, "Pay for a blessing (you have $%d) [yn]? ", countmoney(lf->pack)); mvwprintw(mainwin, y, 0, "Pay for a blessing (you have $%d) [yn]? ", countmoney(lf->pack));
ch = getch(); ch = getch();

View File

@ -4,6 +4,7 @@ int apply_shopob_restrictions(char *buf);
float applyshoppricemod(float origprice, lifeform_t *lf, object_t *shop, enum SHOPACTION action); float applyshoppricemod(float origprice, lifeform_t *lf, object_t *shop, enum SHOPACTION action);
int canafford(lifeform_t *lf, int amt); int canafford(lifeform_t *lf, int amt);
int getshopblessprice(object_t *o, object_t *shop); int getshopblessprice(object_t *o, object_t *shop);
int isalignedtemple(object_t *shop);
int obmatchessellflag(object_t *o, flag_t *f, enum SHOPACTION action); int obmatchessellflag(object_t *o, flag_t *f, enum SHOPACTION action);
void shop(lifeform_t *lf, object_t *vm); void shop(lifeform_t *lf, object_t *vm);
enum SHOPRETURN shopabsolve(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated); enum SHOPRETURN shopabsolve(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated);

83
spell.c
View File

@ -362,6 +362,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
strcpy(verb, "charge"); strcpy(verb, "charge");
break; break;
} }
// check baseid too
if (user->race->baseid == R_LEECH) {
strcpy(verb, "leap");
}
msg("%s %s%s towards %s!",username,verb, isplayer(user) ? "" : "s",targetname); msg("%s %s%s towards %s!",username,verb, isplayer(user) ? "" : "s",targetname);
needredraw = B_TRUE; needredraw = B_TRUE;
drawlevelfor(player); drawlevelfor(player);
@ -1950,8 +1954,12 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
// get list of resizable materials // get list of resizable materials
getworkablematerials(user, SK_METALWORK, repairablemats, cutoffpct, &nmats); if (getskill(user, SK_METALWORK) >= PR_BEGINNER) {
getworkablematerials(user, SK_SEWING, repairablemats, cutoffpct, &nmats); getworkablematerials(user, SK_METALWORK, repairablemats, cutoffpct, &nmats);
}
if (getskill(user, SK_SEWING) >= PR_BEGINNER) {
getworkablematerials(user, SK_SEWING, repairablemats, cutoffpct, &nmats);
}
// 1.compile a list of resizable objects // 1.compile a list of resizable objects
initprompt(&prompt, "Resize which object?"); initprompt(&prompt, "Resize which object?");
@ -6888,6 +6896,30 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
nothinghappens(); nothinghappens();
} }
rv = B_FALSE; rv = B_FALSE;
} else if (spellid == OT_S_DRAINIQ) {
target = targcell->lf;
if (!target) {
fizzle(caster);
return B_TRUE;
}
if (isplayer(target)) {
msg("^%cYour brain cells are blasted!",getlfcol(target, CC_VBAD));
} else if (isplayer(caster)) {
char lfname[BUFLEN];
getlfname(target, lfname);
msg("^%cYou blast %s%s brain cells!", getlfcol(target, CC_VBAD),
lfname, getpossessive(lfname));
}
if (!ischarmable(target) && (reason != F_CHARMEDBY) && (reason != E_LOWIQ)) {
if (isplayer(caster)) {
char tname[BUFLEN];
getlfname(target, tname);
msg("%s %s unaffected.", tname, isplayer(target) ? "are" : "is");
}
return B_TRUE;
}
statdrain(target, A_IQ, roll("2d6") + rolldie(power,6),SC_NONE,-1,caster);
} else if (spellid == OT_S_DRAINLIFE) { } else if (spellid == OT_S_DRAINLIFE) {
char lfname[BUFLEN]; char lfname[BUFLEN];
target = haslf(targcell); target = haslf(targcell);
@ -8726,6 +8758,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(caster->flags, F_MINDSHIELD, B_TRUE, NA, NA, NULL, FROMSPELL); f = addtempflag(caster->flags, F_MINDSHIELD, B_TRUE, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid; f->obfrom = spellid;
} else if (spellid == OT_S_MINDWHIP) { } else if (spellid == OT_S_MINDWHIP) {
int fail = B_FALSE;
target = targcell->lf; target = targcell->lf;
if (!target) { if (!target) {
fizzle(caster); fizzle(caster);
@ -8740,10 +8773,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
lfname, getpossessive(lfname)); lfname, getpossessive(lfname));
} }
if (getattrbracket(getattr(target, A_IQ), A_IQ, NULL) <= AT_VLOW) { if (getattrbracket(getattr(target, A_IQ), A_IQ, NULL) <= AT_VLOW) {
fail = B_TRUE;
} else if (!ischarmable(target) && (reason != F_CHARMEDBY)) {
fail = B_TRUE;
}
if (fail) {
if (isplayer(caster)) { if (isplayer(caster)) {
char tname[BUFLEN]; char tname[BUFLEN];
getlfname(target, tname); getlfname(target, tname);
msg("%s is unaffected.", tname); msg("%s %s unaffected.", tname, isplayer(target) ? "are" : "is");
} }
return B_TRUE; return B_TRUE;
} }
@ -9698,6 +9736,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int dam,iq; int dam,iq;
enum ATTRBRACKET iqb; enum ATTRBRACKET iqb;
char targetname[BUFLEN]; char targetname[BUFLEN];
int fail = B_FALSE;
if (!target) { if (!target) {
target = targcell->lf; target = targcell->lf;
} }
@ -9709,11 +9748,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
iqb = getattrbracket(iq, A_IQ, NULL); iqb = getattrbracket(iq, A_IQ, NULL);
// not smart enough // not smart enough
if (iqb <= AT_EXLOW) { if (iqb <= AT_EXLOW) {
fizzle(caster); fail = B_TRUE;
} else if (!ischarmable(target) && (reason != F_CHARMEDBY)) {
fail = B_TRUE;
}
if (fail) {
if (isplayer(caster)) {
char tname[BUFLEN];
getlfname(target, tname);
msg("%s %s unaffected.", tname, isplayer(target) ? "are" : "is");
}
return B_TRUE; return B_TRUE;
} }
dam = rnd((iq/10),(iq/5)); dam = rnd((iq/10),(iq/5));
losehp(target, dam, DT_DIRECT, caster, "a psionic blast"); losehp(target, dam, DT_DIRECT, caster, "a mental feedback loop");
getlfname(target, targetname); getlfname(target, targetname);
if (isplayer(target)) { if (isplayer(target)) {
msg("^%cYour brain is blasted!",getlfcol(target, CC_BAD) ); msg("^%cYour brain is blasted!",getlfcol(target, CC_BAD) );
@ -13080,6 +13129,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if ((spellid == OT_S_SUMMONANIMALSSM) || } else if ((spellid == OT_S_SUMMONANIMALSSM) ||
(spellid == OT_S_SUMMONANIMALSMD) || (spellid == OT_S_SUMMONANIMALSMD) ||
(spellid == OT_S_SUMMONANIMALSLG) || (spellid == OT_S_SUMMONANIMALSLG) ||
(spellid == OT_S_SUMMONSWARM) ||
(spellid == OT_S_FRIENDS) || (spellid == OT_S_FRIENDS) ||
(spellid == OT_S_HECTASSERVANT) || (spellid == OT_S_HECTASSERVANT) ||
(spellid == OT_S_SUMMONDEMON)) { (spellid == OT_S_SUMMONDEMON)) {
@ -13150,6 +13200,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
successrate = 100; successrate = 100;
friendly = B_TRUE; friendly = B_TRUE;
break; break;
case OT_S_SUMMONSWARM:
wantrc = RC_ANY;
wantsize = SZ_ANY;
nwant = 1;
switch (power) {
case 1: wantrace = R_SWARMRAT; break;
case 2: wantrace = R_SWARMSPIDER; break;
default: wantrace = R_SWARMLOCUST; break;
}
successrate = 100;
friendly = B_TRUE;
break;
default: default:
wantrc = RC_ANY; wantrc = RC_ANY;
wantsize = SZ_ANY; wantsize = SZ_ANY;
@ -14991,6 +15053,17 @@ char *getspelldesc(enum OBTYPE spellid, int power, char *buf) {
case OT_S_SIXTHSENSE: case OT_S_SIXTHSENSE:
snprintf(buf, BUFLEN, "warnings about adjacent enemies"); snprintf(buf, BUFLEN, "warnings about adjacent enemies");
break; break;
case OT_S_SUMMONSWARM:
switch (power) {
case 1:
snprintf(buf, BUFLEN, "Summon a rat swarm."); break;
case 2:
snprintf(buf, BUFLEN, "Summon a spider swarm."); break;
default:
case 3:
snprintf(buf, BUFLEN, "Summon a locust swarm."); break;
}
break;
case OT_S_SUMMONWEAPON: case OT_S_SUMMONWEAPON:
snprintf(buf, BUFLEN, "Create a %d damage rating magical weapon",2+(power*2)); snprintf(buf, BUFLEN, "Create a %d damage rating magical weapon",2+(power*2));
break; break;

1
text.c
View File

@ -1058,6 +1058,7 @@ char *getcolname(enum COLOUR c) {
case C_LIGHTGREEN: return "lightgreen"; case C_LIGHTGREEN: return "lightgreen";
case C_LIGHTMAGENTA: return "lightmagenta"; case C_LIGHTMAGENTA: return "lightmagenta";
case C_LIGHTYELLOW: return "lightyellow"; case C_LIGHTYELLOW: return "lightyellow";
case C_LIGHTPINK: return "lightpink";
case C_LAST: return "last_colour"; case C_LAST: return "last_colour";
} }
return "?unknowncolour?"; return "?unknowncolour?";