- [+] shops on a level should make loud sounds every few turns. (onein3)

- [+] inifniite loop in ?k
- [+] add to balaclava:  equipconfer -> f_anonymous
    - [+] can't get banned from shops with this!
- [+] when randomly increasing skills, don't select maxed ones.
- [+] remove warning for movement while bleeding
- [+] injuries heal too fast.
- [+] bug: The sound of sounds of fighting awakens you!
- [+] shouldnt be able to rest while airborne!
- [+] make drunkenness give more damage resistance!
- [+] "unseen" etc not working on tombstone
- [+] bug: merloch getting infinite attacks!!
- [+] add "a xxx moves out of view"
- [+] why are wizards starting with 2 cold spells? fixed. was getting
      an extra one for gaining a "new" spell skill.
- [+] slowwalking shoudl reduce move volume, not eliminate it.
- [+] i noticed a secret iron door forom 6 cells away!
    - [+] make SC_SEARCH not autopassable on natural 20.
- [+] armour can have a SIZE
    - [+] remove some occurences of "f_noarmouron"  for sz_large,
          sz_small creatures
    - [+] in "canwear", implement size check.  if lf's body size isn't
          sz_human then armour must have "f_armoursize -> sz_xxx"
        - [+] exception for ears / eyes
    - [+] f_multisize
    - [+] f_armoursize sz_xxx
    - [+] can only wear armour whih is your size
    - [+] in io.c, show armour size
    - [+] assign f_multisize to objects
    - [+] when adding objects
        - [+] cope with asking for "large armour" etc
        - [+] adding to a lf's pack? make sure armour is the correct fit
        - [+] somewhere else?  25% chance of different size.  if so,
              50/50 as to which way.
    - [+] in getobname, show "huge armour" etc
        - [+] medium ("halfling size pair of gauntlets"),  human
              ("gauntlets"), or large ("huge gauntlets")
    - [+] high sewing/metalwork skills will let you modify armour for
          custom fit.
        - [+] half the hit points of the object
- [+] implement a multi-level menu system for shops
- [+] text on shop exit ("thank you for your business!")
- [+] shops:
    - [+] only let you donate if you can takeoff / unweild it first.
- [+] replace "vending machine" with shop
- [+] make shops/buildings their own category
    - [+] this will let us say 'random shop'
- [+] enable stealing from shops
- [+] armour
- [+] book
- [+] weapon
- [+] general
- [+] potion
- [+] hardware
- [+] food 
- [+] jeweller
- [+] always show full name for shop items
- [+] temple of xxx -
    - [+] actions
        - [+] donate
        - [+] detect curse
        - [+] bless(costs more if equipped)
        - [+] absolve sins
        - [+] special depending on who the temple is to?
    - [+] temple of'xxx' - assign in addobject()
- [+] extend CHA/SPEECH mods to all shops
- [+] disable stacking for shop objects
- [+] hotel/inn 
    - [+] actions
        - [+] pay to rest (for 100 turns)
            - [+] if you do this, call startresting() before exitting
                  shop
            - [+] and set some kind of flag so monsters will never
                  approach
            - [+] maybe:  f_resting_in_hotel
            - [+] and so that they will never wake up you up through
                  sound
            - [+] remove these when you stop resting.
            - [+] force you to stop resting once your time expires
        - [+] buy food/drink
- [+] weapon shop:
    - [+] donate weapons
- [+] armour shop:
- [+] buy armour
- [+] donate armour (so that monsters don't pick it up!)
* [+] firearm reload messages
- [+] don't take f_throwmissile into account when using telekinesis
- [+] ranged weapons: auto reload after firing.
    - [+] done.
This commit is contained in:
Rob Pearce 2011-11-16 00:57:21 +00:00
parent dd03042c70
commit 10e4713940
25 changed files with 1882 additions and 707 deletions

View File

@ -1,7 +1,7 @@
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 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 vault.c vault.h -lncurses -lsqlite3
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
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 spell.c spell.h vault.c vault.h
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
dist:

21
ai.c
View File

@ -1498,14 +1498,6 @@ void aiturn(lifeform_t *lf) {
if (who && !isdead(who) && !isunconscious(who) && cansee(lf, who)) {
int chance = 100; // chance that we ('lf') will attack 'who'
int reachpenalty;
// targets sleeping in a tent will probably be ignored
if (isresting(who)) {
object_t *restob;
restob = getrestob(who);
if (restob && (restob->type->id == OT_TENT)) {
chance = 5;
}
}
// will usually ignore targets who we can't reach
if (!canreach(lf, who, &reachpenalty)) {
if (!aigetrangedattack(lf, who, NULL, NULL)) { // no ranged attack?
@ -1515,7 +1507,18 @@ void aiturn(lifeform_t *lf) {
if (db) dblog(".oO { target %d (%s) is %d sizes out of reach. %d%% chance to ignore }",who->id, who->race->name,
reachpenalty, reachpenalty*47);
}
}
} else if (isresting(who)) {
// targets sleeping in a tent will probably be ignored
object_t *restob;
restob = getrestob(who);
if (restob) {
switch (restob->type->id) {
case OT_TENT: chance = 5; break;
case OT_MOTEL: chance = 0; break;
default: break;
}
}
}
if (pctchance(chance)) {
if (lfhasflagval(lf, F_HATESRACE, who->race->id, NA, NA, NULL) ||

View File

@ -917,7 +917,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
}
}
if (!isplayer(lf) && !isplayer(victim)) {
noise(lf->cell, lf, NC_OTHER, 3, "sounds of fighting.", NULL);
noise(lf->cell, lf, NC_OTHER, 3, "fighting.", NULL);
}
if (fatal) {
if (strstr(buf, "behead")) {

203
data.c
View File

@ -505,6 +505,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "cloth trousers");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of leather shoes");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "5 shurikens");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "manriki");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "3 smoke grenades");
// shuriken
// initial skills
@ -527,6 +528,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_RANGED, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL);
@ -800,7 +802,7 @@ void initjobs(void) {
}
void initobjects(void) {
//int ch;
flag_t *f;
int i,n;
// generate hidden name text
@ -1097,6 +1099,15 @@ void initobjects(void) {
addflag(lastmaterial->flags, F_HARDNESS, 3, NA, NA, NULL);
// object classes
addoc(OC_BUILDING, "Buildings", "Shops, etc.", '_', C_GREY, RR_RARE);
addocnoun(lastobjectclass, "building");
addocnoun(lastobjectclass, "shop");
addocnoun(lastobjectclass, "store");
addflag(lastobjectclass->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_SHOP, B_TRUE, NA, NA, NULL);
addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addoc(OC_DFEATURE, "Dungeon Features", "Doors, etc.", '\\', C_GREY, RR_RARE);
addoc(OC_FURNITURE, "Furniture", "Various kinds of mundane (or not so mundane) furnishings.", '\\', C_BROWN, RR_COMMON);
addocnoun(lastobjectclass, "furniture");
@ -1318,24 +1329,103 @@ void initobjects(void) {
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_DFEATURE, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, NA, RR_RARE, "");
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "_");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
// 10 random objects
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
// 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_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");
addflag(lastot->flags, F_SHOPMENU, 3, MA_QUIT, NA, "q:leave");
for (i = 0; i < 10; i++) {
f = addflag(lastot->flags, F_STARTOBCLASS, 100, OC_FOOD, NA, NULL);
addcondition(f, FC_NOCONDITION, 33);
addaltval(f, F_STARTOB, 100, NA, NA, "potion of rum");
}
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_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");
addflag(lastot->flags, F_SHOPMENU, 2, MA_QUIT, NA, "q:leave");
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_ARMOUR, NA, 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_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
for (i = 0; i < 10; i++) {
f = addflag(lastot->flags, F_STARTOBCLASS, 100, OC_BOOK, NA, NULL);
addcondition(f, FC_NOCONDITION, 33);
addaltval(f, F_STARTOBCLASS, 100, OC_SCROLL, NA, 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_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, NA, 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_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_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
for (i = 0; i < 10; i++) {
f = addflag(lastot->flags, F_STARTOBCLASS, 100, OC_TOOLS, NA, NULL);
addcondition(f, FC_NOCONDITION, 50);
addaltval(f, F_STARTOBCLASS, 100, OC_TECH, NA, 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_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, NA, 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_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, NA, 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_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");
addflag(lastot->flags, F_SHOPMENU, 2, MA_QUIT, NA, "q:leave");
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_WEAPON, NA, 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_CONTAINER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, 1, "a:speak to a deacon (earthly concerns)");
addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, 2, "b:speak to a priest (minor divine administration)");
addflag(lastot->flags, F_SHOPMENU, 2, MA_GOTOMENU, 3, "c:speak to the bishop (major divine matters)");
addflag(lastot->flags, F_SHOPMENU, 3, MA_QUIT, NA, "q:leave");
addflag(lastot->flags, F_SHOPMENU, 100, MA_GOTOMENU, SM_DETECTCURSE, "a:detect auras");
addflag(lastot->flags, F_SHOPMENU, 101, MA_GOTOMENU, SM_PURCHASEITEMS, "b:buy holy water");
addflag(lastot->flags, F_SHOPMENU, 102, MA_GOTOMENU, SM_DONATE, "c:donate money");
addflag(lastot->flags, F_SHOPMENU, 103, MA_GOTOMENU, 0, "q:finished");
addflag(lastot->flags, F_SHOPMENU, 200, MA_GOTOMENU, SM_ABSOLVE, "a:absolve sins");
addflag(lastot->flags, F_SHOPMENU, 201, MA_GOTOMENU, SM_BLESS, "b:bless items");
addflag(lastot->flags, F_SHOPMENU, 202, MA_GOTOMENU, 0, "q:finished");
addflag(lastot->flags, F_SHOPMENU, 300, MA_GOTOMENU, SM_MIRACLE, "a:pay for miracles");
addflag(lastot->flags, F_SHOPMENU, 301, MA_GOTOMENU, 0, "q:finished");
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOB, 100, OC_WEAPON, NA, "potion of holy water");
}
addot(OT_HOLYCIRCLE, "holy circle", "A consecrated area imbued with holy power.", MT_NOTHING, 0, OC_DFEATURE, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, "");
@ -1905,7 +1995,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EXPLODEONDAM, DT_FIRE, NA, NA, "2d4");
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_DUNGEON, 83, NA, NULL);
addot(OT_POT_RUM, "potion of rum", "Strong liqour which is sure to make you tipsy.", MT_GLASS, 1, OC_POTION, SZ_TINY);
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_DUNGEON, 83, NA, NULL);
addflag(lastot->flags, F_FLAMMABLE, 1, NA, NA, "medium fire");
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
@ -3419,6 +3509,8 @@ void initobjects(void) {
addflag(lastot->flags, F_STAMCOST, 5, NA, NA, NULL);
addot(OT_A_REPAIR, "repair equipment", "Repair damage done to your equipment.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_RESIZE, "resize armour", "Adjust the fit of a piece of armour or clothing.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_SHIELDBASH, "shield bash", "Attempt to stun your opponent by bashing them with your shield.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
@ -4626,9 +4718,11 @@ void initobjects(void) {
addflag(lastot->flags, F_DTVULN, DT_ACID, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
// armour objects
// armour - multipart
addot(OT_WETSUIT, "wetsuit", "Full-body rubber suit which provides good insulation from cold.", MT_RUBBER, 6, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESONMULTI, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
@ -4643,6 +4737,7 @@ void initobjects(void) {
// armour - body
addot(OT_CHEFJACKET, "set of chef whites", "A large double-breasted white jacket. Its thick cotton cloth is resistant to heat.", MT_CLOTH, 2, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
@ -4655,6 +4750,7 @@ void initobjects(void) {
addot(OT_COTTONSHIRT, "cotton shirt", "A comfortable white cotton shirt.", MT_CLOTH, 0.7, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
@ -4662,6 +4758,7 @@ void initobjects(void) {
addflag(lastot->flags, F_CRITPROTECTION, 33, NA, NA, NULL);
addot(OT_ARMOURDEMON, "demonskin vest", "Body armour created by flaying the flesh from a living demon, it retains its innate immunity to fire.", MT_FLESH, 7, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 5, NA, NA, NULL);
@ -4674,6 +4771,7 @@ void initobjects(void) {
addflag(lastot->flags, F_STARTBLESSED, B_CURSED, NA, NA, NULL);
addot(OT_ARMOURLEATHER, "leather armour", "Body armour created from soft leather.", MT_LEATHER, 10, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 10, 10, NULL);
@ -4683,6 +4781,7 @@ void initobjects(void) {
addot(OT_ARMOURRING, "suit of ring mail", "Body armour formed by a series of metallic rings sewn to a leather foundation.", MT_METAL, 15, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 6, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 20, 20, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 7, NA, NULL);
@ -4691,6 +4790,7 @@ void initobjects(void) {
addot(OT_ARMOURSCALE, "suit of scale armour", "Body armour consisting of many small scales attached to leather.", MT_METAL, 20, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 10, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 30, 30, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 9, NA, NULL);
@ -4698,6 +4798,7 @@ void initobjects(void) {
addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL);
addot(OT_ARMOURCHAIN, "suit of chainmail", "Heavy body armour consisting of tightly meshed metal rings.", MT_METAL, 25, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 15, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 40, 40, NULL);
@ -4707,6 +4808,7 @@ void initobjects(void) {
addot(OT_ARMOURSPLINT, "suit of splint mail", "Heavy armour, consisting of strips of metal attached to a leather backing.", MT_METAL, 35, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 20, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 50, 50, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 11, NA, NULL);
@ -4715,6 +4817,7 @@ void initobjects(void) {
addot(OT_ARMOURPLATE, "suit of plate mail", "Heavy armour with embedded metal plates.", MT_METAL, 40, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_RARE, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 25, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 60, 60, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 13, NA, NULL);
@ -4723,6 +4826,7 @@ void initobjects(void) {
addot(OT_FLAKJACKET, "flak jacket", "Heavy metal body armour. Designed to stop a bullet, but ineffective against melee attacks.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 10, 10, NULL);
@ -4732,6 +4836,7 @@ void initobjects(void) {
addot(OT_OVERALLS, "pair of overalls", "Well-made, brightly coloured workman overalls.", MT_CLOTH, 1, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_AGI, 7, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
@ -4739,6 +4844,7 @@ void initobjects(void) {
addot(OT_SILKSHIRT, "silk shirt", "A lightweight, comfortable white silk shirt.", MT_SILK, 0.5, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
@ -4746,12 +4852,14 @@ void initobjects(void) {
addflag(lastot->flags, F_CRITPROTECTION, 50, NA, NA, NULL);
addot(OT_ROBE, "robe", "A plain robe.", MT_CLOTH, 4, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 70, NA, NA, NULL);
addot(OT_VELVETROBE, "velvet robe", "A luxurious velvet robe.", MT_CLOTH, 4, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
@ -4762,6 +4870,7 @@ void initobjects(void) {
addot(OT_CLOAK, "cloak", "A standard leather cloak.", MT_LEATHER, 4, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
@ -4769,6 +4878,7 @@ void initobjects(void) {
addflag(lastot->flags, F_HELPSREST, 5, NA, NA, NULL);
addot(OT_APRON, "apron", "A sturdy rubber apron, designed to protect against stains.", MT_RUBBER, 2, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
@ -4782,6 +4892,7 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
// armour - legs
addot(OT_CLOTHTROUSERS, "pair of cloth trousers", "A rough pair of cloth trousers.", MT_CLOTH, 2, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
@ -4790,6 +4901,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ATTREQ, A_AGI, 3, NA, NULL);
addflag(lastot->flags, F_CRITPROTECTION, 60, NA, NA, NULL);
addot(OT_RIDINGTROUSERS, "pair of riding trousers", "A fitted pair of leather trousers.", MT_LEATHER, 2, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
@ -4800,6 +4912,7 @@ void initobjects(void) {
addot(OT_COMBATPANTS, "pair of combat pants", "An lightly-armoured pair of camoflauged trousers.", MT_CLOTH, 2, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 3, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_AGI, 3, NA, NULL);
@ -4807,6 +4920,7 @@ void initobjects(void) {
addot(OT_GREAVES, "set of greaves", "A set of heavy metal greaves.", MT_METAL, 4, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 25, 25, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 15, 15, NULL);
@ -4816,6 +4930,7 @@ void initobjects(void) {
// armour - feet
addot(OT_SANDALS, "pair of sandals", "Comfortable pair of open leather sandals.", MT_LEATHER, 1, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
@ -4824,6 +4939,7 @@ void initobjects(void) {
addot(OT_SHOESLEATHER, "pair of leather shoes", "Cheap and rather uncomfortable leather shoes.", MT_LEATHER, 2, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
@ -4831,6 +4947,7 @@ void initobjects(void) {
addflag(lastot->flags, F_CRITPROTECTION, 85, NA, NA, NULL);
addot(OT_BOOTSRUBBER, "pair of rubber boots", "A waterproof (but somewhat cumbersome) pair of rubber boots.", MT_RUBBER, 6, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 0, 5, NULL);
@ -4841,6 +4958,7 @@ void initobjects(void) {
addot(OT_BOOTSSPIKED, "pair of spiked boots", "A plain pair of leather boots with spikes on the bottom.", MT_LEATHER, 3, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_STABILITY, NA, NA, NULL);
@ -4849,6 +4967,7 @@ void initobjects(void) {
addot(OT_BOOTSLEATHER, "pair of leather boots", "A stout pair of leather boots.", MT_LEATHER, 4, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
@ -4857,6 +4976,7 @@ void initobjects(void) {
addot(OT_BOOTSMETAL, "pair of metal boots", "A strong pair of metal boots.", MT_METAL, 5, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_RARE, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
@ -4866,6 +4986,7 @@ void initobjects(void) {
addot(OT_GLOVESCLOTH, "pair of cloth gloves", "A pair of soft cloth gloves.", MT_CLOTH, 0.15, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
@ -4874,6 +4995,7 @@ void initobjects(void) {
addot(OT_GLOVESLEATHER, "pair of leather gloves", "A pair of coarse leather gloves.", MT_LEATHER, 0.25, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_AGI, 3, NA, NULL);
@ -4881,6 +5003,7 @@ void initobjects(void) {
addot(OT_GAUNTLETS, "pair of gauntlets", "A durable pair of metal gauntlets.", MT_METAL, 2, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 10, 5, NULL);
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
@ -4903,13 +5026,16 @@ void initobjects(void) {
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_BALACLAVA, "balaclava", "A form of cloth headgear that covers the whole head, exposing only the eyes.", MT_CLOTH, 1, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_ANONYMOUS, NA, NA, NULL);
addot(OT_CAP, "cap", "Close-fitting headwear with a short shade visor at the front.", MT_CLOTH, 1, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
@ -4940,6 +5066,7 @@ void initobjects(void) {
addot(OT_HELMFOOTBALL, "football helmet", "A metal helmet with a grill in front of the face.", MT_METAL, 1, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACYMOD, -10, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
@ -5720,6 +5847,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 10, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_WIZARDSTAFF2, "enchanter staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, ")");
@ -5732,6 +5860,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 1, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 12, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_WIZARDSTAFF3, "sorcerer staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, ")");
@ -5756,6 +5885,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 3, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 16, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_WIZARDSTAFF5, "warlock staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, ")");
@ -5768,6 +5898,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 4, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 17, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_WIZARDSTAFF6, "archmagi staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, ")");
@ -5780,6 +5911,7 @@ void initobjects(void) {
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 5, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 18, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
// clubs (bashing)
addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_WOOD, 8, OC_WEAPON, SZ_MEDIUM);
@ -6305,9 +6437,6 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTSKILL, SK_LISTEN, PR_NOVICE, NA, NULL);
// penalties
addflag(lastrace->flags, F_NOARMOURON, BP_EARS, NA, NA, NULL);
addflag(lastrace->flags, F_NOARMOURON, BP_LEGS, NA, NA, NULL);
addflag(lastrace->flags, F_NOARMOURON, BP_HANDS, NA, NA, NULL);
addflag(lastrace->flags, F_NOARMOURON, BP_FEET, NA, NA, NULL);
addflag(lastrace->flags, F_VISRANGEMOD, -2, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_SONIC, NA, NA, NULL);
addflag(lastrace->flags, F_VEGETARIAN, B_TRUE, NA, NA, NULL);
@ -7715,14 +7844,11 @@ void initrace(void) {
addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "pincers");
addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw");
addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw");
addflag(lastrace->flags, F_NOARMOURON, BP_RIGHTFINGER, NA, NA, NULL);
addflag(lastrace->flags, F_NOARMOURON, BP_LEFTFINGER, NA, NA, NULL);
addflag(lastrace->flags, F_NOARMOURON, BP_HANDS, NA, NA, NULL);
addflag(lastrace->flags, F_NOARMOURON, BP_FEET, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addrace(R_MERLOCH, "merloch", 250, 'm', C_ORANGE, MT_FLESH, RC_AQUATIC, "Merlochs are bipedal, fishlike beings. Equally at home in the water or on land, they use their sonic scream to disable foes.");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 15, NA, NA, NULL); // high armour
@ -7732,7 +7858,7 @@ void initrace(void) {
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, NA, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_WAIST, NA, NA, NULL);
@ -7945,12 +8071,12 @@ void initrace(void) {
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, "");
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+2");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 1, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SONICBOLT, 3, 3, "pw:5;dam:1d6;");
addflag(lastrace->flags, F_CANWILL, OT_A_SONICBOLT, 3, 3, "pw:5;dam:1d4;");
addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_SHOULDERS, NA, NA, NULL);
@ -8188,6 +8314,7 @@ void initrace(void) {
addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw");
addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL);
addflag(lastrace->flags, F_TAMABLE, 30, NA, NA, NULL);
addrace(R_DOGBLINK, "blink dog", 35, 'd', C_YELLOW, MT_FLESH, RC_ANIMAL, "Magical canines who can teleport small distances at will.");
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
@ -8216,6 +8343,7 @@ void initrace(void) {
addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws");
addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw");
addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw");
addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL);
addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL);
addrace(R_DOGDEATH, "death hound", 40, 'd', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Possessed evil canines who thrive on death and destruction.");
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
@ -8247,6 +8375,7 @@ void initrace(void) {
addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws");
addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw");
addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw");
addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL);
addflag(lastrace->flags, F_MORALE, 15, NA, NA, NULL);
addrace(R_DOGWAR, "war hound", 40, 'd', C_BROWN, MT_FLESH, RC_ANIMAL, "Canines bred for war.");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -8273,6 +8402,7 @@ void initrace(void) {
addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws");
addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw");
addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw");
addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_TAMABLE, 40, NA, NA, NULL);
@ -8783,6 +8913,7 @@ void initrace(void) {
addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws");
addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw");
addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw");
addflag(lastrace->flags, F_HASSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL);
addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_TAMABLE, 30, NA, NA, NULL);
addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL, "Highly intelligent members of the canine family.");
@ -8808,6 +8939,7 @@ void initrace(void) {
addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws");
addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw");
addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw");
addflag(lastrace->flags, F_HASSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL);
addflag(lastrace->flags, F_MORALE, 7, NA, NA, NULL);
// end animals
@ -9599,7 +9731,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
// special monsters
addrace(R_GASCLOUD, "cloud of gas", 0.1, '}', C_GREY, MT_GAS, RC_OTHER, "A large cloud of gas which seems to move with a life of its own...");
addrace(R_GASCLOUD, "cloud of gas", 0.1, 'y', C_GREY, MT_GAS, RC_OTHER, "A large cloud of gas which seems to move with a life of its own...");
addflag(lastrace->flags, F_MOVESPEED, SP_ULTRAFAST, NA, NA, "");
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
@ -9812,6 +9944,7 @@ void initskills(void) {
addskilldesc(SK_METALWORK, PR_BEGINNER, "^gYou can repair metal items up to 50% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_ADEPT, "^gYou can repair metal items up to 60% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_SKILLED, "^gYou can repair metal items up to 70% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_SKILLED, "^gYou can re-size metal armour (at the expense of durability).^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_EXPERT, "^gYou can repair metal items up to 85% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_MASTER, "^gYou can fully repair metal items.^n", B_FALSE);
addskill(SK_RANGED, "Ranged Weapons", "Your ability to aim a ranged weapon like a bow or gun.", 50);
@ -9830,6 +9963,7 @@ void initskills(void) {
addskilldesc(SK_SEWING, PR_BEGINNER, "^gYou can repair cloth items up to 50% condition^n", B_FALSE);
addskilldesc(SK_SEWING, PR_ADEPT, "^gYou can repair cloth items up to 60% condition^n", B_FALSE);
addskilldesc(SK_SEWING, PR_SKILLED, "^gYou can repair cloth items up to 70% condition^n", B_FALSE);
addskilldesc(SK_SEWING, PR_SKILLED, "^gYou can re-size cloth armour (at the expense of durability).^n", B_FALSE);
addskilldesc(SK_SEWING, PR_EXPERT, "^gYou can repair cloth items up to 85% condition^n", B_FALSE);
addskilldesc(SK_SEWING, PR_MASTER, "^gYou can fully repair cloth items.^n", B_FALSE);
addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block attacks.", 50);
@ -10097,6 +10231,11 @@ void initskills(void) {
}
}
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");
}
void sortcommands(void) {
command_t *c;
int donesomething = B_TRUE;

1
data.h
View File

@ -6,4 +6,5 @@ void initjobs(void);
void initobjects(void);
void initrace(void);
void initskills(void);
void make_basic_shop(flagpile_t *fp);
void sortcommands(void);

Binary file not shown.

66
defs.h
View File

@ -724,6 +724,7 @@ enum OBCLASS {
OC_ABILITY,
OC_ARMOUR,
OC_BOOK,
OC_BUILDING,
OC_CORPSE,
OC_DFEATURE,
OC_EFFECT,
@ -1019,8 +1020,18 @@ enum OBTYPE {
OT_HOLEINROOF,
OT_STAIRSDOWN,
OT_STAIRSUP,
OT_VENDINGMACHINE,
OT_PORTAL,
// buildings
OT_MOTEL,
OT_SHOPARMOUR,
OT_SHOPBOOK,
OT_SHOPFOOD,
OT_SHOPGENERAL,
OT_SHOPHARDWARE,
OT_SHOPPOTION,
OT_SHOPRING,
OT_SHOPWEAPON,
OT_TEMPLE,
// terrain
OT_WATERDEEP,
// traps
@ -1372,6 +1383,7 @@ enum OBTYPE {
OT_A_PRAY,
OT_A_RAGE,
OT_A_REPAIR,
OT_A_RESIZE,
OT_A_SHIELDBASH,
OT_A_SONICBOLT,
OT_A_SPRINT,
@ -2017,6 +2029,19 @@ enum FLAG {
// v2 = sc_dodge difficulty
F_OBJECTTRAP, // this trap can go onto an object (door, chest, etc)
F_SMELLY, // lfs with enhacned scent can smell this object
// shops
F_BANNEDLF, // lfid v0 is not allowed to enter this shop
F_SHOP, // this object is a shop
F_SHOPMENU, // defines a menu for interaction with a shop
// v0 = (menuid*100) + itemorder
// ie. menu0 would have 0, 1, 2, 3
// menu1 would have 100, 101, 102, 103
// etc.
// v1 = enum MENUACTION
// v2 = value for action (optional)
// text = "x:whatever" (x is letter to press)
// doors
F_DOOR, // this object is a door - ie. can open it
// v0 and v1 are like F_IMPASSABLE
@ -2138,6 +2163,9 @@ enum FLAG {
// ob appearance flags
F_SHINY,
// armour flags
F_MULTISIZE, // this object comes in varying sizes - calculate and
// assign a random f_armoursize on creation.
F_ARMOURSIZE, // v0 = sz_xxx, can be "medium", "human" or "large".
F_ARMOURRATING, // val0 * 2 = pct of damage reduced
F_SHIELD, // this is a shield - use special bodyhitchance code
F_OBHP, // val0 = object health, val1 = object maxhealth
@ -2149,6 +2177,7 @@ enum FLAG {
// misc flags
F_LINKOB, // val0 = linked object id
F_LINKRACE, // val0 = linked race id
F_LINKGOD, // val0 = linked god race id
// scroll flags
F_LINKSPELL, // val0 = spell this scroll will cast when read
// v1 = spell power
@ -2202,6 +2231,11 @@ enum FLAG {
F_DONEDARKMSG, // tells the game not to say 'it is very dark here'
F_DONELISTEN, // supress further 'you hear xx' messages this turn.
// lifeform flags / lf flags / monster flags
F_RESTINGINMOTEL, // sounds will not wake up this lf. monster won't
// see them.
// v0 = max time allowed to rest before checkout
// v1 = total time rested
// text = obid of hotel
F_ALIGNMENT, // v0 = al_good, al_neutral, al_evil. default neutral.
F_PIETY, // for god lifeforms - tracks player's piety with them
F_MOVED, // lf purposely moved in their last turn.
@ -2507,6 +2541,7 @@ enum FLAG {
F_MAGICARMOUR,// armour is magically boosted. f->text is the description
// ie 'magic armour', 'force field'
// v0 is power left.
F_ANONYMOUS, // when worn on eyes, shopkeepers can't ban you
F_ASLEEP, // lf is asleep.
// v1 is enum sleeptype st_xxx
// if v2 is set, means we are sleeping on
@ -2550,7 +2585,7 @@ enum FLAG {
F_DETECTOBS, // autodetect nearby obs of type v1 in orthog dist v0
// v1 = NA means everything.
F_DISEASEIMMUNE, // lf can't be diseased
F_DRUNK, // v1 is drunknness - 1-5.
F_DRUNK, // v0 is drunknness - 1-5.
F_ENHANCESEARCH, // gives v0 bonus on search checks.
F_ENHANCESMELL, // can 'see' scents with v0 range.
F_EXTRADAM, // do 'text' extra damage of damtype v0 when you hit
@ -2858,6 +2893,7 @@ enum ERROR {
E_AVOIDOB,
E_FROZEN,
E_TOOBIG,
E_TOOSMALL,
E_NOTREADY,
E_BLIND,
E_GRABBEDBY,
@ -3493,6 +3529,32 @@ typedef struct choice_s {
} choice_t;
enum MENUACTION {
MA_NONE = 0,
MA_GOTOMENU,
MA_QUIT,
};
// special shop menus - must all be < 0
enum SHOPMENU {
// shops
SM_PURCHASEITEMS = -1,
SM_DONATE = -2,
// temples
SM_ABSOLVE = -3,
SM_BLESS = -4,
SM_DETECTCURSE = -5,
SM_MIRACLE = -6,
// motels
SM_REST = -7,
};
enum SHOPRETURN {
SR_BACK,
SR_CONTINUE,
SR_QUIT
};
#define MAXPROMPTQUESTIONS 5
typedef struct prompt_s {
char *q[MAXPROMPTQUESTIONS];

View File

@ -33,12 +33,15 @@ s = snake
S = spider
h = humanoid
H = large humanoid
U = unearthly/demonic/horrific creature
U = unearthly/horrific creature
w = worm
V = vampire
y/Y = air related creatures like clouds of gas, air elemental
z = lizard-like creature
Z = undead
& = demon
---
C

27
flag.c
View File

@ -347,14 +347,24 @@ void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) {
// gone past the requrested id's number - ie. it's not there.
if (f->id > id) break;
if (f->id == id) {
addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
flag_t *newf;
newf = addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
f->lifetime, f->known, -1);
newf->condition = f->condition;
newf->chance = f->chance;
if (f->altval) {
addaltval(newf, f->altval->id,
f->altval->val[0],
f->altval->val[1],
f->altval->val[2],
f->altval->text);
}
}
}
}
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {
flag_t *f;
flag_t *f,*newf;
for (f = src->first ; f ; f = f->next) {
// omit certain flags
if (lifetime == FROMBRAND) {
@ -364,8 +374,17 @@ void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime) {
continue;
}
}
addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
newf = addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
(lifetime == NA) ? f->lifetime : lifetime, f->known, -1);
newf->condition = f->condition;
newf->chance = f->chance;
if (f->altval) {
addaltval(newf, f->altval->id,
f->altval->val[0],
f->altval->val[1],
f->altval->val[2],
f->altval->text);
}
}
}
@ -977,7 +996,7 @@ void timeeffectsflag(flag_t *f, int howlong) {
howlong *= multiplier;
}
} else if ((f->id == F_INJURY) && hasflag(f->pile, F_ASLEEP)) {
howlong *= 3;
howlong *= 2;
}

402
god.c
View File

@ -417,6 +417,13 @@ enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness) {
return PL_INDIFFERENT;
}
lifeform_t *getrandomgod(void) {
if (ngodlfs == 0) {
return NULL;
}
return godlf[rnd(0,ngodlfs-1)];
}
// get a random god which player has prayed to
lifeform_t *getrandomprayedgod(void) {
int i,nposs = 0;
@ -468,220 +475,227 @@ lifeform_t *godappears(enum RACE rid, cell_t *where) {
}
// maybe get a gift
int godgiftmaybe(enum RACE rid) {
int godgiftmaybe(enum RACE rid, int fromtemple) {
lifeform_t *god;
int piety,gotgift = B_FALSE;
int chance;
god = findgod(rid);
piety = getpiety(rid);
if (piety >= 200) {
int chance;
if (fromtemple) {
chance = 100;
} else if (piety >= 200) {
// ie. 200 -> 4%
// ie. 500 -> 10%
chance = piety / 50;
if (pctchance(chance)) { // if this is true, you get a gift.
char obtogive[BUFLEN];
int rollagain = B_TRUE;
gotgift = B_TRUE;
} else {
chance = 0;
}
godsay(god->race->id, B_TRUE, "I bestow a gift upon you, mortal!");
strcpy(obtogive, "");
switch (god->race->id) {
case R_GODPURITY:
while (rollagain) {
int n,nposs,i;
object_t *poss[MAXCANDIDATES],*o;
flag_t *f;
object_t *wep;
rollagain = B_FALSE;
switch (rnd(1,6)) {
case 1:
snprintf(obtogive, BUFLEN, "2-4 blessed potions of water");
break;
case 2:
snprintf(obtogive, BUFLEN, "blessed great weapon");
break;
case 3:
snprintf(obtogive, BUFLEN, "wand of turn undead");
break;
case 4: // bless your weapon
wep = getweapon(player);
if (wep && !isblessed(wep)) {
blessob(wep);
} else {
rollagain = B_TRUE;
if (pctchance(chance)) { // if this is true, you get a gift.
char obtogive[BUFLEN];
int rollagain = B_TRUE;
gotgift = B_TRUE;
godsay(god->race->id, B_TRUE, "I bestow a gift upon you, mortal!");
strcpy(obtogive, "");
switch (god->race->id) {
case R_GODPURITY:
while (rollagain) {
int n,nposs,i;
object_t *poss[MAXCANDIDATES],*o;
flag_t *f;
object_t *wep;
rollagain = B_FALSE;
switch (rnd(1,6)) {
case 1:
snprintf(obtogive, BUFLEN, "2-4 blessed potions of water");
break;
case 2:
snprintf(obtogive, BUFLEN, "blessed great weapon");
break;
case 3:
snprintf(obtogive, BUFLEN, "wand of turn undead");
break;
case 4: // bless your weapon
wep = getweapon(player);
if (wep && !isblessed(wep)) {
blessob(wep);
} else {
rollagain = B_TRUE;
}
break;
case 5: // holy aura
if (lfhasflag(player, F_HOLYAURA)) {
rollagain = B_TRUE;
} else {
f = addtempflag(player->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
f = addtempflag(player->flags, F_HOLYAURA, NA, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
case 6: // bless 1-3 obs
nposs = 0;
n = rnd(1,3); // num to bless
for (o = player->pack->first ; o ; o = o->next) {
if (!isblessed(o)) {
poss[nposs++] = o;
}
break;
case 5: // holy aura
if (lfhasflag(player, F_HOLYAURA)) {
rollagain = B_TRUE;
} else {
f = addtempflag(player->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
f = addtempflag(player->flags, F_HOLYAURA, NA, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
case 6: // bless 1-3 obs
nposs = 0;
n = rnd(1,3); // num to bless
for (o = player->pack->first ; o ; o = o->next) {
if (!isblessed(o)) {
poss[nposs++] = o;
}
}
if (nposs < n) n = nposs;
for (i = 0; i < n; i++) {
}
if (nposs < n) n = nposs;
for (i = 0; i < n; i++) {
o = poss[rnd(0,nposs-1)];
while (isblessed(o)) {
o = poss[rnd(0,nposs-1)];
while (isblessed(o)) {
o = poss[rnd(0,nposs-1)];
}
blessob(o);
}
break;
}
blessob(o);
}
break;
}
break;
case R_GODDEATH:
while (rollagain) {
flag_t *f;
object_t *wep;
rollagain = B_FALSE;
switch (rnd(1,6)) {
case 1:
if (lfhasflag(player, F_SEEINDARK)) {
}
break;
case R_GODDEATH:
while (rollagain) {
flag_t *f;
object_t *wep;
rollagain = B_FALSE;
switch (rnd(1,6)) {
case 1:
if (lfhasflag(player, F_SEEINDARK)) {
rollagain = B_TRUE;
} else {
msg("\"Henceforth the night shall be your ally!\"");
f = addtempflag(player->flags, F_SEEINDARK, 4, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
case 2:
snprintf(obtogive, BUFLEN, "3-5 cursed potions of water");
break;
case 3:
snprintf(obtogive, BUFLEN, "cursed branded weapon");
break;
case 4: // poison your weapon
wep = getweapon(player);
if (wep && canbepoisoned(wep->type->id)) {
applyobmod(wep, findobmod(OM_POISONED));
msg("A layer of venom covers your weapon!");
} else {
rollagain = B_TRUE;
}
break;
case 5: // resistant/immune to necrotic
if (lfhasflagval(player, F_DTRESIST, DT_NECROTIC, NA, NA, NULL)) {
if (lfhasflagval(player, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL)) {
rollagain = B_TRUE;
} else {
msg("\"Henceforth the night shall be your ally!\"");
f = addtempflag(player->flags, F_SEEINDARK, 4, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
case 2:
snprintf(obtogive, BUFLEN, "3-5 cursed potions of water");
break;
case 3:
snprintf(obtogive, BUFLEN, "cursed branded weapon");
break;
case 4: // poison your weapon
wep = getweapon(player);
if (wep && canbepoisoned(wep->type->id)) {
applyobmod(wep, findobmod(OM_POISONED));
msg("A layer of venom covers your weapon!");
} else {
rollagain = B_TRUE;
}
break;
case 5: // resistant/immune to necrotic
if (lfhasflagval(player, F_DTRESIST, DT_NECROTIC, NA, NA, NULL)) {
if (lfhasflagval(player, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL)) {
rollagain = B_TRUE;
} else {
f = addtempflag(player->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
} else {
f = addtempflag(player->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
case 6:
msg("\"Go forth and kill in my name!\"");
setrace(player, R_VAMPIRE, B_TRUE); // ie. don't set origrace!
break;
}
}
break;
case R_GODTHIEVES:
while (rollagain) {
rollagain = B_FALSE;
switch (rnd(1,7)) {
case 1:
if (getskill(player, SK_TECHUSAGE) >= gettechlevel(OT_LOCKHACKER)) {
snprintf(obtogive, BUFLEN, "lock hacker");
} else {
snprintf(obtogive, BUFLEN, "3-6 blessed lockpicks");
}
break;
case 2:
if (onein(6)) {
snprintf(obtogive, BUFLEN, "large bag of holding");
} else {
snprintf(obtogive, BUFLEN, "bag of holding");
}
break;
case 3:
snprintf(obtogive, BUFLEN, "safebox");
break;
case 4:
snprintf(obtogive, BUFLEN, "wand of opening");
break;
case 5:
snprintf(obtogive, BUFLEN, "wand of invisibility");
break;
case 6:
snprintf(obtogive, BUFLEN, "3-6 potions of invisibility");
break;
case 7:
snprintf(obtogive, BUFLEN, "leather boots of stealth");
break;
}
}
break;
case R_GODMERCY:
while (rollagain) {
flag_t *f;
rollagain = B_FALSE;
switch (rnd(1,4)) {
case 1:
snprintf(obtogive, BUFLEN, "3 vials of ambrosia");
break;
case 2:
snprintf(obtogive, BUFLEN, "ring of regeneration");
break;
case 3:
snprintf(obtogive, BUFLEN, "ring of miracles");
break;
case 4: // immune to disease / poison
if (lfhasflag(player, F_DISEASEIMMUNE)) {
if (lfhasflagval(player, F_DTIMMUNE, DT_POISON, NA, NA, NULL)) {
rollagain = B_TRUE;
} else {
f = addtempflag(player->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
} else {
f = addtempflag(player->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
}
}
break;
default:
break;
} // end switch
if (strlen(obtogive)) {
object_t *o;
o = addob(player->cell->obpile, obtogive);
if (o) {
char buf[BUFLEN];
addflag(o->flags, F_GODGIFT, god->race->id, NA, NA, NULL);
if (haslos(player, player->cell)) {
getobname(o, buf, o->amt);
msg("%s appear%s!", buf, (o->amt == 1) ? "s" : "");
} else {
msg("You hear something hitting the ground.");
} else {
f = addtempflag(player->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
case 6:
msg("\"Go forth and kill in my name!\"");
setrace(player, R_VAMPIRE, B_TRUE); // ie. don't set origrace!
break;
}
}
}
break;
case R_GODTHIEVES:
while (rollagain) {
rollagain = B_FALSE;
switch (rnd(1,7)) {
case 1:
if (getskill(player, SK_TECHUSAGE) >= gettechlevel(OT_LOCKHACKER)) {
snprintf(obtogive, BUFLEN, "lock hacker");
} else {
snprintf(obtogive, BUFLEN, "3-6 blessed lockpicks");
}
break;
case 2:
if (onein(6)) {
snprintf(obtogive, BUFLEN, "large bag of holding");
} else {
snprintf(obtogive, BUFLEN, "bag of holding");
}
break;
case 3:
snprintf(obtogive, BUFLEN, "safebox");
break;
case 4:
snprintf(obtogive, BUFLEN, "wand of opening");
break;
case 5:
snprintf(obtogive, BUFLEN, "wand of invisibility");
break;
case 6:
snprintf(obtogive, BUFLEN, "3-6 potions of invisibility");
break;
case 7:
snprintf(obtogive, BUFLEN, "leather boots of stealth");
break;
}
}
break;
case R_GODMERCY:
while (rollagain) {
flag_t *f;
rollagain = B_FALSE;
switch (rnd(1,4)) {
case 1:
snprintf(obtogive, BUFLEN, "3 vials of ambrosia");
break;
case 2:
snprintf(obtogive, BUFLEN, "ring of regeneration");
break;
case 3:
snprintf(obtogive, BUFLEN, "ring of miracles");
break;
case 4: // immune to disease / poison
if (lfhasflag(player, F_DISEASEIMMUNE)) {
if (lfhasflagval(player, F_DTIMMUNE, DT_POISON, NA, NA, NULL)) {
rollagain = B_TRUE;
} else {
f = addtempflag(player->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
} else {
f = addtempflag(player->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL, FROMGODGIFT);
f->obfrom = god->race->id;
}
break;
}
}
break;
default:
break;
} // end switch
// since you got a gift, lower piety a little.
//setpiety(rid, 101);
if (strlen(obtogive)) {
object_t *o;
o = addob(player->cell->obpile, obtogive);
if (o) {
char buf[BUFLEN];
addflag(o->flags, F_GODGIFT, god->race->id, NA, NA, NULL);
if (haslos(player, player->cell)) {
getobname(o, buf, o->amt);
msg("%s appear%s!", buf, (o->amt == 1) ? "s" : "");
} else {
msg("You hear something hitting the ground.");
}
}
}
// since you got a gift, lower piety a little.
//setpiety(rid, 101);
if (!fromtemple) {
modpiety(rid, -50);
} // end if (pctchance enough to get a gift)
} // end if (piety > 200)
}
} // end if (pctchance enough to get a gift)
return gotgift;
}
@ -748,7 +762,7 @@ void pleasegod(enum RACE rid, int amt) {
msg("You feel like %s approves of your actions.", lfname);
break;
}
godgiftmaybe(rid);
godgiftmaybe(rid, B_FALSE);
}
}
@ -949,7 +963,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
}
if (!godgiftmaybe(god->race->id)) {
if (!godgiftmaybe(god->race->id, B_FALSE)) {
// if you didn't get a gift, lower piety for this god
modpiety(god->race->id, -PIETYPRAYLOSS);
}

3
god.h
View File

@ -6,9 +6,10 @@ void dooffer(void);
lifeform_t *findgod(enum RACE rid);
int getpiety(enum RACE rid);
enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness);
lifeform_t *getrandomgod(void);
lifeform_t *getrandomprayedgod(void);
lifeform_t *godappears(enum RACE rid, cell_t *where);
int godgiftmaybe(enum RACE rid);
int godgiftmaybe(enum RACE rid, int fromtemple);
int godisangry(enum RACE rid);
void godsay(enum RACE rid, int says, char *format, ...);
void modpiety(enum RACE rid, int amt);

242
io.c
View File

@ -21,6 +21,7 @@
#include "objects.h"
#include "text.h"
#include "save.h"
#include "shops.h"
#include "spell.h"
WINDOW *mainwin;
@ -1211,9 +1212,13 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
if (f->val[1] == ST_MEDITATING) meditating = B_TRUE;
restob = getrestob(lf);
if (restob) {
char restobname[BUFLEN];
getobname(restob, restobname, 1);
msg("You start %s (in your %s)...",meditating ? "meditating" : "resting", noprefix(restobname));
if (restob->type->id == OT_MOTEL) {
msg("You start %s (in your motel room)...",meditating ? "meditating" : "resting");
} else {
char restobname[BUFLEN];
getobname(restob, restobname, 1);
msg("You start %s (in your %s)...",meditating ? "meditating" : "resting", noprefix(restobname));
}
} else {
msg("You start %s (on the ground)...", meditating ? "meditating" : "resting" );
}
@ -1567,7 +1572,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
}
break;
case F_NONCORPOREAL:
msg("%s%s body becomes transparent!",lfname, getpossessive(lfname));
msg("%s%s body becomes insubstantial!",lfname, getpossessive(lfname));
donesomething = B_TRUE;
break;
case F_PAIN:
@ -2758,11 +2763,10 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int forpickup, int
}
if (o) {
// make sure count is okay...
if (count && *count > o->amt) {
*count = o->amt;
}
if (count && (*count == ALL)) {
*count = o->amt;
if (count) {
if ((*count > o->amt) || (*count == ALL) || (*count == 0)) {
*count = o->amt;
}
}
// display game windows again
clearmsg();
@ -3550,7 +3554,8 @@ void docomms(lifeform_t *lf) {
}
}
if (isadjacent(lf->cell, player->cell)) {
// if you are allies, use 'trade items' instead
if (isadjacent(lf->cell, player->cell) && !areallies(player,lf)) {
addchoice(&prompt, 'd', "(donate an item)", NULL, NULL, NULL);
}
@ -4040,110 +4045,6 @@ void doeat(obpile_t *op) {
}
}
void dovendingmachine(lifeform_t *lf, object_t *vm) {
int y;
int done;
char ch;
char choices[BUFLEN];
char buf[BUFLEN];
char buf2[BUFLEN];
char toptext[BUFLEN];
object_t *o;
strcpy(toptext, "");
// assign letters to objects
ch = 'a';
for (o = vm->contents->first ; o ; o = o->next) {
o->letter = ch;
if (++ch > 'z') ch = 'A';
}
// list objects for sale and ask for input
done = B_FALSE;
while (!done) {
cls();
mvwprintw(mainwin, 0, 0, toptext);
y = 2;
centre(mainwin,C_WHITE, y, "VENDING MACINE");
y += 2;
// list objects for sale
for (o = vm->contents->first ; o ; o = o->next) {
char obname[BUFLEN];
// get the name of the object
getobname(o, obname, o->amt);
snprintf(buf, BUFLEN, "%c - %s", o->letter, obname);
snprintf(buf2, BUFLEN, "%-60s$%d",buf,getobvalue(o));
mvwprintw(mainwin, y, 0, "%s", buf2);
y++;
}
strcpy(choices, "");
y++;
mvwprintw(mainwin, y, 0, "You have $%d.", countmoney(player->pack));
y++;
y++;
// ask what to do
mvwprintw(mainwin, y, 0, "What will you buy (ESC to exit)? ");
ch = getch();
if (ch == 27) {
done = B_TRUE;
} else {
// try to find that object...
o = hasobletter(vm->contents, ch);
if (o) {
// do you have enough money?
if (countmoney(player->pack) >= getobvalue(o)) {
object_t *gold;
// if so, buy it
// lose money (do this first to avoid potential weight issues)
gold = hasob(player->pack, OT_GOLD);
if (gold) {
char obname[BUFLEN];
char answer;
// confirm
getobname(o, obname, o->amt);
snprintf(buf, BUFLEN, "Buy %s for $%d?",obname, getobvalue(o));
answer = askchar(buf, "yn","n", B_TRUE, B_FALSE);
if (answer == 'y') {
int shopamt;
givemoney(player, NULL, getobvalue(o));
// clear o->letter
o->letter = '\0';
// give object
shopamt = o->amt; // avoid "purchased: 2 apples" when you only bought 1 but were holding 1
o = moveob(o, player->pack, ALL);
getobname(o, obname, shopamt);
snprintf(toptext, BUFLEN, "Purchased: %c - %s", o->letter, obname);
} else {
// cancelled
strcpy(toptext, "");
}
} else {
// error
snprintf(toptext, BUFLEN,"You don't seem to have any gold...");
}
} else {
snprintf(toptext, BUFLEN, "You cannot afford that!");
}
} else {
snprintf(toptext, BUFLEN, "No such item.");
} // end if o
} // end if ch
} // end while not done
restoregamewindows();
}
int dowear(obpile_t *op) {
object_t *o;
int rv;
@ -4886,7 +4787,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
(f->val[0] < 0) ? "lower" : "raise", abs(f->val[0]));
strncat(retbuf, buf, HUGEBUFLEN);
}
f = hasflag(o->flags, F_SCARY);
if (f) {
sprintf(buf, "@It may unnerve others when worn.\n");
@ -4962,6 +4862,27 @@ char *makedesc_ob(object_t *o, char *retbuf) {
strncat(retbuf, "\n", HUGEBUFLEN);
}
f = hasflag(o->flags, F_ARMOURSIZE);
if (f) {
char sizetext[BUFLEN];
switch (f->val[0]) {
case SZ_MEDIUM:
snprintf(sizetext, BUFLEN, "small");
break;
case SZ_LARGE:
snprintf(sizetext, BUFLEN, "very large");
break;
case SZ_HUMAN:
default:
snprintf(sizetext, BUFLEN, "human");
break;
}
snprintf(buf, BUFLEN, "%sIt will only fit %s sized creatures.^n\n",
(f->val[0] != getlfsize(player)) ? "^B" : "^n", sizetext);
strncat(retbuf, buf, HUGEBUFLEN);
}
// charges remaining
if (o->type->obclass->id == OC_WAND) {
if (isidentified(o)) {
@ -5222,6 +5143,10 @@ char *makedesc_ob(object_t *o, char *retbuf) {
strncat(retbuf, buf2, HUGEBUFLEN);
}
break;
case F_ANONYMOUS:
sprintf(buf2, "%s obscures your identity.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_ATTRMOD:
sprintf(buf2, "%s %s your %s.\n", buf, (f->val[2] > 0) ? "increases" : "decreases", getattrname(f->val[1]));
strncat(retbuf, buf2, HUGEBUFLEN);
@ -5360,7 +5285,9 @@ char *makedesc_ob(object_t *o, char *retbuf) {
char sname[BUFLEN];
strcpy(sname, ot->name);
capitalise(sname);
sprintf(buf2, "%s allows you to cast '%s' at will.\n", buf, sname);
sprintf(buf2, "%s allows you to %s '%s' at will.\n", buf,
(ot->obclass->id == OC_SPELL) ? "cast" : "use the ability",
sname);
strncat(retbuf, buf2, HUGEBUFLEN);
}
break;
@ -5390,6 +5317,10 @@ char *makedesc_ob(object_t *o, char *retbuf) {
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]);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_MAGSHIELD:
sprintf(buf2, "%s surrounds you with a magnetic shield.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
@ -5648,25 +5579,34 @@ char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite) {
// descriptions
for (slev = PR_INEPT; slev <= PR_MASTER; slev++) {
int found = B_FALSE;
int hilitethis = B_FALSE;
if ((levhilite != PR_INEPT) && (slev == levhilite)) {
hilitethis = B_TRUE;
}
for (i = 0; i < sk->nskilldesc; i++) {
if (sk->skilldesclev[i] == slev) {
if (slev == PR_INEPT) {
// extra blank line after this one
snprintf(buf, BUFLEN, "%s\n\n",sk->skilldesctext[i]);
} else {
int hilitethis = B_FALSE;
char atxlevel[BUFLEN];
if ((levhilite != PR_INEPT) && (slev == levhilite)) {
hilitethis = B_TRUE;
}
snprintf(atxlevel, BUFLEN, "At %s level", getskilllevelname(sk->skilldesclev[i]));
snprintf(buf, BUFLEN, "%s%-18s%s: %s\n", // right-align "at xx level"
hilitethis ? "^w" : "", atxlevel, hilitethis ? "^n" : "",
sk->skilldesctext[i]);
}
strncat(retbuf, buf, HUGEBUFLEN);
found = B_TRUE;
}
}
if (!found && (slev != PR_INEPT)) {
char atxlevel[BUFLEN];
snprintf(atxlevel, BUFLEN, "At %s level", getskilllevelname(slev));
snprintf(buf, BUFLEN, "%s%-18s%s: %s\n", // right-align "at xx level"
hilitethis ? "^w" : "", atxlevel, hilitethis ? "^n" : "", "No special effects.");
strncat(retbuf, buf, HUGEBUFLEN);
}
}
return retbuf;
}
@ -6227,6 +6167,19 @@ int dopickup(obpile_t *op, int forceask) {
void doenter(lifeform_t *lf) {
object_t *enterob;
if (isplayer(lf)) {
// check for shops first
enterob = hasobwithflag(lf->cell->obpile, F_SHOP);
if (enterob) {
char ch,obname[BUFLEN],buf[BUFLEN];
getobname(enterob,obname, 1);
sprintf(buf, "Enter %s?", obname);
ch = askchar(buf, "yn","n", B_TRUE, B_FALSE);
if (ch == 'y') {
shop(lf, enterob);
return;
}
}
enterob = hasob(lf->cell->obpile, OT_PORTAL);
if (enterob) {
usestairs(lf, enterob, B_TRUE, B_FALSE);
@ -6306,7 +6259,7 @@ void dohelp(char helpmode) {
helpmode = ch;
break;
}
} else if (helpmode == 'c') {
} else if (helpmode == 'k') {
centre(mainwin,C_WHITE, 0, "KEYBOARD COMMAND REFERENCE");
y = 2;
@ -6660,6 +6613,7 @@ int doselguntarget(void) {
return B_FALSE;
}
void dostairs(int dir) {
object_t *o;
o = hasobwithflagval(player->cell->obpile, F_CLIMBABLE, dir, NA, NA, NULL);
@ -8008,7 +7962,11 @@ void handleinput(void) {
domemmagic();
break;
case '<': // go up
dostairs(D_UP);
if (isprone(player)) {
standup(player);
} else {
dostairs(D_UP);
}
break;
case '>': // go down
doenter(player);
@ -9659,6 +9617,9 @@ void showlfstats(lifeform_t *lf, int showall) {
snprintf(buf, BUFLEN,"%s %s attached to %s.",you(lf), is(lf), grabeename);
wrapprint(mainwin, &y, &x, "%s ", buf);
}
if (isbleeding(lf)) {
wrapprint(mainwin, &y, &x, "%s %s bleeding. ", you(lf), is(lf));
}
f = lfhasknownflag(lf, F_CLIMBING);
if (f && (f->known)) {
wrapprint(mainwin, &y, &x, "%s %s climbing on a wall. ", you(lf), is(lf));
@ -9964,23 +9925,29 @@ void showlfstats(lifeform_t *lf, int showall) {
for (i = PR_NOVICE; i <= PR_MASTER; i++) {
char toadd[BUFLEN];
if (i == (max+1)) {
/*if (i == (max+1)) {
sprintf(toadd, "^n]########");
} else if (i > max) {
sprintf(toadd, "^n#########");
} else if (i == slev) {
if (i == getmaxskilllevel(player, sk->id)) {
// draw bar right up to the end
sprintf(toadd, "========|");
} else*/
if (i <= max) {
if (i == slev) {
if (ismaxedskill(lf, sk->id)) {
sprintf(toadd, "*********");
} else {
sprintf(toadd, "========|");
}
} else if (i < slev) {
if (ismaxedskill(lf, sk->id)) {
sprintf(toadd, "*********");
} else {
sprintf(toadd, "=========");
}
} else {
sprintf(toadd, "========|");
sprintf(toadd, "^n.........");
}
} else if (i < slev) {
sprintf(toadd, "=========");
} else {
sprintf(toadd, "^n ");
strcat(thisline, toadd);
}
strcat(thisline, toadd);
}
sprintf(endbit, "^%c]^n",basecolour);
strcat(thisline, endbit);
@ -9996,6 +9963,7 @@ void showlfstats(lifeform_t *lf, int showall) {
textwithcol(mainwin, toadd);
max = getmaxskilllevel(player, sk->id);
for (i = PR_NOVICE; i <= PR_MASTER; i++) {
/*
if (i == max+1) {
textwithcol(mainwin, "^B]########");
} else if (i > max) {
@ -10003,6 +9971,10 @@ void showlfstats(lifeform_t *lf, int showall) {
} else {
wprintw(mainwin, " ");
}
*/
if (i <= max) {
textwithcol(mainwin, "^B.........");
}
}
textwithcol(mainwin, "^B]^n");
printed = B_TRUE;
@ -10533,6 +10505,10 @@ void showlfstats(lifeform_t *lf, int showall) {
y++;
}
}
if (lfhasknownflag(lf, F_ANONYMOUS)) {
mvwprintw(mainwin, y, 0, "%s identity is obscured.", your(lf));
y++;
}
if (lfhasknownflag(lf, F_AWARENESS)) {
mvwprintw(mainwin, y, 0, "%s can see things which are behind %s.", you(lf), you(lf));
y++;

1
io.h
View File

@ -71,7 +71,6 @@ int doselguntarget(void);
void dostairs(int dir);
int dotakeoff(obpile_t *op);
void dothrow(obpile_t *op);
void dovendingmachine(lifeform_t *lf, object_t *vm);
int dowear(obpile_t *op);
int doweild(obpile_t *op);
int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar);

170
lf.c
View File

@ -253,6 +253,21 @@ void breakgrabs(lifeform_t *lf, int fromme, int tome) {
}
}
void breakaitargets(lifeform_t *lf, int onlylowerlev) {
lifeform_t *l;
for (l = lf->cell->map->lf ; l ; l = l->next) {
flag_t *f;
//if ((l != lf) && (gethitdice(l) <= gethitdice(lf)) ) {
if (l == lf) continue;
if (!onlylowerlev || (gethitdice(l) <= gethitdice(lf)) ) {
f = lfhasflagval(l, F_TARGETLF, lf->id, NA, NA, NULL);
if (f) killflag(f);
f = lfhasflagval(l, F_TARGETCELL, lf->cell->x, lf->cell->y, NA, NULL);
if (f) killflag(f);
}
}
}
long calcscore(lifeform_t *lf) {
long points = 0;
object_t *o;
@ -1124,7 +1139,10 @@ int canwear(lifeform_t *lf, object_t *o, enum BODYPART where) {
return B_FALSE;
}
}
if (!armourfits(lf, o, &reason)) {
return B_FALSE;
}
// already equipped?
if (hasflag(o->flags, F_EQUIPPED)) {
@ -3211,7 +3229,7 @@ void enhancerandomskill(lifeform_t *lf) {
int nposs = 0;
int sel;
for (f = lf->flags->first ; f ; f = f->next) {
if ((f->id == F_HASSKILL) && (f->val[1] != PR_MASTER)) {
if ((f->id == F_HASSKILL) && !ismaxedskill(lf, f->val[0])) {
poss[nposs] = f->val[0];
nposs++;
}
@ -5969,6 +5987,10 @@ int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, char *heartext,
if (nid == N_WALK) {
*volume += getarmournoise(lf);
}
if (lfhasflag(lf, F_SNEAK)) {
*volume -= 2;
limit(volume, 1, NA);
}
return B_FALSE;
} else {
// some defaults
@ -6013,6 +6035,10 @@ int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, char *heartext,
if (strlen(movetext)) {
if (volume) *volume += getarmournoise(lf);
if (heartext) strcpy(heartext, movetext);
if (lfhasflag(lf, F_SNEAK)) {
*volume -= 2;
limit(volume, 1, NA);
}
return B_FALSE;
}
} else if (nid == N_SONICBOLT) {
@ -6177,7 +6203,7 @@ enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid) {
int getattacks(lifeform_t *lf, int *min, int *max) {
flag_t *f;
int minattacks,maxattacks;
int minattacks = 1,maxattacks = 1;
int nattacks;
f = lfhasflag(lf, F_MAXATTACKS);
if (f) {
@ -7107,12 +7133,27 @@ object_t *getrestob(lifeform_t *lf) {
object_t *o,*bestob = NULL;
int bestval = -1;
flag_t *f;
f = lfhasflag(lf, F_RESTINGINMOTEL);
if (f) {
o = findobidinmap(lf->cell->map, atol(f->text));
if (o) return o;
}
for (o = lf->pack->first; o ; o = o->next) {
f = hasflag(o->flags, F_HELPSREST);
if (f) {
if (!bestob && (f->val[0] > bestval)) {
bestval = f->val[0];
bestob = o;
int valid = B_TRUE;
// can't rest in armour which doesn't fit
if (isarmour(o) && !armourfits(lf, o, NULL)) {
valid = B_FALSE;
}
if (valid) {
if (!bestob && (f->val[0] > bestval)) {
bestval = f->val[0];
bestob = o;
}
}
}
}
@ -8009,19 +8050,20 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
}
// learning a new spell school skill will grant you a random first level spell from
// that school.
if (isspellskill(id)) {
enum OBTYPE oid;
int tries = 0;
oid = getrandomspellfromschool(getskillschool(id), 1);
while (cancast(lf, oid, NULL) && (tries < 3)) {
// that school. (player and allies only)
if (isspellskill(id) && (gamemode == GM_GAMESTARTED)) {
if (isplayer(lf) || areallies(player, lf)) {
enum OBTYPE oid;
int tries = 0;
oid = getrandomspellfromschool(getskillschool(id), 1);
tries++;
while (cancast(lf, oid, NULL) && (tries < 3)) {
oid = getrandomspellfromschool(getskillschool(id), 1);
tries++;
}
if (oid != OT_NONE) {
addflag(lf->flags, F_CANCAST, oid, NA, NA, NULL);
}
}
if (oid != OT_NONE) {
addflag(lf->flags, F_CANCAST, oid, NA, NA, NULL);
}
}
statdirty = B_TRUE; // in case skill changes your stats
@ -8068,12 +8110,28 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
makeknown(OT_MUSHROOMTOAD);
}
}
} else if (id == SK_METALWORK) {
if (f->val[1] == PR_SKILLED) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_RESIZE, NA, NA, NULL);
if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_RESIZE, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
}
} else if (id == SK_PERCEPTION) {
if ((f->val[1] == PR_ADEPT) || (f->val[1] == PR_MASTER)) {
// our FOV gets wider
lf->losdirty = B_TRUE;
if (isplayer(lf)) needredraw = B_TRUE;
}
} else if (id == SK_SEWING) {
if (f->val[1] == PR_SKILLED) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_RESIZE, NA, NA, NULL);
if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_RESIZE, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
}
} else if (id == SK_SHIELDS) {
if (f->val[1] == PR_BEGINNER) {
newf = addflag(lf->flags, F_CANWILL, OT_A_SHIELDBASH, NA, NA, NULL);
@ -9495,6 +9553,7 @@ void killlf(lifeform_t *lf) {
int isdeaf(lifeform_t *lf) {
if (lfhasflag(lf, F_DEAF)) return B_TRUE;
if (isresting(lf) && lfhasflag(lf, F_RESTINGINMOTEL)) return B_TRUE;
if (lfhasflagval(lf, F_INJURY, IJ_EARSRINGING, NA, NA, NULL)) return B_TRUE;
return B_FALSE;
}
@ -10255,7 +10314,7 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) {
adjustdamhardness(amt, damtype, getlfmaterial(lf));
if (lfhasflag(lf, F_DRUNK)) {
*amt -= rnd(0,3);
*amt -= rnd(1,f->val[0]);
}
if (lf->race->raceclass->id == RC_GOD) {
@ -10503,6 +10562,25 @@ int areallies(lifeform_t *lf1, lifeform_t *lf2) {
return B_FALSE;
}
int armourfits(lifeform_t *lf, object_t *o, enum ERROR *reason) {
enum LFSIZE lfsize,armsize;
lfsize = getlfsize(lf);
armsize = getarmoursize(o);
if (armsize != SZ_ANY) {
if (armsize > lfsize) {
if (reason) *reason = E_TOOBIG;
return B_FALSE;
} else if (armsize < lfsize) {
if (reason) *reason = E_TOOSMALL;
return B_FALSE;
}
}
return B_TRUE;
}
int askforpayment(lifeform_t *shk, lifeform_t *lf) {
char saybuf[BUFLEN];
int totcost = 0;
@ -11200,7 +11278,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
// unseen?
if (fromlf && !cansee(lf, fromlf)) {
strcat(buf2, "^unseen");
strcat(buf, "^unseen");
}
// "while xxx"
@ -11728,7 +11806,7 @@ void modstamina(lifeform_t *lf, float howmuch) {
int movecausesnoise(lifeform_t *lf) {
if (lfhasflag(lf, F_SILENTMOVE) || lfhasflag(lf, F_SNEAK)) {
if (lfhasflag(lf, F_SILENTMOVE)) {
return B_FALSE;
}
return B_TRUE;
@ -12734,6 +12812,15 @@ int startclimbing(lifeform_t *lf) {
int startresting(lifeform_t *lf, int willtrain) {
int traincounter;
// 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!");
return B_TRUE;
}
}
if (willtrain) {
traincounter = 50;
traincounter = modifybystat(traincounter, player, A_IQ);
@ -13064,6 +13151,13 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
}
}
break;
case SP_PAYTHANKS:
switch (rnd(1,2)) {
case 1: snprintf(buf, BUFLEN, "Pleasure doing business with you!"); break;
case 2: snprintf(buf, BUFLEN, "Thank you, come again!"); break;
}
rv = say(lf, buf, volume);
break;
case SP_THANKS:
switch (rnd(1,3)) {
case 1: snprintf(buf, BUFLEN, "Why, thank you!"); break;
@ -13862,7 +13956,6 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
if (roll == 20) {
switch (ct) {
case SC_DODGE:
case SC_SEARCH:
case SC_STEALTH:
if (db) {
msg("%s skillcheck passed with natural 20.", lf->race->name);
@ -15115,6 +15208,15 @@ void stopresting(lifeform_t *lf) {
}
killflagsofid(lf->flags, F_RESTUNTILALLIES);
killflagsofid(lf->flags, F_RESTUNTILBETTER);
/*
if (isplayer(lf)) {
f = lfhasflag(lf, F_RESTINGINMOTEL);
if (f) {
msg("You stayed for %d turns out of %d.", f->val[1], f->val[0]);
}
}
*/
killflagsofid(lf->flags, F_RESTINGINMOTEL);
}
void stoprunning(lifeform_t *lf) {
@ -16097,6 +16199,13 @@ int validateraces(void) {
printf("ERROR in race '%s' - F_STARTOB with zero length text.\n", r->name);
goterror = B_TRUE;
}
} else if (f->id == F_MAXATTACKS) {
for (i = 0; i <= 1; i++) {
if (f->val[i] < 0) {
printf("ERROR in race '%s' - F_MAXATTACKS with v%d < 0.\n", r->name, i);
goterror = B_TRUE;
}
}
} else if (f->id == F_HITCONFER) {
if (!lfhasflag(lf, F_HITCONFERVALS)) {
printf("ERROR in race '%s' - F_HITCONFER, but no HITCONFERVALS defined.\n", r->name);
@ -16387,6 +16496,19 @@ int rest(lifeform_t *lf, int onpurpose) {
}
} // end if !poisoned
if (isresting(lf)) {
f = hasflag(lf->flags, F_RESTINGINMOTEL);
if (f) {
f->val[1]++;
if (f->val[1] >= f->val[0]) {
killflag(f);
stopresting(lf);
msg("\"Your check-out time has arrived!\"");
wantclearmsg = B_FALSE;
}
}
}
if (statdirty || needredraw) {
drawscreen();
}
@ -16611,6 +16733,12 @@ int wear(lifeform_t *lf, object_t *o) {
case E_LOWWIS:
msg("You are not wise enough to wear this.");
break;
case E_TOOSMALL:
if (isplayer(lf)) msg("This armour is too small for you.");
break;
case E_TOOBIG:
if (isplayer(lf)) msg("This armour is too big for you.");
break;
default:
if (isplayer(lf)) {
msg("You can't wear that!");

2
lf.h
View File

@ -15,6 +15,7 @@ void applylfdammod(int *dam, lifeform_t *lf, object_t *wep);
void applywalkdam(lifeform_t *lf, int dam, enum DAMTYPE damtype, object_t *o);
int areallies(lifeform_t *lf1, lifeform_t *lf2);
int areenemies(lifeform_t *lf1, lifeform_t *lf2);
int armourfits(lifeform_t *lf, object_t *o, enum ERROR *reason);
int askforpayment(lifeform_t *shk, lifeform_t *lf);
char *assignnpcname(lifeform_t *lf);
void autoskill(lifeform_t *lf);
@ -25,6 +26,7 @@ void awardxpfor(lifeform_t *killed, float pct);
void bleed(lifeform_t *lf, int splatter);
int bleedfrom(lifeform_t *lf, enum BODYPART bp, int splatter);
void breakgrabs(lifeform_t *lf, int fromme, int tome);
void breakaitargets(lifeform_t *lf, int onlylowerlev);
long calcscore(lifeform_t *lf);
int calcxp(lifeform_t *lf);
int calcxprace(enum RACE rid);

2
map.c
View File

@ -3691,7 +3691,7 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int x
// add doors
if (doorpct) {
autodoors(map, roomid, minx, miny, maxx, maxy, doorpct, 50);
autodoors(map, roomid, minx, miny, maxx, maxy, doorpct, 25);
}
return B_FALSE;

69
move.c
View File

@ -1050,6 +1050,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
int preshop = -1;
int prespeed = B_FALSE, postspeed = B_FALSE;
int prewater = B_FALSE;
int preseenbyplayer = B_FALSE;
vault_t *v;
assert(newcell);
@ -1099,6 +1100,10 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
prewater = B_TRUE;
}
if (!isplayer(lf) && cansee(player, lf)) {
preseenbyplayer = B_TRUE;
}
// move out...
lf->cell->lf = NULL;
@ -1351,11 +1356,13 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
}
if (isplayer(l)) {
if (areenemies(lf, l)) {
if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_TRAINING)) {
if (areenemies(lf, l) && !isplayer(lf)) {
if (!preseenbyplayer) {
//if (lfhasflag(l, F_RUNNING) || lfhasflag(l, F_TRAINING)) {
// TODO: also check for isresting(l), if we have allies standing watch
getlfnamea(lf, lfname);
msg("%s comes into view.", lfname);
//}
}
dointerrupt = B_TRUE;
}
@ -1415,6 +1422,13 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
}
}
if (preseenbyplayer && !cansee(player, lf)) {
if (areenemies(player, lf)) {
real_getlfnamea(lf, lfname, B_FALSE);
msg("%s moves out of view.", lfname);
}
}
// status bar
if ((prespeed != postspeed) && isplayer(lf)) {
statdirty = B_TRUE;
@ -2214,31 +2228,11 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
}
if (willstand) {
if (isplayer(lf)) {
msg("You stand up.");
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s stands up.",lfname);
}
killflagsofid(lf->flags, F_PRONE);
killflagsofid(lf->flags, F_FEIGNINGDEATH);
standup(lf);
reason = E_OK;
// monsters don't take time to stand up if they were feigning death!
// doesn't count as a move for monster who were feigning death!
if (!isplayer(lf) && lfhasflag(lf, F_FEIGNINGDEATH)) {
return B_FALSE;
} else {
int howlong;
float quartermax;
int units;
// time to get up depends on armour
// 1*movespeed for every 1/4 of maxcarryweight being worn.
quartermax = getmaxcarryweight(lf) / 4;
units = (getequippedweight(lf) / quartermax)+1;
howlong = getmovespeed(lf)*units;
taketime(lf, howlong);
}
return B_TRUE;
}
@ -2314,6 +2308,31 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) {
return B_FALSE;
}
void standup(lifeform_t *lf) {
if (isplayer(lf)) {
msg("You stand up.");
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s stands up.",lfname);
}
killflagsofid(lf->flags, F_PRONE);
killflagsofid(lf->flags, F_FEIGNINGDEATH);
// monsters don't take time to stand up if they were feigning death!
if (!isplayer(lf) && lfhasflag(lf, F_FEIGNINGDEATH)) {
} else {
int howlong;
float quartermax;
int units;
// time to get up depends on armour
// 1*movespeed for every 1/4 of maxcarryweight being worn.
quartermax = getmaxcarryweight(lf) / 4;
units = (getequippedweight(lf) / quartermax)+1;
howlong = getmovespeed(lf)*units;
taketime(lf, howlong);
}
}
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir, int onpurpose) {
cell_t *cell1,*cell2;
@ -2477,11 +2496,13 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
cell = getcellindir(lf->cell, dir);
// warn if moving will cause damage
/*
if (cell && !cell->lf && onpurpose && isplayer(lf) ) {
if (!confirm_injury_action(BP_LEGS, DT_SLASH, "move")) {
return B_TRUE;
}
}
*/
// warn before moving onto dangerous cells
if (onpurpose && isplayer(lf) && !lfhasflag(lf, F_SNEAK)) {

1
move.h
View File

@ -28,6 +28,7 @@ int pullnextto(lifeform_t *lf, cell_t *c);
int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg);
int isorthogonal(int dir);
int ispossiblemove(lifeform_t *lf, int dir);
void standup(lifeform_t *lf);
void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir, int onpurpose);
int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke);
void triggertrap(lifeform_t *lf, object_t *o, object_t *trapob, cell_t *where);

View File

@ -1486,7 +1486,7 @@ void timeeffectsworld(map_t *map, int updategametime) {
for (x = 0; x < map->w; x++) {
cell_t *c;
c = getcellat(map, x, y);
if (c) {
if (c) {
object_t *pit;
if (cartskill <= PR_INEPT) {

269
objects.c
View File

@ -14,6 +14,7 @@
#include "move.h"
#include "nexus.h"
#include "objects.h"
#include "shops.h"
#include "spell.h"
#include "text.h"
@ -63,6 +64,7 @@ objecttype_t *lastot = NULL;
enum OBCLASS sortorder[] = {
OC_EFFECT,
OC_TERRAIN,
OC_BUILDING,
OC_MONEY,
OC_WEAPON,
OC_MISSILE,
@ -441,6 +443,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
int wantlit = B_FALSE;
int wantrarity = RR_NONE;
int wantgoodness = G_NA;
enum LFSIZE wantarmsize = SZ_ANY;
enum MATERIAL wantdiffmat = MT_NOTHING;
map_t *targetmap = NULL; // for portals
cell_t *targetcell = NULL; // for portals
@ -606,6 +609,15 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
wantblessed = B_CURSED;
p += strlen("cursed ");
donesomething = B_TRUE;
// armour flags
} else if (strstarts(p, "giant-sized ")) {
wantarmsize = SZ_LARGE;
p += strlen("giant-sized ");
donesomething = B_TRUE;
} else if (strstarts(p, "half-sized ")) {
wantarmsize = SZ_MEDIUM;
p += strlen("half-sized ");
donesomething = B_TRUE;
// door flags
} else if (strstarts(p, "locked ")) {
doorflag[ndoorflags++] = F_LOCKED;
@ -907,6 +919,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
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;
}
// special checks for unique objects
if (hasflag(ot->flags, F_UNIQUE)) {
// does this unique ob already exist?
@ -1111,6 +1128,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
addflag(o->flags, F_MAPLINK, targetmap->id, tx, ty, NULL);
}
// assign gods to temples
if (o->type->id == OT_TEMPLE) {
lifeform_t *god;
god = getrandomgod();
addflag(o->flags, F_LINKGOD, god->race->id, NA, NA, NULL);
}
// fill in door flags
if (ndoorflags && isdoor(o, NULL)) {
int n;
@ -1170,6 +1194,29 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
turnon(NULL, o);
}
// fill in armour size
if (o && hasflag(o->flags, F_MULTISIZE)) {
if (wantarmsize == SZ_ANY) {
// if giving to a lifeform being created, match their size
if (where->owner) {
wantarmsize = getlfsize(where->owner);
} else {
// random size
if (onein(4)) {
// nonstandard size
if (onein(2)) {
wantarmsize = SZ_MEDIUM;
} else {
wantarmsize = SZ_LARGE;
}
} else {
wantarmsize = SZ_HUMAN;
}
}
}
addflag(o->flags, F_ARMOURSIZE, wantarmsize, NA, NA, NULL);
}
// fill in book types
if (o && (o->type->obclass->id == OC_BOOK)) {
hiddenname_t *hn,*selhn = NULL;
@ -2671,7 +2718,9 @@ int doobdieconvert(object_t *o, int wantannounce) {
if (strlen(desc)) {
if (o->pile->owner) {
if (isplayer(o->pile->owner)) {
msg("Your %s %s!",noprefix(obname), desc);
if (!lfhasflag(o->pile->owner, F_ASLEEP)) {
msg("Your %s %s!",noprefix(obname), desc);
}
} else if (cansee(player, o->pile->owner)) {
// don't announce decay death unless we are holding it
if (oblastdamtype(o) != DT_DECAY) {
@ -3201,6 +3250,19 @@ char *genhiddenname(enum OBCLASS id) {
return NULL;
}
enum LFSIZE getarmoursize(object_t *o) {
flag_t *f;
f = hasflag(o->flags, F_MULTISIZE);
if (f) {
f = hasflag(o->flags, F_ARMOURSIZE);
if (f) {
return f->val[0];
}
return SZ_HUMAN;
}
return SZ_ANY;
}
// returns largest posisble container with free space
object_t *getbestcontainer(obpile_t *op) {
object_t *o,*poss[MAXPILEOBS],*poss2[MAXPILEOBS];
@ -3515,7 +3577,9 @@ int getobvalue(object_t *o) {
}
char *getoperateverb(object_t *o) {
if (hasflag(o->flags, F_CONTAINER) && (o->type->id != OT_VENDINGMACHINE)) {
if (hasflag(o->flags, F_SHOP)) {
return "enter";
} else if (hasflag(o->flags, F_CONTAINER)) {
return "open";
}
return "operate";
@ -3648,8 +3712,15 @@ objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity
if ((ot->obclass->id == ocid) && !hasflag(ot->flags, F_UNIQUE)) {
f = hasflag(ot->flags, F_RARITY);
if (f) {
if ( ((minrarity == NA) || (f->val[1] >= minrarity)) &&
int ok = B_FALSE;
if (f->val[1] == NA) {
ok = B_TRUE;
} else if ( ((minrarity == NA) || (f->val[1] >= minrarity)) &&
((maxrarity == NA) || (f->val[1] <= maxrarity)) ) {
ok = B_TRUE;
}
if (ok) {
count++;
}
}
@ -3664,8 +3735,15 @@ objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity
if ((ot->obclass->id == ocid) && !hasflag(ot->flags, F_UNIQUE)) {
f = hasflag(ot->flags, F_RARITY);
if (f) {
if ( ((minrarity == NA) || (f->val[1] >= minrarity)) &&
int ok = B_FALSE;
if (f->val[1] == NA) {
ok = B_TRUE;
} else if ( ((minrarity == NA) || (f->val[1] >= minrarity)) &&
((maxrarity == NA) || (f->val[1] <= maxrarity)) ) {
ok = B_TRUE;
}
if (ok) {
n++;
if (n == sel) {
return ot;
@ -4360,6 +4438,16 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} else {
strcpy(basename, "map");
}
} else if (o->type->id == OT_TEMPLE) {
flag_t *f;
lifeform_t *god = NULL;
f = hasflag(o->flags, F_LINKGOD);
if (f) god = findgod(f->val[0]);
if (god) {
sprintf(basename, "temple of %s", god->race->name);
} else {
sprintf(basename, "abandoned temple");
}
} else if (o->type->id == OT_WATERDEEP) {
snprintf(basename, BUFLEN, "%s water", getwaterdepthname(getobdepth(o, player)));
} else {
@ -4530,6 +4618,30 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
}
}
// handle armour sizes
f = hasflag(o->flags, F_ARMOURSIZE);
if (f) {
char sizetext[BUFLEN];
// prepend size
switch (f->val[0]) {
case SZ_MEDIUM:
strcpy(sizetext, "half-sized");
break;
case SZ_LARGE:
strcpy(sizetext, "giant-sized");
break;
default:
strcpy(sizetext, "");
break;
}
if (strlen(sizetext)) {
char newname[BUFLEN];
sprintf(newname, "%s %s", sizetext, basename);
strcpy(basename, newname);
}
}
// handle ALL
if (count == ALL) {
count = o->amt;
@ -4948,6 +5060,20 @@ float getobunitweight(object_t *o) {
weight *= ratio;
}
f = hasflag(o->flags, F_ARMOURSIZE);
if (f) {
switch (f->val[0]) {
case SZ_LARGE:
weight *= 1.50;
break;
case SZ_MEDIUM:
weight *= 0.50;
break;
default:
break;
}
}
f = hasflag(o->flags, F_WET);
if (f) {
switch (f->val[0]) {
@ -4965,6 +5091,7 @@ float getobunitweight(object_t *o) {
}
}
return weight;
}
@ -5473,20 +5600,7 @@ int getshatterdam(object_t *o) {
float getshopprice(object_t *o, lifeform_t *buyer) {
float val;
val = getobvalue(o);
if (buyer) {
float pricepctmod = 0;
enum SKILLLEVEL slev;
// price goes up/down for charisma (+/- 25%)
pricepctmod -= ((getstatmod(buyer, A_CHA)/2) * -1);
// modify for speech (up to -30%);
slev = getskill(buyer, SK_SPEECH);
if (slev) {
pricepctmod -= (slev*5);
}
val = pctof(val, 100 + pricepctmod);
}
val = applyshoppricemod(getobvalue(o), buyer);
return val;
}
@ -6074,6 +6188,7 @@ int isknown(object_t *o) {
return B_FALSE;
}
return isknownot(o->type);
}
@ -6369,13 +6484,6 @@ int issmellableob(object_t *o) {
return B_FALSE;
}
int isthrownmissile(object_t *o) {
if (hasflag(o->flags, F_THROWMISSILE)) {
return B_TRUE;
}
return B_FALSE;
}
int isweapon(object_t *o) {
if (o->type->obclass->id == OC_WEAPON) {
return B_TRUE;
@ -7592,7 +7700,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
return B_TRUE;
}
if (hasflag(o->flags, F_CONTAINER) && (o->type->id != OT_VENDINGMACHINE)) { // loot it
if (hasflag(o->flags, F_CONTAINER) && !hasflag(o->flags, F_SHOP)) { // loot it
if (isplayer(lf)) { // only player can loot.
char ch;
snprintf(buf, BUFLEN, "Looting %s. Will you:",obname);
@ -8297,18 +8405,8 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
}
}
taketime(lf, getactspeed(lf));
} else if (o->type->id == OT_VENDINGMACHINE) {
if (isplayer(lf)) {
dovendingmachine(lf, o);
restoregamewindows();
} else {
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s fiddles with %s.", lfname, obname);
}
}
taketime(lf, getactspeed(lf));
} else if (hasflag(o->flags, F_SHOP)) {
shop(lf, o);
}
return B_FALSE;
}
@ -8759,13 +8857,13 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
switch (oid) {
case OT_POT_ACID:
dam = rnd(5,10);
losehp(lf, dam, DT_ACID, NULL, "drinking acid");
if (isplayer(lf)) {
msg("Your suffer massive internal burning!");
} else if (cansee(player, lf)) {
msg("%s writhes in agony!", lfname);
}
dam = rnd(5,10);
losehp(lf, dam, DT_ACID, NULL, "drinking acid");
break;
case OT_POT_ACROBATICS:
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
@ -11126,7 +11224,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
}
// announce
if (seen) {
if (haslos(player, where)) {
char buf2[BUFLEN];
char verb[BUFLEN];
if (willtangle) {
@ -11401,7 +11499,7 @@ void timeeffectsob(object_t *o) {
// update location
//if (inv) killflag(inv);
// further effects on this object will come from its new location
location = newc;
} else {
// object can't go anywhere - it disintegrates.
@ -11428,6 +11526,17 @@ void timeeffectsob(object_t *o) {
if (location) {
//buildings/shops make noise
if (o->type->obclass->id == OC_BUILDING) {
if (onein(3)) {
char noisebuf[BUFLEN];
switch (o->type->id) {
case OT_TEMPLE: strcpy(noisebuf, "voices chanting."); break;
default: strcpy(noisebuf, "the chime of a cash register."); break;
}
noise(location, NULL, NC_OTHER, 3, noisebuf, NULL);
}
}
// does object's material change cell type?
if (o->material->id == MT_FIRE) {
if (hasflag(location->type->material->flags, F_FLAMMABLE)) {
@ -12520,82 +12629,6 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
acc -= 30;
}
limit(&acc, 0, NA);
/*
// figure out if you miss or not, based on distance and
// dexterity
// base:
// if throwing, 40% + 10*sk_throwing
// if firing, gun accuracy modified by sk_ranged
// adjust for range:
// pointblank = +30%
// max = -30%
// then modify using dexterity/int/whatever
// then penalise for throwing non-missiles
if (tkthrow) {
whichatt = tkthrow->val[0];
whichskill = tkthrow->val[1];
} else {
whichatt = A_AGI;
whichskill = SK_THROWING;
}
// base accuracy
if (firearm) {
slev = getskill(thrower, SK_RANGED);
acc = getobaccuracy(firearm, thrower);
// ie. inept = -30%, adept = 0%, master = +30%
acc += ((slev - PR_ADEPT) * 10);
} else {
acc = 60;
// ie. inept = -45%, adept = 0%, master = +45%
slev = getskill(thrower, whichskill);
acc += ((slev - PR_ADEPT) * 15);
// acc will now be 25 - 115
}
// adjust for range
if (firearm || missile) {
if (firearm) {
maxrange = getfirearmrange(firearm);
} else {
maxrange = getmaxthrowrange(thrower, missile);
}
} else {
maxrange = getvisrange(thrower, B_TRUE);
}
howfar = getcelldist(thrower->cell, where);
// ie. -30 to 30
if (firearm && (slev == PR_MASTER) ) {
} else {
int rangemod;
rangemod = 30 - ((int) (((float)howfar / (float)maxrange) * 60.0));
acc += rangemod;
}
// modify for dexterity
if (whichatt != A_NONE) {
acc += getstatmod(thrower, whichatt);
}
// penalty for throwing non-missiles
if (missile && !firearm && !isthrowmissile(missile) && !tkthrow) {
acc -= 20;
}
// modify for prone throwers
if (isprone(thrower)) {
acc -= 50;
}
// modify for prone defenders
if (where->lf && isprone(where->lf)) {
acc -= 30;
}
limit(&acc, 0, NA);
*/
return acc;
}

View File

@ -61,6 +61,7 @@ objecttype_t *findotn(char *name); // find objecttype by name
recipe_t *findrecipefor(enum OBTYPE result);
void fragments(cell_t *centre, char *what, int speed, int howfar);
void genhiddennames(void);
enum LFSIZE getarmoursize(object_t *o);
object_t *getbestcontainer(obpile_t *op);
int getchargeinfo(object_t *o, int *cur, int *max);
int getcharges(object_t *o);

686
shops.c Normal file
View File

@ -0,0 +1,686 @@
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "attack.h"
#include "defs.h"
#include "flag.h"
#include "god.h"
#include "io.h"
#include "lf.h"
#include "map.h"
#include "move.h"
#include "nexus.h"
#include "objects.h"
#include "shops.h"
#include "spell.h"
#include "text.h"
#define DEF_REMCURSECOST 60
#define DEF_BLESSCOST 50
#define DEF_SURCHARGE 15
extern enum GAMEMODE gamemode;
extern prompt_t prompt;
extern lifeform_t *player;
extern WINDOW *mainwin;
float applyshoppricemod(float origprice, lifeform_t *lf) {
float newprice;
if (lf) {
float pricepctmod = 0;
enum SKILLLEVEL slev;
// price goes up/down for charisma (+/- 25%)
pricepctmod -= getstatmod(lf, A_CHA)/2;
// modify for speech (up to -30%);
slev = getskill(lf, SK_SPEECH);
if (slev) {
pricepctmod -= (slev*5);
}
newprice = pctof(origprice, 100 + pricepctmod);
} else {
newprice = origprice;
}
if (origprice > 0) {
limitf(&newprice, 1, NA);
}
return newprice;
}
int getshopblessprice(object_t *o) {
int cost = 0;
int remcursecost, blesscost,surcharge;
remcursecost = applyshoppricemod(DEF_REMCURSECOST, player);
blesscost = applyshoppricemod(DEF_BLESSCOST, player);
surcharge = applyshoppricemod(DEF_SURCHARGE, player);
if (iscursed(o)) {
cost = remcursecost;
if (isequipped(o)) cost += surcharge;
} else {
cost = blesscost;
}
cost *= o->amt;
return cost;
}
void shop(lifeform_t *lf, object_t *vm) {
int y,i,done;
int curmenu = 0;
char ch,buf[BUFLEN];
char toptext[BUFLEN],shopname[BUFLEN];
int npurchased = 0;
int ndonated = 0;
flag_t *f;
object_t *o;
strcpy(toptext, "");
taketime(lf, getactspeed(lf));
if (!isplayer(lf)) {
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
getobname(vm, shopname, 1);
msg("%s browses through %s.", lfname, shopname);
}
return;
}
if (hasflagval(vm->flags, F_BANNEDLF, lf->id, NA, NA, NULL)) {
if (!lfhasflag(lf, F_ANONYMOUS)) {
msg("\"You are not welcome here, thief!\"");
return;
}
}
// temple to dead god?
if (vm->type->id == OT_TEMPLE) {
flag_t *f;
lifeform_t *god = NULL;
f = hasflag(vm->flags, F_LINKGOD);
if (f) {
god = findgod(f->val[0]);
}
if (!god) {
msg("This temple seems to have been abandoned.");
return;
}
}
getobname(vm, shopname, 1);
makeuppercase(shopname);
// assign letters to objects
ch = 'a';
for (o = vm->contents->first ; o ; o = o->next) {
o->letter = ch;
if (++ch > 'z') ch = 'A';
}
// list objects for sale and ask for input
done = B_FALSE;
while (!done) {
enum SHOPRETURN (*shopfunc)(lifeform_t *, object_t *, int, char *, int *) = NULL;
int *shoparg = NULL;
cls();
mvwprintw(mainwin, 0, 0, toptext);
y = 2;
centre(mainwin,C_WHITE, y, noprefix(shopname));
y += 2;
// check for special sm_xxx menu ids first
if (curmenu == SM_ABSOLVE) {
shopfunc = shopabsolve;
shoparg = NULL;
} else if (curmenu == SM_BLESS) {
shopfunc = shopbless;
shoparg = NULL;
} else if (curmenu == SM_MIRACLE) {
shopfunc = shopmiracle;
shoparg = NULL;
} else if (curmenu == SM_PURCHASEITEMS) {
shopfunc = shoppurchase;
shoparg = &npurchased;
} else if (curmenu == SM_DETECTCURSE) {
shopfunc = shopdetectcurse;
shoparg = NULL;
} else if (curmenu == SM_DONATE) {
shopfunc = shopdonate;
shoparg = &ndonated;
} else if (curmenu == SM_REST) {
shopfunc = shoprest;
shoparg = &ndonated;
}
if (shopfunc) {
switch (shopfunc(lf, vm, y, toptext, shoparg)) {
case SR_BACK:
curmenu = 0;
break;
case SR_CONTINUE:
break;
case SR_QUIT:
done = B_TRUE;
break;
}
} else {
flag_t *retflag[MAXCANDIDATES];
int nretflags,curidx = 0,found = B_TRUE;
// show menu items
getflags(vm->flags, retflag, &nretflags, F_SHOPMENU, F_NONE);
while (found) {
found = B_FALSE;
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// check menu id
if ((f->val[0] / 100) != curmenu) continue;
// check menuitem index
if ((f->val[0] % 100) == curidx) {
snprintf(buf, BUFLEN, "%c - %s", f->text[0], f->text + 2);
mvwprintw(mainwin, y, 0, "%s", buf);
y++;
found = B_TRUE;
curidx++;
}
}
}
// ask for selection
y += 2;
// ask what to do
mvwprintw(mainwin, y, 0, "What will you do (ESC to exit)? ");
ch = getch();
// handle selection
if (ch == 27) {
done = B_TRUE;
} else {
flag_t *selection = NULL;
// find matching menu item
for (i = 0; i < nretflags; i++) {
f = retflag[i];
// check menu id
if ((f->val[0] / 100) != curmenu) continue;
// check menuitem index
if (f->text[0] == ch) {
// handle the action.
selection = f;
}
}
if (selection) {
switch (selection->val[1]) {
case MA_GOTOMENU:
curmenu = selection->val[2];
break;
case MA_QUIT:
done = B_TRUE;
break;
}
}
}
} // end if curmenu == -1 or something else
} // end while not done
restoregamewindows();
if (hasflagval(vm->flags, F_BANNEDLF, lf->id, NA, NA, NULL)) {
msg("\"...and stay out!\"");
} else if (hasflag(lf->flags, F_RESTINGINMOTEL)) {
switch (rnd(1,2)) {
case 1: snprintf(buf, BUFLEN, "Sleep well!"); break;
case 2: snprintf(buf, BUFLEN, "Enjoy your stay!"); break;
case 3: snprintf(buf, BUFLEN, "Sweet dreams!"); break;
}
msg("\"%s\"", buf);
} else if (npurchased > ndonated) {
switch (rnd(1,2)) {
case 1: snprintf(buf, BUFLEN, "Pleasure doing business with you!"); break;
case 2: snprintf(buf, BUFLEN, "Thank you, come again!"); break;
}
msg("\"%s\"", buf);
} else if (ndonated > npurchased) {
switch (rnd(1,2)) {
case 1: snprintf(buf, BUFLEN, "Thank you again for your generosity!"); break;
case 2: snprintf(buf, BUFLEN, "I look forward to your next visit!"); break;
}
msg("\"%s\"", buf);
} else {
switch (rnd(1,2)) {
case 1: snprintf(buf, BUFLEN, "See you next time."); break;
case 2: snprintf(buf, BUFLEN, "Farewell!"); break;
}
msg("\"%s\"", buf);
}
}
enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
object_t *o;
char ch;
int y;
int cost = 0,possible = B_TRUE;
y = starty;
// calculate cost
for (o = lf->pack->first ; o; o = o->next) {
if (!o->blessknown && !hasflag(o->flags, F_NOBLESS)) {
cost += 10;
}
}
if (cost) {
cost = applyshoppricemod(cost, lf);
}
if (!cost) {
mvwprintw(mainwin, y, 0, "You do not seem to possess anything which merits our services.");
y += 2;
possible = B_FALSE;
} else {
// ask what to detect
mvwprintw(mainwin, y, 0, "It will cost $%d to perform an divination on your items.", cost);
y += 2;
if (countmoney(lf->pack) < cost) {
mvwprintw(mainwin, y, 0, "Unfortunately, you cannot afford this.", cost);
y += 2;
possible = B_FALSE;
}
}
if (possible){
mvwprintw(mainwin, y, 0, "Pay to detect auras on your items (you have $%d) [yn]? ", countmoney(lf->pack));
} else {
mvwprintw(mainwin, y, 0, "[Press a key to return]");
}
ch = getch();
if (possible && (ch == 'y')) {
givemoney(player, NULL, cost);
dospelleffects(lf, OT_S_DETECTAURA, 10, lf, NULL, NULL, B_BLESSED, NULL, B_FALSE);
more();
}
return SR_BACK;
}
enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
int count = 0;
enum FLAG wantflag;
enum OBCLASS wantoc;
object_t *o;
// ask what to donate
switch (vm->type->id) {
case OT_SHOPARMOUR: wantflag = F_ARMOURRATING; wantoc = OC_ARMOUR; break;
case OT_SHOPWEAPON: wantflag = F_DAM; wantoc = OC_WEAPON; break;
case OT_TEMPLE: wantflag = F_NONE; wantoc = OC_MONEY; break;
default: wantflag = F_NONE; wantoc = OC_NONE; break;
}
o = doaskobject(lf->pack, "What will you donate?", &count, B_FALSE, B_FALSE, AO_NONE, wantflag, F_NONE);
// validate it
if (o) {
// can we remove it?
if (isequipped(o)) {
if (takeoff(lf, o)) {
more();
return SR_CONTINUE;
}
}
// okay it!
if ((wantoc != OC_NONE) && (o->type->obclass->id != wantoc)) {
msg("Sorry, we can't accept that!"); more();
} else {
object_t *newob;
char let;
if (vm->contents->first) {
let = vm->contents->last->letter + 1;
} else {
let = 'a';
}
newob = moveob(o, vm->contents, count);
newob->letter = let;
(*ndonated)++;
msg("Thanks!"); more();
}
} else {
return SR_BACK;
}
return SR_CONTINUE;
}
enum SHOPRETURN shopabsolve(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
char ch;
int y;
int piety,cost = 0,possible = B_TRUE;
flag_t *f;
lifeform_t *god = NULL;
y = starty;
// get linked god
f = hasflag(vm->flags, F_LINKGOD);
god = findgod(f->val[0]);
piety = getpiety(god->race->id);
if (piety < 100) {
cost = (100 - piety) * 3;
cost = applyshoppricemod(cost, lf);
mvwprintw(mainwin, y, 0, "It will cost $%d to absolve your sins against %s.", cost, god->race->name);
y += 2;
} else {
mvwprintw(mainwin, y, 0, "You do not appear to have sinned against %s.", god->race->name);
y += 2;
possible = B_FALSE;
}
if (possible) {
if (countmoney(lf->pack) >= cost) {
mvwprintw(mainwin, y, 0, "Pay for absolution (you have $%d) [yn]? ", countmoney(lf->pack));
} else {
mvwprintw(mainwin, y, 0, "You cannot afford to pay $%d for absolution.", cost); y+= 2;
possible = B_FALSE;
}
}
if (!possible) {
mvwprintw(mainwin, y, 0, "[Press any key]");
}
ch = getch();
if (!possible || (ch != 'y')) {
return SR_BACK;
}
givemoney(lf, NULL, cost);
setpiety(god->race->id, 100);
msg("\"You sins are forgiven!\""); more();
return SR_BACK;
}
enum SHOPRETURN shopbless(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
object_t *o;
char ch,buf[BUFLEN];
int y;
int remcursecost, blesscost,surcharge;
y = starty;
remcursecost = applyshoppricemod(DEF_REMCURSECOST, lf);
blesscost = applyshoppricemod(DEF_BLESSCOST, lf);
surcharge = applyshoppricemod(DEF_SURCHARGE, lf);
mvwprintw(mainwin, y, 0, "So long as their aura is known, we can bestow a blessing on most items."); y += 2;
mvwprintw(mainwin, y, 0, "Curse removal - $%d each",remcursecost); y++;
mvwprintw(mainwin, y, 0, "Blessings - $%d each",blesscost); y += 2;
mvwprintw(mainwin, y, 0, "(there is a $%d surcharge for uncursing an equipped item)",surcharge); y += 2;
mvwprintw(mainwin, y, 0, "Pay for a blessing (you have $%d) [yn]? ", countmoney(lf->pack));
ch = getch();
if (ch != 'y') {
return SR_BACK;
}
// ask which object
sprintf(buf, "Bless which object (you have $%d)?", countmoney(lf->pack));
initprompt(&prompt, buf);
for (o = player->pack->first ; o ; o = o->next) {
if (o->blessknown && (o->blessed != B_BLESSED) && !hasflag(o->flags, F_NOBLESS)) {
char costbuf[BUFLEN];
getobname(o, buf, o->amt);
sprintf(costbuf, "%-60s($%d)", buf, getshopblessprice(o));
addchoice(&prompt, o->letter, costbuf, costbuf, o, NULL);
}
}
addchoice(&prompt, '-', "(nothing)", NULL, NULL, NULL);
ch = getchoice(&prompt);
o = (object_t *)prompt.result;
if (o) {
int cost;
cost = getshopblessprice(o);
if (countmoney(player->pack) < cost) {
msg("You cannot afford the $%d blessing price.", cost);
more();
} else {
msg("You hand over $%d to the priest.", cost); more();
givemoney(player, NULL, cost);
msg("The priest raise his hands in supplication."); more();
blessob(o);
more();
}
}
return SR_CONTINUE;
}
enum SHOPRETURN shopmiracle(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
char ch;
int y;
int piety,cost = 0,possible = B_TRUE;
flag_t *f;
lifeform_t *god = NULL;
y = starty;
// get linked god
f = hasflag(vm->flags, F_LINKGOD);
god = findgod(f->val[0]);
piety = getpiety(god->race->id);
cost = 1000 - piety;
cost = applyshoppricemod(cost,lf);
if (godisangry(god->race->id)) {
mvwprintw(mainwin, y, 0, "%s does not currently find you worthy of miracles.", god->race->name);
y += 2;
possible = B_FALSE;
} else {
mvwprintw(mainwin, y, 0, "For $%d, we will ask %s to intervene on your behalf.", cost, god->race->name);
y += 2;
}
if (possible) {
if (countmoney(lf->pack) >= cost) {
mvwprintw(mainwin, y, 0, "Pay for a miracle (you have $%d) [yn]? ", countmoney(lf->pack));
} else {
mvwprintw(mainwin, y, 0, "You cannot afford to pay $%d.", cost); y+= 2;
possible = B_FALSE;
}
}
if (!possible) {
mvwprintw(mainwin, y, 0, "[Press any key]");
}
ch = getch();
if (!possible || (ch != 'y')) {
return SR_BACK;
}
givemoney(lf, NULL, cost);
godgiftmaybe(god->race->id, B_TRUE);
more();
return SR_BACK;
}
// returns B_TRUE if shop transaction should end
enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased) {
object_t *o;
int y;
char buf[BUFLEN], buf2[BUFLEN], choices[BUFLENSMALL];
char ch;
y = starty;
// list objects for sale
for (o = vm->contents->first ; o ; o = o->next) {
char obname[BUFLEN];
// get the name of the object
real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_TRUE);
snprintf(buf, BUFLEN, "%c - %s", o->letter, obname);
snprintf(buf2, BUFLEN, "%-60s$%d",buf,(int)getshopprice(o, player));
mvwprintw(mainwin, y, 0, "%s", buf2);
y++;
}
strcpy(choices, "");
y++;
mvwprintw(mainwin, y, 0, "You have $%d.", countmoney(player->pack));
y++;
y++;
// ask what to do
mvwprintw(mainwin, y, 0, "What will you buy (ESC when done)? ");
ch = getch();
if (ch == 27) {
strcpy(toptext, "");
return SR_BACK;
} else {
// try to find that object...
o = hasobletter(vm->contents, ch);
if (o) {
enum SKILLLEVEL slev;
char obname[BUFLEN],validchars[BUFLENSMALL];
char answer;
int value;
value = (int)getshopprice(o, player);
slev = getskill(player, SK_THIEVERY);
// confirm
getobname(o, obname, o->amt);
snprintf(buf, BUFLEN, "Buy%s %s for $%d?", slev ? "/steal" : "", obname, value);
strcpy(validchars, "yn");
if (slev) {
strcat(validchars, "s");
}
answer = askchar(buf, validchars,"n", B_TRUE, B_FALSE);
if (answer == 'y') {
// do you have enough money?
if (slev || (countmoney(player->pack) >= getobvalue(o)) ) {
int shopamt;
object_t *gold;
gold = hasob(player->pack, OT_GOLD);
if (gold) {
// if so, buy it
// lose money (do this first to avoid potential weight issues)
givemoney(player, NULL, value);
// clear o->letter
o->letter = '\0';
// give object
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, "Purchased: %c - %s", o->letter, obname);
if (npurchased) (*npurchased)++;
} else {
msg("You don't seem to have any money..."); more();
o = NULL;
}
} else {
msg("You can't afford that!"); more();
o = NULL;
}
} else if (answer == 's') { // steal
// skillcheck - difficulty based on total value of objects here
// 15 + value/50 means:
// $50 is diff 16
// $100 is diff 17
// $200 is diff 19
// $500 is diff 25
// $1000 is diff 35
if (skillcheck(player, SC_STEAL, 15+(value/50), 0)) {
int shopamt;
// success
o->letter = '\0';
shopamt = o->amt; // avoid "stolen: 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, "Stolen: %c - %s", o->letter, obname);
pleasegodmaybe(R_GODTHIEVES, (value/50));
o = NULL;
} else {
msg("^B\"HEY! Get out of my shop, thief!\""); more();
// shop closes
addflag(vm->flags, F_BANNEDLF, player->id, NA, NA, NULL);
return SR_QUIT;
}
} else {
// cancelled
strcpy(toptext, "");
}
} else {
snprintf(toptext, BUFLEN, "No such item.");
} // end if o
} // end if ch
return SR_CONTINUE;
}
enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
char ch,obid[BUFLENSMALL],buf[BUFLEN];
int y,i;
int cost = 0,possible = B_TRUE, amt;
y = starty;
cost = applyshoppricemod(100, lf);
mvwprintw(mainwin, y, 0, "We offer good quality rooms for only $%d per hour.", cost);
y += 2;
if (countmoney(lf->pack) >= cost) {
mvwprintw(mainwin, y, 0, "Rent a room (you have $%d) [yn]? ", countmoney(lf->pack));
} else {
mvwprintw(mainwin, y, 0, "You cannot afford to pay $%d.", cost); y+= 2;
possible = B_FALSE;
}
if (!possible) {
mvwprintw(mainwin, y, 0, "[Press any key]");
}
ch = getch();
if (!possible || (ch != 'y')) {
return SR_BACK;
}
// how many hours?
sprintf(buf, "How many hours will you pay for (you have $%d)?", countmoney(lf->pack));
initprompt(&prompt, buf);
for (i = 1; i <= 9; i++) {
int thiscost;
thiscost = cost * i;
sprintf(buf, "%d hour%s ($%d)", i, (i == 1) ? "" : "s", thiscost);
addchoice(&prompt, '0' + i, buf, buf, NULL, NULL);
}
addchoice(&prompt, '-', "Cancel", NULL, NULL, NULL);
ch = getchoice(&prompt);
if (ch == '-') {
return SR_BACK;
}
amt = ch - '0'; // ie. 1 - 12
cost *= amt;
givemoney(lf, NULL, cost);
// mark that we are resting in a hotel
sprintf(obid, "%ld", vm->id);
addflag(lf->flags, F_RESTINGINMOTEL, amt*60, 0, NA, obid);
addflag(lf->flags, F_RESTUNTILBETTER, B_TRUE, NA, NA, NULL);
startresting(lf, B_FALSE);
more();
breakaitargets(lf, B_FALSE);
return SR_QUIT;
}

13
shops.h Normal file
View File

@ -0,0 +1,13 @@
#include "defs.h"
float applyshoppricemod(float origprice, lifeform_t *lf);
int getshopblessprice(object_t *o);
void shop(lifeform_t *lf, object_t *vm);
enum SHOPRETURN shopabsolve(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated);
enum SHOPRETURN shopbless(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated);
enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
enum SHOPRETURN shopmiracle(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);

393
spell.c
View File

@ -1365,7 +1365,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
drawscreen();
}
} else if (abilid == OT_A_REPAIR) {
enum SKILLLEVEL slev;
object_t *o,*helpob = NULL;
enum MATERIAL repairablemats[MAXCANDIDATES];
int repaircutoff = 0;
@ -1375,52 +1374,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
char helpobname[BUFLEN];
// get list of repairable materials
slev = getskill(user, SK_METALWORK);
if (slev) {
int cutoff;
switch (slev) {
case PR_NOVICE: cutoff = 33; break;
case PR_BEGINNER: cutoff = 50; break;
case PR_ADEPT: cutoff = 60; break;
case PR_SKILLED: cutoff = 70; break;
case PR_EXPERT: cutoff = 85; break;
case PR_MASTER: cutoff = 100; break;
default: cutoff = 0; break;
}
helpob = hasob(user->pack, OT_SPANNER);
if (helpob) cutoff += 15;
repairablemats[nmats] = MT_METAL;
cutoffpct[nmats] = cutoff;
nmats++;
}
slev = getskill(user, SK_SEWING);
if (slev) {
int cutoff;
switch (slev) {
case PR_NOVICE: cutoff = 33; break;
case PR_BEGINNER: cutoff = 50; break;
case PR_ADEPT: cutoff = 60; break;
case PR_SKILLED: cutoff = 70; break;
case PR_EXPERT: cutoff = 85; break;
case PR_MASTER: cutoff = 100; break;
default: cutoff = 0; break;
}
helpob = hasob(user->pack, OT_NEEDLE);
if (helpob) cutoff += 15;
repairablemats[nmats] = MT_CLOTH;
cutoffpct[nmats] = cutoff;
nmats++;
repairablemats[nmats] = MT_LEATHER;
cutoffpct[nmats] = cutoff;
nmats++;
}
if (helpob) {
real_getobname(helpob, helpobname, helpob->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE);
} else {
strcpy(helpobname, "");
}
getworkablematerials(user, SK_METALWORK, repairablemats, cutoffpct, &nmats);
getworkablematerials(user, SK_SEWING, repairablemats, cutoffpct, &nmats);
// 1.compile a list of repairable objects
// sk_armour lets you repair armour up to xx% (depends on skill)
initprompt(&prompt, "Repair which object?");
@ -1481,7 +1436,15 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
}
}
assert(repaircutoff != 0);
// get helper ob
helpob = getworkhelpob(user->pack, o->material->id);
if (helpob) {
real_getobname(helpob, helpobname, helpob->amt, B_TRUE, B_FALSE, B_TRUE, B_TRUE, B_FALSE);
} else {
strcpy(helpobname, "");
}
// repair it!
f = hasflag(o->flags, F_OBHP);
f->val[0] = pctof(repaircutoff, f->val[1]);
@ -1503,6 +1466,118 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
buf, withbuf);
}
// TODO: make this like eating/resting/etc ?
taketime(user, getactspeed(user));
} else if (abilid == OT_A_RESIZE) {
object_t *o;
enum MATERIAL repairablemats[MAXCANDIDATES];
enum LFSIZE wantsize,origsize;
int cutoffpct[MAXCANDIDATES];
int i,nmats = 0;
char ch,obname[BUFLEN];
if (!isplayer(user)) {
return B_TRUE;
}
// get list of resizable materials
getworkablematerials(user, SK_METALWORK, repairablemats, cutoffpct, &nmats);
getworkablematerials(user, SK_SEWING, repairablemats, cutoffpct, &nmats);
// 1.compile a list of resizable objects
initprompt(&prompt, "Resize which object?");
addchoice(&prompt, '-', "Cancel", "Cancel", NULL, NULL);
for (o = user->pack->first ; o ; o = o->next) {
int ok = B_FALSE;
for (i = 0; i < nmats; i++) {
if (o->material->id == repairablemats[i]) {
ok = B_TRUE;
break;
}
}
if (ok && hasflag(o->flags, F_MULTISIZE)) {
getobname(o, obname, o->amt);
// we can resize this object
addchoice(&prompt, o->letter, obname, NULL, o, NULL);
}
}
if (prompt.nchoices <= 1) {
msg("You don't have anything which you are able to resize.");
return B_TRUE;
}
// 2. ask which ones to resize (or ALL)
getchoice(&prompt);
o = (object_t *) prompt.result;
getobname(o, obname, 1);
origsize = getarmoursize(o);
// ask what size we want.
sprintf(buf, "Resize %s to what size?", obname);
initprompt(&prompt, buf);
for (i = SZ_MEDIUM; i <= SZ_LARGE; i++) {
if (i != origsize) {
switch (i) {
case SZ_MEDIUM:
addchoice(&prompt, 's', "half-sized", NULL, NULL, NULL);
break;
case SZ_HUMAN:
addchoice(&prompt, 'm', "human-sized", NULL, NULL, NULL);
break;
case SZ_LARGE:
addchoice(&prompt, 'l', "giant-sized", NULL, NULL, NULL);
break;
}
}
}
addchoice(&prompt, '-', "Cancel", "Cancel", NULL, NULL);
ch = getchoice(&prompt);
switch (ch) {
case 's':
wantsize = SZ_MEDIUM;
break;
case 'm':
wantsize = SZ_HUMAN;
break;
case 'l':
wantsize = SZ_LARGE;
break;
default:
msg("Cancelled.");
return B_TRUE;
}
// in case it's on fire, etc
if (touch(user, o)) {
taketime(user, getactspeed(user));
return B_FALSE;
}
// resize it!
f = hasflag(o->flags, F_ARMOURSIZE);
if (f) {
f->val[0] = wantsize;
} else {
addflag(o->flags, F_ARMOURSIZE, wantsize, NA, NA, NULL);
}
f = hasflag(o->flags, F_OBHP);
if (f) {
f->val[1] /= 2;
if (f->val[1] < 1) f->val[1] = 1;
f->val[0] = f->val[1];
}
msg("You %s the size of your %s.", (wantsize > origsize) ? "increase" : "reduce", noprefix(obname));
getobname(o, obname, 1);
more();
msgnocap("%c - %s", o->letter, obname);
// TODO: make this like eating/resting/etc ?
taketime(user, getactspeed(user));
} else if (abilid == OT_A_SHIELDBASH) {
@ -2585,116 +2660,66 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
return B_TRUE;
}
// stealing shop items
if (isroom(user->cell) && hasobwithflagval(user->cell->obpile, F_SHOPITEM, NA, getroomid(user->cell), NA, NULL)) {
// stealing from a shop
char yn;
yn = askchar("Steal something from this shop?", "yn","n", B_TRUE, B_FALSE);
if (yn == 'y') {
object_t *o;
flag_t *f;
int value;
// stealing from a lifeform
// ask for direction
if (!targcell) {
int dir;
dirch = askchar("Steal in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE, B_TRUE);
dir = chartodir(dirch);
if (dir == D_NONE) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE ;
} else {
targcell = getcellindir(user->cell, dir);
}
}
taketime(user, getactspeed(user));
target = targcell->lf;
if (!target) {
if (isplayer(user)) msg("There is nobody there to steal from!");
return B_TRUE;
}
value = 0;
for (o = user->cell->obpile->first ; o ; o = o->next) {
f = hasflagval(o->flags, F_SHOPITEM, NA, getroomid(user->cell), NA, NULL);
if (f) {
value += f->val[0];
}
taketime(user, getactspeed(user));
getlfname(target, targetname);
if (slev == PR_NOVICE) {
penalty = addflag(user->flags, F_ACCURACYMOD, -14, NA, NA, NULL);
} else if (slev == PR_BEGINNER) {
penalty = addflag(user->flags, F_ACCURACYMOD, -7, NA, NA, NULL);
}
// use empty handed attack accuracy
wep = getweapon(user);
if (rolltohit(user, target, wep, NULL)) {
// success!
failed = B_FALSE;
if (steal(user, target->pack, F_NONE)) {
if (isplayer(user)) {
msg("%s has nothing for you to steal!", targetname);
}
// skillcheck - difficulty based on total value of objects here
// 15 + value/50 means:
// $50 is diff 16
// $100 is diff 17
// $200 is diff 19
// $500 is diff 25
// $1000 is diff 35
if (skillcheck(user, SC_STEAL, 15+(value/50), 0)) {
// success
if (steal(user, user->cell->obpile, F_SHOPITEM)) {
if (isplayer(user)) {
msg("There doesn't seem to be anything here which you could steal.");
}
} else {
pleasegodmaybe(R_GODTHIEVES, 5);
}
} else {
lifeform_t *shk;
msg("You try to steal something, but fail.");
// failed
shk = findshopkeeper(user->cell->map, getroomid(user->cell));
if (shk) { // doesn't need to see you - he SENSES it!
say(shk, "THIEF!", SV_ROAR);
fightback(shk, user);
callguards(shk, user);
}
}
}
} else {
// stealing from a lifeform
// ask for direction
if (!targcell) {
int dir;
dirch = askchar("Steal in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE, B_TRUE);
dir = chartodir(dirch);
if (dir == D_NONE) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE ;
} else {
targcell = getcellindir(user->cell, dir);
}
failed = B_TRUE;
}
if (penalty) {
killflag(penalty);
}
if (failed) {
if (isplayer(user)) {
msg("You try to steal from %s, but fail.", targetname);
} else if (cansee(player, user)) {
msg("%s tries to steal from %s, but fails.", username, targetname);
}
target = targcell->lf;
if (!target) {
if (isplayer(user)) msg("There is nobody there to steal from!");
return B_TRUE;
}
taketime(user, getactspeed(user));
getlfname(target, targetname);
if (slev == PR_NOVICE) {
penalty = addflag(user->flags, F_ACCURACYMOD, -14, NA, NA, NULL);
} else if (slev == PR_BEGINNER) {
penalty = addflag(user->flags, F_ACCURACYMOD, -7, NA, NA, NULL);
}
// use empty handed attack accuracy
wep = getweapon(user);
if (rolltohit(user, target, wep, NULL)) {
// success!
failed = B_FALSE;
if (steal(user, target->pack, F_NONE)) {
if (isplayer(user)) {
msg("%s has nothing for you to steal!", targetname);
}
}
} else {
failed = B_TRUE;
}
if (penalty) {
killflag(penalty);
}
if (failed) {
if (isplayer(user)) {
msg("You try to steal from %s, but fail.", targetname);
} else if (cansee(player, user)) {
msg("%s tries to steal from %s, but fails.", username, targetname);
}
// ai will get angry!
if (cansee(target, user) && !isplayer(target)) {
fightback(target, user);
}
} else {
practice(user, SK_THIEVERY, 1);
// ai will get angry!
if (cansee(target, user) && !isplayer(target)) {
fightback(target, user);
}
} else {
practice(user, SK_THIEVERY, 1);
}
} else if (abilid == OT_A_WARCRY) {
// announce
@ -7311,7 +7336,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
needredraw = B_TRUE;
} else if (spellid == OT_S_MIST) {
object_t *o;
lifeform_t *l;
targcell = getcellindir(caster->cell, caster->facing);
if (!targcell || targcell->type->solid) {
@ -7340,15 +7364,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
// hack - make all monsters who can see you stop targetting you.
// otherwise they will just try to go to your last known location.
for (l = caster->cell->map->lf ; l ; l = l->next) {
flag_t *f;
if ((l != caster) && (gethitdice(l) <= gethitdice(caster)) ) {
f = lfhasflagval(l, F_TARGETLF, caster->id, NA, NA, NULL);
if (f) killflag(f);
f = lfhasflagval(l, F_TARGETCELL, caster->cell->x, caster->cell->y, NA, NULL);
if (f) killflag(f);
}
}
breakaitargets(caster, B_TRUE);
} else if (spellid == OT_S_MENDING) {
object_t *o;
@ -10201,6 +10217,61 @@ char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf) {
return buf;
}
// for the given skill (ie. metalwork or sewing) + level, _append_ the materials we can work on to the list, and
// how much we can repair them.
// returns the number of materials/cutoffs which were appended.
int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repairablemats, int *cutoffpct, int *nmats) {
enum SKILLLEVEL slev;
int cutoff,nworkable = 0;
object_t *helpob = NULL;
slev = getskill(lf, skid);
switch (slev) {
case PR_NOVICE: cutoff = 33; break;
case PR_BEGINNER: cutoff = 50; break;
case PR_ADEPT: cutoff = 60; break;
case PR_SKILLED: cutoff = 70; break;
case PR_EXPERT: cutoff = 85; break;
case PR_MASTER: cutoff = 100; break;
default: cutoff = 0; break;
}
if (skid == SK_METALWORK) {
helpob = getworkhelpob(lf->pack, MT_METAL);
} else if (skid == SK_SEWING) {
helpob = getworkhelpob(lf->pack, MT_CLOTH);
}
if (helpob) cutoff += 15;
if (cutoff) {
if (skid == SK_METALWORK) {
repairablemats[*nmats] = MT_METAL;
cutoffpct[*nmats] = cutoff;
(*nmats)++;
nworkable++;
} else if (skid == SK_SEWING) {
repairablemats[*nmats] = MT_CLOTH;
cutoffpct[*nmats] = cutoff;
(*nmats)++;
repairablemats[*nmats] = MT_LEATHER;
cutoffpct[*nmats] = cutoff;
(*nmats)++;
nworkable += 2;
}
}
return nworkable;
}
// returns an object from 'op' which will help with work on the given material
object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat) {
object_t *helpob = NULL;
if ((mat == MT_LEATHER) || (mat == MT_CLOTH)) {
helpob = hasob(op, OT_NEEDLE);
} else if (mat == MT_METAL) {
helpob = hasob(op, OT_SPANNER);
}
return helpob;
}
// magically propel an object into lf's hands.
// if it's too big it'll hit them!
void pullobto(object_t *o, lifeform_t *lf) {

View File

@ -28,6 +28,8 @@ enum SPELLSCHOOL getspellschoolknown(lifeform_t *lf, enum OBTYPE spellid);
enum SKILLLEVEL getspellskill(lifeform_t *lf, enum OBTYPE spellid);
int getspellrange(lifeform_t *lf, enum OBTYPE spellid, int power);
char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf);
int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repairablemats, int *cutoffpct, int *nmats);
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);