From 10e4713940b5fd007ab46f9b5b4efb0f1ce34e6d Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Wed, 16 Nov 2011 00:57:21 +0000 Subject: [PATCH] - [+] 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. --- Makefile | 6 +- ai.c | 21 +- attack.c | 2 +- data.c | 203 +++++++++++--- data.h | 1 + data/hiscores.db | Bin 12288 -> 12288 bytes defs.h | 66 ++++- doc/glyphs.txt | 5 +- flag.c | 27 +- god.c | 402 +++++++++++++-------------- god.h | 3 +- io.c | 242 ++++++++--------- io.h | 1 - lf.c | 170 ++++++++++-- lf.h | 2 + map.c | 2 +- move.c | 69 +++-- move.h | 1 + nexus.c | 2 +- objects.c | 269 +++++++++++-------- objects.h | 1 + shops.c | 686 +++++++++++++++++++++++++++++++++++++++++++++++ shops.h | 13 + spell.c | 393 ++++++++++++++++----------- spell.h | 2 + 25 files changed, 1882 insertions(+), 707 deletions(-) create mode 100644 shops.c create mode 100644 shops.h diff --git a/Makefile b/Makefile index f22ded1..1c3fe7f 100644 --- a/Makefile +++ b/Makefile @@ -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: diff --git a/ai.c b/ai.c index e7febde..157d35f 100644 --- a/ai.c +++ b/ai.c @@ -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) || diff --git a/attack.c b/attack.c index cae83d3..a7f64c5 100644 --- a/attack.c +++ b/attack.c @@ -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")) { diff --git a/data.c b/data.c index 39c8509..e6c0909 100644 --- a/data.c +++ b/data.c @@ -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; diff --git a/data.h b/data.h index 2c75192..1fbdfa3 100644 --- a/data.h +++ b/data.h @@ -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); diff --git a/data/hiscores.db b/data/hiscores.db index 0ee52b5293a03d1b6d8a32b0a07ff1dcb5ba774b..0bd9d3396faaec516cefda96a2476c5b58c9e0a9 100644 GIT binary patch delta 932 zcmXw%S!fec6o&7)XC~=nvUG`!txen5ByF0lNo-TCDMdsPeNgnpy)Lm;D>Z3V3RN2f z5foewsGwNugW}#AEGQ_V;EGZd#SIi+>VsgVA}&asJGJ)?XMVo3%s+Fdr@5#3P_Y#h zHogqn4F;;-U=jXcMtmix8UNrn{DQ;y3E$(ZY_aqf19Fp=k%L;0DorrR)XOmCl}FH zuR_l)RkYkvS#A+W1}7Pug!}M|hj}wU$nWy+=)#3~6dzJ~?r_d=wn4Kn9drxcytKp* zu%~p+TumuQj2awubfGXp^9sXMSQsHiYjPqve{IZ35=t~I=WbFHfeSvqAD2DQMpyh?hkE)e^mO| AHUIzs delta 906 zcmYk4TS$~a6vxlZ`7Zmpm(O)u^U}Jzy1VXbyS7@GREu3OqU%F1lA(s171`=)l3*7J zB2dUU4+TLcMo~}NqEJv4Jro6DMPVWYzVuR*1QAKp%;rPi`S^3@cjla#Gc)H}&b15| zIbaF?`zFF4uuzOG_+C;QF5wSc#LxH%7jQmPq|9NpRxct-REV0N!=|8(B~Z*;#JBhW zC-D}J;uXAzXRr@@@E9hsg?yGq*KhWdeP=Vgn4iU`Y@FTYlXSt7u&{)%Ce}o=mi?Fa zo?Z2WRupTMhY!1}4^tz<TU@7BDMt zJ*W}ksbSh=^?Oyn4EdyZrIg@#P(9LHC528~tMaCotBguwX7MBIw!mw!!fn8N*of=U z$)EEv-pd2*4Lcz4Kii!N+4@;-chAvudosrNLWH?IwFTri-8Aj6(u5f{1g&7MNVJH? zZGIzCssVHPYvVMk7E))(F!&cJ7g;q9k+qUK9eP2fPtFO}mZwvPcJ;=6TT>k!ttZ-2 zlybYN)eO=`Gicxd1Vmbti?m`YFat(uu}t$sLs|085jJra;>=aH8U7Wb&1EiXaGUhP z5i-SnhMCJ-<5-S0=NJ0ya0x7s1bl~0Jjt%Ix4QpkFaPG*> zqujiK94f_VgOXk3anNdra#3-LHHtVz58bfovVknIXB(&{r(Qx$`Wi*>9W<;r(3rhK zw==)E#jcFL;+MIJtpz8n1Mwe$>oCJOlRds$&9>0qFnMtn7d!MI!}PW8ShC4&n})qtjDc7~=@x4=3d1bl{8-K_L QC%V#HJWQ4ujGbhE0cC*1Q~&?~ diff --git a/defs.h b/defs.h index 271bba4..d6c4455 100644 --- a/defs.h +++ b/defs.h @@ -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]; diff --git a/doc/glyphs.txt b/doc/glyphs.txt index 428f28e..fec682c 100644 --- a/doc/glyphs.txt +++ b/doc/glyphs.txt @@ -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 diff --git a/flag.c b/flag.c index 4f36834..2afff8f 100644 --- a/flag.c +++ b/flag.c @@ -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; } diff --git a/god.c b/god.c index a3c8c34..024f7fc 100644 --- a/god.c +++ b/god.c @@ -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); } diff --git a/god.h b/god.h index 9ac0650..3cf0000 100644 --- a/god.h +++ b/god.h @@ -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); diff --git a/io.c b/io.c index 79c4519..648ba67 100644 --- a/io.c +++ b/io.c @@ -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++; diff --git a/io.h b/io.h index 9e87cbb..23194b7 100644 --- a/io.h +++ b/io.h @@ -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); diff --git a/lf.c b/lf.c index c4bd49c..578ad11 100644 --- a/lf.c +++ b/lf.c @@ -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!"); diff --git a/lf.h b/lf.h index 0ef6b91..8c56c7e 100644 --- a/lf.h +++ b/lf.h @@ -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); diff --git a/map.c b/map.c index 916e171..ebbf820 100644 --- a/map.c +++ b/map.c @@ -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; diff --git a/move.c b/move.c index 8b22b8b..1dfc01c 100644 --- a/move.c +++ b/move.c @@ -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)) { diff --git a/move.h b/move.h index 7d1984f..3ec8545 100644 --- a/move.h +++ b/move.h @@ -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); diff --git a/nexus.c b/nexus.c index 843598e..ecfbbe9 100644 --- a/nexus.c +++ b/nexus.c @@ -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) { diff --git a/objects.c b/objects.c index ad1efb1..34db678 100644 --- a/objects.c +++ b/objects.c @@ -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; } diff --git a/objects.h b/objects.h index 18a027a..40b8a1a 100644 --- a/objects.h +++ b/objects.h @@ -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); diff --git a/shops.c b/shops.c new file mode 100644 index 0000000..11b22d0 --- /dev/null +++ b/shops.c @@ -0,0 +1,686 @@ +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/shops.h b/shops.h new file mode 100644 index 0000000..9cd3036 --- /dev/null +++ b/shops.h @@ -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); + diff --git a/spell.c b/spell.c index 226a521..3a0fde1 100644 --- a/spell.c +++ b/spell.c @@ -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) { diff --git a/spell.h b/spell.h index cd75739..b2e165a 100644 --- a/spell.h +++ b/spell.h @@ -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);