* [+] let credit cards be used at some shops?

* [+] bug with adding obejcts to shops
- [+] issue with objects dying and killing their flagpiles
    - [+] A medium fire dies down a little.  A medium fire is no longer
          glowing.
    - [+] shouldn't say "is no longer glowing" when we're changing the
          type... ?
    - [+] put a breakpoint on "is no longer glowing"
* [+] let you bless objects using a holy circle somehow (but it might
      make the circle disappear?).
- [+] darness bug - need to recalc light for anyone who sees a cell's
      lightlevel change.
- [+] call more() after showing vaultentertext()
- [+] remove "inspected" when you ident or makeknown an object.
- [+] BUG - no objects in inventory!!!!
    - [+] listobs failing? mylist[0] = null.
MEMLEAK
- [+] finish implementing CLEANUP()
- [+] crash in cleanup() -> killot() -> findleak.c_stuff while freeing
      STACKABLE flag from cactus fruit???
    - [+] better now?
- [+] now a crash freeing hiddennames!
- [+] forgot to free obmods
- [+] leaking approx. 1 meg per turn!
- [+] where am i leaking?! maybe try valgrind or findleak.c
- [+] findleak.c now finds nothing.
- [+] but i am sitll leaking?????
- [+] related to lifeform count.  killing all but player dramatically
      slows it.
- [+] check calclos()... looks okay.
- [+] setcellknown() ?no.
- [+] startlfturn?? no.
- [+] remove unused "lf->viscell"
- [+] when there are 2 things in a cell, say "you see x and x here."
- [+] restore original stast when polymorphing back to original form!!!
- [+] when making shops, pick new ones more often.
- [+] change to maps: don't let vaults overlap.
- [+] HARDCODE object values
    - [+] potions
    - [+] tech
    - [+] tools
    - [+] rings
- [+] increase evasion skill effects
- [+] changes to  animradial... and animradialorth
    - [+] combine into one function
    - [+] move msg into here
    - [+] refs to spellcloud()
    - [+] refs to animradial()
- [+] fire should spread onto flammable lifeforms
- [+] bug: attack flurry doesn't work for monk
- [+] let monsters climb even when not facing a wall?
    - [+] set their facing first.
- [+] CRASH when you die while climbing (or on a solid cell)
- [+] rings
    - [+] stench
    - [+] breath water
    - [+] detect life
    - [+] deceleration
    - [+] meditation
    - [+] reflection
    - [+] boost magic power
    - [+] education - gain xpskills more quickly
    - [+] crit protection
    - [+] greed - detect obs
- [+] ivy - grows!
- [+] ragefungus - bezerk spores
- [+] nutter - drops peanuts
- [+] dish which slightly increases maxhp (beginner level)
    - [+] stuffed mushroom. shiitake mushroom + bread
This commit is contained in:
Rob Pearce 2011-12-08 02:55:14 +00:00
parent 9da88f06e3
commit 089ce94751
27 changed files with 1940 additions and 1083 deletions

View File

@ -1,5 +1,6 @@
nexus: 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 -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 vault.h -lncurses -lsqlite3
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 -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 findleak.c -lncurses -lsqlite3
check: 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
splint -onlytrans -nullret -nullstate -branchstate -usedef -type -retvalint -retvalother +posixlib -unrecog -boolops -mustfreefresh -predboolint -unqualifiedtrans -compdef *.c

78
ai.c
View File

@ -54,10 +54,10 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) {
// already targetting this lf?
f = lfhasflagval(lf, F_TARGETLF, victim->id, NA, NA, NULL);
if (f) {
dblog(".oO { i am already targetting this lf }");
if (db) dblog(".oO { i am already targetting this lf }");
if ((f->lifetime > 0) && (f->lifetime < timelimit)) {
f->lifetime = timelimit;
dblog(".oO { (flag lifetime updated) }");
if (db) dblog(".oO { (flag lifetime updated) }");
}
return B_TRUE;
}
@ -307,10 +307,12 @@ object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK
if (iqb <= IQ_ANIMAL) {
// animal and lower intelligence won't use ranged
// attacks.
if (!lfhasflag(lf, F_WILLTHROW)) {
if (db) dblog(".oO { no ranged attack due to low iq. }");
if (ra) *ra = RA_NONE;
return NULL;
}
}
o = getfirearm(lf);
if (o && getammo(o)) {
@ -412,7 +414,23 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi
}
if (specialcase) {
if (spelltype->id == OT_S_TELEKINESIS) {
if (spelltype->id == OT_A_CLIMB) {
int i,nposs = 0;
cell_t *poss[MAXCANDIDATES];
// cell in sight and adjacent? aispellok() should have already confirmed
// that there will be at least one of these.
for (i = 1; i < lf->nlos; i++) {
if (!lf->los[i]->lf && lf->los[i]->type->solid && (getcelldist(lf->cell, lf->los[i]) == 1)) {
poss[nposs++] = lf->los[i];
}
}
if (spellcell) {
*spellcell = poss[rnd(0,nposs-1)];
}
if (spelllf) *spelllf = NULL;
if (spellob) *spellob = NULL;
} else if (spelltype->id == OT_S_TELEKINESIS) {
float maxweight;
object_t *poss[MAXPILEOBS];
int nposs;
@ -578,6 +596,19 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
// not attacking anyone in particular
if (db) dblog(".oO { i do not have a target or can't move towards it. }");
// special cases
if (lf->race->id == R_IVYRAPID) {
if (cancast(lf, OT_S_CLONE, NULL)) {
// try to expand
if (!castspell(lf, OT_S_CLONE, lf, NULL, lf->cell, NULL, NULL)) {
// stop reproducing
f = hasflagval(lf->flags, F_CANWILL, OT_S_CLONE, NA, NA, NULL);
if (f) killflag(f);
return B_TRUE;
}
}
}
// shopkeepers will return to their shops
if (hasjob(lf, J_SHOPKEEPER)) {
f = lfhasflag(lf, F_OWNSSHOP);
@ -634,7 +665,13 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
}
if (pctchance(chance)) {
if (lfhasflagval(lf, F_HATESRACE, who->race->id, NA, NA, NULL) ||
if (lfhasflag(lf, F_HATESALL)) {
if (nhateposs < MAXCANDIDATES) {
if (db) dblog(".oO { hate everything - found lfid %d (%s) ! }",who->id, who->race->name);
hateposs[nhateposs++] = who;
}
break;
} else if (lfhasflagval(lf, F_HATESRACE, who->race->id, NA, NA, NULL) ||
lfhasflagval(lf, F_HATESRACE, who->race->baseid, NA, NA, NULL) ) {
if (nhateposs < MAXCANDIDATES) {
if (db) dblog(".oO { found a hated target - lfid %d (%s) ! }",who->id, who->race->name);
@ -1340,7 +1377,11 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// for firearms/projectiles, chance to fire/throw depends on accuracy.
if ((rangedattack == RA_GUN) || (rangedattack == RA_THROW)) {
int acc,chance;
int chance;
if (lfhasflag(lf, F_WILLTHROW)) {
chance = 100;
} else {
int acc;
acc = getmissileaccuracy(lf, target->cell, getammo(rangedob), rangedob, NULL);
switch (getpctletter(acc,100)) {
case 'S':
@ -1353,6 +1394,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
default:
chance = 25; break;
}
}
if (!pctchance(chance)) {
rangedattack = RA_NONE;
rangedob = NULL;
@ -1901,7 +1943,26 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
}
if (specialcase) {
if (ot->id == OT_S_PYROMANIA) {
if (ot->id == OT_A_CLIMB) {
int possible = B_TRUE,i;
enum ERROR reason;
// can't climb for a reason other than that there isn't
// a climbabnle cell in front of us?
if (!canclimb(lf, &reason)) {
if (reason != E_BADCLIMBDIR) {
possible = B_FALSE;
}
}
if (possible) {
// cell in sight and adjacent?
for (i = 1; i < lf->nlos; i++) {
if (!lf->los[i]->lf && lf->los[i]->type->solid && (getcelldist(lf->cell, lf->los[i]) == 1)) {
ok = B_TRUE;
break;
}
}
}
} else if (ot->id == OT_S_PYROMANIA) {
int i;
for (i = 0; i < lf->nlos; i++) {
if ((lf->los[i] != lf->cell) && getflamingobs(lf->los[i]->obpile, NULL, NULL)) {
@ -1964,11 +2025,6 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
if ((ot->id == OT_S_BLINDNESS) && isblind(victim)) {
specificcheckok = B_FALSE;
}
if (ot->id == OT_A_CLIMB) {
if (!canclimb(lf, NULL)) {
specificcheckok = B_FALSE;
}
}
if (ot->id == OT_A_DISARM) {
if (!getweapon(victim)) {
specificcheckok = B_FALSE;

View File

@ -328,6 +328,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
if (isplayer(lf)) {
msg("You cannot attack!");
}
if (op) killobpile(op);
return B_TRUE;
}

306
data.c
View File

@ -26,6 +26,7 @@ extern hiddennamewithcol_t colour[];
extern char *bookadjective[];
extern char *potadjective[];
extern hiddennamewithcol_t gemtype[];
extern char *ringadjective[];
extern char *techadjective[];
extern char *technoun[];
@ -892,6 +893,12 @@ void initobjects(void) {
// add it without an adjective
snprintf(buf, BUFLEN, "%s ring", gemtype[n].name);
addhiddenname(OC_RING, buf);
// add it with all known adjectives
for (i = 0; strlen(ringadjective[i]) ; i++) {
char buf2[BUFLEN];
snprintf(buf2, BUFLEN, "%s %s",ringadjective[i], buf);
addhiddenname(OC_RING, buf);
}
}
for (n = 0; strlen(technoun[n]); n++) {
@ -1378,7 +1385,7 @@ void initobjects(void) {
// buildings
addot(OT_MOTEL, "motel", "A small structure providing cheap overnight rooms for rent", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_REST, "a:rent a room");
addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, SM_PURCHASEITEMS, "b:buy provisions");
@ -1390,7 +1397,7 @@ void initobjects(void) {
}
addot(OT_SHOPARMOUR, "armour store", "A small kiosk dealing in armour.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something");
addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, SM_DONATE, "d:donate something");
@ -1399,7 +1406,7 @@ void initobjects(void) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_ARMOUR, RANDOM, NULL);
}
addot(OT_SHOPBOOK, "book store", "A small kiosk dealing in books.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
for (i = 0; i < 10; i++) {
@ -1408,21 +1415,21 @@ void initobjects(void) {
addaltval(f, F_STARTOBCLASS, 100, OC_SCROLL, RANDOM, NULL);
}
addot(OT_SHOPFOOD, "food vendor", "A small kiosk dealing in food.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_FOOD, RANDOM, NULL);
}
addot(OT_SHOPGENERAL, "general store", "A small kiosk which sells various objects.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
}
addot(OT_SHOPHARDWARE, "hardware store", "A small kiosk which sells tools and technology.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
for (i = 0; i < 10; i++) {
@ -1431,21 +1438,21 @@ void initobjects(void) {
addaltval(f, F_STARTOBCLASS, 100, OC_TECH, RANDOM, NULL);
}
addot(OT_SHOPPOTION, "potion store", "A small kiosk dealing in liqour and potions.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_POTION, RANDOM, NULL);
}
addot(OT_SHOPRING, "jewellery store", "A small kiosk dealing in rings and amulets.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_RING, RANDOM, NULL);
}
addot(OT_SHOPWEAPON, "weapon store", "A small kiosk dealing in weapons.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something");
addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, SM_DONATE, "d:donate something");
@ -1454,7 +1461,7 @@ void initobjects(void) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_WEAPON, RANDOM, NULL);
}
addot(OT_TEMPLE, "temple", "A small structure dedicated to one of the gods.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "voices chanting.");
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, 1, "a:speak to a deacon (earthly concerns)");
@ -1919,8 +1926,8 @@ void initobjects(void) {
addot(OT_CLOVER, "four leafed clover", "A rare 4-leafed clover.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_GREEN, '%', NA, NULL);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_RARE, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_HOLDCONFER, F_EXTRALUCK, 1, NA, NULL);
killflagsofid(lastot->flags, F_STACKABLE);
addot(OT_BREADSTALE, "loaf of stale bread", "A small loaf of old, stale bread.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY);
@ -1969,10 +1976,15 @@ void initobjects(void) {
addflag(lastot->flags, F_EDIBLE, B_TRUE, 30, NA, "");
addot(OT_NUT, "peanut", "A species in the legume family.", MT_FOOD, 0.1, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 12, NA, "");
addflag(lastot->flags, F_EDIBLE, B_TRUE, 22, NA, "");
addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
addflag(lastot->flags, F_NUMAPPEAR, 1, 12, NA, "");
addot(OT_PASSIONFRUIT, "passionfruit", "A succulent passionfruit.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_MAGENTA, '%', NA, NULL);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 100, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL);
addot(OT_ROASTMEAT, "chunk of roast meat", "A chunk of flame-roasted flesh.", MT_FLESH, 1, OC_FOOD, SZ_TINY); // weight normally comes from corpse type
addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL);
addflag(lastot->flags, F_EDIBLE, B_TRUE, 100, NA, "");
@ -2023,33 +2035,41 @@ void initobjects(void) {
// potions
addot(OT_POT_SPIDERCLIMB, "potion of arachnid adhesion", "Temporarily allows you to climb on walls like a spider.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_VALUE, 45, NA, NA, NULL);
addot(OT_POT_JUICE, "potion of fruit juice", "Tasty (but not very fresh) fruit juice! Sates hunger and restores a little stamina.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL);
addot(OT_POT_CANINETRACKING, "potion of canine tracking", "Mimics the effects of a 'canine tracking' spell.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-10 health to whoever drinks it.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 30, NA, NA, NULL);
addot(OT_POT_WATER, "potion of water", "Plain, regular water.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_FREQUENT, NULL);
addflag(lastot->flags, F_RARITY, H_VILLAGE, 100, RR_FREQUENT, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small puddle of water");
modflag(lastot->flags, F_HASHIDDENNAME, NA, NA, NA, "clear potion");
addflag(lastot->flags, F_VALUE, 5, NA, NA, NULL);
addot(OT_POT_HEALING, "potion of healing", "Restores 10-20 health to whoever drinks it.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 90, NA, NA, NULL);
addot(OT_POT_HEALINGMAJ, "potion of major healing", "Restores 20-30 health to whoever drinks it.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 120, NA, NA, NULL);
addot(OT_POT_OIL, "potion of oil", "A bottle of cooking oil.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of oil");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_EXPLODEONDAM, DT_FIRE, NA, NA, "2d4");
addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL);
addot(OT_POT_COFFEE, "potion of coffee", "A caffeinated beverage prepared from coffee beans.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL);
addot(OT_POT_RUM, "potion of rum", "Strong liqour which is sure to make you tipsy. This will make you unsteady and lower your accuracy, but also let you ignore pain, minor damage, and many mental attacks.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_FLAMMABLE, 1, NA, NA, "medium fire");
@ -2057,70 +2077,91 @@ void initobjects(void) {
addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_EXPLODEONDAM, DT_FIRE, NA, NA, "2d6");
addflag(lastot->flags, F_BADOBJECT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL);
addot(OT_POT_RESTORATION, "potion of restoration", "Restores lost abilities to the drinker.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_VALUE, 170, NA, NA, NULL);
addot(OT_POT_SLEEP, "potion of sleep", "Puts the drinker into a deep sleep.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BADOBJECT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 80, NA, NA, NULL);
addot(OT_POT_SPEED, "potion of haste", "Temporarily increasees the drinker's speed.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addot(OT_POT_LEVITATION, "potion of levitation", "Causes the drinker to float up in the air.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addot(OT_POT_MAGIC, "potion of magic", "Fully restores the drinker's magical energy.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 60, NA, NA, NULL);
addot(OT_POT_ACROBATICS, "potion of acrobatics", "Allows the drinker to leap large distances.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_VALUE, 45, NA, NA, NULL);
addot(OT_POT_INVIS, "potion of invisibility", "Temporarily renders the drinker invisible.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 70, NA, NA, NULL);
addot(OT_POT_POISON, "potion of poison", "Poisons the drinker.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BADOBJECT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
addot(OT_POT_ACID, "flask of battery acid", "Causes massive internal burning if ingested.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of acid");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BADOBJECT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
addot(OT_POT_ELEMENTIMMUNE, "potion of elemental immunity", "Grants the imbiber temporary immunity to both fire and cold.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
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, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "splash 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, NA, NULL);
addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL);
addot(OT_POT_ETHEREALNESS, "potion of etherealness", "Allows the walker to temporarily pass through walls.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_VALUE, 140, NA, NA, NULL);
addot(OT_POT_EXPERIENCE, "potion of experience", "Instantly grants the imbiber the next experience level.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, 40, NA, NULL);
addflag(lastot->flags, F_VALUE, 210, NA, NA, NULL);
addot(OT_POT_BLOODC, "potion of cockatrice blood", "A small quantity of cockatrice blood.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "splash of cockatrice blood");
addflag(lastot->flags, F_VALUE, 35, NA, NA, NULL);
addot(OT_POT_COMPETENCE, "potion of competence", "Permemantly increases the drinker's strength, intelligence or dexterity.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_VALUE, 160, NA, NA, NULL);
addot(OT_POT_GASEOUSFORM, "potion of gaseous form", "Turns the drinker into a cloud of gas. Only intended for emergencies, since it will cause you to drop all your items.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 120, NA, NA, NULL);
addot(OT_POT_POLYMORPH, "potion of polymorph self", "Transmutes the drinker into another living race.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 120, NA, NA, NULL);
addot(OT_POT_INVULN, "potion of invulnerability", "Grants the drinker temporary immunity to physical harm.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 200, NA, NA, NULL);
addot(OT_POT_AMBROSIA, "vial of ambrosia", "The nectar of the gods, said to completely restore the drinker's health.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL);
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 220, NA, NA, NULL);
// potions which come from cooking
@ -2304,7 +2345,7 @@ void initobjects(void) {
// death / necromancy
///////////////////
// l1
addot(OT_S_STENCH, "stench", "Nauseates the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_STENCH, "stench of death", "Nauseates the target with the smell of dying flesh.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
@ -3357,6 +3398,11 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
// l5
addot(OT_S_CLONE, "clone", "Creates an identical clone of the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addot(OT_S_SUMMONDEMON, "summon demon", "Summons a random demonic entity.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines its chances of success, and how long the demon will remain.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
@ -3374,13 +3420,13 @@ void initobjects(void) {
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l2
addot(OT_S_BLINK, "bamf", "Teleports the caster to a random location within view.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power VI you can choose where to blink to.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power VI you can choose where to teleport to.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SUCK, "suck", "Sucks the target lifeform towards the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_SUCK, "get over here!", "Sucks the target lifeform towards the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
@ -3537,8 +3583,8 @@ void initobjects(void) {
addot(OT_A_CLIMB, "climb", "Climb up or down whatever is in front of you (walls or pits).", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_STAMCOST, 1, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addot(OT_A_COOK, "cook", "Cook a corpse, or combine various foods into a healthy meal.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_DARKWALK, "darkwalk", "Step between the shadows.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
@ -3749,18 +3795,20 @@ void initobjects(void) {
// tools
addot(OT_BANDAGE, "bandage", "A small medical bandage. When worn, it will counteract bleeding.", MT_CLOTH, 0.5, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
addot(OT_BLANKET, "wool blanket", "A warm wool blanket for those cold winter nights.", MT_CLOTH, 2, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 10, NA, NA, NULL);
addot(OT_BLINDFOLD, "blindfold", "Short length of wide cloth, used for blocking eyesight.", MT_CLOTH, 0.01, OC_TOOLS, SZ_TINY);
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_BLIND, B_TRUE, NA, NULL);
addflag(lastot->flags, F_VALUE, 20, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addot(OT_CALTROP, "caltrop", "Connected metal spikes arranged such that one will always point upwards.", MT_METAL, 0.2, OC_TOOLS, SZ_TINY);
@ -3770,6 +3818,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_GREY, '^', NA, NULL);
addflag(lastot->flags, F_SHARP, 2, 5, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
addflag(lastot->flags, F_VALUE, 20, NA, NA, NULL);
addot(OT_BUGLAMP, "glowing flask", "A glass flask with a glowbug corpse inside.", MT_GLASS, 0.3, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_GLYPH, NA, '!', NA, NULL);
@ -3779,6 +3828,7 @@ void initobjects(void) {
addot(OT_CANDLE, "candle", "A short wax candle.", MT_WAX, 0.2, OC_TOOLS, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_VALUE, 20, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACTIVATEPREFIX, NA, NA, NA, "lit");
@ -3791,6 +3841,7 @@ void initobjects(void) {
addot(OT_FRIDGE, "refrigerator", "An insulated household appliance, made for storing food.", MT_METAL, 120, OC_TOOLS, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 1500, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_WHITE, ']', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -3811,6 +3862,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_EXPLODEONDAM, DT_FIRE, NA, NA, "8d2");
addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6");
@ -3819,6 +3871,7 @@ void initobjects(void) {
addot(OT_LAMPOIL, "oil lamp", "An oil-powered lamp which produces light.", MT_METAL, 1, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_VALUE, 80, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 5, NA, NULL);
@ -3831,6 +3884,7 @@ void initobjects(void) {
addot(OT_LANTERNOIL, "oil lantern", "An oil-powered lantern which produces a lot of light.", MT_METAL, 1, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 55, NA, NULL);
addflag(lastot->flags, F_VALUE, 100, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 6, NA, NULL);
@ -3844,25 +3898,30 @@ void initobjects(void) {
addot(OT_LOCKPICK, "lockpick", "An angled piece of metal, used to open locks.", MT_METAL, 0.05, OC_TOOLS, SZ_TINY);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 10, B_DIEONFAIL, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addot(OT_PANPIPES, "set of panpipes", "A set of musical pipes.", MT_METAL, 0.5, OC_TOOLS, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addot(OT_PICKAXE, "pickaxe", "A heavy tool for breaking rock.", MT_METAL, 8, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_HELPSDIG, 10, NA, NA, NULL);
addot(OT_ROPE, "rope", "A long length of strong rope.", MT_CLOTH, 5, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 75, NA, NULL);
addflag(lastot->flags, F_VALUE, 35, NA, NA, NULL);
addflag(lastot->flags, F_HELPSCLIMB, 3, NA, NA, NULL);
addot(OT_SACK, "sack", "A small cloth sack.", MT_CLOTH, 0.5, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '(', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -3874,6 +3933,8 @@ void initobjects(void) {
addflag(lastot->flags, F_STARTOBRND, 10, NA, NA, NULL);
addot(OT_SACKLARGE, "large sack", "A large cloth sack.", MT_CLOTH, 1, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '(', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -3886,6 +3947,8 @@ void initobjects(void) {
addflag(lastot->flags, F_STARTOBRND, 50, NA, NA, NULL);
addot(OT_SACKHUGE, "huge sack", "An enormous cloth sack.", MT_CLOTH, 1, OC_TOOLS, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 85, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '(', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -3904,6 +3967,7 @@ void initobjects(void) {
addot(OT_BAGOFHOLDING, "bag of holding", "A magical sack which causes items placed inside it to become weightless.", MT_CLOTH, 0.5, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '(', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERWITHOUTID, B_TRUE, NA, NA, NULL);
@ -3918,6 +3982,7 @@ void initobjects(void) {
addot(OT_BAGOFHOLDINGLARGE, "large bag of holding", "A large magical sack which causes items placed inside it to become weightless.", MT_CLOTH, 0.5, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 220, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '(', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERWITHOUTID, B_TRUE, NA, NA, NULL);
@ -3933,6 +3998,7 @@ void initobjects(void) {
addot(OT_BAGOFHOLDINGHUGE, "huge bag of holding", "An enormous magical sack which causes items placed inside it to become weightless.", MT_CLOTH, 0.5, OC_TOOLS, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_VERYRARE, NULL);
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '(', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERWITHOUTID, B_TRUE, NA, NA, NULL);
@ -3952,6 +4018,7 @@ void initobjects(void) {
addot(OT_SAFEBOX, "safebox", "A small metal container for safely storing valuables.", MT_METAL, 2, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 77, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_YELLOW, '(', NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -3966,6 +4033,7 @@ void initobjects(void) {
addot(OT_TORCH, "torch", "A metre-long wooden rod with a flammable end.", MT_WOOD, 2, OC_TOOLS, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 85, NA, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACTIVATEPREFIX, NA, NA, NA, "lit");
@ -3983,18 +4051,20 @@ void initobjects(void) {
addot(OT_TOWEL, "towel", "An large absorbent cloth used for drawing off moisture.", MT_CLOTH, 1.5, OC_TOOLS, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 73, NA, NULL);
addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
// tech - l0
addot(OT_CREDITCARD, "credit card", "A rectangular plastic card.", MT_PLASTIC, 0.01, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RNDCHARGES, 75, 500, NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_FALSE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 2, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addot(OT_PAPERCLIP, "paperclip", "A thin, looped wire for holding paper together.", MT_WIRE, 0.01, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_VALUE, 5, NA, NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
@ -4006,11 +4076,13 @@ void initobjects(void) {
addot(OT_SLEEPINGBAG, "sleeping bag", "An insulated bag for sleeping in. Very comfortable.", MT_CLOTH, 2, OC_TECH, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 15, NA, NA, NULL);
// tech - l1
addot(OT_BUTANETORCH, "butane torch", "A cooking tool which creates an intensely hot flame using butane gas.", MT_METAL, 0.5, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 85, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, TR_NEEDLOF, 1, "Where will you aim?");
@ -4019,17 +4091,20 @@ void initobjects(void) {
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_POCKETWATCH, "pocket watch", "A portable timekeeping device made to be carried in a pocket.", MT_METAL, 0.1, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_DIGITALWATCH, "digital watch", "An electronic timekeeping device which shows the time as a number.", MT_METAL, 0.1, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 85, NA, NULL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_INSECTICIDE, "can of insecticide", "A spraycan containing poisonous chemicals.", MT_METAL, 0.5, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_SWAMP, 85, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 85, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, "Where will you spray?");
@ -4039,6 +4114,7 @@ void initobjects(void) {
addot(OT_LANTERNLED, "LED lantern", "A low-powered but efficient lantern which will last almost forever.", MT_METAL, 0.5, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 3, NA, NULL);
@ -4049,11 +4125,13 @@ void initobjects(void) {
// tech - l2
addot(OT_TENT, "tent", "A easy to use, portable shelter made of fabric.", MT_CLOTH, 10, OC_TECH, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 15, 1, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addot(OT_FLASHBANG, "flashbang", "A stun grenade which temporarily blinds all within sight.", MT_METAL, 1, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 90, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 60, NA, NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
@ -4071,6 +4149,7 @@ void initobjects(void) {
addot(OT_GRENADE, "grenade", "An explosive weapon which explodes a short time after activation.", MT_METAL, 1, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 100, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -4087,6 +4166,7 @@ void initobjects(void) {
addot(OT_GRENADESMOKE, "smoke grenade", "A device which once activated, will explode into a cloud of smoke upon impact.", MT_METAL, 1, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 80, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 55, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -4104,6 +4184,7 @@ void initobjects(void) {
addot(OT_C4, "block of c4", "An extremely explosive plastic which explodes a medium time after activation.", MT_PLASTIC, 1, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 76, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
@ -4118,11 +4199,13 @@ void initobjects(void) {
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_MOTIONSCANNER, "motion scanner", "Small scanning device which detects nearby lifeforms.", MT_METAL, 1.5, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 200, NA, NA, NULL);
addflag(lastot->flags, F_HOLDCONFER, F_DETECTLIFE, 10, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_NVGOGGLES, "nightvis goggles", "Special goggles which allow the wear to see in the dark.", MT_METAL, 1.5, OC_TECH, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 200, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
@ -4132,6 +4215,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_SOLDERINGIRON, "soldering iron", "A hand tool with an electrically heated metal tip. This unit is operated by an in-built battery.", MT_METAL, 0.5, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, RR_UNCOMMON, NA, NULL);
addflag(lastot->flags, F_VALUE, 100, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastot->flags, F_DAM, DT_HEAT, 5, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
@ -4142,6 +4226,7 @@ void initobjects(void) {
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addot(OT_STYPTIC, "styptic", "A medical compound designed to inhibit bleeding.", MT_METAL, 0.5, OC_TECH, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 65, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
@ -4152,6 +4237,7 @@ void initobjects(void) {
addot(OT_INFOVISOR, "infovisor", "Sleek looking metal visor which displays info directly into the retina.", MT_METAL, 0.2, OC_TECH, SZ_SMALL);
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 125, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_EXTRAINFO, B_TRUE, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ENHANCESEARCH, 10, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_ADEPT, NA, NA, NULL);
@ -4159,18 +4245,21 @@ void initobjects(void) {
addot(OT_LOCKHACKER, "lock hacker", "A sophisticated machine to manipulate physical locks.", MT_METAL, 3, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 78, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_ADEPT, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_PORTLADDER, "portable ladder", "A lightweight two metre ladder which automatically folds down to pocket size.", MT_METAL, 2, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 83, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 150, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_ADEPT, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
// tech - l4
addot(OT_JETPACK, "jet pack", "A portable ion-thruster which allows the wearer to fly.", MT_METAL, 10, OC_TECH, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 68, RR_RARE, NULL);
addflag(lastot->flags, F_VALUE, 200, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RNDCHARGES, 10, 30, NA, NULL);
@ -4183,10 +4272,12 @@ void initobjects(void) {
// tech - l5
addot(OT_TELEPAD, "teleport beacon", "A metal cone which will teleport the user to the nearest similar cone.", MT_METAL, 3, OC_TECH, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 68, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_TECHLEVEL, PR_EXPERT, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
addot(OT_XRAYGOGGLES, "pair of xray goggles", "Bulky looking goggles which allow you to see through walls.", MT_METAL, 0.3, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_XRAYVIS, 2, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 60, RR_RARE, NULL);
@ -5337,9 +5428,17 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL);
// rings
addot(OT_RING_EDUCATION, "ring of education", "Boosts earned XP and Skill points.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_LEARNBOOST, 35, NA, NULL);
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
addot(OT_RING_ENDURANCE, "ring of endurance", "Boosts stamina regeneration.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_STAMREGEN, NA, NA, "0.5");
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
addot(OT_RING_GREED, "ring of greed", "Much sought after by treasure hunters, this ring detects the presence of any nearby objects.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_DETECTOBS, 10, NA, NULL);
addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL);
addot(OT_RING_SIGHT, "ring of sight", "Allows the caster to see the invisible, and in the dark.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
@ -5419,10 +5518,41 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_RESISTMAG, 5, NA, NULL);
addflag(lastot->flags, F_VALUE, 350, NA, NA, NULL);
addot(OT_RING_MEDITATION, "ring of meditation", "Allows the wearer to rest by entering a state of meditation.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_MEDITATES, B_TRUE, NA, NULL);
addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL);
addot(OT_RING_MIRACLES, "ring of miracles", "Grants a limited number of miracles to the wearer.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_CHARGES, 1, 3, NA, NULL);
addflag(lastot->flags, F_VALUE, 400, NA, NA, NULL);
addot(OT_RING_MPBOOST, "ring of arcane power", "Increases the power of the wearer's spells.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 1, NA, NULL);
addot(OT_RING_NOINJURY, "ring of injury prevention", "Completely protects the wearer from crippling body injuries.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_VALUE, 350, NA, NA, NULL);
addot(OT_RING_DECELERATION, "ring of deceleration", "Protects the wearer from projectile attacks.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_PROJECTILE, B_TRUE, NULL);
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
addot(OT_RING_DETECTLIFE, "ring of detect life", "Warns the wearer about any nearby lifeforms.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_DETECTLIFE, 5, NA, NULL);
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
addot(OT_RING_REFLECTION, "ring of reflection", "Bounces any projectiles which hit the wearer back to their source.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_REFLECTION, B_TRUE, NA, NULL);
addflag(lastot->flags, F_VALUE, 350, NA, NA, NULL);
addot(OT_RING_STENCH, "ring of stench", "Causes the wearer to emit a foul stench.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_STENCH, 2, 1, NULL);
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
addot(OT_RING_WATERBREATHING, "ring of water breathing", "Allows the wearer to breath normally while underwater.", MT_METAL, 0.1, OC_RING, SZ_MINI);
addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, "");
addflag(lastot->flags, F_EQUIPCONFER, F_BREATHWATER, B_TRUE, NA, NULL);
addflag(lastot->flags, F_VALUE, 300, NA, NA, NULL);
// unarmed weapons - note these damage/accuracys can be
// overridded with the lifeform flag F_HASATTACK
@ -8309,7 +8439,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
// plants
addrace(R_CACTUS, "cactus", 30, 'F', C_YELLOW, MT_PLANT, RC_PLANT, "A wide upright plant coated with sharp spines. Said to sprout delicious fruit.");
addrace(R_CACTUS, "cactus", 30, 'F', C_BOLDGREEN, MT_PLANT, RC_PLANT, "A wide upright plant coated with sharp spines. Said to sprout delicious fruit.");
addbodypart(lastrace, BP_BODY, "stalk");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HARMLESS, B_TRUE, NA, NA, NULL);
@ -8323,7 +8453,8 @@ void initrace(void) {
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4");
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addrace(R_DREAMFUNGUS, "dreamfungus", 0.5, 'F', C_MAGENTA, MT_PLANT, RC_PLANT, "A huge, spotty, purple mold which releases speed-inducing spores on the slightest contact.");
addrace(R_FUNGUSDREAM, "dreamfungus", 0.5, 'F', C_MAGENTA, MT_PLANT, RC_PLANT, "A huge, spotty, purple mold which releases speed-inducing spores on the slightest contact.");
addbodypart(lastrace, BP_BODY, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, NULL);
@ -8338,10 +8469,73 @@ void initrace(void) {
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4");
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addrace(R_FUNGUSRAGE, "ragefungus", 0.5, 'F', C_RED, MT_PLANT, RC_PLANT, "This deep red fungus protects itself by explelling rage-inducing pheremones, causing predators to attack each other instead of it.");
addbodypart(lastrace, BP_BODY, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HARMLESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "1-4 shiitake mushrooms");
addflag(lastrace->flags, F_DOESNTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOPRINTS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4");
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addrace(R_IVYRAPID, "rapid ivy", 1, 'F', C_CYAN, MT_PLANT, RC_PLANT, "A strain of ivy which reproduces with incredible speed. Farmers find it difficult to remove due to its sharp spines.");
addbodypart(lastrace, BP_BODY, "stalk");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 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_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DOESNTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOPRINTS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "passionfruit");
addflag(lastrace->flags, F_RETALIATE, 1, 1, DT_PIERCE, "sharp spines");
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_CLONE, 0, 100, "pw:1;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_CLONE, NA, NA, "grows");
addrace(R_NUTTER, "nutter", 0.5, 'F', C_BROWN, MT_PLANT, RC_PLANT, "Nutters are dense brown bushes covered by clumps of hard-shelled nuts. When threatened, they can propel these nuts towards their predators at very high speeds.");
addbodypart(lastrace, BP_BODY, NULL);
addbodypart(lastrace, BP_HANDS, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HARMLESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "5-10 peanuts");
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "5-10 peanuts");
addflag(lastrace->flags, F_WILLTHROW, OT_NUT, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_THROWING, PR_SKILLED, NA, NULL);
addflag(lastrace->flags, F_DOESNTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOPRINTS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4");
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addrace(R_SAWGRASS, "sawgrass", 1, 'F', C_GREY, MT_METAL, RC_PLANT, "Razor sharp metallic grass with serrated edges. This plant senses vibrations in the air around it and lashes out with its sharp fronds.");
addbodypart(lastrace, BP_BODY, "stalk");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
@ -8354,6 +8548,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
// end plants
// animals
@ -8427,7 +8622,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, 5, NA, NA, NULL);
addrace(R_BEAR, "black bear", 150, 'q', C_BLUE, MT_FLESH, RC_ANIMAL, "A medium sized omnivore bear.");
addrace(R_BEAR, "black bear", 150, 'Q', C_BLUE, MT_FLESH, RC_ANIMAL, "A medium sized omnivore bear.");
setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
@ -8453,7 +8648,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MINIONS, 25, 1, 2, "bear cub");
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addrace(R_BEARGRIZZLY, "grizzly bear", 200, 'q', C_YELLOW, MT_FLESH, RC_ANIMAL, "A large angry bear.");
addrace(R_BEARGRIZZLY, "grizzly bear", 200, 'Q', C_YELLOW, MT_FLESH, RC_ANIMAL, "A large angry bear.");
setbodytype(lastrace, BT_QUADRAPED);
lastrace->baseid = R_BEAR;
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -9809,6 +10004,29 @@ void initrace(void) {
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addrace(R_STINKBUG, "stinkbeetle", 1, 'x', C_MAGENTA, MT_FLESH, RC_INSECT, "A dog-sized beetle with tough scales. Emits a foul odour upon death.");
setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, 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, NA, NA, NA, "1d4+0");
addflag(lastrace->flags, F_ARMOURRATING, 10, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_ZAPPER, 1, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_STINGACID, NA, NA, "dam:1d1;");
addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling");
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CORPSEFLAG, F_STENCH, 1, 3, NULL);
// demons
addrace(R_DRETCH, "dretch", 30, '&', C_BROWN, MT_FLESH, RC_DEMON, "An ape-like creature with extended forearms ending in clawed hands. They stand about 4 feet tall and weigh 60 pounds.");
@ -10250,12 +10468,12 @@ void initskills(void) {
addskilldesc(SK_COOKING, PR_EXPERT, "^gYou can now cook recipes using up to 5 ingredients.", B_TRUE);
addskilldesc(SK_COOKING, PR_MASTER, "^gYou can now cook all recipes.", B_TRUE);
addskill(SK_EVASION, "Evasion", "Your ability to dodge blows or traps.", 50);
addskilldesc(SK_EVASION, PR_NOVICE, "^gIncreases your EV by 5%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_BEGINNER, "^gIncreases your EV by 10%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_ADEPT, "^gIncreases your EV by 15%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_SKILLED, "^gIncreases your EV by 20%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_EXPERT, "^gIncreases your EV by 25%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_MASTER, "^gIncreases your EV by 30%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_NOVICE, "^gIncreases your EV by 12%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_BEGINNER, "^gIncreases your EV by 24%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_ADEPT, "^gIncreases your EV by 36%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_SKILLED, "^gIncreases your EV by 48%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_EXPERT, "^gIncreases your EV by 60%.^n", B_FALSE);
addskilldesc(SK_EVASION, PR_MASTER, "^gIncreases your EV by 72%.^n", B_FALSE);
addskill(SK_FIRSTAID, "First Aid", "Increases your healing rate and reduces duration of poison.", 0); // untrainable
addskilldesc(SK_FIRSTAID, PR_INEPT, "- Lets you recognise how healthy your opponents are.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_INEPT, "- Determines how fast you heal when resting. ", B_FALSE);
@ -10561,6 +10779,32 @@ void initskills(void) {
}
}
void killcommand(command_t *cmd) {
command_t *nextone, *lastone;
// free mem
if (cmd->desc) free(cmd->desc);
// remove from list
nextone = cmd->next;
if (nextone != NULL) {
nextone->prev = cmd->prev;
} else { /* last */
lastcommand = cmd->prev;
}
if (cmd->prev == NULL) {
/* first */
nextone = cmd->next;
free(firstcommand);
firstcommand = nextone;
} else {
lastone = cmd->prev;
free (lastone->next );
lastone->next = nextone;
}
}
void make_basic_shop(flagpile_t *fp) {
addflag(fp, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something");
addflag(fp, F_SHOPMENU, 1, MA_QUIT, NA, "q:leave");

1
data.h
View File

@ -7,5 +7,6 @@ void initjobs(void);
void initobjects(void);
void initrace(void);
void initskills(void);
void killcommand(command_t *cmd);
void make_basic_shop(flagpile_t *fp);
void sortcommands(void);

Binary file not shown.

41
defs.h
View File

@ -1,6 +1,7 @@
#ifndef __DEFS_H
#define __DEFS_H
//#include "findleak.h"
// MACROS
#define MAXOF(a,b) (a > b ? a : b)
@ -20,7 +21,8 @@
// Defaults
#define DEF_AIFOLLOWTIME (50) // if target lf is out of view
// for this many turns, abandon chase
#define DEF_ANIMDELAY (1000000 / 50) // 1/100 of a second
//#define DEF_ANIMDELAY (1000000 / 50) // 1/100 of a second
#define DEF_ANIMDELAY (1000000 / 25) // 1/50 of a second
#define DEF_RESTHEALTIME (3)
#define DEF_SCREENW 80
@ -902,7 +904,10 @@ enum RACE {
R_EELGIANT,
// plants
R_CACTUS,
R_DREAMFUNGUS,
R_IVYRAPID,
R_FUNGUSDREAM,
R_FUNGUSRAGE,
R_NUTTER,
R_SAWGRASS,
// animals
R_ANT,
@ -955,6 +960,7 @@ enum RACE {
R_GLOWBUG,
R_GIANTFLY,
R_GIANTBLOWFLY,
R_STINKBUG,
R_STIRGE,
// demons
R_DRETCH,
@ -1058,7 +1064,7 @@ enum OBTYPE {
OT_STAIRSDOWN,
OT_STAIRSUP,
OT_PORTAL,
// buildings
// buildings - rememebr to update MAXBUILDINGTYPES!
OT_MOTEL,
OT_SHOPARMOUR,
OT_SHOPBOOK,
@ -1135,6 +1141,7 @@ enum OBTYPE {
OT_MUSHROOMTOAD,
OT_MUSHROOMSTUFFED,
OT_NUT,
OT_PASSIONFRUIT,
OT_ROASTMEAT,
OT_RUMBALL,
OT_SALT,
@ -1372,6 +1379,7 @@ enum OBTYPE {
OT_S_WARPWOOD,
OT_S_WATERJET,
// -- summoning
OT_S_CLONE,
OT_S_CREATEFOOD,
OT_S_FLOATINGDISC,
OT_S_FRIENDS,
@ -1649,23 +1657,33 @@ enum OBTYPE {
OT_SHIELDTOWER,
// rings
OT_RING_ENDURANCE,
OT_RING_GREED,
OT_RING_INVIS,
OT_RING_INVULN,
OT_RING_LUCK,
OT_RING_CONTROL,
OT_RING_CON,
OT_RING_DECELERATION,
OT_RING_DETECTLIFE,
OT_RING_DEX,
OT_RING_EDUCATION,
OT_RING_HUNGER,
OT_RING_IQ,
OT_RING_STR,
OT_RING_MANA,
OT_RING_MEDITATION,
OT_RING_MIRACLES,
OT_RING_MPBOOST,
OT_RING_MPREGEN,
OT_RING_NOINJURY,
OT_RING_PROTFIRE,
OT_RING_PROTCOLD,
OT_RING_REFLECTION,
OT_RING_REGENERATION,
OT_RING_RESISTMAG,
OT_RING_SIGHT,
OT_RING_STENCH,
OT_RING_WATERBREATHING,
OT_RING_WOUNDING,
// innate / animal weapons
OT_BEAK,
@ -1780,6 +1798,8 @@ enum OBTYPE {
};
#define MAXBUILDINGTYPES (10)
#define BP_NONE (-1)
enum BODYPART {
@ -2364,6 +2384,7 @@ enum FLAG {
F_SNEAK, // moving slowly on purpose to avoid slipping.
F_AUTOCMD, // val0 = how many times to repeat this
F_LASTCMD, // text[0] = last command performed, v0/1 = x/y of cell, v2=various
F_WILLTHROW, // this lf will treat obid v0 as a thrown missile.
F_CANLEARN, // lf is able to learn skill val0
// v1 = max lev
F_STARTOB, // val0 = %chance of starting with it, text = ob name
@ -2439,7 +2460,7 @@ enum FLAG {
// our targets out of the room.
F_FALLDISTANCE, // how many floors this lf has fallen through.
// ABILITY/SPELL FLAGS / ability flags / spell flags
F_FAILEDINSPECT, // lf has failed an inspect check for item id v0
F_FAILEDINSPECT, // lf has failed an inspect check for objecttype v0
F_TARGETTEDSPELL, // this spell needs you to specify a target cell
// v0 is the tt_targettype
F_BOOSTSPELL, // v0 is active boost spell, v1 is ongoing mpcost, v2 is power
@ -2485,6 +2506,7 @@ enum FLAG {
// when at zero, lf vanishes.
F_OWNSSHOP, // v0 is roomid of the shop which this shopkeeper owns.
F_GUARD, // this lf is a guard, who can be called by shopkeepers
F_HATESALL, // lf will attack ALL other lfs on sight
F_HATESRACE, // lf will attack lfs with race=v0 or baseid=v0 on
// sight
F_HATESRACEWITHFLAG, // lf will attack lfs with flag v0 on sight
@ -2717,6 +2739,7 @@ enum FLAG {
F_FROZEN, // made of ice
F_HOLYAURA, // holy aura - attacks deal holy damage to vulnerable
// enemies.
F_LEARNBOOST, // +v0% xp and skillxp
F_LEVITATING, // like flying but uncontrolled
F_MAGSHIELD,// magnetic shield
F_NAUSEATED, // lf has a stench penalty of v0 (-v0*10 to hit).
@ -3274,6 +3297,11 @@ typedef struct glyph_s {
int colour;
} glyph_t;
typedef struct buildingusage_s {
enum OBTYPE oid;
int count;
} buildingusage_t;
typedef struct hiddennamewithcol_s {
char *name;
enum COLOUR col;
@ -3378,6 +3406,7 @@ typedef struct lifeform_s {
int att[MAXATTS];
int baseatt[MAXATTS];
int origatt[MAXATTS];
float forgettimer;
@ -3400,7 +3429,7 @@ typedef struct lifeform_s {
int losdirty;
int nlos;
cell_t **los;
int *viscell;
//int *viscell;
int visw;
int visrange;
int eyeadjustment; // have your eyes adjusted to the dark?
@ -3566,6 +3595,8 @@ typedef struct object_s {
int blessknown;
int amt; // for stackable objects
long birthtime;
int dying; // not saved, just used to avoid flag messages for dying
// objects.
flagpile_t *flags;
struct obpile_s *contents;

7
doc/add_building.txt Normal file
View File

@ -0,0 +1,7 @@
defs.h
add OT_xxx
inc MAXBUILDINGTYPES
data.c
define it
shops.c
update details

4
doc/dungeon_layout.txt Normal file
View File

@ -0,0 +1,4 @@
1: first dungeon level
6: jimbo's lair
7-10: swamp
25: godstone

View File

@ -9,33 +9,33 @@ UNI_SOLID = deep water
A = avian / bird
a = ant
B = bat
c = cockatricoe
C = celestial / divine ?
d = canine/dog
e = eye
f = feline/cat
F = flora (flowers, plants, etc)
g = goblin
G = large goblin
h = humanoid
H = large humanoid
i = insect
j = jelly/ooze/leech
k = kobold
G = large goblin
m = mutant
n = small humanoid / nymph / sprite
o = orc
O = ogre
p = sPirit
c = cockatricoe
q = quadraped
Q = large quadraped
r = rodent
R = robot
s = snake
S = spider
h = humanoid
H = large humanoid
U = unearthly/horrific creature
w = worm
V = vampire
w = worm
x = small creature/monster
X = unknown thing!
y/Y = air related creatures like clouds of gas, air elemental

2
flag.c
View File

@ -901,7 +901,7 @@ void killflag(flag_t *f) {
setstamina(lf, 0);
}
} else if (f->pile->ob) {
} else if (f->pile->ob && !isdeadob(f->pile->ob)) {
announceobflagloss(f->pile->ob, f);
}
}

300
io.c
View File

@ -33,6 +33,9 @@ int statdirty = B_TRUE;
int inaskcoords = B_FALSE; // are we inside this function?
extern buildingusage_t buildingusage[];
extern int nbuildingusage;
int hascolour = B_TRUE;
int noredraw = B_FALSE;
@ -357,10 +360,11 @@ void animline(cell_t *src, cell_t *dst, int gradual, char ch, char ch2, int colo
needredraw = B_TRUE;
}
void animradial(cell_t *src, int radius, char ch, int colour) {
void animradial(cell_t *src, int radius, int ch,int colour, int dirtype, char *seetext, char *noseetext) {
glyph_t gl;
int i;
int x,y;
int nseen = 0;
cell_t *c;
gl.ch = ch;
@ -372,6 +376,29 @@ void animradial(cell_t *src, int radius, char ch, int colour) {
// hide cursor
curs_set(0);
if (dirtype == DT_ORTH) {
for (i = 0; i <= radius; i++) {
int drawn = B_FALSE;
for (y = src->y - radius ; y <= src->y + radius ; y++) {
for (x = src->x - radius ; x <= src->x + radius ; x++) {
c = getcellat(src->map, x, y);
if (c && haslos(player, c) && (getcelldistorth(src, c) <= i)) {
// draw char & cursor at its current pos...
//mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
drawglyph(&gl, c->x - viewx, c->y - viewy);
drawn = B_TRUE;
nseen++;
}
}
}
if (drawn) {
wrefresh(gamewin);
usleep(DEF_ANIMDELAY);
}
}
} else { // radial
for (i = 0; i <= radius; i++) {
int drawn = B_FALSE;
@ -383,60 +410,30 @@ void animradial(cell_t *src, int radius, char ch, int colour) {
//mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
drawglyph(&gl, c->x - viewx, c->y - viewy);
drawn = B_TRUE;
nseen++;
}
}
}
wrefresh(gamewin);
if (drawn) {
wrefresh(gamewin);
usleep(DEF_ANIMDELAY);
}
}
// show cursor
curs_set(1);
needredraw = B_TRUE;
}
void animradialorth(cell_t *src, int radius, char ch,int colour) {
glyph_t gl;
int i;
int x,y;
cell_t *c;
gl.ch = ch;
gl.colour = colour;
// update screen
updateviewfor(src);
drawlevelfor(player);
// hide cursor
curs_set(0);
for (i = 0; i <= radius; i++) {
int drawn = B_FALSE;
for (y = src->y - radius ; y <= src->y + radius ; y++) {
for (x = src->x - radius ; x <= src->x + radius ; x++) {
c = getcellat(src->map, x, y);
if (c && haslos(player, c) && (getcelldistorth(src, c) <= i)) {
// draw char & cursor at its current pos...
//mvwprintw(gamewin, c->y - viewy, c->x - viewx, "%c", ch);
drawglyph(&gl, c->x - viewx, c->y - viewy);
drawn = B_TRUE;
}
}
}
wrefresh(gamewin);
if (drawn) {
usleep(DEF_ANIMDELAY);
if (nseen) {
if (seetext && haslos(player, src)) {
msg(seetext);
more();
} else if (noseetext) {
msg(noseetext);
more();
}
}
// show cursor
curs_set(1);
needredraw = B_TRUE;
drawscreen();
}
@ -1585,6 +1582,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
msg("%s %s surrounded by a holy aura!", lfname, isplayer(lf) ? "are" : "is");
donesomething = B_TRUE;
break;
case F_LEARNBOOST:
if (isplayer(lf)) {
msg("You feel more receptive to new knowledge!");
donesomething = B_TRUE;
}
break;
case F_LEVITATING:
msg("%s begin%s to levitate in the air!",lfname, isplayer(lf) ? "" : "s");
donesomething = B_TRUE;
@ -2168,6 +2171,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("%s%s holy aura vanishes.", lfname, getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_LEARNBOOST:
if (isplayer(lf)) {
msg("You no longer feel receptive to new knowledge.");
donesomething = B_TRUE;
}
break;
case F_LEVITATING:
msg("%s %s down to the ground.", lfname, isplayer(lf) ? "float" : "floats");
donesomething = B_TRUE;
@ -2515,7 +2524,6 @@ lifeform_t *askgod(char *prompttext, int onlyprayed) {
snprintf(godof, BUFLEN, " (%s of %s)", (f->val[0] == B_FEMALE) ? "goddess" : "god", f->text);
strcat(buf, godof);
makedesc_god(lf, longdesc);
addchoice(&prompt, tolower(buf[0]), buf, NULL, lf, longdesc);
}
@ -2546,13 +2554,6 @@ object_t *askobjectwithflag(obpile_t *op, char *prompt, int *count, char action,
return doaskobject(op, prompt, count, B_TRUE, B_TRUE, B_FALSE, action, opts, withflag, F_NONE);
}
/*
object_t *askobjectofclass(obpile_t *op, char *prompt, int *count, long opts, enum OBCLASS obclass) {
return doaskobject(op, prompt, count, opts, F_NONE, obclass, OC_NULL);
}
*/
int contains(enum OBCLASS *array, int nargs, enum OBCLASS want) {
int i;
for (i = 0; i < nargs; i++) {
@ -3711,7 +3712,6 @@ void docomms(lifeform_t *lf) {
c = askcoords(buf, buf2, TT_MONSTER, lf, UNLIMITED, LOF_DONTNEED, B_FALSE);
if (c && c->lf) {
lf2 = c->lf;
}
if (!lf2) {
msg("Cancelled.");
@ -3720,7 +3720,7 @@ void docomms(lifeform_t *lf) {
getlfname(lf2, lfname2);
msg("You say \"Attack %s!\" to %s.",isplayer(lf2) ? "me" : lfname2, lfname);
if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) {
if (lfhasflag(lf, F_RAGE) || !canhear(lf, player->cell, SV_SHOUT)) {
msg("%s doesn't respond.", lfname);
break;
}
@ -3746,7 +3746,7 @@ void docomms(lifeform_t *lf) {
break;
case 'c':
msg("You say \"Come here!\" to %s.",lfname);
if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) {
if (lfhasflag(lf, F_RAGE) || !canhear(lf, player->cell, SV_SHOUT)) {
msg("%s doesn't respond.", lfname);
break;
}
@ -3902,7 +3902,7 @@ void docomms(lifeform_t *lf) {
// stop attacking all current targets first...
killflagsofid(lf->flags, F_TARGETLF);
msg("You say \"Go over there!\" to %s.", lfname);
if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) {
if (lfhasflag(lf, F_RAGE) || !canhear(lf, player->cell, SV_SHOUT)) {
msg("%s doesn't respond.", lfname);
break;
}
@ -3911,7 +3911,7 @@ void docomms(lifeform_t *lf) {
case 'j':
// charisma check to see if they'll join you.
msg("You say \"Join me on my quest!\" to %s.", lfname);
if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) {
if (lfhasflag(lf, F_RAGE) || !canhear(lf, player->cell, SV_SHOUT)) {
msg("%s doesn't respond.", lfname);
break;
}
@ -3957,7 +3957,7 @@ void docomms(lifeform_t *lf) {
break;
case 'r':
msg("You say \"Get some rest.\" to %s.", lfname);
if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) {
if (lfhasflag(lf, F_RAGE) || !canhear(lf, player->cell, SV_SHOUT)) {
msg("%s doesn't respond.", lfname);
break;
}
@ -4011,7 +4011,7 @@ void docomms(lifeform_t *lf) {
break;
case '<':
msg("You say \"Stay close!\" to %s.", lfname);
if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) {
if (lfhasflag(lf, F_RAGE) || !canhear(lf, player->cell, SV_SHOUT)) {
msg("%s doesn't respond.", lfname);
break;
}
@ -4019,7 +4019,7 @@ void docomms(lifeform_t *lf) {
break;
case '>':
msg("You say \"Keep your distance!\" to %s.", lfname);
if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) {
if (lfhasflag(lf, F_RAGE) || !canhear(lf, player->cell, SV_SHOUT)) {
msg("%s doesn't respond.", lfname);
break;
}
@ -4374,9 +4374,50 @@ void dolook(cell_t *where, int onpurpose) {
}
msg("You %s %s here.", seeverb, buf);
}
} else if ((numobs > 1) && (numobs <= 3)) {
} else if (numobs == 2) {
char buf2[BUFLEN];
object_t *secondob;
secondob = firstob->next;
if (hasflag(firstob->flags, F_THEREISHERE)) {
strcpy(buf, ""); // don't show it
} else {
if (streq(seeverb, "feel")) {
f = hasflag(firstob->flags, F_FEELTEXT);
if (f) {
strcpy(buf, f->text);
} else {
getobname(firstob, buf, firstob->amt);
}
} else {
getobname(firstob, buf, firstob->amt);
}
}
if (hasflag(secondob->flags, F_THEREISHERE)) {
strcpy(buf2, ""); // don't show it
} else {
if (streq(seeverb, "feel")) {
f = hasflag(secondob->flags, F_FEELTEXT);
if (f) {
strcpy(buf2, f->text);
} else {
getobname(secondob, buf2, secondob->amt);
}
} else {
getobname(secondob, buf2, secondob->amt);
}
}
if (!strlen(buf) && !strlen(buf2)) {
// both obs shown later!
} else if (!strlen(buf)) {
msg("You %s %s here.", seeverb, buf2);
} else if (!strlen(buf2)) {
msg("You %s %s here.", seeverb, buf);
} else {
msg("You %s %s and %s here.", seeverb, buf, buf2);
}
} else if ((numobs >= 3) && (numobs <= 4)) {
msg("You %s a few things here.", seeverb);
} else if ((numobs > 3) && (numobs <= 6)) {
} else if ((numobs >= 5) && (numobs <= 6)) {
msg("You %s some things here.", seeverb);
} else if (numobs > 6) {
msg("You %s many things here.", seeverb);
@ -5071,6 +5112,17 @@ char *makedesc_ob(object_t *o, char *retbuf) {
}
strncat(retbuf, buf, HUGEBUFLEN);
}
} else if (o->type->id == OT_CREDITCARD) {
if (isidentified(o)) {
int charges;
charges = getcharges(o);
if (charges) {
sprintf(buf, "It has $%d remaining until its limit.\n",charges);
} else {
sprintf(buf, "It is maxed out.\n");
}
strncat(retbuf, buf, HUGEBUFLEN);
}
}
f = hasflag(o->flags, F_PICKLOCKS);
@ -5349,11 +5401,11 @@ char *makedesc_ob(object_t *o, char *retbuf) {
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_DETECTLIFE:
sprintf(buf2, "%s will detect nearby lifeforms.\n", buf);
sprintf(buf2, "%s lets you detect nearby lifeforms.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_DETECTOBS:
sprintf(buf2, "%s will detect nearby objects.\n", buf);
sprintf(buf2, "%s lets you detect nearby objects.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_DETECTMAGIC:
@ -5486,12 +5538,20 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf2, "%s surrounds you with a holy aura.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_LEARNBOOST:
sprintf(buf2, "%s grants a bonus to earned experience points.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_LEVITATING:
sprintf(buf2, "%s causes you to levitate.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_MAGICBOOST:
sprintf(buf2, "%s boosts the power of your spells by %d.\n", buf, f->val[0]);
sprintf(buf2, "%s boosts the power of your spells by %d.\n", buf, f->val[1]);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_MEDITATES:
sprintf(buf2, "%s allows you to retain awareness while resting.", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_MAGSHIELD:
@ -5530,10 +5590,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf2, "%s produces light.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_REFLECTION:
sprintf(buf2, "%s reflects all missiles back to their source.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_RETALIATE:
sprintf(buf2, "%s protects you with %s.\n", buf, f->text);
strncat(retbuf, buf2, HUGEBUFLEN);
@ -5542,6 +5598,10 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf2, "%s makes you enraged.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_REFLECTION:
sprintf(buf2, "%s reflects all projectiles back to their source.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_REGENERATES:
if (f->val[1] == 1) {
strcpy(buf3, "");
@ -5875,7 +5935,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
strcpy(buf, "");
for (n = 0; n < MAXDAMTYPE; n++) {
if (basedamagetype(n) != n) continue;
if (isimmuneto(r->flags, n, B_FALSE)) {
if (isresistantto(r->flags, n, B_FALSE)) {
if (first) {
sprintf(buf2, "Resistant to: %s", getdamname(n));
first = B_FALSE;
@ -5889,30 +5949,6 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
addflag(doneflags, F_DTRESIST, B_TRUE, NA, NA, NULL);
}
break;
case F_DTVULN:
if (!hasflag(doneflags, F_DTVULN)) {
if (f->val[0] == DT_ALL) {
sprintf(buf, "Vulnerable to %s.", getdamname(DT_ALL));
} else {
char buf2[BUFLEN];
int first = B_TRUE,n;
strcpy(buf, "");
for (n = 0; n < MAXDAMTYPE; n++) {
if (basedamagetype(n) != n) continue;
if (isimmuneto(r->flags, n, B_FALSE)) {
if (first) {
sprintf(buf2, "Vulnerable to: %s", getdamname(n));
first = B_FALSE;
} else {
sprintf(buf2, ", %s", getdamname(n));
}
strcat(buf, buf2);
}
}
}
addflag(doneflags, F_DTVULN, B_TRUE, NA, NA, NULL);
}
break;
case F_ENHANCESMELL: sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break;
case F_FLYING: sprintf(buf, "Can fly at will"); break;
case F_HEAVYBLOW: sprintf(buf, "Attacks will knock enemies backwards"); break;
@ -5983,12 +6019,36 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
case F_CARNIVORE: sprintf(buf, "Will only eat meat."); break;
case F_DEAF: sprintf(buf, "Deaf"); break;
case F_DIURNAL: sprintf(buf, "Sleeps at night."); break;
case F_DTVULN:
if (!hasflag(doneflags, F_DTVULN)) {
if (f->val[0] == DT_ALL) {
sprintf(buf, "Vulnerable to %s.", getdamname(DT_ALL));
} else {
char buf2[BUFLEN];
int first = B_TRUE,n;
strcpy(buf, "");
for (n = 0; n < MAXDAMTYPE; n++) {
if (basedamagetype(n) != n) continue;
if (isvulnto(r->flags, n, B_FALSE)) {
if (first) {
sprintf(buf2, "Vulnerable to: %s", getdamname(n));
first = B_FALSE;
} else {
sprintf(buf2, ", %s", getdamname(n));
}
strcat(buf, buf2);
}
}
}
addflag(doneflags, F_DTVULN, B_TRUE, NA, NA, NULL);
}
break;
case F_FASTMETAB: sprintf(buf, "Fast metabolism (needs to eat often)"); break;
case F_MATVULN:
mt = findmaterial(f->val[0]);
sprintf(buf, "Takes %d%% damage from weapons made of %s.", retflag[i]->val[1], mt->name);
break;
case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "-%d Mana", f->val[0]); break;
case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break;
case F_NEEDSWATER: sprintf(buf, "Will suffocate without water"); break;
case F_NOCTURNAL: sprintf(buf, "Sleeps during the day."); break;
case F_NOPACK: sprintf(buf, "Cannot carry objects."); break;
@ -6668,12 +6728,12 @@ void doexplain(char *question) {
void dofinaloblist(obpile_t *op) {
object_t *o;
o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, AO_NONE, F_NONE);
o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, '\0', AO_NONE, F_NONE);
while (o) {
// describe it
describeob(o);
// ask for another one
o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, AO_NONE, F_NONE);
o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE,'\0', AO_NONE, F_NONE);
}
real_clearmsg(B_TRUE);
}
@ -6808,7 +6868,7 @@ void doinventory(obpile_t *op) {
maxweight = getmaxcarryweight(player);
pct = (packweight / maxweight) * 100;
snprintf(buf, BUFLEN, "Inventory (%0.0f/%0.0f kg, %0.0f%%)", packweight, maxweight, pct);
o = doaskobject(op, buf, NULL, B_TRUE, B_TRUE, B_FALSE, AO_NONE, F_NONE);
o = doaskobject(op, buf, NULL, B_TRUE, B_TRUE, B_FALSE, '\0', AO_NONE, F_NONE);
while (o) {
// describe it
describeob(o);
@ -7139,41 +7199,6 @@ void dothrow(obpile_t *op) {
}
}
/*
void drawscannedcell(cell_t *cell, int x, int y) {
if (cell->lf) {
char glyph;
// draw glyph based on size
switch(getlfsize(cell->lf)) {
case SZ_ENORMOUS:
glyph = '6';
break;
case SZ_HUGE:
glyph = '5';
break;
case SZ_LARGE:
glyph = '4';
break;
case SZ_HUMAN:
glyph = '3';
break;
case SZ_MEDIUM:
glyph = '2';
break;
case SZ_SMALL:
glyph = '1';
break;
case SZ_MINI:
case SZ_TINY:
default:
glyph = '0';
break;
}
mvwprintw(gamewin, y, x, "%c", glyph);
}
}
*/
// returns TRUE if escape pressed
int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar) {
char headbuf[BUFLEN];
@ -7641,6 +7666,17 @@ int drop(object_t *o, int count) {
return B_FALSE;
}
void dumpbuildingusage(void) {
int i;
objecttype_t *ot;
dblog("BEGIN BUILDING USAGE DUMP");
for (i = 0; i < nbuildingusage; i++) {
ot = findot(buildingusage[i].oid);
dblog("'%s' used %d times", ot->name, buildingusage[i].count);
}
dblog("END BUILDING USAGE DUMP");
}
void dumpoc(void) {
enum RARITY rr;
objectclass_t *oc;
@ -8001,7 +8037,7 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
}
} else {
int yy;
char gamewinbuf[BUFLEN];
int gamewinbuf[BUFLEN];
// copy text from gamewin
for (yy = y ; yy < lastline; yy++) {
mvwinchstr(gamewin, yy-2, 0, (chtype *)gamewinbuf);
@ -8043,7 +8079,7 @@ char getchoicestr(prompt_t *prompt, int useshortcuts, int showallatstart) {
*/
// show the remainder of what we have typed.
// ('validchoice' was calculated earlier)
snprintf(remainder, BUFLEN, "^g%s",prompt->choice[validchoice].text + strlen(inpstring));
snprintf(remainder, BUFLEN, "^g%s^n",prompt->choice[validchoice].text + strlen(inpstring));
textwithcol(mainwin, remainder);
// move cursor back
wmove(mainwin, cy, cx);

5
io.h
View File

@ -7,8 +7,8 @@ void addpromptq(prompt_t *p, char *q);
void anim(cell_t *src, cell_t *dst, char ch, int colour);
void animline(cell_t *src, cell_t *dst, int gradual, char ch, char ch2, int colour);
void animcells(cell_t *src, cell_t **dst, int ndst, int gradual, char ch, char ch2, int colour);
void animradial(cell_t *src, int radius, char ch, int colour);
void animradialorth(cell_t *src, int radius, char ch, int colour);
//void animradial(cell_t *src, int radius, int ch, int colour);
void animradial(cell_t *src, int radius, int ch, int colour, int dirtype, char *text, char *noseetext);
void animsky(cell_t *src, char ch, int colour);
//void announceob(enum OBTYPE oid);
void announcearrival(lifeform_t *lf, map_t *newmap);
@ -83,6 +83,7 @@ void drawmsg(void);
void drawscreen(void);
void drawstatus(void);
int drop(object_t *o, int count);
void dumpbuildingusage(void);
void dumpoc(void);
void dumpspells(void);
void dumpweps(void);

165
lf.c
View File

@ -2210,6 +2210,7 @@ void die(lifeform_t *lf) {
object_t *corpse = NULL;
flag_t *retflag[MAXCANDIDATES];
int nretflags;
cell_t *corpsecell;
if (cansee(player, lf)) {
needredraw = B_TRUE;
@ -2238,11 +2239,10 @@ void die(lifeform_t *lf) {
return;
}
if (!willbecomeghost) {
if (isplayer(lf) && hasjob(lf, J_GOD)) {
char ch;
msg("^BYou die..."); more();
msg("^BYou are about to die..."); more();
ch = askchar("Die", "yn", "n", B_TRUE, B_FALSE);
if (ch == 'n') {
lf->hp = lf->maxhp;
@ -2394,13 +2394,24 @@ void die(lifeform_t *lf) {
}
}
// determine where to drop objects
corpsecell = lf->cell;
if (corpsecell && corpsecell->type->solid) {
// try the cell in front (in case they were climbing)
corpsecell = getcellindir(corpsecell, lf->facing);
// still solid? give up.
if (corpsecell && corpsecell->type->solid) {
corpsecell = NULL;
}
}
// drop/kill all objects
if (willbecomeghost || !isplayer(lf)) {
if (corpsecell && (willbecomeghost || !isplayer(lf))) {
while (lf->pack->first) {
if (vaporised) {
killob(lf->pack->first);
} else {
if (!moveob(lf->pack->first, lf->cell->obpile, ALL)) {
if (!moveob(lf->pack->first, corpsecell->obpile, ALL)) {
killob(lf->pack->first);
}
}
@ -2408,18 +2419,19 @@ void die(lifeform_t *lf) {
}
// drop corpse/splatter blood
if (corpsecell) {
if (vaporised) {
switch (rnd(1,2)) {
case 1:
fragments(lf->cell, "chunk of flesh", 2, UNLIMITED);
fragments(corpsecell, "chunk of flesh", 2, UNLIMITED);
break;
case 2:
fragments(lf->cell, "pool of blood", 2, UNLIMITED);
fragments(corpsecell, "pool of blood", 2, UNLIMITED);
break;
}
} else if ((lf->lastdamtype == DT_BASH) && lfhasflag(lf, F_FROZEN)) {
// shattered
fragments(lf->cell, "chunk of ice", 2, UNLIMITED);
fragments(corpsecell, "chunk of ice", 2, UNLIMITED);
} else {
if (lfhasflag(lf, F_NOCORPSE)) {
if (isundead(lf) && cansee(player, lf)) {
@ -2428,7 +2440,7 @@ void die(lifeform_t *lf) {
}
} else if (lf->lastdamtype == DT_MELT) {
// drop a pool of water
addob(lf->cell->obpile, "large puddle of water");
addob(corpsecell->obpile, "large puddle of water");
} else if (lf->lastdamtype == DT_NECROTIC) {
int n;
int numbones = 0;
@ -2438,7 +2450,7 @@ void die(lifeform_t *lf) {
}
// drop bones
snprintf(bonestring, BUFLEN, "%d bones",numbones);
addob(lf->cell->obpile, bonestring);
addob(corpsecell->obpile, bonestring);
} else {
char corpseprefix[BUFLEN];
char corpsename[BUFLEN];
@ -2465,7 +2477,7 @@ void die(lifeform_t *lf) {
snprintf(corpsename, BUFLEN, "%s%s corpse", corpseprefix, lf->race->name);
}
corpse = addob(lf->cell->obpile, corpsename);
corpse = addob(corpsecell->obpile, corpsename);
if (corpse) {
if ((lf->lastdamtype == DT_FIRE) && isflammable(corpse)) {
addflag(corpse->flags, F_ONFIRE, B_TRUE, NA, NA, NULL);
@ -2508,7 +2520,7 @@ void die(lifeform_t *lf) {
char headname[BUFLEN];
// drop head too
snprintf(headname, BUFLEN, "%s head",lf->race->name);
headob = addob(lf->cell->obpile, headname);
headob = addob(corpsecell->obpile, headname);
colourmatchob(headob, lf);
}
@ -2520,9 +2532,10 @@ void die(lifeform_t *lf) {
flag_t *f;
f = lfhasflag(lf, F_DIESPLATTER);
if (f) {
fragments(lf->cell, f->text, 1, f->val[0]);
fragments(corpsecell, f->text, 1, f->val[0]);
}
}
} // end if corpsecell
if (willbecomeghost) {
@ -4435,9 +4448,14 @@ void gainmp(lifeform_t *lf, int amt) {
void gainxp(lifeform_t *lf, long amt) {
int newskillpoints = 0;
int doxp = B_TRUE;
int boostamt = 0;
assert(amt >= 0);
// adjust for xp boosts...
sumflags(lf->flags, F_LEARNBOOST, &boostamt, NULL, NULL);
amt = pctof(100+boostamt, amt);
if (lfhasflag(lf, F_HASNEWLEVEL) || (lf->level == 0)) {
doxp = B_FALSE;
}
@ -5289,15 +5307,17 @@ int getevasion(lifeform_t *lf) {
}
}
// level based evasion (modified by evasion skill)
// level based evasion
level_ev = gethitdice(lf);
skillpctmod = (getskill(lf, SK_EVASION) + 1) * 40;
level_ev = pctof(skillpctmod, level_ev);
ev += level_ev;
// dexterity mod
ev += getattr(lf, A_AGI);
// apply skill based evasion modifier
skillpctmod = 100 + (getskill(lf, SK_EVASION)) * 12;
ev = pctof(skillpctmod, ev);
// you are easier to hit if you're glowing
if (hasflag(lf->flags, F_PRODUCESLIGHT)) {
ev -= 5;
@ -5326,9 +5346,14 @@ object_t *getbestthrowmissile(lifeform_t *lf, lifeform_t *target) {
object_t *o;
for (o = lf->pack->first ; o ; o = o->next) {
int ismissileob = B_FALSE;
if (!isequipped(o) && isthrowmissile(o) ) {
ismissileob = B_TRUE;
} else if (lfhasflagval(lf, F_WILLTHROW, o->type->id, NA, NA, NULL)) {
ismissileob = B_TRUE;
}
if (ismissileob) {
int valid = B_TRUE;
// powder is only a valid missile if we're adjacent to our target
if (target && hasflag(o->flags, F_POWDER)) {
if (getcelldist(lf->cell,target->cell) > 1) valid = B_FALSE;
@ -7021,7 +7046,7 @@ char *getplayernamefull(char *buf) {
if (strlen(pname)) {
j = getjob(player);
if (j) {
snprintf(buf, BUFLEN, "%s the %s", pname, j->name);
snprintf(buf, BUFLEN, "%s the %s %s", pname, player->race->name, j->name);
} else {
snprintf(buf, BUFLEN, "%s the %s", pname, player->race->name);
}
@ -8555,7 +8580,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
// note: we use getplayername here even if this isn't a player,
// since in that case the prompt will never be displayed.
getplayernamefull(buf2);
getplayername(buf2);
snprintf(buf, BUFLEN, "%s, select your starting weapon:", buf2);
initprompt(&prompt, buf);
@ -8907,9 +8932,31 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
char *desc = NULL;
enum INJURY inj = IJ_NONE;
enum BODYPART bp2;
object_t *wep = NULL;
object_t *wep = NULL,*o;
int howlong;
getlfname(lf, lfname);
o = hasequippedobid(lf->pack, OT_RING_NOINJURY);
if (o) {
char obname[BUFLEN];
int seen = B_FALSE;
getobname(o, obname, 1);
if (isplayer(lf)) {
msg("Your %s throbs.", noprefix(obname));
seen = B_TRUE;
} else if (cansee(player, lf)) {
msg("%s%s %s throbs.", lfname, getpossessive(lfname), obname);
seen = B_TRUE;
}
if (seen && !isknown(o)) {
makeknown(o->type->id);
if (isplayer(lf)) {
msg("Amazingly, your %s is unharmed!", getbodypartname(lf, where));
}
}
return B_TRUE;
}
if (where == BP_NONE) return B_TRUE;
@ -9016,7 +9063,6 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
if (isplayer(lf)) {
msg("^BYour heart is pierced!");
} else if (cansee(player, lf)) {
getlfname(lf, lfname);
msg("^%c%s%s heart is pierced!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname));
}
if (lf->hp > 0) lf->hp = 0;
@ -9051,9 +9097,7 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
getobname(o,obname,o->amt);
msg("Your %s drops to the ground.",noprefix(obname));
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getobname(o,obname,o->amt);
getlfname(lf,lfname);
msg("%s%s %s drops to the ground.",lfname,getpossessive(lfname),noprefix(obname));
}
moveob(o, lf->cell->obpile, o->amt);
@ -9068,7 +9112,6 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
if (isplayer(lf)) {
msg("^BYour brain is ruptured!");
} else if (cansee(player, lf)) {
getlfname(lf, lfname);
msg("^%c%s%s brain ruptures!", getlfcol(lf, CC_VBAD), lfname, getpossessive(lfname));
}
if (lf->hp > 0) lf->hp = 0;
@ -9150,7 +9193,6 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype) {
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getobname(o[i],obname,o[i]->amt);
getlfname(lf,lfname);
msg("%s%s %s drops to the ground.",lfname,getpossessive(lfname),noprefix(obname));
}
moveob(o[i], lf->cell->obpile, o[i]->amt);
@ -9668,6 +9710,7 @@ int xytoidx(lifeform_t *lf, int x, int y) {
return idx;
}
/*
void setviscell(lifeform_t *lf, cell_t *cell, int how) {
int idx;
int x,y;
@ -9677,7 +9720,6 @@ void setviscell(lifeform_t *lf, cell_t *cell, int how) {
assert(idx < (lf->visw * lf->visw));
lf->viscell[idx] = how;
// checks
if (how == B_VIS) {
assert (abs(lf->cell->x - cell->x) <= 10);
@ -9700,6 +9742,7 @@ int getviscell(lifeform_t *lf, cell_t *cell) {
return lf->viscell[idx];
}
*/
int haslos(lifeform_t *viewer, cell_t *dest) {
int numpixels;
@ -10490,10 +10533,8 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
a->facing = rnd(DC_N, DC_NW);
a->losdirty = B_TRUE;
a->nlos = 0;
//a->los = malloc(sizeof(cell_t *) * MAXVISRANGE);
a->los = malloc( sizeof(cell_t *) * ((MAXVISRANGE*2+1)*(MAXVISRANGE*2+1)));
//a->viscell = NULL;
a->viscell = malloc( sizeof(int) * ((MAXVISRANGE*2+1)*(MAXVISRANGE*2+1)));
//a->los = malloc( sizeof(cell_t *) * ((MAXVISRANGE*2+1)*(MAXVISRANGE*2+1)));
a->los = NULL; // will be alloced in precalclos
a->eyeadjustment = 0;
@ -10528,6 +10569,12 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
a->race = NULL;
setrace(a, rid, B_FALSE);
// remember original attribs so that if we are polymorphed, we're
// able to revert back.
for (i = 0; i < MAXATTS; i++) {
a->origatt[i] = a->baseatt[i];
}
// set stamina AFTER setrace as it depends on your attribs
a->stamina = getmaxstamina(a);
@ -11393,34 +11440,33 @@ void killjob(job_t *job) {
}
void killrace(race_t *race) {
void killrace(race_t *r) {
race_t *nextone, *lastone;
// free mem
free(race->name);
killflagpile(race->flags);
free(r->name);
killflagpile(r->flags);
// remove from list
nextone = race->next;
nextone = r->next;
if (nextone != NULL) {
nextone->prev = race->prev;
nextone->prev = r->prev;
} else { /* last */
lastrace = race->prev;
lastrace = r->prev;
}
if (race->prev == NULL) {
if (r->prev == NULL) {
/* first */
nextone = race->next;
free(race);
race = nextone;
nextone = r->next;
free(firstrace);
firstrace = nextone;
} else {
lastone = race->prev;
lastone = r->prev;
free (lastone->next );
lastone->next = nextone;
}
}
flag_t *levelabilityready(lifeform_t *lf) {
flag_t *f;
int i;
@ -11861,14 +11907,17 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
}
}
// special case
if (lf->race->id == R_DREAMFUNGUS) {
if (cansee(player, lf)) {
animradialorth(lf->cell, 4, '}', C_MAGENTA);
msg("^w%s releases a cloud of purple spores!", lfname);
drawscreen();
}
spellcloud(lf->cell, 3, '\0', C_MAGENTA, OT_S_SLEEP, 8, B_TRUE);
// special cases
if (lf->race->id == R_FUNGUSDREAM) {
char buf2[BUFLEN];
sprintf(buf, "^w%s releases a cloud of purple spores!", lfname);
sprintf(buf2, "^wSomething releases a cloud of purple spores!");
spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, 8, B_TRUE, buf, buf2);
} else if (lf->race->id == R_FUNGUSRAGE) {
char buf2[BUFLEN];
sprintf(buf, "^w%s releases a cloud of red spores!", lfname);
sprintf(buf2, "^wSomething releases a cloud of red spores!");
spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_RED, OT_A_RAGE, 8, B_TRUE, buf, buf2);
}
// further effects if not dead...
@ -13025,13 +13074,14 @@ void precalclos_new(lifeform_t *lf) {
// right eye missing?
missingeye = lfhasflagval(lf, F_INJURY, IJ_EYEDESTROYED, NA, NA, NULL);
los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
blocker = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
nlos = 0;
if (lf->los) {
free(lf->los); lf->los = NULL;
}
los = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
blocker = malloc( sizeof(cell_t *) * (MAX_MAPW * MAX_MAPH));
nlos = 0;
maxvisrange = getvisrange(lf, B_FALSE);
nightvisrange = getnightvisrange(lf);
plev = getskill(lf, SK_PERCEPTION);
@ -13464,12 +13514,12 @@ int startresting(lifeform_t *lf, int willtrain) {
// player can't rest while in the air, unless you're in a motel room
if (isplayer(lf)) {
if (isairborne(lf) && !lfhasflag(lf, F_RESTINGINMOTEL)) {
msg("You can't rest while airborne!");
msg("You can't %s while airborne!", willtrain ? "train" : "rest");
return B_TRUE;
}
}
if (lfhasflag(lf, F_RAGE)) {
if (isplayer(lf)) msg("You are too enraged to rest!");
if (isplayer(lf)) msg("You are too enraged to %s!", willtrain ? "train" : "rest");
return B_TRUE;
}
@ -14122,6 +14172,13 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
}
killflagsofid(lf->flags, F_ORIGRACE);
killflagsofid(lf->flags, F_POLYMORPHED);
// restore stats
for (i = 0; i < MAXATTS; i++) {
lf->att[i] = lf->origatt[i];
lf->baseatt[i] = lf->origatt[i];
if (isplayer(lf)) statdirty = B_TRUE;
}
} else {
if (isplayer(lf)) {
msg("^wYou transform into %s %s!", isvowel(newrace->name[0]) ? "an" : "a", newrace->name);

4
lf.h
View File

@ -185,8 +185,8 @@ float getmaxstamina(lifeform_t *lf);
int getmr(lifeform_t *lf);
int getvisrange(lifeform_t *lf, int useambient);
void idxtoxy(lifeform_t *lf, int idx, int *x, int *y);
void setviscell(lifeform_t *lf, cell_t *cell, int how);
int getviscell(lifeform_t *lf, cell_t *cell);
//void setviscell(lifeform_t *lf, cell_t *cell, int how);
//int getviscell(lifeform_t *lf, cell_t *cell);
int xytoidx(lifeform_t *lf, int x, int y);
int getmovespeed(lifeform_t *lf);
char *getmoveverb(lifeform_t *lf);

122
map.c
View File

@ -1194,6 +1194,7 @@ int doelementspread(cell_t *c) {
getradiuscells(c, 1, DT_COMPASS, B_FALSE, LOF_DONTNEED, B_FALSE, retcell, &nretcells, B_FALSE);
for (i = 0; i < nretcells; i++) {
object_t *oo;
int celldone = B_FALSE;
for (oo = retcell[i]->obpile->first ; oo ; oo = oo->next) {
if (isflammable(oo) && !hasobofmaterial(retcell[i]->obpile, MT_FIRE)) {
ignite(oo);
@ -1202,6 +1203,18 @@ int doelementspread(cell_t *c) {
addobfast(retcell[i]->obpile, fireob->type->id);
}
nspread++;
celldone = B_TRUE;
}
}
// lifeforms made out of something flammable? ie. plants
// don't include flesh even though it's technically flammable
if (retcell[i]->lf && (retcell[i]->lf->material->id != MT_FLESH)) {
if (!hasobofmaterial(retcell[i]->obpile, MT_FIRE)) {
if (lfhasflag(retcell[i]->lf, F_FLAMMABLE)) {
addobfast(retcell[i]->obpile, fireob->type->id);
nspread++;
celldone = B_TRUE;
}
}
}
}
@ -1650,6 +1663,10 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int
if (cellwalkable(NULL, cell, NULL) && isroom(cell)) {
valid = B_FALSE;
}
// - overlap any part of an existing vault
if (cell->room && cell->room->vault) {
valid = B_FALSE;
}
// is this cell adjacent to an empty cell and not a
// corner (ie. a valid door location)
@ -2992,7 +3009,6 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
addcell(map, x, y);
}
}
roomon = malloc((roomcountx * roomcounty) * sizeof(int));
rowfirst = malloc(roomcounty * sizeof(int));
rowlast = malloc(roomcounty * sizeof(int));
@ -3315,11 +3331,73 @@ int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *r
return B_FALSE;
}
void killcell(cell_t *c) {
killobpile(c->obpile);
if (c->writing) free(c->writing);
}
void killcelltype(celltype_t *ct) {
celltype_t *nextone, *lastone;
if (ct->name) free(ct->name);
if (ct->flags) killflagpile(ct->flags);
// remove from list
nextone = ct->next;
if (nextone != NULL) {
nextone->prev = ct->prev;
} else { /* last */
lastcelltype = ct->prev;
}
if (ct->prev == NULL) {
/* first */
nextone = ct->next;
free(firstcelltype);
firstcelltype = nextone;
} else {
lastone = ct->prev;
free (lastone->next );
lastone->next = nextone;
}
}
void killfakes(map_t *map, cell_t *cell) {
killobpile(cell->obpile);
free(map->name);
}
void killmap(map_t *m) {
map_t *nextone, *lastone;
int i;
// free mem
while (m->lf) killlf(m->lf);
killflagpile(m->flags);
for (i = 0; i < (m->w*m->h); i++){
killcell(m->cell[i]);
}
// remove from list
nextone = m->next;
if (nextone != NULL) {
nextone->prev = m->prev;
} else { /* last */
lastmap = m->prev;
}
if (m->prev == NULL) {
/* first */
nextone = m->next;
free(firstmap);
firstmap = nextone;
} else {
lastone = m->prev;
free (lastone->next );
lastone->next = nextone;
}
}
// link a single cell up to the rest of the map.
// make sure it links to an empty cell of a DIFFERENT roomid.
// if 'wantfilled' is set, only link to "filled" cells.
@ -4130,18 +4208,18 @@ void dumpoutlines(void) {
// dirtype of DT_COMPASS will give a circular explosion
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce) {
int x,y;
char buf[BUFLEN];
if (wantannounce) {
sprintf(buf, "You see %s explosion!", (range > 0) ? "a huge" : "an");
}
if (dirtype == DT_COMPASS) {
animradial(c, range, '}', C_RED);
animradial(c, range, '}', C_RED, DT_COMPASS, wantannounce ? buf : NULL, wantannounce ? buf : NULL);
} else { // ie. DT_ORTH
animradialorth(c, range, '}', C_RED);
animradial(c, range, '}', C_RED, DT_ORTH, wantannounce ? buf : NULL, wantannounce ? buf : NULL);
}
if (haslos(player, c)) {
if (wantannounce) {
msg("You see %s explosion!", (range > 0) ? "a huge" : "an");
}
} else {
if (!haslos(player, c)) {
noise(c, NULL, NC_OTHER, (range > 0) ? 6 : 5, "an explosion!", NULL);
}
@ -4857,6 +4935,7 @@ cell_t *getrandomroomcell(map_t *map, int roomid) {
}
}
if (npossible <= 0) {
free(poss);
return NULL;
}
@ -5680,6 +5759,14 @@ void makelit(cell_t *c, enum LIGHTLEV how, int howlong) {
c->origlittimer = c->littimer;
c->littimer = howlong;
}
if ((gamemode == GM_GAMESTARTED) && (c->lit != how)) {
lifeform_t *lf;
for (lf = c->map->lf ; lf ; lf = lf->next) {
if (haslos(lf, c)) {
setlosdirty(lf);
}
}
}
c->lit = how;
}
@ -5864,7 +5951,6 @@ void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc,
void setcellknown(cell_t *cell, int forcelev) {
enum SKILLLEVEL slev;
object_t *o;
if (forcelev > 0) {
slev = forcelev;
} else {
@ -6089,24 +6175,6 @@ void updateknowncells(void) {
if (isairborne(player) && !lfhasflag(player, F_PHOTOMEM)) {
return;
}
/*
map = player->cell->map;
//wep = getweapon(player);
for (y = viewy; y < viewy + viewh; y++) {
for (x = viewx; x < viewx + vieww; x++) {
cell_t *cell;
cell = getcellat(map, x, y);
if (cell) {
//if ((player->cell == cell) || haslos(player, cell)) {
if (haslos(player, cell)) {
setcellknown(cell, B_FALSE);
}
}
}
}
*/
for (i = 0; i < player->nlos; i++) {
setcellknown(player->los[i], B_FALSE);
}

3
map.h
View File

@ -121,7 +121,10 @@ int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m);
int isroom(cell_t *c);
int iswallindir(cell_t *cell, int dir);
void killcell(cell_t *c);
void killcelltype(celltype_t *ct);
void killfakes(map_t *map, cell_t *cell);
void killmap(map_t *m);
int linkexit(cell_t *c, int wantfilled, int *ncellsadded);
int linkexits(map_t *m, int roomid);
int linkholes(map_t *map);

21
move.c
View File

@ -298,13 +298,26 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
if (lf && isclimbing(lf)) {
cell_t *rightcell,*leftcell,*frontcell;
int rightdir,leftdir,i;
int gotlf = B_FALSE;
// climbing rules: you can climb into a cell if:
// - it contains a lifeform and is in front of you
// OR
// - it is directly to your side
// - the target cell (beside you) is a wall
// - the cell in FRONT (ie. dir you are facing) of the target cell
// is NOT a wall
// OR
// - it is straight forward (ie. off the wall)
if (cell->lf && (cell->lf != lf)) {
if (getrelativedir(lf, getdirtowards(lf->cell, cell, lf, B_FALSE, DT_ORTH)) == RD_FORWARDS) {
if (error) *error = E_LFINWAY; // ok but still set reason
gotlf = B_TRUE;
}
}
if (!gotlf) {
rightdir = lf->facing;
leftdir = lf->facing;
for (i = 0; i < 2; i++) {
@ -346,6 +359,7 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
return B_FALSE;
}
}
}
// if okay, now drop through to below code which checks
// whether there are any lfs or objects in the way
} else {
@ -490,6 +504,7 @@ int diropposite(int dir) {
// restonfail means "if we can't find any valid moves, just rest"
// returns true on error
int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) {
int origtimespent;
int dir;
int tries = 0;
int moveok,rv;
@ -534,8 +549,10 @@ int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) {
}
}
}
origtimespent = lf->timespent;
rv = trymove(lf, dir, B_TRUE, B_FALSE);
if (rv && restonfail) {
if (restonfail && (rv || (lf->timespent == origtimespent))) {
// ie move failed
rest(lf, B_TRUE);
}
@ -1356,7 +1373,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if (!preroom && postroom && postroom->vault) {
f = hasflag(postroom->vault->flags, F_VAULTENTERTEXT);
if (f) {
msg("%s", f->text);
msg("%s", f->text); more();
didmsg = B_TRUE;
}
}

36
nexus.c
View File

@ -44,6 +44,9 @@ hiddenname_t *firsthiddenname = NULL, *lasthiddenname = NULL;
npcname_t *npcname;
int numnpcnames;
buildingusage_t buildingusage[MAXBUILDINGTYPES];
int nbuildingusage = 0;
warning_t *firstwarning = NULL,*lastwarning = NULL;
int maxmonhitdice = 0; // highest number of hitdice for any monster
@ -428,7 +431,9 @@ int main(int argc, char **argv) {
curtime = rnd(0,DAYSECS-1);
} else {
snprintf(welcomemsg, BUFLEN, "Welcome back!");
char pname[BUFLEN];
getplayernamefull(pname);
snprintf(welcomemsg, BUFLEN, "Welcome back, %s!", pname);
}
// start game - this will cause debug messages to now
@ -520,7 +525,6 @@ int main(int argc, char **argv) {
donextturn(curmap);
// show level (if required)
//if (haslos(player, curmap->lf->cell)) {
drawscreen();
//dblog("**** END of turn, numdraws = %d", numdraws);
@ -537,6 +541,8 @@ int main(int argc, char **argv) {
dofinaloblist(player->pack);
// print tombstone
tombstone(player);
//WriteMemLeak();
return B_FALSE;
}
@ -645,13 +651,31 @@ void cleanup(void) {
fclose(logfile);
cleanupgfx();
// free maps
// free commands
while (firstcommand) killcommand(firstcommand);
// free maps (this will kill its lifeforms & obs & cells too)
while (firstmap) killmap(firstmap);
// free knowledge
while (knowledge) killknowledge(knowledge);
// free brands
while (firstbrand) killbrand(firstbrand);
// free obmods
while (firstobmod) killobmod(firstobmod);
// free obtypes
// free objects
while (objecttype) killot(objecttype);
// free obclasses
while (objectclass) killoc(objectclass);
// free materials
while (material) killmaterial(material);
// free races
while (firstrace) killrace(firstrace);
// free celltypes
while (firstcelltype) killcelltype(firstcelltype);
// free npcnames
free(npcname);
// free hidden names
while (firsthiddenname) killhiddenname(firsthiddenname);
//WriteMemLeak();
}
void dbtimestart(char *text) {
@ -1276,6 +1300,10 @@ int loadnpcnames(void) {
return B_FALSE;
}
void *mymalloc(size_t sz) {
return malloc(sz);
}
int onein(int howmany) {
if (howmany <= 0) return B_FALSE;
if (rnd(1,howmany) == 1) return B_TRUE;

View File

@ -25,6 +25,7 @@ int limit(int *what, int min, int max);
int limitf(float *what, float min, float max);
int limitd(double *what, double min, double max);
int loadnpcnames(void);
void *mymalloc(size_t sz);
int onein(int howmany);
int parseplayerfile(FILE *f, lifeform_t *lf);
int pctchance(int pct);

303
objects.c
View File

@ -28,6 +28,9 @@ extern material_t *material,*lastmaterial;
extern recipe_t *firstrecipe,*lastrecipe;
extern skill_t *firstskill, *lastskill;
extern buildingusage_t buildingusage[];
extern int nbuildingusage;
extern int inaskcoords;
void (*precalclos)(lifeform_t *);
@ -194,11 +197,12 @@ hiddennamewithcol_t gemtype[] = {
{ "copper",C_BROWN },
{ "diamond",C_BOLDCYAN },
{ "emerald",C_GREEN },
{ "flourite",C_GREY },
{ "flourite",C_RED },
{ "garnet",C_ORANGE },
{ "gold",C_YELLOW },
{ "iridium",C_WHITE },
{ "jade",C_GREEN },
{ "jasper",C_RED },
{ "lapis lazuli",C_BOLDBLUE },
{ "malachite",C_BOLDCYAN },
{ "onyx",C_BLUE },
@ -207,10 +211,20 @@ hiddennamewithcol_t gemtype[] = {
{ "quartz",C_GREY },
{ "ruby",C_RED },
{ "sapphire",C_BLUE },
{ "topaz", C_YELLOW },
{ "zinc",C_GREY },
{ "zircon",C_CYAN },
{ "",C_GREY },
};
char *ringadjective[] = {
"cracked",
"dusty",
"ornate",
"sparkling",
"twinkling",
"",
};
long nextoid = 0;
@ -924,6 +938,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// don't give nopickup objects to lifeforms
if (hasflag(ot->flags, F_NOPICKUP) && where->owner) {
if (db) dblog("DB: trying to give NOPICKUP object '%s' to a lifeform ('%s').", ot->name, where->owner->race->name );
nretobs = 0;
return NULL;
}
@ -934,10 +949,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
if (db) dblog("DB: setting canstack = false, objecttype '%s' not stackable", ot->name );
canstack = B_FALSE;
}
if (where->parentob && hasflag(where->parentob->flags, F_SHOP)) {
if (db) dblog("DB: setting canstack = false, object is going into a shop");
canstack = B_FALSE;
// also override amount
howmany = 1;
}
// special checks for unique objects
@ -1035,6 +1051,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
o->contents = addobpile(NOOWNER, NOLOC, o);
o->birthtime = curtime;
o->dying = B_FALSE;
// inherit props from objecttype
o->material = ot->material;
@ -1049,6 +1066,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// don't want certain objecttype only flags...
//killflagsofid(o->flags, F_RARITY);
if (gamemode != GM_LOADING) {
// random flags...
f = hasflag(o->flags, F_RNDCHARGES);
if (f) {
@ -1083,6 +1101,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// new object on the ground - has no letter yet.
o->letter = '\0';
}
}
if (canstack) {
// add the full amount!
@ -1091,7 +1110,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
o->amt = 1;
}
addedob[nadded++] = o;
if (canstack) {
@ -1110,6 +1128,18 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
o = addedob[i];
obloc = getoblocation(o);
// inc usage counter for buildings
if (gamemode > GM_VALIDATION) {
if (o->type->obclass->id == OC_BUILDING) {
for (n = 0; n < nbuildingusage; n++) {
if (buildingusage[n].oid == o->type->id) {
buildingusage[n].count++;
}
}
}
}
if (gamemode != GM_LOADING) {
if (hasflag(o->flags, F_NOBLESS)) {
setblessed(o, B_UNCURSED);
} else {
@ -1190,7 +1220,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
}
}
// foundtain flags
// fountain flags
if (o && (o->type->id == OT_FOUNTAIN)) {
f = hasflag(o->flags, F_LINKOB);
if (where->where && (where->where->habitat->id != H_VILLAGE)) {
@ -1338,7 +1368,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// other special changes we need to make based on what was
// asked for
if ((gamemode != GM_LOADING) && o) {
if (o) {
// corpses - fill in details
if (o->type->id == OT_CORPSE) {
flag_t *rf, *cf;
@ -1679,6 +1709,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
}
}
}
} // end if !loading
if ((gamemode == GM_GAMESTARTED) && !inaskcoords) {
if (o && where->where && !hasflag(o->flags, F_NOGLYPH) && haslos(player, where->where) ) {
@ -2241,14 +2272,11 @@ int blessob(object_t *o) {
void brightflash(cell_t *centre, int range, lifeform_t *immunelf) {
int x,y;
cell_t *c;
char buf[BUFLEN];
animradial(centre, range, '}', C_WHITE);
sprintf(buf, "You see an intense flash of light!");
animradial(centre, range, '}', DT_ORTH, C_WHITE, buf, buf);
// announce
if (haslos(player, centre) && !isblind(player)) {
msg("You see an intense flash of light!");
more();
}
// blind monsters
for (y = centre->y - range; y <= centre->y + range; y++) {
for (x = centre->x - range; x <= centre->x + range; x++) {
@ -3270,7 +3298,7 @@ void genhiddennames(void) {
if (strlen(f->text)) {
thisname = strdup(f->text);
} else {
thisname = genhiddenname(ot->obclass->id);
thisname = strdup(genhiddenname(ot->obclass->id));
}
sethiddenname(ot, thisname);
free(thisname);
@ -3486,6 +3514,10 @@ int getobvalue(object_t *o) {
return o->amt;
}
if (o->type->id == OT_CREDITCARD) {
return getcharges(o);
}
// base value: weight * material value
price = (float)getobweight(o) * (float)getmaterialvalue(o->material->id);
//adjustprice(o->type, &price);
@ -3544,15 +3576,16 @@ int getobvalue(object_t *o) {
// rarity
rarity = getobrarity(o, &rr);
// potions
/*
if (o->type->obclass->id == OC_POTION) {
// potion value is based on rarity
price += ((100 - rarity)*0.5);
price += (rr * 112);
} else if (o->type->obclass->id == OC_TOOLS) {
// tool value is based on rarity
price += ((100 - rarity)*3.75);
//price += ((100 - rarity)*3.75);
price += ((rr*43) + (r-1)*22);
} else if (o->type->obclass->id == OC_TECH) {
// tech value is based on tech level & rarity
// tech value is based on tech level
float multiplier = 1;
switch (gettechlevel(o->type->id)) {
case PR_INEPT:
@ -3577,8 +3610,10 @@ int getobvalue(object_t *o) {
multiplier = 10.25;
break;
}
price += ((100 - rarity)*multiplier);
//price += ((100 - rarity)*multiplier);
price += ((rr*20)*multiplier);
}
*/
// TODO: conferred intrinsics - depends on which one
@ -4329,6 +4364,12 @@ char *getobextrainfo(object_t *o, char *buf) {
} else {
snprintf(chargestr, BUFLEN, " (depleted)");
}
} else if (o->type->id == OT_CREDITCARD) {
if (f->val[0] > 0) {
snprintf(chargestr, BUFLEN, " ($%d balance)",f->val[0]);
} else {
snprintf(chargestr, BUFLEN, " (maxed out)");
}
} else {
if (f->val[0] > 0) {
snprintf(chargestr, BUFLEN, " (%d charge%s left)",f->val[0], (f->val[0] == 1) ? "" : "s");
@ -4375,6 +4416,15 @@ cell_t *getobpilelocation(obpile_t *op) {
return NULL;
}
char *getshopobname(object_t *o, char *buf, int count) {
if (gettechlevel(o->type->id) > getskill(player, SK_TECHUSAGE)) {
// unidentified tech - hide the name
return real_getobname(o, buf, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_FALSE);
}
// anything else - show the real name
return real_getobname(o, buf, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_TRUE);
}
char *getobname(object_t *o, char *buf, int count) {
return real_getobname(o, buf, count, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_FALSE);
}
@ -4922,11 +4972,13 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
else strcpy(triedbuf, " [");
strcat(triedbuf, "tried");
}
if (!isknown(o)) {
if (lfhasflagval(player, F_FAILEDINSPECT, o->type->id, NA, NA, NULL)) {
if (strlen(triedbuf)) strcat(triedbuf, ", ");
else strcpy(triedbuf, " [");
strcat(triedbuf, "inspected");
}
}
if (strlen(triedbuf)) {
strcat(triedbuf, "]");
strcat(localbuf, triedbuf);
@ -5180,12 +5232,10 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat,
va_list args;
objecttype_t *ot;
objecttype_t *poss[MAXRANDOMOBCANDIDATES];
enum OBCLASS wantclass[MAXCANDIDATES];
int nwantclass = 0;
enum DAMTYPE wantdt[MAXCANDIDATES];
int nwantdt = 0;
int nposs = 0;
int selidx;
int amt;
@ -5264,6 +5314,25 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat,
nwantclass = 1;
}
if ((nwantclass == 1) && (wantclass[0] == OC_BUILDING)) {
int minused = 9999;
// find least used building
for (i = 0; i < nbuildingusage; i++) {
if (buildingusage[i].count < minused) {
minused = buildingusage[i].count;
}
}
// find possibilities
for (i = 0; i < nbuildingusage; i++) {
if (buildingusage[i].count == minused) {
poss[nposs++] = findot(buildingusage[i].oid);
}
}
assert(nposs > 0);
sprintf(buf, "%s", poss[rnd(0,nposs-1)]->name);
return buf;
}
while (!done) {
if (db || partdb) dblog("adding random object with rarity value between %d - %d and rr <= %d, for habitat %s",
raritymin,raritymax,wantrr, habname);
@ -5374,9 +5443,6 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat,
// matches wanted weapon skill?
if (wantsk) {
if (ot->id == OT_QUICKBLADE) {
dblog("xxx");
}
if (!hasflagval(ot->flags, F_USESSKILL, wantsk->id, NA, NA, NULL)) {
condok = B_FALSE;
if (db) dblog(" %s doesn't use correct weapon skill.", ot->name);
@ -5423,9 +5489,6 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat,
// give up
strcpy(buf, "");
if (db || partdb) dblog("no possible random objects at all for habitat %s! giving up.", habname);
if (!hab) {
dblog("xxx");
}
return NULL;
}
}
@ -5561,7 +5624,7 @@ char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf) {
char *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;
//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);
}
@ -6256,6 +6319,9 @@ int isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown) {
}
int isdeadob(object_t *o) {
if (o->dying) {
return B_TRUE;
}
if (hasflag(o->flags, F_DEAD)) {
return B_TRUE;
}
@ -6679,6 +6745,88 @@ int killallobsexcept(obpile_t *op, ...) {
return nkilled;
}
void killbrand(brand_t *b) {
brand_t *nextone, *lastone;
// free mem
if (b->description) free(b->description);
if (b->suffix) free(b->suffix);
killflagpile(b->flags);
// remove from list
nextone = b->next;
if (nextone != NULL) {
nextone->prev = b->prev;
} else { /* last */
lastbrand = b->prev;
}
if (b->prev == NULL) {
/* first */
nextone = b->next;
free(firstbrand);
firstbrand = nextone;
} else {
lastone = b->prev;
free (lastone->next );
lastone->next = nextone;
}
}
void killhiddenname(hiddenname_t *hn) {
hiddenname_t *nextone, *lastone;
// free mem
if (hn->text) free(hn->text);
hn->text = NULL;
// remove from list
nextone = hn->next;
if (nextone != NULL) {
nextone->prev = hn->prev;
} else { /* last */
lasthiddenname = hn->prev;
}
if (hn->prev == NULL) {
/* first */
nextone = hn->next;
free(firsthiddenname);
firsthiddenname = nextone;
} else {
lastone = hn->prev;
free (lastone->next );
lastone->next = nextone;
}
}
void killknowledge(knowledge_t *k) {
knowledge_t *nextone, *lastone;
// free mem
if (k->hiddenname) free(k->hiddenname);
// remove from list
nextone = k->next;
if (nextone != NULL) {
nextone->prev = k->prev;
} else { /* last */
lastknowledge = k->prev;
}
if (k->prev == NULL) {
/* first */
nextone = k->next;
free(knowledge);
knowledge = nextone;
} else {
lastone = k->prev;
free (lastone->next );
lastone->next = nextone;
}
}
void killmaterial(material_t *m) {
material_t *nextone, *lastone;
@ -6727,6 +6875,8 @@ void killob(object_t *o) {
// free mem
if (o->inscription) free(o->inscription);
if (o->contents) killobpile(o->contents);
if (o->flags) killflagpile(o->flags);
// remove from list
nextone = o->next;
@ -6748,6 +6898,33 @@ void killob(object_t *o) {
}
}
void killobmod(obmod_t *om) {
obmod_t *nextone, *lastone;
// free mem
if (om->prefix) free(om->prefix);
killflagpile(om->flags);
// remove from list
nextone = om->next;
if (nextone != NULL) {
nextone->prev = om->prev;
} else { /* last */
lastobmod = om->prev;
}
if (om->prev == NULL) {
/* first */
nextone = om->next;
free(firstobmod);
firstobmod = nextone;
} else {
lastone = om->prev;
free (lastone->next );
lastone->next = nextone;
}
}
void killobpile(obpile_t *op) {
killallobs(op);
free(op);
@ -6943,14 +7120,6 @@ void makeknown(enum OBTYPE otid) {
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0;
/*
objecttype_t *ot;
ot = findot(otid);
if (ot && (ot->obclass->id == OC_TECH)) {
dblog("xxx");
}
*/
if (player) {
// if player is holding an object of that type with F_CONFER.. IFKNOWN... and isn't known...
// then by making the object known, we also need to give them the flag.
@ -6989,6 +7158,10 @@ void makeknown(enum OBTYPE otid) {
for (i = 0; i < nobs; i++) {
giveobflags(player, srcob[i], fttogive[i]);
}
f = lfhasflagval(player, F_FAILEDINSPECT, otid, NA, NA, NULL);
if (f) {
killflag(f);
}
}
void maketried(enum OBTYPE otid) {
@ -7203,14 +7376,13 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
while (tempop->first) {
o = relinkob(tempop->first, dst);
}
free(tempop);
killobpile(tempop);
}
}
if (o) {
if (dst->owner && isplayer(dst->owner) && isblessknown(o)) {
o->blessknown = B_TRUE;
}
@ -7287,6 +7459,30 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
if (f && (f->val[1] != curtime)) {
triggertrap(NULL, o, oo, dst->where);
}
// bless objects which land on a holy circle.
if ((oo->type->id == OT_HOLYCIRCLE) && !blessob(o)) {
// holy circle vanishes.
if (onein(3)) {
if (haslos(player, dst->where)) {
char ooname[BUFLEN];
getobname(oo, ooname, 1);
msg("%s fades and vanishes.", ooname);
}
removeob(oo, oo->amt);
}
}
// curse objects which land on a pentagram.
if ((oo->type->id == OT_PENTAGRAM) && !curseob(o)) {
// pentagrams don't vanish as often as holy circles
if (onein(6)) {
if (haslos(player, dst->where)) {
char ooname[BUFLEN];
getobname(oo, ooname, 1);
msg("%s fades and vanishes.", ooname);
}
removeob(oo, oo->amt);
}
}
}
}
}
@ -7365,6 +7561,8 @@ void obdie(object_t *o) {
char obname[BUFLEN];
flag_t *f;
o->dying = B_TRUE;
// handle object conversion
if (!doobdieconvert(o, B_TRUE)) {
char desc[BUFLEN];
@ -11136,18 +11334,17 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
explodecells(thrower->cell, roll(diebuf), B_FALSE, o, 1, DT_COMPASS, B_FALSE);
} else if (o->type->id == OT_ASHSLEEP) {
int radius;
char buf[BUFLEN];
// make smoke
if (haslos(player, srcloc)) {
msg("%s dispers%s into a wispy mist!", obname,
(amt == 1) ? "es" : "e",
(amt == 1) ? "es" : "e" );
sprintf(buf, "%s dispers%s into a wispy mist!", obname, (amt == 1) ? "es" : "e" );
if (haslos(player, srcloc)) {
if (!isknown(o)) makeknown(o->type->id);
}
radius = o->amt * 2;
if (radius > 10) radius = 10;
spellcloud(srcloc, radius, '}', C_MAGENTA, OT_S_SLEEP, radius, B_TRUE);
spellcloud(srcloc, radius, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, radius, B_TRUE, buf, "A wispy mist appears!");
} else if (o->type->id == OT_SALT) {
if (target && (getcelldist(srcloc, where) <= 1)) {
if (hasbp(target, BP_EYES) && !isblind(target) && !getequippedob(target->pack, BP_EYES)) {
@ -12442,6 +12639,21 @@ int usecharge(object_t *o) {
return -1;
}
// returns charges remaining, -1 if object doesn't have the flag
int usecharges(object_t *o, int amt) {
flag_t *f;
f = hasflag(o->flags, F_CHARGES);
if (f) {
f->val[0] -= amt;
if (f->val[0] < 0) {
f->val[0] = 0;
}
return f->val[0];
}
return -1;
}
int validateobs(void) {
objecttype_t *ot;
int foundspells = B_FALSE;
@ -12457,6 +12669,13 @@ int validateobs(void) {
}
}
// remember buildings
if (ot->obclass->id == OC_BUILDING) {
buildingusage[nbuildingusage].oid = ot->id;
buildingusage[nbuildingusage].count = 0;
nbuildingusage++;
}
if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) {
if (!foundspells) foundspells = B_TRUE;
if (!hasflag(ot->flags, F_SPELLSCHOOL)) {
@ -12887,8 +13106,10 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
// penalty for throwing non-missiles
if (missile && !firearm && !isthrowmissile(missile) && !tkthrow) {
if (!lfhasflagval(thrower, F_WILLTHROW, missile->type->id, NA, NA, NULL)) {
acc -= 20;
}
}
// modify for prone throwers
if (isprone(thrower)) {
acc -= 50;

View File

@ -119,6 +119,7 @@ char *getobextrainfo(object_t *o, char *buf);
cell_t *getoblocation(object_t *o);
cell_t *getobpilelocation(obpile_t *op);
char *getobname(object_t *o, char *buf, int count);
char *getshopobname(object_t *o, char *buf, int count);
char *getobnametrue(object_t *o, char *buf, int count);
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse, int showall);
float getobpileweight(obpile_t *op);
@ -203,9 +204,14 @@ int isweapon(object_t *o);
int iswearable(object_t *o);
void killallobs(obpile_t *op);
int killallobsexcept(obpile_t *op, ...);
void killbrand(brand_t *b);
void killhiddenname(hiddenname_t *hn);
void killknowledge(knowledge_t *k);
void killmaterial(material_t *m);
void killob(object_t *o);
void killobmod(obmod_t *om);
void killobpile(obpile_t *o);
void killobtype(object_t *o);
void killoc(objectclass_t *oc);
void killot(objecttype_t *ot);
int knockbackob(object_t *o, int dir, int howfar, int power, lifeform_t *pusher);
@ -260,6 +266,7 @@ void turnoff(lifeform_t *lf, object_t *o);
void turnon(lifeform_t *lf, object_t *o);
int uncurseob(object_t *o, int *seen);
int usecharge(object_t *o);
int usecharges(object_t *o, int amt);
int usefountaincharge(object_t *o, flag_t *drinkflag);
int validateobs(void);
int wepdullable(object_t *o);

4
save.c
View File

@ -63,6 +63,8 @@ int loadall(void) {
printf("Error loading map from file '%s'",ent->d_name);
exit(1);
}
// remove this map
unlink(ent->d_name);
}
}
closedir(dir);
@ -260,7 +262,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
}
if (db) dblog("--> Finished oblist. Found %d objects.",obcount);
// now load load object defs for this player!
// now load object defs for this player!
fscanf(f, "obdefs\n");
for (i = 0; i < obcount; i++) {
long thisid;

63
shops.c
View File

@ -558,13 +558,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
for (o = vm->contents->first ; o ; o = o->next) {
char obname[BUFLEN];
// get the name of the object
if (gettechlevel(o->type->id) > getskill(player, SK_TECHUSAGE)) {
// unidentifie tech - hide the name
real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_FALSE);
} else {
// anything else - show the real name
real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_TRUE);
}
getshopobname(o, obname, o->amt);
snprintf(buf, BUFLEN, "%c - %s", o->letter, obname);
snprintf(buf2, BUFLEN, "%-60s$%d",buf,(int)getshopprice(o, player));
mvwprintw(mainwin, y, 0, "%s", buf2);
@ -598,7 +592,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
slev = getskill(player, SK_THIEVERY);
// confirm
getobname(o, obname, o->amt);
getshopobname(o, obname, o->amt);
snprintf(buf, BUFLEN, "Buy%s %s for $%d?", slev ? "/steal" : "", obname, value);
strcpy(validchars, "yn");
if (slev) {
@ -606,8 +600,59 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
}
answer = askchar(buf, validchars,"n", B_TRUE, B_FALSE);
if (answer == 'y') {
// prompt to use a card
if (hasob(player->pack, OT_CREDITCARD)) {
char ch2;
ch2 = askchar("Charge this purchase to your credit card?","yn","n", B_TRUE, B_FALSE);
if (ch2 == 'y') {
object_t *cc;
// ask which one
initprompt(&prompt, "Which credit card will you use?");
for (cc = player->pack->first ; cc ; cc = cc->next) {
if (cc->type->id == OT_CREDITCARD) {
char cardname[BUFLEN];
getobname(cc, cardname, 1);
addchoice(&prompt, cc->letter, cardname, cardname, cc, NULL);
}
}
if (prompt.nchoices == 1) {
// only one card?
cc = (object_t *)prompt.choice[0].data;
} else {
addchoice(&prompt, '-', "(cancel)", "(cancel)", NULL, NULL);
prompt.maycancel = B_TRUE;
getchoice(&prompt);
cc = (object_t *)prompt.result;
}
if (cc) {
if (getcharges(cc) >= getobvalue(o)) {
int shopamt;
// you got it!
usecharges(cc, getobvalue(o));
o->letter = '\0';
shopamt = o->amt; // avoid "purchased: 2 apples" when you only bought 1 but were holding 1
o = moveob(o, player->pack, ALL);
identify(o);
getobname(o, obname, shopamt);
snprintf(toptext, BUFLEN, "Charged to card: %c - %s", o->letter, obname);
if (npurchased) (*npurchased)++;
// god of thieves likes credit cards...
pleasegodmaybe(R_GODTHIEVES, (value/75));
return SR_CONTINUE;
} else {
// maxed!
usecharges(cc, getcharges(o)); // use up all remaining charges
// get kicked out
msg("^B\"Trying to use a maxed out card, eh? Get out of here, thief!\""); more();
// shop closes
addflag(vm->flags, F_BANNEDLF, player->id, NA, NA, NULL);
return SR_QUIT;
}
}
}
}
// do you have enough money?
if (slev || (countmoney(player->pack) >= getobvalue(o)) ) {
if (countmoney(player->pack) >= getobvalue(o) ) {
int shopamt;
object_t *gold;
gold = hasob(player->pack, OT_GOLD);

108
spell.c
View File

@ -567,6 +567,12 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
taketime(user, getactspeed(user)*2);
} else if (abilid == OT_A_CLIMB) {
enum ERROR why;
// for ai only: turn to face target cell first.
if (!isplayer(user) && targcell) {
turntoface(user, targcell);
}
if (!canclimb(user, &why)) {
if (isplayer(user)){
switch (why) {
@ -1072,8 +1078,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (hasjob(user, J_MONK)) {
if (getweapon(user)) {
if (isplayer(user)) msg("You need be unarmed to perform an attack flurry!");
}
return B_TRUE;
}
} else if (!isdualweilding(user)) {
if (isplayer(user)) msg("You need to be dual-weilding to perform an attack flurry!");
return B_TRUE;
@ -1240,10 +1246,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) msg("You can't jump with gravity boosted around you!");
return B_TRUE;
} else if (lfhasflag(user, F_GRABBING)) {
if (isplayer(user)) msg("You can't jump while being held!");
if (isplayer(user)) msg("You can't jump while holding someone!");
return B_TRUE;
} else if (lfhasflag(user, F_GRABBEDBY)) {
if (isplayer(user)) msg("You can't jump while holding someone!");
if (isplayer(user)) msg("You can't jump while being held!");
return B_TRUE;
}
@ -1732,7 +1738,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) {
int dir,dirch;
dirch = askchar("Sprint in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE, B_TRUE);
if (dirch == '.') {
if ((dirch == '.') || (dirch == '\0')) {
msg("Cancelled.");
return B_TRUE;
}
@ -1753,8 +1759,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
targetname);
}
losehp(target, roll(damstr), DT_ACID, user, killername);
if (!lfhasflagval(target, F_PAIN, DT_ACID, NA,NA, NULL)) {
// cause ongoing pain for 2 turns
addtempflag(target->flags, F_PAIN, DT_ACID, NA, NA, damstr, 2);
}
taketime(user, getactspeed(user));
} else if (abilid == OT_A_STUDYSCROLL) {
object_t *o;
@ -2110,10 +2118,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if (isplayer(user)) msg("You can't tumble while airbourne!");
return B_TRUE;
} else if (lfhasflag(user, F_GRABBING)) {
if (isplayer(user)) msg("You can't tumble while being held!");
if (isplayer(user)) msg("You can't tumble while holding someone!");
return B_TRUE;
} else if (lfhasflag(user, F_GRABBEDBY)) {
if (isplayer(user)) msg("You can't tumble while holding someone!");
if (isplayer(user)) msg("You can't tumble while being held!");
return B_TRUE;
}
@ -3882,6 +3890,17 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("The electricity arcs!");
}
} // end while narccells
} else if (spellid == OT_S_CLONE) {
// duplicate the caster
targcell = getrandomadjcell(caster->cell, WE_WALKABLE, B_NOEXPAND);
if (!targcell) {
if (isplayer(caster)) fizzle(caster);
return B_TRUE;
}
if (isplayer(caster) || haslos(player, targcell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
addmonster(targcell, caster->race->id, NULL, B_FALSE, 1, B_FALSE, NULL);
} else if (spellid == OT_S_CLOUDKILL) {
int radius;
@ -4074,17 +4093,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_COLDBURST) {
int range = 1;
int x,y;
char buf[BUFLEN];
range = 1 + (power / 5);
// announce
sprintf(buf, "%s emit%s a blast of icy cold!",castername,isplayer(caster) ? "" : "s");
animradial(caster->cell, range, '}', C_GREY, DT_ORTH, buf, "Something emits a blast of icy cold!");
if (isplayer(caster) || cansee(player, caster)) {
msg("%s emit%s a blast of icy cold!",castername,isplayer(caster) ? "" : "s");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
animradialorth(caster->cell, range, '}', C_GREY);
for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) {
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y);
@ -4439,8 +4459,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
makelitradius(targcell, power*2, L_PERMDARK, rnd(5,10) + power );
}
calclight(targcell->map);
needredraw = B_TRUE;
drawscreen();
} else if (spellid == OT_S_DETECTAURA) {
if (isplayer(caster)) {
object_t *o;
@ -4912,17 +4930,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_ENERGYBLAST) {
int range;
int x,y;
// announce
if (caster) {
if (!targcell) targcell = caster->cell;
if (isplayer(caster) || cansee(player, caster)) {
msg("%s emit%s a radial blast of energy!",castername,isplayer(caster) ? "" : "s");
char buf[BUFLEN];
if (caster && !targcell) targcell = caster->cell;
range = 2 + (power / 4);
sprintf(buf, "%s emit%s a radial blast of energy!",castername,isplayer(caster) ? "" : "s");
animradial(targcell, range, '}', C_CYAN, DT_COMPASS, buf, "Something emits a radial blast of energy!");
if (isplayer(caster) || haslos(player, targcell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
}
range = 2 + (power / 4);
animradial(targcell, range, '}', C_CYAN);
for (y = targcell->y - range ; y <= targcell->y + range; y++) {
for (x = targcell->x - range ; x <= targcell->x + range; x++) {
@ -5265,18 +5282,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (spellid == OT_S_FLAMEBURST) {
int range = 1;
int x,y;
char buf[BUFLEN],buf2[BUFLEN];
range = 1 + (power / 5);
// announce
if (isplayer(caster) || cansee(player, caster)) {
msg("%s emit%s a %sblast of fire!",castername,isplayer(caster) ? "" : "s",
sprintf(buf, "%s emit%s a %sblast of fire!",castername,isplayer(caster) ? "" : "s",
(power >= 5) ? "huge " : "");
sprintf(buf2, "Something emit%s a %sblast of fire!",isplayer(caster) ? "" : "s",
(power >= 5) ? "huge " : "");
animradial(caster->cell, range, '}', C_RED, DT_ORTH, buf, buf2);
if (isplayer(caster) || cansee(player, caster)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
animradialorth(caster->cell, range, '}', C_RED);
for (y = caster->cell->y - range ; y <= caster->cell->y + range; y++) {
for (x = caster->cell->x - range ; x <= caster->cell->x + range; x++) {
targcell = getcellat(caster->cell->map, x,y);
@ -6143,17 +6163,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
nothinghappens();
return B_TRUE;
} else {
int charges;
char extrabuf[BUFLEN];
identify(o);
getobname(o, buf, o->amt);
//getobname(o, buf, o->amt);
real_getobname(o, buf, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_TRUE);
getobextrainfo(o, extrabuf);
if (strlen(extrabuf)) strcat(buf, extrabuf);
// charges
charges = getcharges(o);
if (charges == -1) {
msgnocap("%c - %s.",o->letter, buf);
} else {
msgnocap("%c - %s (%d charges left).",o->letter, buf, charges);
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
@ -8238,6 +8256,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (targcell) {
if (!targcell->type->solid || hasflag(targcell->type->material->flags, F_FLAMMABLE)) {
int dir;
char buf[BUFLEN];
cell_t *c;
// centre snowball here...
if (isplayer(caster)) {
@ -8246,12 +8265,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (cansee(player, caster)) {
msg("%s launches a huge snowball!",castername);
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, targcell)) {
msg("An enormous ball of fire explodes!");
}
anim(caster->cell, targcell, '^', C_WHITE);
animradialorth(targcell, 1, '}', C_WHITE);
sprintf(buf, "A huge snowball explodes! ");
animradial(targcell, 1, '}', C_WHITE, DT_ORTH, buf, buf);
redrawpause();
// add snow as follows (3 = medium, 2 = medium, 1 = smell)
@ -8427,7 +8446,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
howlong = getspellduration(5,10,blessed) + power;
if (makenauseated(target, power, howlong)) {
fizzle(caster);
if (isplayer(caster)) nothinghappens();
return B_FALSE;
}
if (isplayer(target) || haslos(player, target->cell)) {
@ -10563,13 +10582,14 @@ int schoolappearsinbooks(enum SPELLSCHOOL ss) {
return B_TRUE;
}
void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot) {
void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext) {
int x,y;
objecttype_t *ot;
ot = findot(sid);
if (!ot) return;
if (ch != '\0') {
if (haslos(player, srcloc)) {
animradialorth(srcloc, radius, ch, col);
drawscreen();
}
animradial(srcloc, radius, ch, col, DT_ORTH, seetext, noseetext);
}
for (y = srcloc->y - radius ; y <= srcloc->y + radius; y++) {
for (x = srcloc->x - radius ; x <= srcloc->x + radius; x++) {
@ -10578,8 +10598,12 @@ void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYP
if (c && c->lf && (c != srcloc) && !c->type->solid &&
haslof(srcloc, c, LOF_WALLSTOP, NULL)) {
if (getcelldistorth(srcloc, c) <= radius) {
// fall asleep
dospelleffects(NULL, sid, power, c->lf, NULL, c, B_UNCURSED, NULL, frompot);
// cast the spell
if (ot->obclass->id == OC_SPELL) {
dospelleffects(NULL, ot->id, power, c->lf, NULL, c, B_UNCURSED, NULL, frompot);
} else if (ot->obclass->id == OC_ABILITY) {
abilityeffects(c->lf, ot->id, c, c->lf, NULL);
}
}
}
}

View File

@ -32,7 +32,7 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat);
void pullobto(object_t *o, lifeform_t *lf);
int schoolappearsinbooks(enum SPELLSCHOOL ss);
void spellcloud(cell_t *srcloc, int radius, char ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot);
void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext);
int spellisfromschool(int spellid, enum SPELLSCHOOL school);
int spellresisted(lifeform_t *target, lifeform_t *caster, int spellid, int power, int *seenbyplayer, int announce);
void stopspell(lifeform_t *caster, enum OBTYPE spellid);

View File

@ -75,6 +75,8 @@ vault_t *addvault(void) {
v->valid = B_TRUE;
v->state = VS_ALLOCATED;
v->flags = addflagpile(NULL, NULL);
v->legend = NULL;
v->lastlegend = NULL;
v->map[0].mlen = 0;
v->map[0].w = 0;
v->map[0].h = 0;