diff --git a/data.c b/data.c index 92d500d..9e3d36a 100644 --- a/data.c +++ b/data.c @@ -127,6 +127,7 @@ void initcommands(void) { addcommand(CMD_TAKEOFF, 'T', "Take off an item of clothing/jewelery."); addcommand(CMD_WEILD, 'w', "Weild a weapon."); addcommand(CMD_WEAR, 'W', "Wear an item of clothing/jewelery."); + addcommand(CMD_EXCHANGE, 'x', "Exchange weapon for spare weapon."); // Firearms addcommand(CMD_FIRE, 'f', "Fire your firearm/bow at your current target."); addcommand(CMD_FIRENEW, 'F', "Fire your firearm/bow at a new target."); @@ -389,7 +390,7 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, PR_BEGINNER, NA, NULL); // abilities //mayusespellschool(lastjob->flags, SS_NATURE, F_CANCAST); - addflag(lastjob->flags, F_LEVSPELLSCHOOL, 101, SS_NATURE, B_TRUE, NULL); // new enviromancy spell every 1 level + addflag(lastjob->flags, F_LEVSPELLSCHOOLFROMX, 101, SS_NATURE, 3, NULL); // new enviromancy spell every 1 level addflag(lastjob->flags, F_HASPET, NA, NA, NA, "young wolf"); addflag(lastjob->flags, F_PARTVEGETARIAN, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_LEVSKILL, 5, SK_LORE_NATURE, NA, NULL); @@ -1480,6 +1481,7 @@ void initobjects(void) { 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"); + addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "a cash register chiming."); for (i = 0; i < 10; i++) { f = addflag(lastot->flags, F_STARTOBCLASS, 100, OC_FOOD, NA, NULL); addcondition(f, FC_NOCONDITION, 33); @@ -1490,11 +1492,13 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_ARMOURRATING, NA, OC_ARMOUR, 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_GOTOMENU, SM_REPAIR, "r:repair equipment"); addflag(lastot->flags, F_SHOPMENU, 3, MA_GOTOMENU, SM_RESIZE, "s:resize equipment"); addflag(lastot->flags, F_SHOPMENU, 4, MA_QUIT, NA, "q:leave"); + addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "a cash register chiming."); for (i = 0; i < 10; i++) { addflag(lastot->flags, F_STARTOBCLASS, 100, OC_ARMOUR, RANDOM, NULL); } @@ -1546,7 +1550,11 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_VERYRARE, NULL); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); - make_basic_shop(lastot->flags); + addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_GEM, 75, NA, NULL); + addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something"); + addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, SM_SELLITEMS, "b:sell gems"); + addflag(lastot->flags, F_SHOPMENU, 2, MA_QUIT, NA, "q:leave"); + addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "a cash register chiming."); for (i = 0; i < 10; i++) { if (onein(3)) { addflag(lastot->flags, F_STARTOBCLASS, 100, OC_ROCK, RANDOM, NULL); @@ -1558,10 +1566,12 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_DAM, NA, OC_WEAPON, 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_GOTOMENU, SM_RESIZE, "r:resize equipment"); addflag(lastot->flags, F_SHOPMENU, 3, MA_QUIT, NA, "q:leave"); + addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "a cash register chiming."); for (i = 0; i < 10; i++) { addflag(lastot->flags, F_STARTOBCLASS, 100, OC_WEAPON, RANDOM, NULL); } @@ -1569,6 +1579,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_RARE, NULL); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_NONE, NA, OC_MONEY, NULL); addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "voices chanting."); addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, 1, "a:speak to a deacon (earthly concerns)"); addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, 2, "b:speak to a priest (minor divine administration)"); @@ -2158,6 +2169,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, NULL); addflag(lastot->flags, F_RARITY, H_SWAMP, 100, RR_FREQUENT, NULL); addflag(lastot->flags, F_RARITY, H_CAVE, 100, RR_COMMON, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_MUSHROOMSHI, NA, NA, NULL); addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, ""); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "mushroom"); addot(OT_MUSHROOMSTUFFED, "stuffed mushroom", "A large brown mushroom stuffed with breadcrumbs. This healthy food slightly increases your maximum hit points..", MT_FOOD, 0.2, OC_FOOD, SZ_TINY); @@ -2272,6 +2284,7 @@ void initobjects(void) { addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); addflag(lastot->flags, F_EXPLODEONDAM, DT_FIRE, NA, NA, "2d6"); addflag(lastot->flags, F_BADOBJECT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_POT_WATER, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL); addot(OT_POT_RESTORATION, "potion of restoration", "Restores lost abilities to the drinker.", MT_GLASS, 1, OC_POTION, SZ_TINY); addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL); @@ -2306,12 +2319,14 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BADOBJECT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_POT_WATER, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL); addot(OT_POT_ACID, "flask of acid", "Causes massive internal burning if ingested.", MT_GLASS, 1, OC_POTION, SZ_TINY); addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of acid"); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BADOBJECT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_POT_WATER, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 25, NA, NA, NULL); addot(OT_POT_ELEMENTIMMUNE, "potion of elemental immunity", "Grants the imbiber temporary immunity to both fire and cold.", MT_GLASS, 1, OC_POTION, SZ_TINY); addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL); @@ -3101,10 +3116,14 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addot(OT_S_PURIFYFOOD, "purify food", "Changes any kind of harmful food or drink into a harmless equivilant.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level I, this spell target's the caster's possessions."); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level III, this spell can target other locations."); + addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, 3, 3, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); - addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL); addot(OT_S_STICKTOSNAKE, "sticks to snakes", "Transforms all rod-shaped objects in sight into allied snakes.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell does not affect the caster's weapon."); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); @@ -4767,6 +4786,7 @@ void initobjects(void) { addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL); addflag(lastot->flags, F_DRINKABLE, B_TRUE, 0, NA, NULL); addflag(lastot->flags, F_TAINTED, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATERL, NA, NA, NULL); addot(OT_ACIDPOOL, "pool of acid", "A pool of corrosive acid.", MT_ACID, 0, OC_MISC, SZ_MEDIUM); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4782,6 +4802,7 @@ void initobjects(void) { addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "2d4"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATERL, NA, NA, NULL); addot(OT_ACIDPUDDLE, "puddle of acid", "A small puddle of corrosive acid.", MT_ACID, 0, OC_MISC, SZ_SMALL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4796,6 +4817,7 @@ void initobjects(void) { addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "1d4"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATER, NA, NA, NULL); addot(OT_ACIDSPLASH, "splash of acid", "A splash corrosive acid.", MT_ACID, 0, OC_MISC, SZ_SMALL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4810,6 +4832,7 @@ void initobjects(void) { addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_ACID, FALLTHRU, "1d2"); addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL); addot(OT_SLIMEPOOL, "pool of slime", "A deep pool of foul-smelling slime.", MT_SLIME, 300, OC_TERRAIN, SZ_HUGE); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); @@ -4818,6 +4841,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DEEPWATER, DP_MAX, NA, NA, NULL); addflag(lastot->flags, F_ONEPERCELL, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATERL, NA, NA, NULL); addot(OT_SLIMEPUDDLE, "puddle of slime", "A disgusting mass of foul-smelling slime.", MT_SLIME, 20, OC_MISC, SZ_MEDIUM); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4825,6 +4849,7 @@ void initobjects(void) { addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_EDIBLE, B_TRUE, 2, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATER, NA, NA, NULL); addot(OT_PUDDLEOIL, "puddle of oil", "A slippery puddle of oil.", MT_OIL, 15, OC_MISC, SZ_SMALL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4842,6 +4867,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates"); + addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATER, NA, NA, NULL); // this isn't made out of water, so that it won't put out fire etc addot(OT_SPLASHWATER, "splash of water", "A small splash of water.", MT_NOTHING, 0.5, OC_MISC, SZ_SMALL); @@ -4875,6 +4901,7 @@ void initobjects(void) { addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); //addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1"); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+1"); + addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATERL, NA, NA, NULL); addot(OT_PUDDLEWATER, "small puddle of water", "A small puddle of water.", MT_WATER, 10, OC_MISC, SZ_SMALL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4929,6 +4956,7 @@ void initobjects(void) { addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_COSMETIC, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL); addot(OT_BLOODCSPLASH, "splash of cockatrice blood", "A small pool of cockatrice blood.", MT_BLOOD, 0, OC_MISC, SZ_SMALL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4945,6 +4973,7 @@ void initobjects(void) { addflag(lastot->flags, F_DRINKABLE, B_TRUE, 0, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_BLOODC, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL); addot(OT_BLOODSPLASH, "splash of blood", "A small pool of blood.", MT_BLOOD, 0, OC_MISC, SZ_SMALL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4965,6 +4994,7 @@ void initobjects(void) { addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL); addflag(lastot->flags, F_COSMETIC, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_SPLASHWATER, NA, NA, NULL); addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC, SZ_MEDIUM); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); @@ -4983,6 +5013,7 @@ void initobjects(void) { addflag(lastot->flags, F_DRINKABLE, B_TRUE, 0, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_PURIFIESTO, OT_PUDDLEWATERL, NA, NA, NULL); addot(OT_SIGN, "sign", "A marker with something written on it.", MT_WOOD, 25, OC_MISC, SZ_MEDIUM); addflag(lastot->flags, F_GLYPH, C_BROWN, '|', NA, NULL); @@ -6182,6 +6213,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 67, NA, ""); addflag(lastot->flags, F_RARITY, H_CAVE, 67, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); + addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL); addot(OT_DARTTRANQ, "tranquiliser dart", "A metal dart coated with a strong sleep-inducing serum.", MT_METAL, 0.5, OC_MISSILE, SZ_TINY); @@ -6192,6 +6224,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_CAVE, 100, NA, NULL); addflag(lastot->flags, F_NUMAPPEAR, 1, 4, NA, NULL); addflag(lastot->flags, F_HITCONFER, F_ASLEEP, SC_CON, 27, "20-30"); + addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_HITCONFERVALS, B_TRUE, ST_ASLEEP, NA, NULL); addot(OT_MANRIKI, "manriki", "A pair of weights on the end of a metal chain, designed to entangle those at whom it is thrown.", MT_METAL, 0.1, OC_MISSILE, SZ_SMALL); diff --git a/data/hiscores.db b/data/hiscores.db index 92a97cb..ca6388b 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/data/vaults/caveboss2.vlt b/data/vaults/caveboss2.vlt index 941a368..ab4547c 100644 --- a/data/vaults/caveboss2.vlt +++ b/data/vaults/caveboss2.vlt @@ -16,7 +16,7 @@ @legend #:cell:rock wall f:ob:wooden footstool -f:mon:young red wyrm +f:mon:red wyrmling w:ob:goblin corpse c:ob:lit candelabrum +:ob:iron gate diff --git a/defs.h b/defs.h index dbf8273..c29766f 100644 --- a/defs.h +++ b/defs.h @@ -295,6 +295,11 @@ enum TRADEINFOTYPE { TI_SPELL, }; +enum SHOPACTION { + SA_BUY, + SA_SELL, +}; + /////////////////////////////////////// // STRINGS /////////////////////////////////////// @@ -2115,6 +2120,7 @@ enum FLAG { F_ONLYFORWEPSKILL, // brand can only go on obclass v0 // weapon/armour flags F_EQUIPPED, // val0 = where it is equipped. CLEAR WHEN OB MOVED! + F_SECONDARY, // this object is player's secondary weapon. F_GOESON, // val0 = where it can be equipped. F_GOESONMULTI, // ob is equipped on _ALL_ F_GOESON flags, rather than // equipped on _ONE OF_ the. @@ -2174,6 +2180,7 @@ enum FLAG { F_MATIMMUNE, // immune to damage from obs with material 'v0' F_MATVULN, // vulnarable to damage from obs with material 'v0' // v1 = this % of damage is done. ie. 110% + F_PURIFIESTO, // v0 = new obid after purify food spell F_DAMAGABLE, // this ob can be damaged via takedamage() F_TINTED, // when worn on eyes, protects against bright lights F_HASBRAND, // has the object mod v0 (ie. OM_FLAMESTRIKE) @@ -2290,6 +2297,10 @@ enum FLAG { // shops F_BANNEDLF, // lfid v0 is not allowed to enter this shop F_SHOP, // this object is a shop + F_SHOPDONATED, // v0 = how much gold worth you have donated + F_SHOPACCEPTSFLAG, // v0 = can sell items with flag v0 to this shop, for + // v1 percent of full value. + // v2 = must be this objectclass (or NA) F_SHOPMENU, // defines a menu for interaction with a shop // v0 = (menuid*100) + itemorder // ie. menu0 would have 0, 1, 2, 3 @@ -2690,6 +2701,8 @@ enum FLAG { F_FAILEDINSPECT, // lf has failed an inspect check for objecttype v0 F_TARGETTEDSPELL, // this spell needs you to specify a target cell // v0 is the tt_targettype + // if V1/v2 are set, then this is only spells with + // power in the range v1-v2 are targetted. F_BOOSTSPELL, // v0 is active boost spell, v1 is ongoing mpcost, v2 is power F_SWOOPRANGE, // v0 = how far a flying creature can swoop F_LOSLOF, // v0 = whether this spell needs line of sight @@ -3108,6 +3121,11 @@ enum FLAG { // of their choice from school v1. if v1 is SS_NONE, they can // pick from any school they are skilled in. // if v0 is >100, this triggers every (v0-100) levels. + F_LEVSPELLSCHOOLFROMX, // at level v0, this job gains f_cancast for a + // spell from school v1. you can pick one from + // v2. if v1 is SS_NONE, they can + // pick from any school they are skilled in. + // if v0 is >100, this triggers every (v0-100) levels. F_LEVFLAG, // at level v0, this job gains flagid v1, flagval0=v2, // flagtext = text @@ -3373,6 +3391,7 @@ enum COMMAND { CMD_UP, CMD_WEAR, CMD_WEILD, + CMD_EXCHANGE, }; @@ -3503,6 +3522,10 @@ typedef struct region_s { struct region_s *parentregion; int nthings; // is this used??? int depthmod; + int createdbymapid; // which map ID created this region ? + // used to figure out which regions to delete + // if/when we have to regenerate a map. + // -1 means "Created at start of game" struct region_s *next, *prev; } region_t; @@ -4052,16 +4075,17 @@ enum SHOPMENU { // shops SM_PURCHASEITEMS = -1, SM_DONATE = -2, + SM_SELLITEMS = -3, // temples - SM_ABSOLVE = -3, - SM_BLESS = -4, - SM_DETECTCURSE = -5, - SM_MIRACLE = -6, + SM_ABSOLVE = -4, + SM_BLESS = -5, + SM_DETECTCURSE = -6, + SM_MIRACLE = -7, // motels - SM_REST = -7, + SM_REST = -8, // weapon/armour shops - SM_RESIZE = -8, - SM_REPAIR = -9, + SM_RESIZE = -9, + SM_REPAIR = -10, }; enum SHOPRETURN { diff --git a/io.c b/io.c index b315df4..74f3c87 100644 --- a/io.c +++ b/io.c @@ -1044,10 +1044,10 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src tempob = addob(c->obpile, obname); } // show objects - o = doaskobject(c->obpile, "Describe which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE); + o = doaskobject(c->obpile, "Describe which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', NULL, AO_NONE, F_NONE); while (o) { describeob(o); - o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE); + o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, B_FALSE, '\0', NULL, AO_NONE, F_NONE); } if (tempob) killob(tempob); } @@ -2687,11 +2687,11 @@ object_t *askobject(obpile_t *op, char *prompt, int *count, char action, long o if (op->owner && isplayer(op->owner)) { showlong = B_FALSE; } - return doaskobject(op, prompt, count, showlong, B_TRUE, B_FALSE, action, opts, F_NONE); + return doaskobject(op, prompt, count, showlong, B_TRUE, B_FALSE, action, NULL, opts, F_NONE); } object_t *askobjectwithflag(obpile_t *op, char *prompt, int *count, char action, long opts, enum FLAG withflag) { - return doaskobject(op, prompt, count, B_TRUE, B_TRUE, B_FALSE, action, opts, withflag, F_NONE); + return doaskobject(op, prompt, count, B_TRUE, B_TRUE, B_FALSE, action, NULL, opts, withflag, F_NONE); } int contains(enum OBCLASS *array, int nargs, enum OBCLASS want) { @@ -2704,10 +2704,19 @@ int contains(enum OBCLASS *array, int nargs, enum OBCLASS want) { return B_FALSE; } -void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints) { +void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints, object_t *sellshop) { int lastclass = OC_NULL; int i; int useobletters = B_TRUE; + flag_t *sellflag[MAXCANDIDATES]; + int nsellflags = 0; + + if (sellshop) { + // determine sell value from the shop + getflags(sellshop->flags, sellflag, &nsellflags, F_SHOPACCEPTSFLAG, F_NONE); + } + + if (myletters) { useobletters = B_FALSE; } @@ -2747,6 +2756,36 @@ void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int fi snprintf(buf, BUFLEN, "%c %c - %s", selchar, useobletters ? mylist[i]->letter : myletters[i], obname); } + if (sellshop) { + int n,sellprice = 0; + flag_t *curflag = NULL; + char pricebuf[BUFLEN]; + int markdownpct; + for (n = 0; n < nsellflags; n++) { + if (obmatchessellflag(mylist[i], sellflag[n])) { + curflag = sellflag[n]; + break; + } + } + // doaskobject should have already only populated mylist[] with valid objects for this store! + assert(curflag); + + markdownpct = curflag->val[1]; + + // calculate sale price for 1 item + if ((markdownpct != NA) && (markdownpct != 0)) { + sellprice = applyshoppricemod( + pctof(markdownpct, real_getobvalue(mylist[i], 1)), + player, + sellshop, + SA_SELL); + + + // append this. + sprintf(pricebuf, " [$%d each]", sellprice); + strcat(buf, pricebuf); + } + } strcpy(pointsbuf, ""); if (showpoints && (mylist[i]->type->id != OT_GOLD)) { @@ -2783,7 +2822,14 @@ void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int fi *counter = i; } -object_t *doaskobject(obpile_t *op, char *prompt, int *count, int showlong, int forpickup, int showpoints, char action, long opts, ...) { + +// varargs are: +// F_xxx +// F_xxx +// F_NONE +// +// If you pass "sellshop", DONT also pass F_xxx. +object_t *doaskobject(obpile_t *op, char *prompt, int *count, int showlong, int forpickup, int showpoints, char action, object_t *sellshop, long opts, ...) { int c,i; char defchar = '\0'; static char defaults[52] = {'\0'}; @@ -2816,6 +2862,18 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int showlong, int va_end(flags); //dblog("nwantflags is %d",nwantflags); + // if selecting from a shop, we now override wantflags + if (sellshop) { + flag_t *sellflag[MAXCANDIDATES]; + int nsellflags = 0; + nwantflags = 0; + getflags(sellshop->flags, sellflag, &nsellflags, F_SHOPACCEPTSFLAG, F_NONE); + for (i = 0; i < nsellflags; i++) { + wantflag[nwantflags] = sellflag[i]->val[0]; + nwantflags++; + } + } + if (countobs(op, B_TRUE) <= 0) { // no objects here cls(); @@ -2918,7 +2976,7 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int showlong, int // list the objects y = 2; - listobs(mainwin, mylist, NULL, NULL, firstob, &i, lastline, &y, useobletters ? NULL : myletters , forpickup, showpoints); + listobs(mainwin, mylist, NULL, NULL, firstob, &i, lastline, &y, useobletters ? NULL : myletters , forpickup, showpoints, sellshop); } if (mylist[i] == NULL) { @@ -3152,7 +3210,7 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) { // list the objects y = 2; - listobs(mainwin, mylist, selected, selcount, firstob, &i, lastline, &y, useobletters ? NULL : myletters , B_TRUE, B_FALSE); + listobs(mainwin, mylist, selected, selcount, firstob, &i, lastline, &y, useobletters ? NULL : myletters , B_TRUE, B_FALSE, NULL); if (mylist[i] == NULL) { nextpage = -1; @@ -7369,12 +7427,12 @@ void doexplain(char *question) { void dofinaloblist(obpile_t *op) { object_t *o; - o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, '\0', AO_NONE, F_NONE); + o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, '\0', NULL, AO_NONE, F_NONE); while (o) { // describe it describeob(o); // ask for another one - o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE,'\0', AO_NONE, F_NONE); + o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE,'\0', NULL, AO_NONE, F_NONE); } real_clearmsg(B_TRUE); } @@ -7509,7 +7567,7 @@ void doinventory(obpile_t *op) { maxweight = getmaxcarryweight(player); pct = (packweight / maxweight) * 100; snprintf(buf, BUFLEN, "Inventory (%0.0f/%0.0f kg, %0.0f%%)", packweight, maxweight, pct); - o = doaskobject(op, buf, NULL, B_TRUE, B_TRUE, B_FALSE, '\0', AO_NONE, F_NONE); + o = doaskobject(op, buf, NULL, B_TRUE, B_TRUE, B_FALSE, '\0', NULL, AO_NONE, F_NONE); while (o) { // describe it describeob(o); @@ -9321,6 +9379,16 @@ void handleinput(void) { //dodrop(player->pack, B_SINGLE, player->cell->obpile); dodrop(player->pack, B_MULTIPLE, player->cell->obpile); break; + case 'o': // operate + addflag(player->flags, F_LASTCMD, NA, NA, NA, temp); + dooperate(player->pack); + break; + case 'O': + dooffer(); + break; + case 'P': // Pour + dopour(player->pack); + break; case 'W': // wear dowear(player->pack); break; @@ -9342,15 +9410,8 @@ void handleinput(void) { case 't': // throw dothrow(player->pack, NULL); break; - case 'P': // Pour - dopour(player->pack); - break; - case 'o': // operate - addflag(player->flags, F_LASTCMD, NA, NA, NA, temp); - dooperate(player->pack); - break; - case 'O': - dooffer(); + case 'x': // eXchange wepaon for secondary + exchangeweapon(player); break; // GAME FUNCTIONS case '=': // options diff --git a/io.h b/io.h index 9af4a4d..ce0e065 100644 --- a/io.h +++ b/io.h @@ -21,7 +21,7 @@ int confirm_injury_action(enum BODYPART bp, enum DAMTYPE dt, char *actionname); lifeform_t *askgod(char *prompt, int onlyprayed); object_t *askobject(obpile_t *op, char *title, int *count, char action, long opts); object_t *askobjectwithflag(obpile_t *op, char *title, int *count, char action, long opts, enum FLAG withflag); -object_t *doaskobject(obpile_t *op, char *title, int *count, int showlong, int forpickup, int showpoints, char action, long opts, ...); +object_t *doaskobject(obpile_t *op, char *title, int *count, int showlong, int forpickup, int showpoints, char action, object_t *sellshop, long opts, ...); int askobjectmulti(obpile_t *op, char *prompt, long opts); char askchar(char *prompt, char *validchars, char *def, int showchars, int maycancel); cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *srclf, int maxrange, enum LOFTYPE loftype, int wanttrail); @@ -103,7 +103,7 @@ void doheadingsmall(WINDOW *win, int y, int x, char *format, char *heading); void initgfx(void); void initprompt(prompt_t *p, char *q1); int keycodetokey(int keycode, int escseqok); -void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints); +void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints, object_t *sellshop); char *makedesc_god(lifeform_t *god, char *retbuf); char *makedesc_ob(object_t *o, char *retbuf); char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel); diff --git a/lf.c b/lf.c index 20422ea..0060b5a 100644 --- a/lf.c +++ b/lf.c @@ -1629,8 +1629,13 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar // ask for target cell if ((f = hasflag(sp->flags, F_TARGETTEDSPELL)) != NULL) { - targettype = f->val[0]; - needtovalidate = B_TRUE; + if ((f->val[1] != NA) && (f->val[2] != NA) && (power >= f->val[1]) && (power <= f->val[2])) { + targettype = f->val[0]; + needtovalidate = B_TRUE; + } else { + targettype = TT_NONE; + needtovalidate = B_FALSE; + } } else if (targcell) { targettype = TT_NONE; needtovalidate = B_FALSE; @@ -4070,6 +4075,90 @@ void enhanceskills(lifeform_t *lf) { } } } + } else if (f->id == F_LEVSPELLSCHOOLFROMX) { // select from X spells from given school + int nleft,highestlev = -1,n,i; + enum SPELLSCHOOL wantschool; + int possidx[MAXCANDIDATES],nposs; + char qbuf[BUFLEN]; + objecttype_t *ot; + + wantschool = f->val[1]; + nleft = f->val[2]; + // get all possible spells to learn, from the given school + sprintf(qbuf, "Learn which new spell (maxmp=%d):", getmaxmp(player)); + makespellchoicelist(&prompt, player, qbuf, "Describe which spell:", f->val[1], B_TRUE, B_FALSE, B_FALSE, player->maxmp); + // find highest possible level, and mark all choices as invalid. + for (i = 0; i < prompt.nchoices; i++) { + int thislev; + if (prompt.choice[i].heading) continue; + + ot = (objecttype_t *)(prompt.choice[i].data); + thislev = getspelllevel(ot->id); + if (thislev > highestlev) highestlev = thislev; + prompt.choice[i].valid = B_FALSE; + } + // select 1 from the highest possible level, and mark it ok + nposs = 0; + for (i = 0; i < prompt.nchoices; i++) { + int thislev; + if (prompt.choice[i].heading) continue; + + ot = (objecttype_t *)(prompt.choice[i].data); + thislev = getspelllevel(ot->id); + if (thislev == highestlev) { + possidx[nposs++] = i; + } + } + i = possidx[rnd(0,nposs-1)]; + prompt.choice[i].valid = B_TRUE; + nleft--; + + // TODO: select nleft-1 random other ones. + for (n = 0; n < nleft; n++) { + nposs = 0; + for (i = 0; i < prompt.nchoices; i++) { + if (!prompt.choice[i].valid && !prompt.choice[i].heading) { + possidx[nposs++] = i; + } + } + if (!nposs) { + break; + } + i = possidx[rnd(0,nposs-1)]; + prompt.choice[i].valid = B_TRUE; + } + // now let player select one, or pick randomly if a mosnter + if (isplayer(lf)) { + int done = B_FALSE; + while (!done) { + if (prompt.nchoices > 0) { + objecttype_t *ot; + getchoicestr(&prompt, B_TRUE, B_TRUE); + ot = prompt.result; + if (ot) { + if (prompt.whichq == 0) { // learn the spell + addtempflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL, FROMJOB); + done = B_TRUE; + } else { + describespell(ot); + } + } + } else { + msg("There are no new spells for you to learn at this time."); + done = B_TRUE; + } + } + } else { + if (prompt.nchoices > 0) { + // pick randomly + ot = (objecttype_t *)prompt.choice[rnd(0,prompt.nchoices)].data; + if (ot) { + addtempflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL, FROMJOB); + } + } + } + + } f->lifetime = LEVABILITYDONE; // mark as done. @@ -4155,6 +4244,46 @@ void enhanceskills(lifeform_t *lf) { } // end if gainedxplev } +int exchangeweapon(lifeform_t *lf) { + object_t *wep,*sec = NULL,*newsec = NULL; + // get secondary (if available) + sec = hasobwithflag(lf->pack, F_SECONDARY); + + + // get current weapon + wep = getweapon(lf); + // try to unweild current weapon + if (wep) { + if (unweild(lf, wep)) { + // error + return B_TRUE; + } else { + // success + addflag(wep->flags, F_SECONDARY, B_TRUE, NA, NA, NULL); + newsec = wep; + } + } + + + if (sec) { + killflagsofid(sec->flags, F_SECONDARY); + // try to weild secondary + if (weild(lf, sec)) { + // error + return B_TRUE; + } + } + // success! + if (newsec) { + char obname[BUFLEN]; + getobname(newsec, obname, 1); + msg("Spare weapon: %c - %s", newsec->letter, obname); + } else { + msg("Spare weapon: (none)"); + } + return B_FALSE; +} + void extinguishlf(lifeform_t *lf) { object_t *o,*nexto; for (o = lf->pack->first ; o ; o = nexto) { @@ -12540,7 +12669,7 @@ flag_t *levelabilityready(lifeform_t *lf) { if (!lfhasflag(lf, F_HASNEWLEVEL)) return NULL; - getflags(lf->flags, retflag, &nretflags, F_LEVABIL, F_LEVFLAG, F_LEVSPELL, F_LEVSPELLSCHOOL, F_LEVSKILL, F_NONE); + getflags(lf->flags, retflag, &nretflags, F_LEVABIL, F_LEVFLAG, F_LEVSPELL, F_LEVSPELLSCHOOL, F_LEVSPELLSCHOOLFROMX, F_LEVSKILL, F_NONE); for (i = 0; i < nretflags; i++) { f = retflag[i]; // we'll set lifetime to -1 while actually assigning these. @@ -12555,6 +12684,7 @@ flag_t *levelabilityready(lifeform_t *lf) { case F_LEVSKILL: case F_LEVSPELL: case F_LEVSPELLSCHOOL: + case F_LEVSPELLSCHOOLFROMX: if ((f->val[0] < 100) && (lf->newlevel == f->val[0])) { return f; } else if ((f->val[0] >= 100) && (lf->newlevel % (f->val[0] - 100) == 0) ) { @@ -12806,12 +12936,29 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml // bashing damage sometimes ko's if (!ko) { + int threshold,kochance; + int playerinvolved = B_FALSE; + + if (isplayer(lf)) { + playerinvolved = B_TRUE; + } else if (fromlf && isplayer(fromlf)) { + playerinvolved = B_TRUE; + } + + if (playerinvolved && godprayedto(R_GODMERCY)) { + threshold = -10; + kochance = 75; + } else { + threshold = -5; + kochance = 50; + } + if (damtype == DT_BASH) { int hpleftafterdam; - // if this damage would reduce the lf to between -1 and 0 hp + // if this damage would reduce the lf to between -threshold and 0 hp hpleftafterdam = lf->hp - amt; - if ((lf->hp > 1) && (hpleftafterdam >= -5) && (hpleftafterdam <= 0)) { - if (onein(2)) { + if ((lf->hp > 1) && (hpleftafterdam >= threshold) && (hpleftafterdam <= 0)) { + if (pctchance(kochance)) { ko = B_TRUE; } } @@ -17210,7 +17357,7 @@ void startlfturn(lifeform_t *lf) { if (!movedlastturn) { getflags(lf->flags, retflag, &nretflags, F_HOTFEET, F_NONE); - if (nretflags && !hasobofmaterial(lf->cell->obpile, MT_WATER)) { + if (nretflags && !hasobofmaterial(lf->cell->obpile, MT_WATER) && !isimmuneto(lf->flags, DT_FIRE)) { for (i = 0; i < nretflags; i++) { int dam; enum DAMTYPE dt; @@ -17315,7 +17462,7 @@ void startlfturn(lifeform_t *lf) { // effects from pack objects for (o = lf->pack->first ; o ; o = o->next) { // hot equipped objects? - if (isequipped(o) && !isweapon(o)) { + if (isequipped(o) && !isweapon(o) && !isimmuneto(lf->flags, DT_FIRE)) { f = hasflag(o->flags, F_HOT); if (f) { f->known = B_TRUE; diff --git a/lf.h b/lf.h index dc94b6d..1c68881 100644 --- a/lf.h +++ b/lf.h @@ -90,6 +90,7 @@ int eat(lifeform_t *lf, object_t *o); void endlfturn(lifeform_t *lf); void enhancerandomskill(lifeform_t *lf); void enhanceskills(lifeform_t *lf); +int exchangeweapon(lifeform_t *lf); void extinguishlf(lifeform_t *lf); object_t *eyesshaded(lifeform_t *lf); int fall(lifeform_t *lf, lifeform_t *fromlf, int announce); diff --git a/map.c b/map.c index 9bba32e..9a5a9b9 100644 --- a/map.c +++ b/map.c @@ -650,7 +650,7 @@ void getroomedge(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, } // if outlineid is -1, it's automatically assigned -region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid, int depthmod) { +region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid, int depthmod, int createdby) { region_t *a; regionoutline_t *ro,*poss[MAXCANDIDATES]; int nposs = 0; @@ -695,6 +695,7 @@ region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid, int a->rtype = findregiontype(rtype); a->parentregion = parent; a->depthmod = depthmod; + a->createdbymapid = createdby; if (outlineid == -1) { // randomly assign a regionoutline @@ -3220,12 +3221,20 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging if (failed) { + region_t *r,*nextr; dblog("********* got errors - restarting map creation. *********"); // remove map flags added during vault creation. killflagsofid(map->flags, F_MAPSHAPE); killflagsofid(map->flags, F_ROOMEXIT); // unlink stairs on adjacent maps unlinkstairsto(map); + // remove regions created by regionlinks in this map. + for (r = firstregion ; r ; r = nextr ){ + nextr = r->next; + if (r->createdbymapid == map->id) { + killregion(r); + } + } } } //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging @@ -3967,6 +3976,28 @@ void killmap(map_t *m) { } } +void killregion(region_t *r) { + region_t *nextone, *lastone; + // remove from list + nextone = r->next; + if (nextone != NULL) { + nextone->prev = r->prev; + } else { /* last */ + lastregion = r->prev; + } + + if (r->prev == NULL) { + /* first */ + nextone = r->next; + free(firstregion); + firstregion = nextone; + } else { + lastone = r->prev; + free (lastone->next ); + lastone->next = nextone; + } +} + // link a single cell up to the rest of the map. // make sure it links to an empty cell of a DIFFERENT roomid. // if 'wantfilled' is set, only link to "filled" cells. @@ -4460,9 +4491,8 @@ void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIO if (newregiontype != RG_MAINDUNGEON) { basedepth = getmapdifficulty(m); } - // does the new region exist yet ? // create a new region. - r = addregion(newregiontype, m->region, -1, basedepth); + r = addregion(newregiontype, m->region, -1, basedepth, m->id); // add stairs going to the new region, if required if (!c) { c = NULL; @@ -6184,8 +6214,8 @@ void initmaplayout(void) { addregionthing(lastregionoutline, 5, NA, NA, RT_RNDVAULTWITHTAG, NA, "caveboss"); // add initial regions - addregion(RG_WORLDMAP, NULL, -1, 0); - addregion(RG_HEAVEN, NULL, -1, 0); + addregion(RG_WORLDMAP, NULL, -1, 0, -1); + addregion(RG_HEAVEN, NULL, -1, 0, -1); } int isadjacent(cell_t *src, cell_t *dst) { diff --git a/map.h b/map.h index 402a9d5..bd81fb6 100644 --- a/map.h +++ b/map.h @@ -7,7 +7,7 @@ map_t *addmap(void); lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int amt, int autogen, int *nadded); object_t *addrandomob(cell_t *c); int addrandomthing(cell_t *c, int obchance, int *nadded); -region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid, int depthmod); +region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid, int depthmod, int createdby); regionoutline_t *addregionoutline(enum REGIONTYPE rtype); regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum REGIONTHING whatkind, int value, char *what); regiontype_t *addregiontype(enum REGIONTYPE id, char *name, int pluralname, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major, int depthmod); @@ -146,6 +146,7 @@ void killcell(cell_t *c); void killcelltype(celltype_t *ct); void killfakes(map_t *map, cell_t *cell); void killmap(map_t *m); +void killregion(region_t *r); int linkexit(cell_t *c, int wantfilled, int *ncellsadded); int linkexits(map_t *m, int roomid); int linkholes(map_t *map); diff --git a/objects.c b/objects.c index 25e8ddb..3e11259 100644 --- a/objects.c +++ b/objects.c @@ -1836,11 +1836,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes vault_t *v; v = getcellvault(o->pile->where); // apply cost to shop items + /* if (v && hasflag(v->flags, F_VAULTISSHOP)) { if (canpickup(NULL, o, 1)) { addflag(o->flags, F_SHOPITEM, getobvalue(o), getroomid(o->pile->where), NA, NULL); } } + */ // blood will stain things on the ground if (o->material->id == MT_BLOOD) { object_t *poss[MAXPILEOBS],*oo; @@ -2493,10 +2495,12 @@ void brightflash(cell_t *centre, int range, lifeform_t *immunelf) { } } +/* void calcshopprice(object_t *o, flag_t *shopitemflag) { // initial value shopitemflag->val[0] = (int) getshopprice(o, o->pile->owner); } +*/ int canbepoisoned(enum OBTYPE oid) { flag_t *f; @@ -4626,6 +4630,11 @@ char *getobequipinfo(object_t *o, char *buf) { } } + f = hasflag(o->flags,F_SECONDARY); + if (f) { + strcat(buf, " (spare weapon)"); + } + f = hasflag(o->flags,F_EQUIPPED); if (f) { if (f->val[0] == BP_WEAPON) { @@ -5425,7 +5434,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan if (shopitem) { char pricebuf[BUFLEN]; // get price for _player_ - snprintf(pricebuf, BUFLEN, " [$%d%s]", (int)getshopprice(o, player), o->pile->owner ? ", unpaid" : ""); + snprintf(pricebuf, BUFLEN, " [$%d%s]", (int)getshopprice(o, player, NULL), o->pile->owner ? ", unpaid" : ""); strcat(localbuf, pricebuf); } @@ -6237,9 +6246,9 @@ int getshatterdam(object_t *o) { return shatterdam; } -float getshopprice(object_t *o, lifeform_t *buyer) { +float getshopprice(object_t *o, lifeform_t *buyer, object_t *shop) { float val; - val = applyshoppricemod(getobvalue(o), buyer); + val = applyshoppricemod(getobvalue(o), buyer, shop, SA_BUY); return val; } @@ -7954,6 +7963,8 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) { if (o) { + killflagsofid(o->flags, F_SECONDARY); + if (dst->owner && isplayer(dst->owner) && isblessknown(o)) { o->blessknown = B_TRUE; } @@ -8000,16 +8011,19 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) { } + /* // special effects when an object moves f = hasflag(o->flags, F_SHOPITEM); if (f) { // recalculate object price baesd on who is holding it calcshopprice(o, f); } + */ // special effects if a lifeform picked up an object if (dst->owner) { - flag_t *f; + //flag_t *f; + /* // picked up an object in a shop f = hasflag(o->flags, F_SHOPITEM); if (f) { @@ -8020,6 +8034,7 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) { askforpayment(shk, dst->owner); } } + */ // did this make us burdened? if (isplayer(dst->owner)) { @@ -14136,7 +14151,7 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob // (firearm == null) means we are throwing. acc = getobaccuracy(firearm, thrower); - // for each cell travelled, lower accuracy, based on skill. + // for each cell travelled after the first, lower accuracy, based on skill. slev = getskill(thrower, whichskill); // masterwork firearms? @@ -14154,7 +14169,9 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob default: case PR_INEPT: cellpenalty = 32; break; } - howfar = getcelldist(thrower->cell, where); + howfar = getcelldist(thrower->cell, where) - 1; + + limit(&howfar, 0, NA); acc -= (cellpenalty*howfar); diff --git a/objects.h b/objects.h index 8e86deb..c1a0eb8 100644 --- a/objects.h +++ b/objects.h @@ -149,7 +149,7 @@ enum SPELLSCHOOL getschool(enum OBTYPE sid); char *getschoolname(enum SPELLSCHOOL sch); char *getschoolnameshort(enum SPELLSCHOOL sch); int getshatterdam(object_t *o); -float getshopprice(object_t *o, lifeform_t *buyer); +float getshopprice(object_t *o, lifeform_t *buyer, object_t *shop); int getstairdirection(object_t *o); enum SKILLLEVEL gettechlevel(enum OBTYPE oid); int getthrowdam(object_t *o); diff --git a/save.c b/save.c index fefb3fc..bf23d19 100644 --- a/save.c +++ b/save.c @@ -663,7 +663,7 @@ int loadregions(FILE *f) { region_t *r; enum REGIONTYPE rtid; int rid; - int outlineid,parentid,nthings; + int outlineid,parentid,nthings,createdby; fscanf(f, "startregion\n"); fscanf(f, " rid:%d\n",(int *)&rid); fscanf(f, " rtypeid:%d\n",(int *)&rtid); @@ -671,8 +671,9 @@ int loadregions(FILE *f) { fscanf(f, " parentregion:%d\n",&parentid); fscanf(f, " nthings:%d\n",&nthings); fscanf(f, " depthmod:%d\n",&depthmod); + fscanf(f, " createdby:%d\n",&createdby); fscanf(f, "endregion\n"); - r = addregion(rtid, (parentid == -1) ? NULL : findregion(parentid), outlineid, depthmod); + r = addregion(rtid, (parentid == -1) ? NULL : findregion(parentid), outlineid, depthmod, createdby); r->id = rid; r->nthings = nthings; if (db) dblog("Loaded region #%d / %d",n+1, numregions); @@ -1069,6 +1070,7 @@ int saveregions(FILE *f) { fprintf(f, " parentregion:%d\n",r->parentregion ? r->parentregion->id : -1); fprintf(f, " nthings:%d\n",r->nthings); fprintf(f, " depthmod:%d\n",r->depthmod); + fprintf(f, " createdby:%d\n",r->createdbymapid); fprintf(f, "endregion\n"); } fprintf(f, "end_regions\n"); diff --git a/shops.c b/shops.c index 21ede5a..c822d4c 100644 --- a/shops.c +++ b/shops.c @@ -29,24 +29,40 @@ extern prompt_t prompt; extern lifeform_t *player; extern WINDOW *mainwin; -float applyshoppricemod(float origprice, lifeform_t *lf) { +// dir == 1 means "better skills increase the price" +// dir == -1 means "better skills decrease the price" +float applyshoppricemod(float origprice, lifeform_t *lf, object_t *shop, enum SHOPACTION action) { float newprice; + float pricepct = 100; + int dir; + if (action == SA_BUY) { + dir = -1; + } else { + dir = 1; + } if (lf) { - float pricepct = 100; enum SKILLLEVEL slev; // price goes up/down for charisma (+/- 25%) // high bonus = lower price. - pricepct -= (getstatmod(lf, A_CHA)/2); + pricepct += ((getstatmod(lf, A_CHA)/2) * dir); // reduce based on speech (up to -30%); slev = getskill(lf, SK_SPEECH); if (slev) { - pricepct -= (slev*5); + pricepct += ((slev*5)*dir); } - newprice = pctof(pricepct, origprice); - } else { - newprice = origprice; } + + if (shop) { + flag_t *f; + f = hasflag(shop->flags, F_SHOPDONATED); + if (f) { + pricepct += ((((float)f->val[0]) / 100.0) * dir); + } + } + + newprice = pctof(pricepct, origprice); + if (origprice > 0) { limitf(&newprice, 1, NA); } @@ -57,7 +73,7 @@ int canafford(lifeform_t *lf, int amt) { int goldamt = 0,gemamt = 0; goldamt = countmoney(lf->pack); if (getskill(lf, SK_SPEECH) >= PR_NOVICE) { - gemamt = applyshoppricemod(counthighestobflagvalue(lf->pack, F_GEM), lf); // adjust using charisma etc + gemamt = applyshoppricemod(counthighestobflagvalue(lf->pack, F_GEM), lf, NULL, SA_BUY); // adjust using charisma etc } if ((goldamt >= amt ) || (gemamt >= amt) || hasob(lf->pack, OT_CREDITCARD)) { return B_TRUE; @@ -65,12 +81,12 @@ int canafford(lifeform_t *lf, int amt) { return B_FALSE; } -int getshopblessprice(object_t *o) { +int getshopblessprice(object_t *o, object_t *shop) { int cost = 0; int remcursecost, blesscost,surcharge; - remcursecost = applyshoppricemod(DEF_REMCURSECOST, player); - blesscost = applyshoppricemod(DEF_BLESSCOST, player); - surcharge = applyshoppricemod(DEF_SURCHARGE, player); + remcursecost = applyshoppricemod(DEF_REMCURSECOST, player, shop, SA_BUY); + blesscost = applyshoppricemod(DEF_BLESSCOST, player, shop, SA_BUY); + surcharge = applyshoppricemod(DEF_SURCHARGE, player, shop, SA_BUY); if (iscursed(o)) { cost = remcursecost; @@ -84,13 +100,22 @@ int getshopblessprice(object_t *o) { return cost; } +int obmatchessellflag(object_t *o, flag_t *f) { + if ((f->val[0] == F_NONE) || hasflag(o->flags, f->val[0])) { + if ((f->val[2] == NA) || (o->type->obclass->id == f->val[2])) { + return B_TRUE; + } + } + return B_FALSE; +} + 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; + int ntaken = 0; + int ngiven = 0; flag_t *f; object_t *o; strcpy(toptext, ""); @@ -163,22 +188,25 @@ void shop(lifeform_t *lf, object_t *vm) { shoparg = NULL; } else if (curmenu == SM_PURCHASEITEMS) { shopfunc = shoppurchase; - shoparg = &npurchased; + shoparg = &ntaken; } else if (curmenu == SM_DETECTCURSE) { shopfunc = shopdetectcurse; shoparg = NULL; } else if (curmenu == SM_DONATE) { shopfunc = shopdonate; - shoparg = &ndonated; + shoparg = &ngiven; } else if (curmenu == SM_REST) { shopfunc = shoprest; - shoparg = &ndonated; + shoparg = &ngiven; } else if (curmenu == SM_RESIZE) { shopfunc = shopresize; - shoparg = &ndonated; + shoparg = &ngiven; } else if (curmenu == SM_REPAIR) { shopfunc = shoprepair; - shoparg = &ndonated; + shoparg = &ngiven; + } else if (curmenu == SM_SELLITEMS) { + shopfunc = shopsell; + shoparg = &ngiven; } if (shopfunc) { @@ -297,13 +325,13 @@ void shop(lifeform_t *lf, object_t *vm) { if (strlen(buf)) { msg("\"%s\"", buf); } - } else if (npurchased > ndonated) { + } else if (ntaken > ngiven) { 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) { + } else if (ngiven > ntaken) { 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; @@ -332,7 +360,7 @@ enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char * } if (cost) { - cost = applyshoppricemod(cost, lf); + cost = applyshoppricemod(cost, lf, vm, SA_BUY); } if (!cost) { @@ -366,21 +394,23 @@ enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char * 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_TRUE, B_FALSE, B_FALSE, '\0', AO_NONE, wantflag, F_NONE); + */ + o = doaskobject(lf->pack, "What will you donate?", &count, B_TRUE, B_FALSE, B_FALSE, '\0', vm, AO_NONE, F_NONE); // validate it if (o) { + int goldgiven = 0; + flag_t *f; // can we remove it? if (isequipped(o)) { if (takeoff(lf, o)) { @@ -401,47 +431,50 @@ enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *topte if (count > o->amt) count = o->amt; } - // okay it! - if ((wantoc != OC_NONE) && (o->type->obclass->id != wantoc)) { - msg("Sorry, we can't accept that!"); more(); + if (o->type->id == OT_GOLD) { + givemoney(lf, NULL, count); + (*ndonated)++; + goldgiven += count; } else { - int goldgiven = 0; - if (o->type->id == OT_GOLD) { - givemoney(lf, NULL, count); - (*ndonated)++; - goldgiven += count; + object_t *newob; + char let; + if (vm->contents->first) { + let = vm->contents->last->letter + 1; } 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)++; - practice(player, SK_SPEECH, 1); + let = 'a'; } + newob = moveob(o, vm->contents, count); + newob->letter = let; + (*ndonated)++; + practice(player, SK_SPEECH, 1); + goldgiven += getobvalue(o); + } - if ((vm->type->id == OT_TEMPLE) && goldgiven) { - flag_t *f; - f = hasflag(o->flags, F_LINKGOD); - if (f) { - lifeform_t *god = NULL; - god = findgod(f->val[0]); - msg("%s appreciates your kind donation.", god->race->name); - modpiety(god->race->id, (goldgiven/2)); - } else { - msg("We appreciate your kind donation."); - } + if ((vm->type->id == OT_TEMPLE) && goldgiven) { + flag_t *f; + f = hasflag(o->flags, F_LINKGOD); + if (f) { + lifeform_t *god = NULL; + god = findgod(f->val[0]); + msg("%s appreciates your kind donation.", god->race->name); + modpiety(god->race->id, (goldgiven/2)); } else { - msg("Thanks!"); more(); + msg("We appreciate your kind donation."); } + } else { + msg("Thanks!"); more(); + } + + f = hasflag(vm->flags, F_SHOPDONATED); + if (f) { + f->val[0] += goldgiven; + } else { + addflag(vm->flags, F_SHOPDONATED, goldgiven, NA, NA, NULL); } } else { return SR_BACK; } + return SR_CONTINUE; } @@ -464,7 +497,7 @@ enum SHOPRETURN shopabsolve(lifeform_t *lf, object_t *vm, int starty, char *topt if (piety < 100) { cost = (100 - piety) * 3; - cost = applyshoppricemod(cost, lf); + cost = applyshoppricemod(cost, lf, vm, SA_BUY); mvwprintw(mainwin, y, 0, "It will cost $%d to absolve your sins against %s.", cost, god->race->name); y += 2; } else { @@ -504,9 +537,9 @@ enum SHOPRETURN shopbless(lifeform_t *lf, object_t *vm, int starty, char *toptex int remcursecost, blesscost,surcharge; y = starty; - remcursecost = applyshoppricemod(DEF_REMCURSECOST, lf); - blesscost = applyshoppricemod(DEF_BLESSCOST, lf); - surcharge = applyshoppricemod(DEF_SURCHARGE, lf); + remcursecost = applyshoppricemod(DEF_REMCURSECOST, lf, vm, SA_BUY); + blesscost = applyshoppricemod(DEF_BLESSCOST, lf, vm, SA_BUY); + surcharge = applyshoppricemod(DEF_SURCHARGE, lf, vm, SA_BUY); mvwprintw(mainwin, y, 0, "So long as their aura is known, we can bestow a blessing on most items."); y += 2; @@ -527,7 +560,7 @@ enum SHOPRETURN shopbless(lifeform_t *lf, object_t *vm, int starty, char *toptex 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)); + sprintf(costbuf, "%-60s($%d)", buf, getshopblessprice(o, vm)); addchoice(&prompt, o->letter, costbuf, costbuf, o, NULL); } } @@ -537,7 +570,7 @@ enum SHOPRETURN shopbless(lifeform_t *lf, object_t *vm, int starty, char *toptex o = (object_t *)prompt.result; if (o) { int cost; - cost = getshopblessprice(o); + cost = getshopblessprice(o, vm); if (countmoney(player->pack) < cost) { msg("You cannot afford the $%d blessing price.", cost); more(); @@ -570,7 +603,7 @@ enum SHOPRETURN shopmiracle(lifeform_t *lf, object_t *vm, int starty, char *topt piety = getpiety(god->race->id); cost = 1000 - piety; - cost = applyshoppricemod(cost,lf); + cost = applyshoppricemod(cost,lf, vm, SA_BUY); if (godisangry(god->race->id)) { mvwprintw(mainwin, y, 0, "%s does not currently find you worthy of miracles.", god->race->name); @@ -625,7 +658,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top enum COLOUR col; getshopobname(o, obname, o->amt); - thisprice = (int)getshopprice(o, player); + thisprice = (int)getshopprice(o, player, vm); snprintf(buf, BUFLEN, "%c - %s", o->letter, obname); if (shopmode == BUY) { @@ -677,7 +710,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top char answer; int value; - value = (int)getshopprice(o, player); + value = (int)getshopprice(o, player, vm); slev = getskill(player, SK_THIEVERY); // confirm @@ -715,7 +748,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top } else if ((slev >= PR_NOVICE) && hasflag(oo->flags, F_GEM)) { // only list gems which are worth enough int thisval; - thisval = applyshoppricemod(getobvalue(oo), player); + thisval = applyshoppricemod(getobvalue(oo), player, vm, SA_SELL); if (thisval >= value) { valid = B_TRUE; sprintf(fullname, "%s (worth $%d)", moneyname, thisval); @@ -780,7 +813,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top int gemsneeded; char gemname[BUFLEN]; int valpergem; - valpergem = applyshoppricemod(real_getobvalue(money, 1), player); + valpergem = applyshoppricemod(real_getobvalue(money, 1), player, vm, SA_SELL); gemsneeded = value / valpergem; limit(&gemsneeded, 1, NA); // (in case gem is worth more than object) getobname(money, gemname, gemsneeded); @@ -887,7 +920,7 @@ enum SHOPRETURN shoprepair(lifeform_t *lf, object_t *vm, int starty, char *topte // determine cost... f = hasflag(o->flags, F_OBHP); - thiscost = applyshoppricemod((f->val[1] - f->val[0]) * hpcost, lf); + thiscost = applyshoppricemod((f->val[1] - f->val[0]) * hpcost, lf, vm, SA_BUY); // add to prompt getobname(o, obname, o->amt); sprintf(desc, "%s ($%d)", obname,thiscost); @@ -919,7 +952,7 @@ enum SHOPRETURN shoprepair(lifeform_t *lf, object_t *vm, int starty, char *topte int thiscost; // determine cost... f = hasflag(o->flags, F_OBHP); - thiscost = applyshoppricemod((f->val[1] - f->val[0]) * hpcost, lf); + thiscost = applyshoppricemod((f->val[1] - f->val[0]) * hpcost, lf, vm, SA_BUY); if (thiscost > countmoney(player->pack)) { msg("You can't afford to repair that item!"); more(); return SR_CONTINUE; @@ -941,7 +974,7 @@ enum SHOPRETURN shopresize(lifeform_t *lf, object_t *vm, int starty, char *topte int resizecost; y = starty; - resizecost = applyshoppricemod(pctof(75, DEF_RESIZECOST), lf); + resizecost = applyshoppricemod(pctof(75, DEF_RESIZECOST), lf, vm, SA_BUY); mvwprintw(mainwin, y, 0, "For just $%d per item, we can resize weapons or armour to fit you.", resizecost); y ++; mvwprintw(mainwin, y, 0, "(item quality will not be affected)"); y += 2; @@ -992,7 +1025,7 @@ enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext y = starty; - cost = applyshoppricemod(100, lf); + cost = applyshoppricemod(100, lf, vm, SA_BUY); mvwprintw(mainwin, y, 0, "We offer good quality rooms for only $%d per hour.", cost); y += 2; @@ -1040,3 +1073,91 @@ enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext more(); return SR_QUIT; } + +enum SHOPRETURN shopsell(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *nsold) { + int count = 0; + flag_t *sellflag[MAXCANDIDATES],*curflag = NULL ; + char buf[BUFLEN]; + int nsellflags; + object_t *o; + int y,ch,i; + y = starty; + + *nsold = 0; + + mvwprintw(mainwin, y, 0, "We offer good prices for quality items."); y += 2; + mvwprintw(mainwin, y, 0, "Sell items [y/n]? ", countmoney(lf->pack)); + + ch = getch(); + if (ch != 'y') { + return SR_BACK; + } + + getflags(vm->flags, sellflag, &nsellflags, F_SHOPACCEPTSFLAG, F_NONE); + + // ask what to sell + sprintf(buf, "What will you sell (you have $%d)?", countmoney(lf->pack)); + + o = doaskobject(player->pack, buf, &count, B_TRUE, B_FALSE, B_FALSE, '\0', vm, AO_NONE, F_NONE); + if (!o) { + return SR_BACK; + } + + // validate it + if (o) { + object_t *newob; + char let, paymentbuf[BUFLEN],obname[BUFLEN],buf[BUFLEN]; + int sellprice; + // can we remove it? + if (isequipped(o)) { + if (takeoff(lf, o)) { + more(); + return SR_CONTINUE; + } + } + + // get matching sell flag + curflag = NULL; + for (i = 0; i < nsellflags; i++) { + if (obmatchessellflag(o, sellflag[i])) { + curflag = sellflag[i]; + break; + } + } + assert(curflag); + + // calculate sale price + sellprice = applyshoppricemod ( + pctof(curflag->val[1], real_getobvalue(o, 1)), + lf, vm, SA_SELL ); + sellprice *= count; + + // confirm + getobname(o, obname, count); + sprintf(buf, "Sell %s for $%d?", obname, sellprice); + ch = askchar(buf, "yn","n", B_TRUE, B_FALSE); + if (ch == 'y') { + // move object to the shop + if (vm->contents->first) { + let = vm->contents->last->letter + 1; + } else { + let = 'a'; + } + newob = moveob(o, vm->contents, count); + newob->letter = let; + (*nsold)++; + // give money to player + sprintf(paymentbuf, "%d gold coins", sellprice); + addob(player->pack, paymentbuf); + + practice(player, SK_SPEECH, 1); + msg("Pleasure doing business with you!!"); more(); + } + } else { + return SR_BACK; + } + return SR_CONTINUE; +} + + + diff --git a/shops.h b/shops.h index c3e8ac8..ab629be 100644 --- a/shops.h +++ b/shops.h @@ -1,8 +1,9 @@ #include "defs.h" -float applyshoppricemod(float origprice, lifeform_t *lf); +float applyshoppricemod(float origprice, lifeform_t *lf, object_t *shop, enum SHOPACTION action); int canafford(lifeform_t *lf, int amt); -int getshopblessprice(object_t *o); +int getshopblessprice(object_t *o, object_t *shop); +int obmatchessellflag(object_t *o, flag_t *f); 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); @@ -13,4 +14,6 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top enum SHOPRETURN shoprepair(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased); enum SHOPRETURN shopresize(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); +enum SHOPRETURN shopsell(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased); + diff --git a/spell.c b/spell.c index c9110f1..fc5d7f9 100644 --- a/spell.c +++ b/spell.c @@ -2043,7 +2043,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // this map will be destroyed when you leave it. r = findregionbytype(RG_STOMACH); if (!r) { - r = addregion(RG_STOMACH, NULL, -1, 0); + r = addregion(RG_STOMACH, NULL, -1, 0, user->cell->map->id); } // create stomach map newmap = addmap(); @@ -7239,7 +7239,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int seen; if (targcell->obpile->first) { - targob = doaskobject(targcell->obpile, "Target which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', AO_NONE, F_NONE); + targob = doaskobject(targcell->obpile, "Target which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', NULL, AO_NONE, F_NONE); } if (!targob) { @@ -8736,17 +8736,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_PURIFYFOOD) { object_t *o,*nexto; + obpile_t *op; int ndone = 0; - if (!target) { - target = caster; + if (power < 3) { + targcell = caster->cell; } - if (!o) { - fizzle(caster); - return B_TRUE; + if (targcell->lf) { + target = targcell->lf; + op = targcell->lf->pack; + } else { + target = NULL; + op = targcell->obpile; } - - for (o = target->pack->first ; o ; o = nexto) { + for (o = op->first ; o ; o = nexto) { char obname[BUFLEN]; int donesomething = B_FALSE; flag_t *f; @@ -8754,14 +8757,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ getobname(o, obname, o->amt); - if (o->type->id == OT_POT_POISON) { - if (isplayer(target)) { + if ((f = hasflag(o->flags, F_PURIFIESTO)) != NULL) { + if (target && isplayer(target)) { msg("Your %s sparkles for a while.", noprefix(obname)); - makeknown(o->type->id); // you now know that it was poison. + } else if (haslos(player, targcell)) { + msg("%s sparkles for a while.", obname); } - o->type = findot(OT_POT_WATER); + o->type = findot(f->val[0]); if (isplayer(target)) { - makeknown(o->type->id); // you now know what water is too. + // you now know what water is. + // you DONT know what the original type was, since it could have been a number + // of different things. + makeknown(o->type->id); } donesomething = B_TRUE; ndone++; @@ -8784,13 +8791,20 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (donesomething) { - if (isplayer(target)) { + if (target && isplayer(target)) { if (isdrinkable(o)) { msg("Your %s looks more clean now.", noprefix(obname)); - } else { + } else if (isedible(o)) { msg("Your %s looks more fresh now.", noprefix(obname)); } if (seenbyplayer) *seenbyplayer = B_TRUE; + } else if (haslos(player, targcell)) { + if (isdrinkable(o)) { + msg("%s looks more clean now.", obname); + } else if (isedible(o)) { + msg("%s looks more fresh now.", obname); + } + if (seenbyplayer) *seenbyplayer = B_TRUE; } } } @@ -9593,8 +9607,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } else if (spellid == OT_S_STICKTOSNAKE) { int i; - cell_t *poss[MAXCANDIDATES]; - int nposs; + //cell_t *poss[MAXCANDIDATES]; + //int nposs; race_t *raceposs[MAXCANDIDATES],*r; int nraceposs = 0; cell_t *c = NULL,*newcell = NULL; @@ -9625,6 +9639,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } + /* poss[0] = caster->cell; nposs = 1; for (i = 0; i < caster->nlos; i++) { @@ -9632,54 +9647,53 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ poss[nposs++] = caster->los[i]; } } + */ // for each cell we can see... (including our own) for (i = 0; i < caster->nlos; i++) { - c = poss[i]; - if (c->lf) { - if (cansee(caster, c->lf)) { - for (o = c->lf->pack->first ; o ; o = nexto) { - nexto = o->next; - if ( hasflag(o->flags, F_RODSHAPED) && - (!isequipped(o) || (c->lf != caster)) && - (o->blessed == B_UNCURSED) && - !hasflag(o->flags, F_HASBRAND)) { - char obname[BUFLEN]; - char lfname[BUFLEN]; - getobname(o, obname, o->amt); - getlfname(c->lf, lfname); - newcell = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND); - if (newcell) { - lifeform_t *snake; - // add a snake there. - snake = addlf(newcell, raceposs[rnd(0,nraceposs-1)]->id, 1); - if (snake) { - msg("%s%s %s transforms into a snake!",lfname, - getpossessive(lfname), - noprefix(obname)); - killflagsofid(snake->flags, F_XPVAL); - addflag(snake->flags, F_XPVAL, 0, NA, NA, NULL); - killflagsofid(snake->flags, F_FLEEONDAM); - killflagsofid(snake->flags, F_FLEEONHPPCT); - addflag(snake->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); - makefriendly(snake, PERMENANT); - if (c->lf == caster) { - char fullobname[BUFLEN]; - getobnametrue(o, fullobname, 1); - killflagsofid(snake->flags, F_CORPSETYPE); - addflag(snake->flags, F_CORPSETYPE, NA, NA, NA, fullobname); - } - killob(o); - ndone++; - } - } else { - msg("%s%s %s quivers for a moment.",lfname, getpossessive(lfname), + c = caster->los[i]; + if (c->lf && cansee(caster, c->lf)) { + for (o = c->lf->pack->first ; o ; o = nexto) { + nexto = o->next; + if ( hasflag(o->flags, F_RODSHAPED) && + (!isequipped(o) || (c->lf != caster)) && + (o->blessed == B_UNCURSED) && + !hasflag(o->flags, F_HASBRAND)) { + char obname[BUFLEN]; + char lfname[BUFLEN]; + getobname(o, obname, o->amt); + getlfname(c->lf, lfname); + newcell = getrandomadjcell(c, WE_WALKABLE, B_NOEXPAND); + if (newcell) { + lifeform_t *snake; + // add a snake there. + snake = addlf(newcell, raceposs[rnd(0,nraceposs-1)]->id, 1); + if (snake) { + msg("%s%s %s transforms into a snake!",lfname, + getpossessive(lfname), noprefix(obname)); + killflagsofid(snake->flags, F_XPVAL); + addflag(snake->flags, F_XPVAL, 0, NA, NA, NULL); + killflagsofid(snake->flags, F_FLEEONDAM); + killflagsofid(snake->flags, F_FLEEONHPPCT); + addflag(snake->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); + makefriendly(snake, PERMENANT); + if (c->lf == caster) { + char fullobname[BUFLEN]; + getobnametrue(o, fullobname, 1); + killflagsofid(snake->flags, F_CORPSETYPE); + addflag(snake->flags, F_CORPSETYPE, NA, NA, NA, fullobname); + } + killob(o); ndone++; } + } else { + msg("%s%s %s quivers for a moment.",lfname, getpossessive(lfname), + noprefix(obname)); + ndone++; } } } - } else { // ie. no lf there + } else { // ie. no lf there, or can't see it for (o = c->obpile->first ; o ; o = nexto) { lifeform_t *snake = NULL; nexto = o->next;