- [+] redo throw hit%. even inept sk_throwing should have 40% or so to

hit at point blank range.
    - [+] only reduce hit% after first cell? 
- [+] increase change of player ko with yumi
- [+] tranq dart and nanodart should be rodshaped.
- [+] genericise purification
    - [+] F_PURIFIESTO v0 = newobject
    - [+] add toadstool -> shiitake
    - [+] posion potion -> water
    - [+] acid potion -> water
    - [+] rum -> water
    - [+] DONT make the original object type known now 
- [+] higher level purify food lets you select a cell!
    - [+] need f_targettedspell v1 & v2 to specify power.
- [+] druid should get to pick one of 3 spells (from each available
      level) upon levelup, not anything!
    - [+] implement f_levspellschoolfromx
    - [+] TEST!
- [+] implement secondary weapon swap with 'x'
    - [+] initial press:  unweild curwep. if successful, mark as
          secondayr.
    - [+] subsequent presses:  find secondary wep (or fail). remember
          cur. weild secondary. if successful, remove scondary flag and
          mark old cur wep as secondary
    - [+] when you move an object, it loses secondary flag.
- [+] BUG:  I had TWO regions with rtype->id == RG_CAVE!!!
    - [+] have added debug code
    - [+] think this is fixed - need to remove created regions when i
          regenerate a map.
- [+] should be able to sell gems to jewelery store
    - [+] sm_sellitems
    - [+] shopsell()
    - [+] shop has f_cansellobclass xxx, val[0] = pct of full price you
          can sell for. normally 50% but 75% for gems. 
    - [+] allow COUNT - modified askobjectwithflag ?
        - [+] OR add an extra *sellshop option to doaskobject ??
        - [+] if this is set, only allow selection of objects which
              match the shop's f_shopsell flags
            - [+] ie. replace wantflags[]
        - [+] when passing this, don't  also pass wantflag args!!!
    - [+] rename shopsell flag to  f_shopacceptsflag
    - [+] accept F_NONE in shopacceptsflag
    - [+] make shopdonate use the same code
- [+] make donating to shops lower their prices ?
    - [+] for each 100 value you donate, reduce prices by 1%
        - [+] ie. donate 1000 worth, reduce by 10% = 1 level of speech
              skill
- [+] change shopsell to use  applyshoppricemod
    - [+] applyshoppricemod needs a new arg - up or down
    - [+] check code in objects.c for naming too!  listobs()
This commit is contained in:
Rob Pearce 2012-02-07 02:50:17 +00:00
parent 734a6c5d90
commit 24d95368b6
16 changed files with 641 additions and 187 deletions

39
data.c
View File

@ -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);

Binary file not shown.

View File

@ -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

38
defs.h
View File

@ -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 {

101
io.c
View File

@ -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

4
io.h
View File

@ -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);

163
lf.c
View File

@ -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;

1
lf.h
View File

@ -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);

40
map.c
View File

@ -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) {

3
map.h
View File

@ -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);

View File

@ -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);

View File

@ -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);

6
save.c
View File

@ -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");

263
shops.c
View File

@ -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;
}

View File

@ -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);

130
spell.c
View File

@ -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;