- [+] might need to increase effectiveness of armour again. incease

damreduced.
- [+] reduce sliperriness of blood now that we get lots more.
- [+] restrict hiscores to scores of >= 1.
    - [+] (and remove all current entries with score of 0)
- [+] modifications:
    - [+] make levels more sparse
    - [+] make "things"more common
    - [+] make objects more common (as opposed to lfs)
- [+] monsters with territorial CAN approach if you're sleeping/ko
- [+] monsters with territorial don't get angry if you're sleeping/ko
- [+] CRASH when i tried to dismantle something.
- [+] speed up map generation.
    - [+] most time is in createhabitat.
    - [+] calcposandmakeroom(). speed this up.
    - [+] linkexit()
- [+] FIX reachability algorithm
    - [+] unless we can make a dircet path, REMOVE all other code.
    - [+] instead, use modified a*
    - [+] distance to dest roomm, not dest cell
        - [+] = distance to centre of dest room
    - [+] cell is okay for pathfinding
        - [+] adjcellokforreachability(cell) = true
    - [+] cell is the finish spot if:
        - [+] it is in a different room and
              adjcellokforreachability(cell) = true
    - [+] i THINK this is working now.
- [+] f_startobwepsk ... text = "common" not working. fixed.
This commit is contained in:
Rob Pearce 2012-11-19 04:57:48 +00:00
parent 893540af19
commit 2867b4488f
25 changed files with 1374 additions and 554 deletions

View File

@ -1,58 +1,61 @@
#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
nexus: ai.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 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
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
ai.o: ai.c ai.h attack.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
attack.o: attack.c ai.h attack.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h attack.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
data.o: data.c ai.h attack.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
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
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
findleak.o: findleak.c ai.h attack.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
flag.o: flag.c ai.h attack.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
god.o: god.c ai.h attack.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
io.o: io.c ai.h attack.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
lf.o: lf.c ai.h attack.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
map.o: map.c ai.h attack.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
move.o: move.c ai.h attack.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
nexus.o: nexus.c 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.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
objects.o: objects.c ai.h attack.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
save.o: save.c ai.h attack.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
shops.o: shops.c ai.h attack.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
spell.o: spell.c ai.h attack.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
text.o: text.c ai.h attack.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
vault.o: vault.c ai.h attack.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

74
ai.c
View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include "ai.h"
#include "astar.h"
#include "attack.h"
#include "defs.h"
#include "flag.h"
@ -152,79 +153,6 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
return B_FALSE;
}
int calcheuristic(cell_t *c, cell_t *end) {
int h,xd,yd;
xd = abs(c->x - end->x);
yd = abs(c->y - end->y);
if (xd > yd) {
h = (14*yd) + 10*(xd - yd);
} else {
h = (14*xd) + 10*(yd - xd);
}
return h;
}
// inserts node 'n' into list 'list' (sorted by cost)
// returns index of insert position.
int insert(node_t *n, node_t *list, int *listcount) {
int pos,i;
// add it to open list, with parent = node[cur]
pos = -1;
for (pos = 0; pos < *listcount; pos++) {
if (n->cost <= list[pos].cost) {
// add here.
break;
}
}
// shuffle others up
for (i = *listcount; i > pos; i--) {
list[i] = list[i-1];
}
(*listcount)++;
// fill in .
list[pos] = *n;
return pos;
}
int calcg(lifeform_t *lf, cell_t *thiscell, node_t *parent, int dirfromparent) {
int fromstart;
object_t *o;
int dooropen;
enum ATTRBRACKET wis = AT_EXHIGH;
if (lf) {
wis = getattrbracket(getattr(lf, A_WIS), A_WIS, NULL);
}
if (isorthogonal(dirfromparent)) {
fromstart = parent->fromstart + 10;
} else {
fromstart = parent->fromstart + 14;
}
// closed doors count for more.
if (wis >= AT_AVERAGE) {
o = hasdoor(thiscell);
if (o && isdoor(o, &dooropen) && !dooropen) {
fromstart += 10;
}
}
// lf's wisdom will affect what is the "best" path
if (wis >= AT_GTAVERAGE) {
// avoid mud, etc
o = hasobwithflag(thiscell->obpile, F_REDUCEMOVEMENT);
if (o) {
int howmuch;
sumflags(o->flags, F_REDUCEMOVEMENT, &howmuch, NULL, NULL);
if (howmuch > 0) {
fromstart += (10*howmuch);
}
}
}
return fromstart;
}
// A* algorithm. Returns F_AIPATH flag.
flag_t *ai_createpathto(lifeform_t *lf, cell_t *targcell) {
char *pathbuf;

1
ai.h
View File

@ -34,6 +34,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
void aiturn(lifeform_t *lf);
int aiwants(lifeform_t *lf, object_t *o, int *covets);
int aiwants_real(lifeform_t *lf, object_t *o, int *covets, int *noids, enum OBTYPE *oid, int *oidcovet,int *nwantflags, enum FLAG *wantflag, int *wantflagcovet);
void clearnode(node_t *n;);
lifeform_t *gettargetlf(lifeform_t *lf);
object_t *hasbetterarmour(lifeform_t *lf, obpile_t *op);
object_t *hasbetterweapon(lifeform_t *lf, obpile_t *op);

View File

@ -2551,8 +2551,8 @@ int getarmourdamreduction(lifeform_t *lf, object_t *wep, int dam, enum DAMTYPE d
// for a given ArmourRating (AR), return range of damage which it might reduce
void getarrange(int arating, int *min, int *max) {
*min = pctof(20,arating);
*max = pctof(60, arating);
*min = pctof(50,arating);
*max = pctof(80, arating);
}
/*
@ -3392,7 +3392,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam, int isu
readuntil(frombuf, p, '^');
}
poison(victim, howlong, ptype, ppower, frombuf, owner ? owner->race->id : R_NONE);
poison(victim, howlong, ptype, ppower, frombuf, owner ? owner->race->id : R_NONE, B_FALSE);
} else {
// flag values
if (valflag) {
@ -3415,7 +3415,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam, int isu
int pct;
pct = f->val[0] * 10;
if (pctchance(pct)) {
poison(victim, PERMENANT, P_TETANUS, 1, frombuf, owner ? owner->race->id : R_NONE);
poison(victim, PERMENANT, P_TETANUS, 1, frombuf, owner ? owner->race->id : R_NONE, B_FALSE);
}
} // end if (fid == xxx)

118
data.c
View File

@ -2020,6 +2020,7 @@ void initobjects(void) {
addmaterial(MT_SLIME, "slime", 9);
addmaterial(MT_STONE, "stone", 10);
addflag(lastmaterial->flags, F_HARDNESS, 4, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
addmaterial(MT_SILVER, "silver", 11);
@ -3470,12 +3471,14 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_MAGENTA, '%', NA, NULL);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, "");
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_VENOMSAC, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addot(OT_POISONSACBL, "blue venom sac", "A small sac of flesh, filled with blindness-inducing venom. A skilled Chemist could use it to create a blindness potion.", MT_FLESH, 0.2, OC_FOOD, SZ_TINY); // weight normally comes from corpse type
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "You can 'o'perate this to mix it into a poiton.");
addflag(lastot->flags, F_GLYPH, C_BLUE, '%', NA, NULL);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, "");
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_VENOMSAC, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addot(OT_PSITRUFFLE, "psitruffle", "Psitruffles are extremely rare forms of truffle which can unlock potentials within a living brain. Eating one will double all experience earned for a short period thereafter.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_MAGENTA, '%', NA, NULL);
@ -3635,7 +3638,7 @@ void initobjects(void) {
addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL);
addot(OT_POT_BLOOD, "potion of blood", "A small quantity of blood.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "splash of blood");
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "5 splashes of blood");
addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL);
addot(OT_POT_SANCTUARY, "potion of sanctuary", "Creates a temporary magical barrier abour the drinker.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
@ -3650,9 +3653,9 @@ void initobjects(void) {
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, 40, NA, NULL);
addflag(lastot->flags, F_VALUE, 410, NA, NA, NULL);
addot(OT_POT_BLOODC, "potion of cockatrice blood", "A small quantity of cockatrice blood.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addot(OT_POT_BLOODC, "potion of antistoning", "A small quantity of bottled blood from a cockatrice, able to reverse the effects of petrification.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "splash of cockatrice blood");
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "5 splashes of cockatrice blood");
addflag(lastot->flags, F_VALUE, 35, NA, NA, NULL);
addot(OT_POT_COMPETENCE, "potion of competence", "Permemantly increases the drinker's base attribites (Strength, IQ, etc).", MT_GLASS, 1, OC_POTION, SZ_TINY);
@ -6923,7 +6926,7 @@ void initobjects(void) {
addflag(lastot->flags, F_FILLPOT, OT_POT_WATER, NA, NA, NULL);
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+2");
addot(OT_BLOODSTAIN, "blood stain", "A dried stain of blood.", MT_BLOOD, 0, OC_MISC, SZ_TINY);
addot(OT_BLOODSTAIN, "blood stain", "A dried stain of blood.", MT_BLOOD, 0, OC_MISC, SZ_MINI);
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_RED, ',', NA, NULL);
@ -6934,24 +6937,8 @@ void initobjects(void) {
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL);
addot(OT_BLOODCSPLASH, "splash of cockatrice blood", "A small pool of cockatrice blood.", MT_BLOOD, 0, OC_MISC, SZ_SMALL);
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, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 50, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SLIPPERY, 10, NA, NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates");
addflag(lastot->flags, F_OBHP, 3, 3, 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_BLOODC, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL);
addot(OT_BLOODSPLASH, "splash of blood", "A small pool of blood.", MT_BLOOD, 0, OC_MISC, SZ_SMALL);
addot(OT_BLOODSPLASH, "splash of blood", "A small pool of blood.", MT_BLOOD, 0, OC_MISC, SZ_MINI);
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, NULL);
@ -6959,7 +6946,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 75, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SLIPPERY, 10, NA, NA, NULL);
addflag(lastot->flags, F_SLIPPERY, 5, 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");
@ -6973,14 +6960,14 @@ void initobjects(void) {
addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL);
addflag(lastot->flags, F_FILLPOT, OT_POT_BLOOD, 5, NA, NULL);
addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC, SZ_MEDIUM);
addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC, SZ_SMALL);
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, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastot->flags, F_RARITY, H_CAVE, 65, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SLIPPERY, 50, NA, NA, NULL);
addflag(lastot->flags, F_SLIPPERY, 25, 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");
@ -7269,6 +7256,9 @@ void initobjects(void) {
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "roaring flames.");
addflag(lastot->flags, F_SHRINKSTO, OT_FIREMED, VT_OB, NA, NULL);
addflag(lastot->flags, F_GENERATES, 10, 0, B_INADJCELL, "cloud of smoke");
addflag(lastot->flags, F_GENERATES, 50, 0, B_INADJCELL, "puff of smoke");
addflag(lastot->flags, F_GENERATES, 50, 0, B_INADJCELL, "puff of smoke");
addot(OT_FIREMED, "medium fire", "A medium-sized roaring fire.", MT_FIRE, 0, OC_EFFECT, SZ_MEDIUM);
addflag(lastot->flags, F_GLYPH, C_RED, '}', NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small fire");
@ -7283,6 +7273,8 @@ void initobjects(void) {
addflag(lastot->flags, F_MAKESNOISE, 33, 2, NA, "roaring flames.");
addflag(lastot->flags, F_GROWSTO, OT_FIRELARGE, VT_OB, NA, NULL);
addflag(lastot->flags, F_SHRINKSTO, OT_FIRESMALL, VT_OB, NA, NULL);
addflag(lastot->flags, F_GENERATES, 50, 0, B_INADJCELL, "puff of smoke");
addflag(lastot->flags, F_GENERATES, 50, 0, B_INADJCELL, "puff of smoke");
addot(OT_FIRESMALL, "small fire", "A small blaze.", MT_FIRE, 0, OC_EFFECT, SZ_SMALL);
addflag(lastot->flags, F_GLYPH, C_RED, '}', NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "goes out");
@ -7295,6 +7287,7 @@ void initobjects(void) {
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addflag(lastot->flags, F_MAKESNOISE, 33, 1, NA, "crackling flames.");
addflag(lastot->flags, F_GROWSTO, OT_FIREMED, VT_OB, NA, NULL);
addflag(lastot->flags, F_GENERATES, 50, 0, B_INADJCELL, "puff of smoke");
addot(OT_STEAMCLOUD, "cloud of steam", "A thick cloud of scalding steam.", MT_GAS, 0, OC_EFFECT, SZ_HUMAN);
addflag(lastot->flags, F_GLYPH, C_WHITE, UNI_SHADEMED, NA, NULL);
@ -7360,6 +7353,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addflag(lastot->flags, F_CAUSESCOUGH, 125, NA, NA, NULL);
addflag(lastot->flags, F_OBMOVESRANDOMLY, NA, NA, NA, NULL);
addot(OT_SMOKEPUFF, "puff of smoke", "A small puff of black smoke.", MT_GAS, 0, OC_EFFECT, SZ_MEDIUM);
addflag(lastot->flags, F_GLYPH, C_GREY, UNI_SHADELIGHT, NA, NULL);
@ -7371,6 +7365,7 @@ void initobjects(void) {
addflag(lastot->flags, F_BLOCKSVIEW, 2, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, ".");
addflag(lastot->flags, F_CAUSESCOUGH, 80, NA, NA, NULL);
addflag(lastot->flags, F_OBMOVESRANDOMLY, NA, NA, NA, NULL);
addot(OT_POISONCLOUD, "cloud of poison gas", "A thick cloud of poisonous gas.", MT_GAS, 0, OC_EFFECT, SZ_LARGE);
addflag(lastot->flags, F_GLYPH, C_GREEN, UNI_SHADEMED, NA, NULL);
@ -7634,12 +7629,16 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 120, 120, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
addot(OT_FLAKJACKET, "flak jacket", "Heavy metal vest, worn over the shoulders. Designed to stop a bullet, but ineffective against melee attacks.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM);
addot(OT_FLAKJACKET, "flak jacket", "Heavy metal vest, worn over the shoulders. Designed protect against bullets and explosions, but less effective against melee attacks.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 0, 5, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_DTRESIST, DT_EXPLOSIVE, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_DTRESIST, DT_PROJECTILE, NA, NULL);
addflag(lastot->flags, F_DTRESIST, DT_EXPLOSIVE, NA, NA, NULL);
addflag(lastot->flags, F_DTRESIST, DT_PROJECTILE, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 50, NA, NULL);
addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
@ -10054,7 +10053,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, NULL);
addflag(lastrace->flags, F_HITCONFERVALS, P_LYCANTHROPY, -1, PERMENANT, "10^dire rat");
addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addrace(R_SEBASTIAN, "Sebastian", 75, '@', C_WHITE, MT_FLESH, RC_HUMANOID, "An impeccably-dressed man with long sideburns.");
@ -11294,7 +11293,7 @@ void initrace(void) {
}
}
addflag(lastrace->flags, F_GODPOISON, B_FALSE, 25, NA, NULL);
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying the undead");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying the undead or robots");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting certain holy spells");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "natural healing");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the destruction of healing potions");
@ -11487,6 +11486,7 @@ void initrace(void) {
addflag(lastrace->flags, F_GENDER, G_FEMALE, NA, NA, NULL);
addflag(lastrace->flags, F_MPREGEN, NA, NA, NA, "100"); // ie. basically infinite
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "the use of magic");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying robots");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of missile or ranged weapons");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of technology");
// sacrifices
@ -11616,7 +11616,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 50, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_LEVITATION, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_LEVITATION, BLOODFORPOT, NA, NULL);
addrace(R_BOGGART, "bogle", 15, 'n', C_BROWN, MT_WOOD, RC_MAGIC, "An evil household fairy made of wood. They delight in sowing disease and misfortune.");
setbodytype(lastrace, BT_HUMANOID);
@ -11789,7 +11789,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_ANTNEST, NA, RR_VERYRARE, NULL);
addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, "splash of cockatrice blood");
//addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, "splash of cockatrice blood");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
@ -12029,6 +12029,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings");
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_LEVITATION, BLOODFORPOT, NA, NULL);
addrace(R_TRICLOPS, "triclops", 160, 'H', C_BROWN, MT_FLESH, RC_HUMANOID, "The three-eyes triclops race are blessed with extraordiny perceptive and are nearly impossible to surprise. They commonly use their third eye to stun enemies, then finish them off with their huge weapons.");
setbodytype(lastrace, BT_HUMANOID);
@ -12277,7 +12278,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_ATTRMOD, A_STR, 5, "50");
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_FIRE, NA, "50");
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, BLOODFORPOT, NA, NULL);
addrace(R_GIANTFIREFC, "flame giant firemaster", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID, "A subspecies of flame giant who have developed the ability to command the primal volcanic fires around them.");
setbodytype(lastrace, BT_HUMANOID);
@ -12321,7 +12322,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 15, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_ATTRMOD, A_STR, 5, "50");
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_FIRE, NA, "50");
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, BLOODFORPOT, NA, NULL);
// TODO: storm giant
@ -12855,7 +12856,7 @@ void initrace(void) {
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_ALL, NA, RR_VERYRARE, NULL);
@ -12890,7 +12891,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL);
addrace(R_KOBOLD, "kobold", 18, 'k', C_BROWN, MT_FLESH, RC_HUMANOID, "An evil humanoid race with doglike features, kobolds are known for their cowardace and prefer to attack from a distance if at all possible.");
@ -12966,7 +12967,7 @@ void initrace(void) {
addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL);
addrace(R_LEPRECHAUN, "leprechaun", 35, 'n', C_BOLDGREEN, MT_FLESH, RC_HUMANOID, "Leprechauns are tiny Irish humans, with a love for gold and practical jokes. Known for their supernatural luck.");
setbodytype(lastrace, BT_HUMANOID);
@ -14167,7 +14168,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_FIRE, NA, "25");
addflag(lastrace->flags, F_WANTSOBFLAG, F_GEM, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, BLOODFORPOT, NA, NULL);
addrace(R_SPRITEGRAVE, "grave sprite", 5, 'n', C_GREY, MT_FLESH, RC_MAGIC, "A small magical creature made from corpse dust.");
setbodytype(lastrace, BT_HUMANOID);
@ -14246,7 +14247,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_COLD, NA, "25");
addflag(lastrace->flags, F_WANTSOBFLAG, F_GEM, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, BLOODFORPOT, NA, NULL);
addrace(R_SPRITEWEED, "weed sprite", 5, 'n', C_ORANGE, MT_FLESH, RC_MAGIC, "The bright colour of weed sprites belies their evil nature.");
setbodytype(lastrace, BT_HUMANOID);
@ -14297,9 +14298,9 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMIN, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALING, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMAJ, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMIN, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALING, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMAJ, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
@ -14369,9 +14370,9 @@ void initrace(void) {
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMIN, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALING, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMAJ, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMIN, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALING, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMAJ, BLOODFORPOT, NA, 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_SWAMP, NA, RR_COMMON, NULL);
@ -14413,9 +14414,9 @@ void initrace(void) {
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMIN, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALING, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMAJ, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMIN, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALING, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_HEALINGMAJ, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL);
@ -14572,7 +14573,7 @@ void initrace(void) {
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 2, NA, "^gurgling");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "gurgles loudly^a loud gurgle");
addflag(lastrace->flags, F_EATCONFER, F_MUTABLE, B_TRUE, NA, "100");
addflag(lastrace->flags, F_FILLPOT, OT_POT_FISHLUNG, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_FISHLUNG, BLOODFORPOT, NA, NULL);
addrace(R_PIRANHA, "piranha", 0.5, ';', C_GREEN, MT_FLESH, RC_AQUATIC, "A vicious, flesh-eating fish");
setbodytype(lastrace, BT_FISH);
@ -14829,7 +14830,7 @@ void initrace(void) {
addflag(lastrace->flags, F_TR, 1, NA, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_FURY, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_FURY, BLOODFORPOT, NA, NULL);
addrace(R_GLUON, "gluon", 1, 'F', C_YELLOW, MT_PLANT, RC_PLANT, "A walking plant-based monster whose body is covered with a thick glue-like secretion.");
addbodypart(lastrace, BP_BODY, "stalk");
@ -15059,7 +15060,7 @@ void initrace(void) {
addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL);
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_MAGIC, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_MAGIC, BLOODFORPOT, NA, NULL);
addrace(R_BATVAMPIRE, "vampire bat", 6, 'B', C_BLUE, MT_FLESH, RC_ANIMAL, "Bats which suck the blood of their victims.");
setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
@ -15960,7 +15961,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_COLD, NA, "20");
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_ELEMENTIMMUNE, BLOODFORPOT, NA, NULL);
addrace(R_ELEPHANT, "elephant", 4000, 'Q', C_GREY, MT_LEATHER, RC_ANIMAL, "A massive grey mammal with a long trunk and sharp tusks.");
setbodytype(lastrace, BT_QUADRAPED);
@ -16282,7 +16283,7 @@ void initrace(void) {
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_POISONCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL);
addflag(lastrace->flags, F_GERMS, NA, NA, NA, NULL);
addrace(R_ROC, "roc", 1, 'A', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Rocs are unbelievably gargantuan birds or prey, large enough to carry a fully-grown elephant. They are generally peaceful, but deadly once provoked."); // 'A' for Avian
@ -16699,7 +16700,7 @@ void initrace(void) {
addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, "");
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_POISON, NA, "15");
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep");
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL);
addrace(R_SPIDERREDBACK, "giant redback", 5, 'S', C_RED, MT_FLESH, RC_ANIMAL, "A version of a giant spider with a highly painful bite.");
setbodytype(lastrace, BT_SPIDER);
lastrace->baseid = R_SPIDER;
@ -16739,7 +16740,7 @@ void initrace(void) {
addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, "");
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_POISON, NA, "10");
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "creep");
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL);
addrace(R_SPIDERTOMB, "tomb spider", 5, 'S', C_BLUE, 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);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
@ -17794,6 +17795,7 @@ void initrace(void) {
addflag(lastrace->flags, F_TR, 3, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 1, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling");
addflag(lastrace->flags, F_GERMS, NA, NA, NA, NULL);
addrace(R_FIREBUG, "firebug", 2, 'x', C_RED, MT_FLESH, RC_INSECT, "Constantly burning insects which attack their victims with fire.");
setbodytype(lastrace, BT_QUADRAPED);
@ -18813,7 +18815,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, NULL);
addflag(lastrace->flags, F_HITCONFERVALS, P_LYCANTHROPY, -1, PERMENANT, "10^grizzly bear");
addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, BLOODFORPOT, NA, NULL);
addrace(R_WERERAT, "wererat", 50, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "Weedy humans with shifty eyes and whiskers, wererats are known for their extreme cunning.");
setbodytype(lastrace, BT_HUMANOID);
@ -18856,7 +18858,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, NULL);
addflag(lastrace->flags, F_HITCONFERVALS, P_LYCANTHROPY, -1, PERMENANT, "10^dire rat");
addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, BLOODFORPOT, NA, NULL);
addrace(R_WEREWOLF, "werewolf", 100, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "Shaggy humans with the uncanny ability to shapeshift into a ferocious wolf.");
setbodytype(lastrace, BT_HUMANOID);
@ -18898,7 +18900,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL);
addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, NULL);
addflag(lastrace->flags, F_HITCONFERVALS, P_LYCANTHROPY, -1, PERMENANT, "10^dire wolf");
addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, NA, NA, NULL);
addflag(lastrace->flags, F_FILLPOT, OT_POT_LYCANTHROPY, BLOODFORPOT, NA, NULL);
// special monsters
addrace(R_GASCLOUD, "cloud of gas", 0.1, 'y', C_GREY, MT_GAS, RC_OTHER, "A large cloud of gas which seems to move with a life of its own...");
@ -19580,8 +19582,14 @@ void initskills(void) {
snprintf(buf, BUFLEN, "^gYou now have common knowledge about %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_NOVICE, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou now know about the abilities of %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_BEGINNER, buf, B_TRUE);
if (raceclassbleeds(rc->id)) {
snprintf(buf, BUFLEN, "^gYou can now recognise the blood of %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_BEGINNER, buf, B_TRUE);
}
snprintf(buf, BUFLEN, "^gYou have now comprehensively studied %s.^n", rc->pluralname);
addskilldesc(sk->id, PR_ADEPT, buf, B_TRUE);
snprintf(buf, BUFLEN, "^gYou can now anticipate how %s will react.^n", rc->pluralname);

Binary file not shown.

35
defs.h
View File

@ -19,6 +19,12 @@
// skill check difficulty
#define D_ALWAYSFAIL -99
// how many blood splashes you need before you
// can fill a flask with it.
#define BLOODFORPOT 2
#define TEMPVAULTLOCK "temporary vaultcell lock"
// Text
#define TEXT_WARN_ATTACK_NOXP "You will not gain experience until you train. Really attack?"
#define TEXT_WARN_CLIMB "Really attempt to climb without Climbing skill?"
@ -50,8 +56,10 @@
// Map building defaults
#define DEF_LOOPPCT 95
#define DEF_SPARSENESS 25
#define DEF_TURNPCT 40
//#define DEF_SPARSENESS 25
#define DEF_SPARSENESS 35
//#define DEF_TURNPCT 40
#define DEF_TURNPCT 30
#define DEF_WINDOWPCT 5
#define DEF_WARNINGTIME 20
@ -88,6 +96,8 @@
#define B_TRUE (-1)
#define B_MAYBE (-2)
#define B_INADJCELL (-1)
#define B_DODAM (-1)
#define B_NODAM (0)
@ -152,6 +162,9 @@
#define B_COVETS (-1)
#define B_ANY (0)
#define B_FIRSTONE (0)
#define B_ANYONE (-1)
#define B_SINGLE (0)
#define B_MULTI (-1)
#define B_MULTIPLE (-1)
@ -2163,7 +2176,6 @@ enum OBTYPE {
OT_BLOODSTAIN,
OT_BLOODSPLASH,
OT_BLOODPOOL,
OT_BLOODCSPLASH,
OT_METALCHUNK,
OT_MELTEDWAX,
OT_SOGGYPAPER,
@ -2654,8 +2666,6 @@ enum FLAG {
F_ENCHANTABLE, // object can get +1/-1 ect
F_FILLPOT, // can fill empty flasks with this object to create
// a potion of obtype v0.
// if v1 != NA, then object count must be >= v1 to
// fill from this ob.
F_GEM, // this object is a gem.
F_JEWELERY, // this object counts as jewelery
F_GODGIFT, // this was a gift form god with race v0.
@ -3122,6 +3132,12 @@ enum FLAG {
// optional v1 = minrange (for spells only)
F_RELOADTURNS, // # actions it takes to reload this gun
// end gun flags
F_GENERATES, // this object has a v0 pct chance of generating
// the object 'text' each turn.
// v1 = radius to generate obejcts within (including
// centre)
// if v2 is set, obs will be created in a random
// adjacent cell.
F_FLAMESTRIKE, // causes fires where you hit
F_BALANCE, // heals target if their maxhp < your maxhp
F_HOMING, // missile always hits
@ -3403,6 +3419,8 @@ enum FLAG {
// calculation
// optional text = prefix for ob name.
// eg "good" "branded" "cursed" etc
// if this text is a rarity (ie. common) then
// it will be specially handled.
F_CONTAINER, // this object is a container - you can use 'o'
// to take stuff out or put it in.
F_HOLDING, // this container is a xxx of holding and makes objects
@ -3582,6 +3600,8 @@ enum FLAG {
// this is cleared at start of turn.
F_TARGETCELL, // lf will go towards this place. val0=x,val1=y
// optional: v2 = mr_lf or mr_ob. text=lf or ob id.
F_TURNSINPEACE, // v0 is a counter for how many turns this ai
// mosnter has gone without being in battle.
F_PHANTASM, // this lf is a phantasm - can deal no damage, and
// uses v0 as a fake hp counter.
//F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed
@ -3685,6 +3705,7 @@ enum FLAG {
F_NAMED, // text = lf's name. ie. lfname = "xat named Fred"
F_XPMOD, // add/subtract this much from calculated xpval
F_BLOODOB, // text = type of object to drop for blood
// corpses will inherit the FIRST one of these only.
F_UNSUMMONOB, // text = type of object to drop when this creature
// uis unsummoned.
F_DIESPLATTER, // this lf will splatter objcets of type 'text'
@ -3870,6 +3891,8 @@ enum FLAG {
// obfrom = if you ate a corpse, this records its race
// otherwise, NA.
// text = power^fromwhat .eg'a bad egg'
F_VENOMSAC, // this object is a venom sac, used to create poison
// potions
F_POISONED, // has poisoning. v0 = poison type,
// v1 = power
// v2 = if you ate a corpse, this records its race
@ -4704,6 +4727,7 @@ typedef struct cell_s {
int hp;
char *reason;
char *lockedreason;
char *writing;
int writinglifetime;
@ -5181,6 +5205,7 @@ typedef struct prompt_s {
typedef struct node_s {
struct cell_s *c;
struct node_s *parent;
int dirfromparent;
int fromstart, heur, cost;
} node_t;

34
flag.c
View File

@ -90,6 +90,18 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
if ((id == F_PARTVEGETARIAN) && hasflag(fp, F_CARNIVORE)) return NULL;
if ((id == F_CARNIVORE) && (hasflag(fp, F_VEGETARIAN) || hasflag(fp, F_PARTVEGETARIAN)) ) return NULL;
// no dupes allowed
if (id == F_LINKRACE) {
if (hasflagval(fp, F_LINKRACE, val1, val2, val3, NULL)) {
return NULL;
}
}
if (id == F_FILLPOT) {
if (hasflagval(fp, F_FILLPOT, val1, NA, NA, NULL)) {
return NULL;
}
}
// overrite NA rarity
if ((id == F_RARITY) && (val3 == NA)) {
val3 = RR_COMMON;
@ -566,15 +578,19 @@ void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {
}
newf = addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
(lifetime == NA) ? f->lifetime : lifetime, f->known, -1);
newf->condition = f->condition;
newf->origlifetime = f->origlifetime;
newf->chance = f->chance;
if (f->altval) {
addaltval(newf, f->altval->id,
f->altval->val[0],
f->altval->val[1],
f->altval->val[2],
f->altval->text);
// newf might not be set, if (for example) we are coyping a duplicate
// f_linkrace flag.
if (newf) {
newf->condition = f->condition;
newf->origlifetime = f->origlifetime;
newf->chance = f->chance;
if (f->altval) {
addaltval(newf, f->altval->id,
f->altval->val[0],
f->altval->val[1],
f->altval->val[2],
f->altval->text);
}
}
}
}

8
god.c
View File

@ -754,7 +754,7 @@ void dooffer(void) {
pleasegod(god->race->id, pietyplus);
if (strlen(splatterob)) {
addob(player->cell->obpile, splatterob);
addobsinradius(player->cell, 1, DT_COMPASS, splatterob, B_TRUE, NULL);
addobsinradius(player->cell, 1, DT_COMPASS, splatterob, B_TRUE, B_NOCENTRE, NULL, NULL, NULL, NULL);
}
if (god->race->id == R_GODFIRE) {
dospelleffects(player, OT_S_FLAMEBURST, 1, NULL, NULL, player->cell, B_UNCURSED, NULL, B_FALSE, NULL);
@ -1085,11 +1085,11 @@ lifeform_t *godappears(enum RACE rid, cell_t *where) {
switch (god->race->id) {
case R_GODBATTLE: // bloodsplatter
addob(god->cell->obpile, "splash of blood");
addobsinradius(god->cell, 2, DT_COMPASS, "splash of blood", B_TRUE, NULL);
addobsinradius(god->cell, 2, DT_COMPASS, "splash of blood", B_TRUE, B_INCLUDECENTRE, NULL, NULL, NULL, NULL);
break;
case R_GODLIFE: //light
addob(god->cell->obpile, "bright light");
addobsinradius(god->cell, 2, DT_COMPASS, "bright light", B_TRUE, NULL);
addobsinradius(god->cell, 2, DT_COMPASS, "bright light", B_TRUE, B_INCLUDECENTRE, NULL, NULL, NULL, NULL);
break;
case R_GODFIRE: // fire
addob(god->cell->obpile, "large fire");
@ -1477,7 +1477,7 @@ int godgiftmaybe(enum RACE rid, int fromtemple, int announce) {
if (getskill(player, SK_RANGED)) {
char obname[BUFLEN];
if (real_getrandomob(NULL, obname, 25, NA, getlfsize(player),
SK_RANGED, B_TRUE, OC_WEAPON, OC_NONE, DT_NONE, F_NONE)) {
SK_RANGED, RR_NONE, B_TRUE, OC_WEAPON, OC_NONE, DT_NONE, F_NONE)) {
snprintf(obtogive, BUFLEN, "excellent %s", obname);
} else {
rollagain = B_TRUE;

13
io.c
View File

@ -4304,12 +4304,11 @@ void describespell(objecttype_t *ot) {
restoregamewindows();
}
void doattackcell(char dirch) {
int dir = D_NONE;
void doattackcell(int dir) {
flag_t *f;
cell_t *c;
if (dirch == '\0') {
if (dir == D_NONE) {
dir = askdir("Attack in which direction (- to cancel)", B_TRUE, B_TRUE);
}
@ -4326,7 +4325,7 @@ void doattackcell(char dirch) {
// update last cmd
f = hasflag(player->flags, F_LASTCMD);
if (f) {
f->val[2] = dirch;
f->val[2] = dir;
}
@ -10683,7 +10682,7 @@ void handleinput(void) {
if (wantrepeat) {
doattackcell(repeatflag.val[2]);
} else {
doattackcell('\0');
doattackcell(D_NONE);
}
break;
case CMD_GO: // go somewhere (pathfind)
@ -14407,11 +14406,11 @@ void tombstone(lifeform_t *lf) {
cls();
y = 0;
if (rank == -1) {
if (rank == -1) { // -1 means 'cheating'
mvwprintw(mainwin, y, 0, "Since you were cheating, your score will not be listed."); y++;
minrank = 1;
maxrank = 10;
} else if (rank > 100) {
} else if ((rank == -2) || (rank > 100)) { // -2 means 'no points'
mvwprintw(mainwin, y, 0, "Your score of %ld didn't make the top 100 list.", playerscore); y++;
minrank = 1;
maxrank = 10;

2
io.h
View File

@ -47,7 +47,7 @@ void describeob(object_t *o);
void describerace(enum RACE rid);
void describeskill(enum SKILL skid, enum SKILLLEVEL levhilite);
void describespell(objecttype_t *ot);
void doattackcell(char dirch);
void doattackcell(int dir);
void doclose(void);
void docomms(lifeform_t *target);
void docomms_areainfo(char *who, flagpile_t *fp, lifeform_t *lf);

225
lf.c
View File

@ -218,48 +218,26 @@ void awardxpfor(lifeform_t *killed, float pct) {
}
void bleed(lifeform_t *lf, int splatter) {
flag_t *f;
char obname[BUFLEN];
flag_t *retflag[MAXCANDIDATES];
int nretflags;
if (lf->cell->type->solid) return;
if (hasobwithflag(lf->cell->obpile, F_DEEPWATER)) return;
if (hasequippedobid(lf->pack, OT_AMU_BLOOD)) return;
getflags(lf->flags, retflag, &nretflags, F_BLOODOB, F_NONE);
if (nretflags) {
// pick a random one
f = retflag[rnd(0,nretflags-1)];
if (f->text) {
strcpy(obname, f->text);
} else {
strcpy(obname, "");
}
} else {
strcpy(obname, "splash of blood");
}
getbloodobname(lf->flags, obname, B_ANYONE);
if (strlen(obname) > 0) {
int nfillpot = 0;
object_t *o;
o = addob(lf->cell->obpile, obname);
if (hasflag(lf->flags, F_FILLPOT)) {
// override object flags
killflagsofid(o->flags, F_FILLPOT);
}
nfillpot = copyflag(o->flags, lf->flags, F_FILLPOT);
setbloodfrom(o, lf);
if (splatter) {
addobsinradius(lf->cell, 1, DT_COMPASS, obname, B_TRUE, NULL);
if (nfillpot) {
int i;
for (i = 0; i < nretobs; i++) {
copyflag(retobs[i]->flags, lf->flags, F_FILLPOT);
}
object_t *bloodob[MAXCANDIDATES];
int i,nbloodobs = 0;
// this call will populate retobs[]...
addobsinradius(lf->cell, 1, DT_COMPASS, obname, B_TRUE, B_NOCENTRE, NULL, bloodob, NULL, &nbloodobs);
for (i = 0; i < nbloodobs; i++) {
setbloodfrom(bloodob[i], lf);
}
}
}
@ -3512,6 +3490,10 @@ void die(lifeform_t *lf) {
case RC_PLANT:
pleasegodmaybe(R_GODFIRE, 10);
break;
case RC_ROBOT:
pleasegodmaybe(R_GODLIFE, rnd(2,3));
pleasegodmaybe(R_GODMAGIC, rnd(2,3));
break;
default:
break;
}
@ -3642,7 +3624,7 @@ void die(lifeform_t *lf) {
msg("%s explodes into flames!", lfname);
}
// explode into flames
addobsinradius(corpsecell, 1, DT_COMPASS, "medium fire", B_TRUE, NULL);
addobsinradius(corpsecell, 1, DT_COMPASS, "medium fire", B_TRUE, B_INCLUDECENTRE, NULL, NULL, NULL, NULL);
} else if ((lf->lastdamtype == DT_BASH) && lfhasflag(lf, F_FROZEN)) {
// shattered
fragments(corpsecell, "chunk of ice", 2, UNLIMITED);
@ -3732,6 +3714,33 @@ void die(lifeform_t *lf) {
// some corpses will regenerate...
if (copyflag(corpse->flags, lf->flags, F_REVIVETIMER)) {
killflagsofid(corpse->flags, F_OBHPDRAIN);
} else {
// non-regenerating corpses might bleed...
if (damtypecausesbleed(lf->lastdamtype, NULL)) {
char bname[BUFLEN];
if (getbloodobname(lf->flags, bname, B_FIRSTONE)) {
int howlong;
char *locbname;
locbname = strdup(bname);
// insert race name. for example,
// replace 'splash of blood' with 'splash of xat blood'
if (strends(locbname, " of blood")) {
char replacewith[BUFLEN];
sprintf(replacewith, " of %s blood",lf->race->name);
strrep(&locbname, " of blood", replacewith, NULL);
}
// amount of time blood will appear for depends
// on size.
howlong = getlfsize(lf)*4;
if (howlong > 0) {
flag_t *bf;
bf = addtempflag(corpse->flags, F_GENERATES,
80, 0, NA, locbname, howlong);
dblog("xx");
}
free(locbname);
}
}
}
// special case
if (lf->race->id == R_BLASTBUG) {
@ -4925,7 +4934,7 @@ int eat(lifeform_t *lf, object_t *o) {
if (corpserace && (corpserace->id == lf->race->baseid)) {
ppower = 3;
}
poison(lf, rnd(20,40), ptid, ppower, dambuf, cf ? cf->val[0] : R_NONE);
poison(lf, rnd(20,40), ptid, ppower, dambuf, cf ? cf->val[0] : R_NONE, B_FALSE);
} else if (!drinking) {
// raw meat?
if (corpserace && israwmeat(o) && !lfhasflag(lf, F_CANEATRAW)) {
@ -4961,7 +4970,7 @@ int eat(lifeform_t *lf, object_t *o) {
ppower = 3;
}
if (!skillcheck(lf, SC_POISON, checkdiff, 0)) {
poison(lf, rnd(timemin,timemax), ptid, ppower, dambuf, corpserace ? corpserace->id : R_NONE);
poison(lf, rnd(timemin,timemax), ptid, ppower, dambuf, corpserace ? corpserace->id : R_NONE, B_FALSE);
}
}
}
@ -5083,7 +5092,7 @@ int eat(lifeform_t *lf, object_t *o) {
addtempflag(lf->flags, F_DTRESIST, DT_COLD, NA, NA, NULL, rnd(20,40));
} else if (o->type->id == OT_POISONSAC) {
// very bad!
poison(lf, rnd(10,20), P_VENOM, 4, "eating a venom sac", R_NONE);
poison(lf, rnd(10,20), P_VENOM, 4, "eating a venom sac", R_NONE, B_TRUE);
}
if (isplayer(lf)) makeknown(o->type->id);
@ -7090,6 +7099,42 @@ int getadjenemies(lifeform_t *who, lifeform_t **adjlf, int *nadjlfs) {
return nadj;
}
// populates (and returns) buf with object name for this flagpile's blood.
// if no bloodob, buf will be set to "" and NULL returned.
//
// 'userandom' determines the behaviour if the flagpile has multiple F_BLOODOB flags.
// B_FIRSTONE means just return the first flag.
// B_ANYONE means return a random flag
char *getbloodobname(flagpile_t *fp, char *buf, int userandom) {
flag_t *retflag[MAXCANDIDATES],*f = NULL;
int nretflags;
getflags(fp, retflag, &nretflags, F_BLOODOB, F_NONE);
if (nretflags) {
if (nretflags == 1) {
f = retflag[0];
} else {
if (userandom) {
// pick a random one
f = retflag[rnd(0,nretflags-1)];
} else {
// pick first one
f = retflag[0];
}
}
if (f->text) {
strcpy(buf, f->text);
} else {
strcpy(buf, "");
return NULL;
}
} else {
// default
strcpy(buf, "splash of blood");
}
return buf;
}
// include allies or enemies which will follow you up/down stairs etc
// ie. allies within LOS
// ie. adjacent enemies
@ -12184,7 +12229,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
default: break;
}
depthmod += depthmod2;
if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE, B_TRUE, OC_NONE, DT_NONE, F_NONE)) {
if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE, RR_NONE, B_TRUE, OC_NONE, DT_NONE, F_NONE)) {
if (isshop) apply_shopob_restrictions(buf);
o = addob(op, buf);
}
@ -12203,7 +12248,8 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
default: break;
}
depthmod += depthmod2;
if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE, B_TRUE, OC_NONE, val[1], DT_NONE, F_NONE)) {
if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE,
RR_NONE, B_TRUE, OC_NONE, val[1], DT_NONE, F_NONE)) {
if (db) snprintf(buf2, BUFLEN, "finished startobdt successfuly.");
if (isshop) apply_shopob_restrictions(buf);
o = addob(op, buf);
@ -12226,7 +12272,8 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
default: break;
}
depthmod += depthmod2;
if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, val[1], B_TRUE, OC_NONE, DT_NONE, F_NONE)) {
if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, val[1],
getrarityval(text), B_TRUE, OC_NONE, DT_NONE, F_NONE)) {
char buf3[BUFLEN];
if (db) snprintf(buf2, BUFLEN, "finished startobwepsk successfuly.");
sprintf(buf3, "%s%s%s",text,strlen(text) ? " " : "",buf);
@ -12258,7 +12305,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
//obdb = B_TRUE;
if (real_getrandomob(targmap, buf, getmapdifficulty(targmap) + depthmod,
NA, maxobsize, SK_NONE, B_TRUE,
NA, maxobsize, SK_NONE, RR_NONE, B_TRUE,
val[1], OC_NONE, DT_NONE, wantflagid, F_NONE)) {
if (db) snprintf(buf2, BUFLEN, "finished startobclass, success.");
if (isshop) apply_shopob_restrictions(buf);
@ -16407,6 +16454,11 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
// if they died
if (lf->hp <= 0) {
// bleed some more.
if (damtypecausesbleed(damtype, fromob)) {
bleed(lf, B_NOSPLATTER);
}
if (fromlf && (getallegiance(fromlf) == AL_FRIENDLY)) {
addflag(lf->flags, F_KILLEDBYPLAYER, B_TRUE, NA, NA, NULL);
}
@ -16522,7 +16574,7 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr
}
// catch a cold?
if (!skillcheck(lf, SC_CON, (dam/2) + (getexposedlimbs(lf)*20), 0)) {
poison(lf, 20+(dam*3), P_COLD, 0, "the cold", fromlf ? fromlf->race->id : R_NONE);
poison(lf, 20+(dam*3), P_COLD, 0, "the cold", fromlf ? fromlf->race->id : R_NONE, B_FALSE);
}
// cold will heal bruised limbs
getflags(lf->flags, retflag, &nretflags, F_INJURY, F_NONE);
@ -16570,7 +16622,7 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr
} else if (damtype == DT_POISONGAS) {
if (dam > 0) {
if (!skillcheck(lf, SC_POISON, 170, 0)) { // HARD.
poison(lf, rnd(20,40), P_GAS, 2, "poison gas", fromlf ? fromlf->race->id : R_NONE);
poison(lf, rnd(20,40), P_GAS, 2, "poison gas", fromlf ? fromlf->race->id : R_NONE, B_TRUE);
}
}
}
@ -18096,6 +18148,7 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int want
// picked up something our god doesn't like?
if (isplayer(lf)) {
if ( hasflagknown(o->flags, F_POISONED) ||
hasflag(o->flags, F_VENOMSAC) ||
hasflagvalknown(o->flags, F_HITCONFER, F_POISONED, NA, NA, NULL)) {
int i,nretgods;
lifeform_t *retgod[MAXGODS];
@ -18117,7 +18170,7 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int want
}
// returns true on failure
int poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *fromwhat, enum RACE srcraceid) {
int poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *fromwhat, enum RACE srcraceid, int immediate) {
flag_t *f;
int found = B_FALSE,i;
enum POISONSEVERITY psev;
@ -18187,7 +18240,7 @@ int poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *
if (!found) {
// incubation period?
if (pt->incubationtime && isplayer(lf)) {
if (!immediate && pt->incubationtime && isplayer(lf)) {
flag_t *ii;
int multiplier = 0;
int tempmult;
@ -18604,6 +18657,7 @@ void preparecorpse(lifeform_t *lf, object_t *corpse) {
// add flag _before_ getting the name
addflag(corpse->flags, F_PREPARED, B_TRUE, NA, NA, NULL);
killflagsofid(corpse->flags, F_FROZEN);
killflagsofid(corpse->flags, F_GENERATES); // stop making blood
if (!hasflag(corpse->flags, F_TAINTED)) {
flag_t *f;
// it lasts a lot longer now.
@ -18622,6 +18676,7 @@ void preparecorpse(lifeform_t *lf, object_t *corpse) {
msg("You cook %s.", obname);
addflag(corpse->flags, F_PREPARED, B_TRUE, NA, NA, NULL);
killflagsofid(corpse->flags, F_FROZEN);
killflagsofid(corpse->flags, F_GENERATES); // stop making blood
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
// add flag after getting the name
@ -18630,9 +18685,11 @@ void preparecorpse(lifeform_t *lf, object_t *corpse) {
msg("%s cooks %s.", obname);
addflag(corpse->flags, F_PREPARED, B_TRUE, NA, NA, NULL);
killflagsofid(corpse->flags, F_FROZEN);
killflagsofid(corpse->flags, F_GENERATES); // stop making blood
} else {
addflag(corpse->flags, F_PREPARED, B_TRUE, NA, NA, NULL);
killflagsofid(corpse->flags, F_FROZEN);
killflagsofid(corpse->flags, F_GENERATES); // stop making blood
}
}
@ -18706,6 +18763,21 @@ int racecantalk(enum RACE rid) {
return B_FALSE;
}
// returns wheter, in general, creatures of this raceclass will bleed.
// (individual creatures may override this though)
int raceclassbleeds(enum RACECLASS id) {
switch (id) {
case RC_ANIMAL:
case RC_AQUATIC:
case RC_DRAGON:
case RC_HUMANOID:
case RC_INSECT:
return B_TRUE;
default: break;
}
return B_FALSE;
}
int racemeetscondition(race_t *r, enum CELLCONDITION cond, int arg, int val) {
int ok = B_FALSE;
flag_t *f;
@ -19279,6 +19351,20 @@ int safetorest(lifeform_t *lf) {
}
}
}
// extra checks for monsters
if (!isplayer(lf)) {
int timeneeded;
flag_t *f;
// must have gone at lesat 10 turns without being in battle
timeneeded = 16 - (getmorale(lf) / 5);
limit(&timeneeded, 5, NA);
f = lfhasflag(lf, F_TURNSINPEACE);
if (!f || (f->val[0] < timeneeded)) {
return B_FALSE;
}
}
return B_TRUE;
}
@ -19869,6 +19955,40 @@ void setattr(lifeform_t *lf, enum ATTRIB attr, int val) {
}
}
// if object o is a single object, mark that it came from lf.
//
// if it is more than one object, then maybe turn it into 'mixed blood'
// if there was already blood from a different kind of lf here.
// this will also make it unusable for filling flasks (ie. removes
// the F_FILLPOT flag)
//
// returns TRUE if blood is pure, FALSE if we now have mixed blood
int setbloodfrom(object_t *o, lifeform_t *lf) {
int pure = B_TRUE;
if (o->amt == 1) {
// ie. not joining a stack
addflag(o->flags, F_LINKRACE, lf->race->id, NA, NA, NULL);
if (hasflag(lf->flags, F_FILLPOT)) {
// override object flags
killflagsofid(o->flags, F_FILLPOT);
copyflag(o->flags, lf->flags, F_FILLPOT);
}
} else {
// if object isn't already linked to this lf, do so.
if (!hasflagval(o->flags, F_LINKRACE, lf->race->id, NA, NA, NULL)) {
addflag(o->flags, F_LINKRACE, lf->race->id, NA, NA, NULL);
}
// if there are now more than a single F_LINKRACE, it means that
// this is mixed blood.
if (countflagsofid(o->flags, F_LINKRACE) > 1) {
// mixed blood - can't use it for potions anymore
killflagsofid(o->flags, F_FILLPOT);
pure = B_FALSE;
}
}
return pure;
}
void setbodypartname(race_t *r, enum BODYPART bp, char *name) {
int i;
for (i = 0; i < r->nbodyparts; i++) {
@ -21511,11 +21631,13 @@ void startlfturn(lifeform_t *lf) {
movedlastturn += killflagsofid(lf->flags, F_HASBEENMOVED);
movedlastturn += killflagsofid(lf->flags, F_MOVED);
// if we didn't turn lsat move, kill our turncounter
if (!killflagsofid(lf->flags, F_TURNED)) {
lf->turncounter = 0;
}
// update where player knows
// (but without a map you will then slowly forget it)
if (isplayer(lf)) {
@ -21526,6 +21648,21 @@ void startlfturn(lifeform_t *lf) {
// ai start of turn code
killflagsofid(lf->flags, F_IGNORECELL);
// track how long we have gone without fighitng.
// this is used to determine when it is safe to
// rest.
if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) {
killflagsofid(lf->flags, F_TURNSINPEACE);
} else {
f = lfhasflag(lf, F_TURNSINPEACE);
if (f) {
f->val[0]++;
} else {
addflag(lf->flags, F_TURNSINPEACE, 1, NA, NA, NULL);
}
}
// cope with hecta's "sacrifices" escaping from the player
f = lfhasflag(lf, F_HECTAESCAPEE);
if (f) {
@ -21971,7 +22108,7 @@ void startlfturn(lifeform_t *lf) {
for (i = 1 ; i < lf->nlos; i++) {
lifeform_t *otherlf;
otherlf = lf->los[i]->lf;
if (otherlf && !areallies(lf, otherlf) && cansee(lf, otherlf)) {
if (otherlf && !areallies(lf, otherlf) && cansee(lf, otherlf) && !isasleep(otherlf)) {
int dist;
dist = getcelldist(lf->cell, lf->los[i]);
if (dist == (f->val[0] + 1) || (dist == (f->val[0] + 2))) {
@ -22030,7 +22167,7 @@ void startlfturn(lifeform_t *lf) {
addob(c->obpile, f->text);
}
} else {
addobsinradius(lf->cell, f->val[0], DT_COMPASS, f->text, B_FALSE, lf);
addobsinradius(lf->cell, f->val[0], DT_COMPASS, f->text, B_FALSE, B_INCLUDECENTRE, lf, NULL, NULL, NULL);
}
}
}

5
lf.h
View File

@ -150,6 +150,7 @@ int get_adjacent_quadrants(int dir, enum QUADRANT *start, enum QUADRANT *end);
int get_circular_fov_endpoints(lifeform_t *lf, int maxvisrange, int *endx, int *endy, int *nendcells);
int getactspeed(lifeform_t *lf);
int getadjenemies(lifeform_t *lf, lifeform_t **adjlf, int *nadjlfs);
char *getbloodobname(flagpile_t *fp, char *buf, int userandom);
void getwhowillfollow(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, int *seen, int *nadjallies);
enum ALIGNMENT getalignment(lifeform_t *lf);
int getalignmod(lifeform_t *lf);
@ -449,7 +450,7 @@ enum NOISECLASS noisetypetoclass(enum NOISETYPE nt);
void outfitlf(lifeform_t *lf);
void petify(lifeform_t *lf, lifeform_t *owner);
int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int antannounce);
int poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *fromwhat, enum RACE srcraceid);
int poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char *fromwhat, enum RACE srcraceid, int immediate);
int poisoneffects(lifeform_t *lf, enum POISONTYPE ptid, int power);
int poisoncausesvomit(enum POISONTYPE ptype);
int poisonthreatenslife(lifeform_t *lf, flag_t *f);
@ -460,6 +461,7 @@ void precalclos(lifeform_t *lf);
void preparecorpse(lifeform_t *lf, object_t *corpse);
int push(lifeform_t *lf, object_t *o, int dir);
int racecantalk(enum RACE rid);
int raceclassbleeds(enum RACECLASS id);
int racemeetscondition(race_t *r, enum CELLCONDITION cond, int arg, int val);
int racemeets(enum RACE rid, condset_t *cs);
int readytotrain(lifeform_t *lf);
@ -482,6 +484,7 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus);
//int setammo(lifeform_t *lf, object_t *o);
void setalignment(lifeform_t *lf, enum ALIGNMENT al);
void setattr(lifeform_t *lf, enum ATTRIB attr, int val);
int setbloodfrom(object_t *o, lifeform_t *lf);
void setbodypartname(race_t *r, enum BODYPART bp, char *name);
void setbodytype(race_t *r, enum BODYTYPE bt);
int setfacing(lifeform_t *lf, int dir);

1035
map.c

File diff suppressed because it is too large Load Diff

8
map.h
View File

@ -19,7 +19,7 @@ int cellisfixedvaultwall(cell_t *c);
//int cellmatchescondition(cell_t *c, int wecond);
int cellmeetscondition(cell_t *c, enum CELLCONDITION cond, int arg, int value);
int cellmeets(cell_t *c, condset_t *cs);
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom);
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom, char *why);
void clearcell(cell_t *c);
void clearcell_exceptflags(cell_t *c, ...);
int delve(map_t *map, int neighbourmin, int neighbourmax, int connchance, int chancepct, int newneighbourmin, int newneighbourmax, int newconnchance, enum CELLTYPE empty, enum CELLTYPE solid);
@ -61,6 +61,7 @@ int getmapmaxvisrange(map_t *m);
void getradiuscells(cell_t *centre, int radius, int dirtype, int outsideonly, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells, int scatterdensity);
int getroomid(cell_t *c);
void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid, int includefixed);
cell_t *getroommidcell(map_t *m, int roomid);
enum TIMEPHASE gettimephase(void);
object_t *gettopobject(cell_t *where, int forglyph);
//void calclight(map_t *map);
@ -102,12 +103,12 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r
int dirtox(int dt, int dir);
int dirtoy(int dt, int dir);
int doorisvalid(object_t *o);
void dumpmap(map_t *map, int showrooms);
void dumpmap(map_t *map, int showrooms, char *reasontext);
void expand_cave(map_t *map, int numpasses);
void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre, lifeform_t *fromwho, int doknockback);
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce, lifeform_t *fromwho);
void explosion_knockback(cell_t *c, int radius, int dirtype, int dam, lifeform_t *fromwho);
void finalisemap(map_t *map, object_t *entryob, int exitdir);
int finalisemap(map_t *map, object_t *entryob, int exitdir);
void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags, enum BEHAVIOUR wantbehaviour, int idx);
celltype_t *findcelltype(enum CELLTYPE cid);
celltype_t *findcelltypebyname(char *name);
@ -203,6 +204,7 @@ void selectcelltypes(map_t *map);
void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph);
void setcellknown(cell_t *cell, int forcelev);
void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype);
void setcelllocked(cell_t *c, char *why, ...);
void setcellreason(cell_t *c, char *why, ...);
void setcelltype(cell_t *cell, enum CELLTYPE id);
int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring);

12
move.c
View File

@ -3796,10 +3796,14 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
// is there a lf in sight, who is within our territorial
// radius of the cell we are testing?
for (i = 0; i < lf->nlos; i++) {
if (lf->los[i]->lf && !areallies(lf, lf->los[i]->lf) &&
(getcelldist(cell, lf->los[i]) <= tdist)) {
if (error) *error = E_WONT;
return B_FALSE;
lifeform_t *otherlf;
otherlf = lf->los[i]->lf;
if (otherlf && !areallies(lf, otherlf) &&
(getcelldist(cell, otherlf->cell) <= tdist)) {
if (!isasleep(otherlf)) {
if (error) *error = E_WONT;
return B_FALSE;
}
}
}
}

33
nexus.c
View File

@ -890,25 +890,46 @@ void dbtimeendlf(lifeform_t *lf) {
dbtimeend(buf);
}
void dbtimestart(char *text) {
void dbtimestart(char *format, ...) {
char buf[BUFLEN];
va_list args;
gettimeofday(&tv, NULL);
starttv = tv;
dblog("START\t%s", text);
va_start(args, format);
vsnprintf( buf, BUFLEN, format, args );
va_end(args);
dblog("START\t%s", buf);
}
void dbtime(char *text) {
void dbtime(char *format, ...) {
double ticks;
char buf[BUFLEN];
va_list args;
va_start(args, format);
vsnprintf( buf, BUFLEN, format, args );
va_end(args);
gettimeofday(&newtv, NULL);
ticks = ((newtv.tv_sec - tv.tv_sec) * 1000000) + (newtv.tv_usec - tv.tv_usec);
dblog("+%f\t%s", ticks, text);
dblog("+%f\t%s", ticks, buf);
tv = newtv;
}
void dbtimeend(char *text) {
void dbtimeend(char *format, ...) {
double ticks;
char buf[BUFLEN];
va_list args;
va_start(args, format);
vsnprintf( buf, BUFLEN, format, args );
va_end(args);
gettimeofday(&newtv, NULL);
ticks = ((newtv.tv_sec - starttv.tv_sec) * 1000000) + (newtv.tv_usec - starttv.tv_usec);
dblog("FINISHED %s (total time %f)", text, ticks);
dblog("FINISHED %s (total time %f)", buf, ticks);
}
void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, int dinc2, int *xinc, int *yinc, int *dinc) {

View File

@ -6,10 +6,10 @@ warning_t *addwarning(char *text, int lifetime);
void checkdeath(void);
void checkendgame(void);
void cleanup(void);
void dbtime(char *text);
void dbtimeend(char *text);
void dbtime(char *format, ...);
void dbtimeend(char *format, ...);
void dbtimeendlf(lifeform_t *lf);
void dbtimestart(char *text);
void dbtimestart(char *format, ...);
void dbtimestartlf(lifeform_t *lf);
void dobresnham(int d, int xinc1, int yinc1, int dinc1, int xinc2, int yinc2, int dinc2, int *xinc, int *yinc, int *dinc);
void donextturn(map_t *map);

207
objects.c
View File

@ -509,6 +509,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
cell_t *targetcell = NULL; // for portals
int donesomething;
object_t *addedob[MAXPILEOBS];
race_t *wantbloodrace = NULL;
int nadded = 0;
flagpile_t *wantflags;
// for doors
@ -716,6 +717,37 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
wantblessed = B_CURSED;
p += strlen("cursed ");
donesomething = B_TRUE;
// blood
} else if (strends(p, " blood")) {
char *spaceblood,*pp,rname[BUFLEN],*rp,replacefrom[BUFLEN];
race_t *r = NULL;
spaceblood = strends(p, " blood");
pp = strstr(p, " of ");
if (pp) {
pp += 4;
}
rp = rname;
for (;pp < spaceblood; pp++, rp++) {
*rp = *pp;
}
*rp = '\0';
if (strlen(rname)) {
r = findracebyname(rname, NULL);
if (r) {
wantbloodrace = r;
}
}
if (r) {
// now replace the end of the string.
// initially we'll have (eg) 'splash of xxx blood'
// change it to 'splash of blood'
sprintf(replacefrom, "%s blood", r->name);
pp = strstr(p, replacefrom);
assert(pp);
strcpy(pp, "blood");
}
// food flags
} else if (strstarts(p, "bruised ")) {
addflag(wantflags, F_BRUISED, B_TRUE, NA, NA, NULL);
@ -1432,11 +1464,27 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
}
}
if (linkrace && (linkrace->id != R_NONE)) {
addflag(o->flags, F_LINKRACE, linkrace->id, NA, NA, NULL);
}
if (gamemode != GM_LOADING) {
if (linkrace && (linkrace->id != R_NONE)) {
addflag(o->flags, F_LINKRACE, linkrace->id, NA, NA, NULL);
}
if (wantbloodrace && (wantbloodrace->id != R_NONE)) {
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0,i;
// don't duplicate this as then it will count as 'mixed blood'
if (!hasflagval(o->flags, F_LINKRACE, wantbloodrace->id, NA, NA, NULL)) {
addflag(o->flags, F_LINKRACE, wantbloodrace->id, NA, NA, NULL);
}
// not using copyflag, in order to avoid duplicates
getflags(wantbloodrace->flags, retflag, &nretflags, F_FILLPOT, F_NONE);
for (i = 0; i < nretflags; i++) {
addflag(o->flags, retflag[i]->id, retflag[i]->val[0], retflag[i]->val[1],
retflag[i]->val[2], retflag[i]->text);
//copyflag(o->flags, wantbloodrace->flags, F_FILLPOT);
}
}
if (hasflag(o->flags, F_NOBLESS)) {
setblessed(o, B_UNCURSED);
} else {
@ -2379,18 +2427,19 @@ void addomprefix(enum OBMOD id, char *altprefix) {
om->naltprefix++;
}
void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int allowdupes, lifeform_t *creator) {
void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int allowdupes, int includecentre, lifeform_t *creator, object_t **retob, int **retobcount, int *nretobs) {
cell_t *cell[MAXCANDIDATES],*c;
int ncells,i;
objecttype_t *ot;
object_t *o;
int nmade = 0;
ot = findotn(name);
if (!ot) return;
getradiuscells(centre, radius, DT_ORTH, B_FALSE, LOF_WALLSTOP, (radius == 0) ? B_TRUE : B_FALSE, cell, &ncells, B_FALSE);
getradiuscells(centre, radius, DT_ORTH, B_FALSE, LOF_WALLSTOP,
(radius == 0) || includecentre ? B_TRUE : B_FALSE, cell, &ncells, B_FALSE);
// global return values
nretobs = 0;
if (nretobs) *nretobs = 0;
for (i = 0; i < ncells; i++) {
c = cell[i];
@ -2401,10 +2450,10 @@ void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int all
if (creator) {
setobcreatedby(o, creator);
}
// global return values
retobs[nretobs] = o;
retobscount[nretobs] = o->amt;
nretobs++;
if (retob) retob[nmade] = o;
if (retobcount) *(retobcount[nmade]) = o->amt;
nmade++;
if (nretobs) (*nretobs) = nmade;
}
}
}
@ -5496,6 +5545,29 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} else {
sprintf(basename, "abandoned temple");
}
} else if ((o->type->id == OT_BLOODSPLASH) || (o->type->id == OT_BLOODPOOL)) {
race_t *brace = NULL;
enum SKILLLEVEL lorelev = PR_INEPT;
char *p,xblood[BUFLEN];
if (countflagsofid(o->flags, F_LINKRACE) > 1) {
sprintf(xblood, "mixed blood");
} else {
// you might recognise the type of blood
f = hasflag(o->flags, F_LINKRACE);
if (f) {
brace = findrace(f->val[0]);
if (brace) lorelev = getlorelevel(player, brace->raceclass->id);
}
if (brace && (lorelev >= PR_BEGINNER)) {
sprintf(xblood, "%s blood", brace->name);
} else {
sprintf(xblood, "unidentifiable blood");
}
}
p = strdup(o->type->name);
strrep(&p, "blood", xblood, NULL);
snprintf(basename, BUFLEN, "%s", p);
free(p);
} else if (hasflag(o->flags, F_DEEPWATER)) {
snprintf(basename, BUFLEN, "%s %s", getwaterdepthname(getobdepth(o, player)), o->type->name);
} else {
@ -6314,7 +6386,7 @@ objecttype_t *getoppositestairs(objecttype_t *ot) {
// OC_CLASS1, OC_CLAS2, OC_NONE, ..., DT_DAMTYPE1, DT_DAMTYPE2, .., DT_NONE, F_WANTFLAG1, F_WANTFLAG2, ..., F_NONE
//
// if no objectclass given then it will be picked randomly, or (if wepsk isn't sk_none) set to oc_weapon.
objecttype_t *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, enum SKILL wepsk, int forpickup, ... ) {
objecttype_t *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, enum SKILL wepsk, enum RARITY forcerr, int forpickup, ... ) {
va_list args;
objecttype_t *ot;
objecttype_t *poss[MAXRANDOMOBCANDIDATES];
@ -6396,7 +6468,11 @@ objecttype_t *real_getrandomob(map_t *map, char *buf, int forcedepth, int forceh
getrarityrange(depth, &raritymin, &raritymax, RARITYVARIANCEOB, B_TRUE);
// pick rr...
wantrr = pickrr(TT_OBJECT);
if (forcerr == RR_NONE) {
wantrr = pickrr(TT_OBJECT);
} else {
wantrr = forcerr;
}
origwantrr = wantrr;
// no obclass given? pick one randomly.
@ -6407,10 +6483,10 @@ objecttype_t *real_getrandomob(map_t *map, char *buf, int forcedepth, int forceh
} else if (!nwantflag) {
wantclass[0] = getrandomobclass(hab->id);
nwantclass = 1;
if (wantclass[0] == OC_WAND) {
dblog("random WAND picked!");
partdb = B_TRUE;
}
//if (wantclass[0] == OC_WAND) {
//dblog("random WAND picked!");
//partdb = B_TRUE;
//}
}
}
@ -6740,25 +6816,25 @@ objecttype_t *real_getrandomob(map_t *map, char *buf, int forcedepth, int forceh
}
objecttype_t *getrandomob(map_t *map, char *buf) {
return real_getrandomob(map, buf, NA, NA, SZ_MAX, SK_NONE, B_FALSE, OC_NONE, DT_NONE, F_NONE);
return real_getrandomob(map, buf, NA, NA, SZ_MAX, SK_NONE, RR_NONE, B_FALSE, OC_NONE, DT_NONE, F_NONE);
}
objecttype_t *getrandomobofsize(map_t *map, char *buf, enum LFSIZE maxsize) {
return real_getrandomob(map, buf, NA, NA, maxsize, SK_NONE, B_FALSE, OC_NONE, DT_NONE, F_NONE);
return real_getrandomob(map, buf, NA, NA, maxsize, SK_NONE,RR_NONE, B_FALSE, OC_NONE, DT_NONE, F_NONE);
}
objecttype_t *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf) {
return real_getrandomob(map, buf, NA, NA, SZ_MAX, SK_NONE, B_TRUE, OC_NONE, damtype, DT_NONE, F_NONE);
return real_getrandomob(map, buf, NA, NA, SZ_MAX, SK_NONE,RR_NONE, B_TRUE, OC_NONE, damtype, DT_NONE, F_NONE);
}
objecttype_t *getrandomobwithflag(map_t *map, enum FLAG fid, char *buf) {
return real_getrandomob(map, buf, NA, NA, SZ_MAX, SK_NONE, B_TRUE, OC_NONE, DT_NONE, fid, F_NONE);
return real_getrandomob(map, buf, NA, NA, SZ_MAX, SK_NONE,RR_NONE, B_TRUE, OC_NONE, DT_NONE, fid, F_NONE);
}
objecttype_t *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod) {
//return real_getrandomob(map, buf, RO_OBCLASS, cid, map->depth + depthmod);
//if (depthmod == NA) depthmod = 0;
return real_getrandomob(map, buf, getmapdifficulty(map) + depthmod, NA, SZ_MAX, SK_NONE, B_FALSE, cid, OC_NONE, DT_NONE, F_NONE);
return real_getrandomob(map, buf, getmapdifficulty(map) + depthmod, NA, SZ_MAX, SK_NONE, RR_NONE, B_FALSE, cid, OC_NONE, DT_NONE, F_NONE);
}
enum OBCLASS getrandomobclass(enum HABITAT hab) {
@ -10506,16 +10582,27 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
} else if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) {
object_t *oo,*nextoo;
object_t *notenough = NULL;
if (isplayer(lf)) {
int donedip = B_FALSE;
int anydippable = B_FALSE;
// anything here to fill with?
for (oo = lf->cell->obpile->first ; (oo && !donedip); oo = nextoo) {
flag_t *fillflag;
int dippable = B_FALSE;
nextoo = oo->next;
fillflag = hasflag(oo->flags, F_FILLPOT);
if (fillflag && ((fillflag->val[1] == NA) || (oo->amt >= fillflag->val[1]))) {
dippable = B_TRUE;
if (fillflag) {
if (getobsize(oo) < getobsize(o)) {
// not dippable, but display a different message
if (!notenough) {
notenough = oo;
}
} else {
dippable = B_TRUE;
anydippable = B_TRUE;
notenough = NULL;
}
}
if (dippable) {
@ -10593,7 +10680,16 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
if (!donedip) {
msg("There is nothing here to fill your %s from.",noprefix(obname));
if (anydippable) {
msg("There is nothing else here to fill your %s from.",noprefix(obname));
} else if (notenough) {
char poolname[BUFLEN];
getobname(notenough, poolname, notenough->amt);
msg("%s %s not sufficient to fill your %s.",poolname,
(notenough->amt == 1) ? "is" : "are", noprefix(obname));
} else {
msg("There is nothing here to fill your %s from.",noprefix(obname));
}
}
}
} else if (o->type->id == OT_MISTLETOE) {
@ -11710,7 +11806,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
if (isplayer(lf)) msg("Yuck, this tastes like blood!");
// find random lycanthrope type
r = getrandomracewithflag(F_LYCANTHROPE);
poison(lf, PERMENANT, P_LYCANTHROPY, 1, r->name, R_NONE);
poison(lf, PERMENANT, P_LYCANTHROPY, 1, r->name, R_NONE, B_FALSE);
break;
case OT_POT_MAGIC:
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 150, -10)) {
@ -11746,7 +11842,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
if (isplayer(lf)) {
msg("^%cThis tastes like poison!", getlfcol(lf, CC_BAD));
}
if (poison(lf, rnd(10,20), P_VENOM, 1, "a potion of poison", R_NONE)) {
if (poison(lf, rnd(10,20), P_VENOM, 1, "a potion of poison", R_NONE, B_TRUE)) {
if (isplayer(lf)) msg("Luckily, it has no effect.");
}
break;
@ -13923,7 +14019,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
}
radius = o->amt * 2;
if (radius > 10) radius = 10;
addobsinradius(thrower->cell, radius, DT_COMPASS, "cloud of smoke", B_FALSE, thrower);
addobsinradius(thrower->cell, radius, DT_COMPASS, "cloud of smoke", B_FALSE, B_INCLUDECENTRE, thrower, NULL, NULL, NULL);
} else if (o->type->id == OT_ASHEXPLODE) {
char diebuf[BUFLEN];
// explosion!
@ -14610,8 +14706,12 @@ void timeeffectsob(object_t *o) {
newoid = f->val[1];
}
// some flags will be inherited by the new object
// remember certain flags from the objects which are combining.
copyflag(fp, o->flags, F_FILLPOT);
copyflag(fp, o->flags, F_LINKRACE);
killflagsofid(o->flags, F_FILLPOT);
killflagsofid(o->flags, F_LINKRACE);
// remove some instances of the original object.
removeob(o, newamt * f->val[0]);
@ -14624,6 +14724,9 @@ void timeeffectsob(object_t *o) {
newob = addobfast(op, newoid);
}
if (newob) {
killflagsofid(newob->flags, F_FILLPOT);
killflagsofid(newob->flags, F_LINKRACE);
// restore remembered flags
copyflags(newob->flags, fp, NA);
}
}
@ -14632,6 +14735,12 @@ void timeeffectsob(object_t *o) {
return;
}
// mixed blood loses other properties.
// shoudl never happen - but check just in case
if (countflagsofid(o->flags, F_LINKRACE) > 1) {
killflagsofid(o->flags, F_FILLPOT);
}
// expire flags
timeeffectsflags(o->flags);
checkflagpile(o->flags);
@ -14874,7 +14983,6 @@ void timeeffectsob(object_t *o) {
}
if (location && onground) {
if ((o->type->material->id == MT_WATER) || (o->type->id == OT_SPLASHWATER)) {
if (location->type->absorbent) {
if (haslos(player, location)) {
@ -14885,6 +14993,29 @@ void timeeffectsob(object_t *o) {
return;
}
}
getflags(o->flags, retflag, &nretflags, F_GENERATES, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (pctchance(f->val[0])) {
cell_t *where;
if (f->val[2] == NA) {
where = location;
} else {
condset_t cs;
initcondv(&cs, CC_IMPASSABLE, B_FALSE, NA, CC_NONE);
where = getrandomadjcell(location, &cs, B_NOEXPAND);
}
if (where) {
if (f->val[1] == 0) {
addob(where->obpile, f->text);
} else {
addobsinradius(where, f->val[1], DT_COMPASS, f->text, B_TRUE, B_INCLUDECENTRE,
NULL, NULL, NULL, NULL);
}
}
}
}
}
@ -15359,13 +15490,21 @@ void timeeffectsob(object_t *o) {
// now move other adjacent objects in the same direction (if we can).
for (i = 0; i < nadjobs; i++) {
int dead = B_FALSE;
c = getcellindir(adjob[i]->pile->where, dir);
if (c) {
if (c->type->solid) {
// this should always kill it!
damagecell(c, c->hp, DT_DIRECT, NULL);
if (f->val[0] == B_TRUE) {
// this should always kill it!
damagecell(c, c->hp, DT_DIRECT, NULL);
} else {
killob(adjob[i]);
dead = B_TRUE;
}
}
if (!dead) {
moveob(adjob[i], c->obpile, adjob[i]->amt);
}
moveob(adjob[i], c->obpile, adjob[i]->amt);
}
}
}
@ -15506,7 +15645,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped
}
}
if (!avoided) {
poison(lf, rnd(10,20), P_VENOM, 1, "a needle trap", R_NONE);
poison(lf, rnd(10,20), P_VENOM, 1, "a needle trap", R_NONE, B_TRUE);
}
} else {
if (haslos(player, c)) {

View File

@ -16,7 +16,7 @@ int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fr
obmod_t *addobmod(enum OBMOD id, char *prefix);
obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob);
void addomprefix(enum OBMOD id, char *altprefix);
void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int allowdupes, lifeform_t *creator);
void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int allowdupes, int includecentre, lifeform_t *creator, object_t **retob, int **retobcount, int *nretobs);
objecttype_t *addot(enum OBTYPE id, char *name, char *description, int material, float weight, int obclassid, enum LFSIZE size);
recipe_t *addrecipe(enum OBTYPE result, ...);
void adjustdamhardness(int *dam, enum DAMTYPE damtype, enum MATERIAL mat);
@ -146,7 +146,7 @@ char *getobhurtname(object_t *o, enum DAMTYPE damtype);
float getobweight(object_t *o);
float getobunitweight(object_t *o);
objecttype_t *getoppositestairs(objecttype_t *ot);
objecttype_t *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, enum SKILL wepsk, int forpickup, ... );
objecttype_t *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, enum SKILL wepsk, enum RARITY forcerr, int forpickup, ... );
objecttype_t *getrandomob(map_t *map, char *buf);
objecttype_t *getrandomobofsize(map_t *map, char *buf, enum LFSIZE maxsize);
objecttype_t *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf);

9
save.c
View File

@ -1282,6 +1282,7 @@ int showhiscores(lifeform_t *lf, int min, int max) {
if (lf && !lfhasflag(lf, F_NOSCORE)) {
hilitescore = calcscore(lf);
if (hilitescore == 0) hilitescore = -1;
} else {
hilitescore = -1;
}
@ -1301,9 +1302,9 @@ int showhiscores(lifeform_t *lf, int min, int max) {
snprintf(hilitescoretext, BUFLEN, "%ld",hilitescore);
rc = sqlite3_exec(db, cmd, showhiscoreline, hilitescoretext, &errmsg);
if (rc != SQLITE_OK) {
msg("error writing hiscores: '%s'", errmsg);
msg("error readin hiscores: '%s'", errmsg);
dblog("query was: '%s'", cmd);
dblog("error writing hiscores: '%s'\n sql command: [%s]", errmsg, cmd);
dblog("error readin hiscores: '%s'\n sql command: [%s]", errmsg, cmd);
sqlite3_free(errmsg);
}
free(cmd);
@ -1351,7 +1352,7 @@ int writehiscore(lifeform_t *lf, int *rank) {
escaped = strdup(killedby);
strrep(&escaped, "'", "''", NULL);
if (!lfhasflag(lf, F_NOSCORE)) {
if (!lfhasflag(lf, F_NOSCORE) && (score > 0)) {
asprintf(&cmd, "insert into 'hiscores' (score,name,job,killedby) VALUES (%ld, '%s', '%s', '%s')", score, pname, jobname, escaped);
rc = sqlite3_exec(db, cmd, NULL, NULL, &errmsg);
free(cmd);
@ -1367,6 +1368,8 @@ int writehiscore(lifeform_t *lf, int *rank) {
if (rank) {
if (lfhasflag(lf, F_NOSCORE)) {
*rank = -1;
} else if (score == 0) {
*rank = -2;
} else {
// find out the player's rank
asprintf(&cmd, "select (select count(*) from hiscores b where b.score > a.score) + 1 as rank from hiscores a where score = %ld;",score);

23
spell.c
View File

@ -1197,11 +1197,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
slev = getskill(user, SK_ENGINEERING);
dir = askdir("Dismantle obstacle in which direction (- to cancel)", B_TRUE, B_FALSE);
if (dir == D_NONE) {
dirch = askdir("Dismantle obstacle in which direction (- to cancel)", B_TRUE, B_FALSE);
if (dirch == D_NONE) {
msg("Cancelled.");
return B_TRUE;
} else if (dir == D_MYSELF) {
} else if (dirch == D_MYSELF) {
c = user->cell;
} else {
dir = chartodir(dirch);
@ -2093,7 +2093,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else {
object_t *oo;
for (oo = targcell->obpile->first; oo ; oo = oo->next) {
if (aiwants(user, oo, NULL)) {
if (canpickup(user, oo, 1) && aiwants(user, oo, NULL)) {
o = oo;
break;
}
@ -4054,7 +4054,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// destroy WORN metal objects by the caster (not CARRIED ones)
for (o = caster->pack->first ; o ; o = o->next) {
if (isequipped(o) && ismetal(o->material->id) && isweapon(o)) {
if (isequipped(o) && ismetal(o->material->id)) {
takedamage(o, 9999, DT_DIRECT, caster);
if (hasflag(o->flags, F_DEAD)) {
totalmass += getobweight(o);
@ -6171,10 +6171,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
}
}
addobsinradius(c, 1, DT_COMPASS, "5-10 stones", B_TRUE, NULL);
addobsinradius(c, 1, DT_COMPASS, "5-10 stones", B_TRUE, B_NOCENTRE, NULL, NULL, NULL, NULL);
addob(c->obpile, "5-10 stones");
} else if (c->type->material->id == MT_BLOOD) {
addobsinradius(c, 1, DT_COMPASS, "pool of blood", B_TRUE, NULL);
addobsinradius(c, 1, DT_COMPASS, "pool of blood", B_TRUE, B_NOCENTRE, NULL, NULL, NULL, NULL);
addob(c->obpile, "pool of blood");
}
@ -7726,7 +7726,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
radius = power / 2;
if (radius < 1) radius = 1;
addobsinradius(targcell, radius, DT_ORTH, "hail storm", B_FALSE, caster);
addobsinradius(targcell, radius, DT_ORTH, "hail storm", B_FALSE, B_INCLUDECENTRE,
caster, NULL, NULL, NULL);
// replace damage per sec with power d4
asprintf(&dambuf, "%dd4", power);
@ -9381,7 +9382,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("^%cA glob of venom hits %s.",getlfcol(target, CC_BAD), lfname);
}
if (!isimmuneto(target->flags, DT_POISON, B_FALSE)) {
poison(target, power*3, P_VENOM, (power/4)+1, "a glob of venom", caster ? caster->race->id : R_NONE);
poison(target, power*3, P_VENOM, (power/4)+1, "a glob of venom",
caster ? caster->race->id : R_NONE, B_TRUE);
}
}
}
@ -11597,7 +11599,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
radius = power / 2;
if (radius < 1) radius = 1;
addobsinradius(targcell, radius, DT_ORTH, "storm of sleet", B_FALSE, caster);
addobsinradius(targcell, radius, DT_ORTH, "storm of sleet", B_FALSE, B_INCLUDECENTRE,
caster, NULL, NULL, NULL);
} else {
failed = B_TRUE;
}

17
text.c
View File

@ -1644,6 +1644,23 @@ char *getrarityname(enum RARITY rr) {
return "?unknownrarity?";
}
// converts text to rarity value
enum RARITY getrarityval(char *name) {
enum RARITY wantrarity = RR_NONE;
if (streq(name,"frequent")) {
wantrarity = RR_FREQUENT;
} else if (streq(name,"common")) {
wantrarity = RR_COMMON;
} else if (streq(name,"uncommon")) {
wantrarity = RR_UNCOMMON;
} else if (streq(name,"rare")) {
wantrarity = RR_RARE;
} else if (streq(name,"very rare")) {
wantrarity = RR_VERYRARE;
}
return wantrarity;
}
// pass in EITHER m or r, not both.
//
// if how is anything other than RF_SHORT, "m" should be passed.

1
text.h
View File

@ -42,6 +42,7 @@ char *getinjuryname(enum DAMTYPE dt);
char *getinjurydesc(enum BODYPART bp, enum DAMTYPE dt);
char *getobmodprefix(object_t *o, obmod_t *om);
char *getrarityname(enum RARITY rr);
enum RARITY getrarityval(char *name);
char *getregionname(char *buf, map_t *m, region_t *r, enum REGIONNAMEFORMAT how);
char *getreldirname(int reldir);
char *getsizetext(enum LFSIZE sz);

View File

@ -2,6 +2,7 @@
#include <ctype.h>
#include <dirent.h>
#include <math.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -409,7 +410,9 @@ int addvaultthing(cell_t *c, vault_t *v, enum VAULTTHING vt, char *what) {
case VT_LF:
lf = addmonster(c, R_SPECIFIED, what, B_TRUE, 1, B_TRUE, NULL);
if (!lf) {
dblog("invalid racename '%s' in vault", what);
dblog("invalid racename '%s' in vault %s", what, v->id);
msg("invalid racename '%s' in vault %s", what, v->id);
raise(SIGINT);
rv = B_TRUE;
}
// first lifeform in a shop is the shopkeeper