From 9da88f06e3f38ebbfbcad2ac20aedd3fe81c85a4 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Mon, 5 Dec 2011 17:03:47 +0000 Subject: [PATCH] - [+] ob1() macros - [+] healing potions should heal even "permenant" injuries - [+] potions/spells - [+] summon decoy (chicken horde) spell - "friends!" - [+] potion of spider climb (arachnid adhesion) - [+] gloves of the spider - [+] F_startobwepskill sk_shortblades etc - [+] change mosnter starting weapons to be based on wepsk, not specific named weapons - [+] make wrapprint cope properly with 0 length strings - [+] fix io.c showlfstats layout - [+] fountains of xp should always dry up after one use! - [+] plants shouldn't leave footprints! - [+] fix overcomplicated code in updateknowncells - [+] you always "see" allies following you down/up stairs, even if they are behind you. - [+] remove dtresist slash from skeletons - their bone skin reduces this already. - [+] leave dtresist pierce because it's hard to hit them. - [+] confirm gold amount when donating to shops - [+] increase piety by half of any gold donated to temples - [+] move hp, mp, sp to same line as target, and make them into bars - [+] HP:[ 11 / 11 ] - [+] makebar(window,min,max, loss,barcol, losscol) - [+] print the prefix: "HP:[" - [+] construct the bar string to fit into 10 chars: " 11 / 11 " - [+] print it one char at a time, setting bg as follows: - [+] background: - [+] 0 - min is barcol - [+] min+1 - min+loss is losscol - [+] rest is black - [+] print the suffix: "] " - [+] remember last dam amount for hp. - [+] show mp and stamina like this too. - [+] update viewpoint sooner when moving vertically - [+] if you can't comprehend the contents of a spellbook, don't ID it! - [+] hpbar: pass textcol and texcolwithbg - [+] show f_stability in @e - [+] don't identify tech inside shops if it's beyond your skill level - [+] bug: "a cursed +-1 ring of dexterity" - [+] enraged or deaf lfs shouldn't respond to chats - [+] drawbar: show mp/sp text in orange if it's at 0. - [+] allow vegetarians to eat frozen corpses. - [+] anything flying + stunned loses flying. - [+] chance for monsters to throw missiles is reduced when acc < C - [+] use same code as firearms - [+] undead shouldn't lose consciousness - they should jsut die. --- ai.c | 4 +- attack.c | 2 +- data.c | 73 +++++----- data/hiscores.db | Bin 13312 -> 13312 bytes defs.h | 23 +++- doc/add_intrinsic.txt | 6 +- flag.c | 6 + god.c | 25 ++-- io.c | 302 +++++++++++++++++++++++++++++++++--------- io.h | 1 + lf.c | 193 ++++++++++++++++++++------- map.c | 49 +++---- move.c | 4 +- nexus.c | 18 ++- objects.c | 129 ++++++++++++------ objects.h | 2 +- shops.c | 62 +++++++-- spell.c | 137 ++++++++++++------- spell.h | 2 +- text.c | 2 +- 20 files changed, 744 insertions(+), 296 deletions(-) diff --git a/ai.c b/ai.c index 483209b..abfa89d 100644 --- a/ai.c +++ b/ai.c @@ -1338,8 +1338,8 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { // to maintain distance. rangedob = aigetrangedattack(lf, target, &rangedattack, &shootrange); - // for firearms, chance to fire depends on accuracy. - if (rangedattack == RA_GUN) { + // for firearms/projectiles, chance to fire/throw depends on accuracy. + if ((rangedattack == RA_GUN) || (rangedattack == RA_THROW)) { int acc,chance; acc = getmissileaccuracy(lf, target->cell, getammo(rangedob), rangedob, NULL); switch (getpctletter(acc,100)) { diff --git a/attack.c b/attack.c index f39acd2..9749a48 100644 --- a/attack.c +++ b/attack.c @@ -2028,7 +2028,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) if (lorelev != PR_INEPT) acc += (lorelev*10); // modify for attacking while climbing - if (isclimbing(lf)) { + if (isclimbing(lf) && !lfhasflag(lf, F_SPIDERCLIMB)) { switch (getskill(lf, SK_CLIMBING)) { case PR_INEPT: acc -= 100; break; case PR_NOVICE: acc -= 100; break; diff --git a/data.c b/data.c index cc97ee1..b99ade1 100644 --- a/data.c +++ b/data.c @@ -167,7 +167,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_SS_MENTAL, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_SUMMONING, PR_MASTER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_TECHUSAGE, PR_ADEPT, NA, NULL); - addflag(lastjob->flags, F_HASPET, NA, NA, NA, "young wolf"); + //addflag(lastjob->flags, F_HASPET, NA, NA, NA, "young wolf"); for (i = 1; i < MAXSKILLS; i++) { addflag(lastjob->flags, F_CANLEARN, i, NA, NA, NULL); } @@ -996,6 +996,8 @@ void initobjects(void) { addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_STR, -3, NULL, PERMENANT, B_UNKNOWN, -1); addbrand(BR_NIMBLENESS, "of nimbleness", BP_HANDS); addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_AGI, 3, NULL, PERMENANT, B_UNKNOWN, -1); + addbrand(BR_SPIDERCLIMB, "of the spider", BP_HANDS); + addflag_real(lastbrand->flags, F_EQUIPCONFER, F_SPIDERCLIMB, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1); // head addbrand(BR_THINKING, "of thinking", BP_HEAD); @@ -2018,7 +2020,9 @@ void initobjects(void) { addflag(lastot->flags, F_ISMEAT, B_TRUE, 80, NA, ""); - // potions (sorted by rarity) + // potions + addot(OT_POT_SPIDERCLIMB, "potion of arachnid adhesion", "Temporarily allows you to climb on walls like a spider.", MT_GLASS, 1, OC_POTION, SZ_TINY); + addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); addot(OT_POT_JUICE, "potion of fruit juice", "Tasty (but not very fresh) fruit juice! Sates hunger and restores a little stamina.", MT_GLASS, 1, OC_POTION, SZ_TINY); addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL); addot(OT_POT_CANINETRACKING, "potion of canine tracking", "Mimics the effects of a 'canine tracking' spell.", MT_GLASS, 1, OC_POTION, SZ_TINY); @@ -3348,6 +3352,10 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); + addot(OT_S_FRIENDS, "friends!", "Surrounds the caster with a horde of tiny animals to act as a decoy.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); + addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); // l5 addot(OT_S_SUMMONDEMON, "summon demon", "Summons a random demonic entity.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines its chances of success, and how long the demon will remain."); @@ -3530,6 +3538,7 @@ void initobjects(void) { addflag(lastot->flags, F_STAMCOST, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_ANYWHERE, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addot(OT_A_COOK, "cook", "Cook a corpse, or combine various foods into a healthy meal.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_DARKWALK, "darkwalk", "Step between the shadows.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); @@ -3553,7 +3562,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addot(OT_A_FLURRY, "flurry", "Perform a flurry of attacks, forcing your opponent backwards.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); - addflag(lastot->flags, F_STAMCOST, 3, NA, NA, NULL); + addflag(lastot->flags, F_STAMCOST, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); @@ -4763,7 +4772,7 @@ void initobjects(void) { addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); - addflag(lastot->flags, F_CAUSESCOUGH, 26, NA, NA, NULL); + addflag(lastot->flags, F_CAUSESCOUGH, 25, NA, NA, NULL); addot(OT_SMOKEPUFF, "puff of smoke", "A small puff of black smoke.", MT_GAS, 0, OC_EFFECT, SZ_MEDIUM); addflag(lastot->flags, F_GLYPH, C_GREY, UNI_SHADELIGHT, NA, NULL); @@ -4774,7 +4783,7 @@ void initobjects(void) { addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSVIEW, 2, NA, NA, NULL); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "."); - addflag(lastot->flags, F_CAUSESCOUGH, 18, NA, NA, NULL); + addflag(lastot->flags, F_CAUSESCOUGH, 16, NA, NA, NULL); addot(OT_POISONCLOUD, "cloud of poison gas", "A thick cloud of poisonous gas.", MT_GAS, 0, OC_EFFECT, SZ_LARGE); addflag(lastot->flags, F_GLYPH, C_GREEN, UNI_SHADEMED, NA, NULL); @@ -7206,7 +7215,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 80, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 80, OC_ARMOUR, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "glaive"); + addflag(lastrace->flags, F_STARTOBWEPSK, 100, SK_POLEARMS, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL); @@ -7383,7 +7392,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 10, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "spear"); + addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_POLEARMS, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "shield"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-40 gold coins"); @@ -7453,8 +7462,8 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-25 gold coins"); - addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "gladius"); - addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "sling"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "sling"); + addflag(lastrace->flags, F_STARTOBWEPSK, 100, SK_SHORTBLADES, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 40, OC_POTION, NA, NULL); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_GOLD, B_COVETS, NA, NULL); @@ -7486,7 +7495,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "spear"); + addflag(lastrace->flags, F_STARTOBWEPSK, 100, SK_POLEARMS, NA, NULL); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "1-5 javelins"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-50 gold coins"); @@ -7518,7 +7527,6 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "gladius"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "hand crossbow"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "1-15 bolts"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather armour"); @@ -7553,7 +7561,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "club"); + addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_CLUBS, NA, NULL); addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "leather armour"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); @@ -7610,7 +7618,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "longsword"); + addflag(lastrace->flags, F_STARTOBWEPSK, 80, SK_LONGBLADES, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "buckler"); addflag(lastrace->flags, F_STARTOBCLASS, 100, OC_ARMOUR, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-50 gold coins"); @@ -7646,7 +7654,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "flail"); + addflag(lastrace->flags, F_STARTOBWEPSK, 100, SK_CLUBS, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-75 gold coins"); addflag(lastrace->flags, F_STARTOB, 90, NA, NA, "large shield"); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "scale armour"); @@ -7688,7 +7696,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTOBDT, 20, DT_PIERCE, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 25, OC_POTION, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_THROWING, PR_ADEPT, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-3 darts"); + addflag(lastrace->flags, F_STARTOB, 33, NA, NA, "1-3 darts"); addflag(lastrace->flags, F_STARTOB, 10, NA, NA, "javelin"); addflag(lastrace->flags, F_STARTOB, 15, NA, NA, "buckler"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-10 gold coins"); @@ -7720,7 +7728,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TAIL, 2, NA, NULL); addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "club"); + addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_CLUBS, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "buckler"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-10 gold coins"); addflag(lastrace->flags, F_DTVULN, DT_COLD, B_TRUE, NA, NULL); @@ -7773,7 +7781,7 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TAIL, 4, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-50 gold coins"); - addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "spear"); + addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_POLEARMS, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-2 javelins"); addflag(lastrace->flags, F_DTVULN, DT_COLD, B_TRUE, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_FIRE, B_TRUE, NA, NULL); @@ -7806,7 +7814,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_STR, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_BUTT, 14, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_BUTT, 14, NA, NULL); - addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "+2 heavy flail"); + addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "good heavy flail"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "greataxe"); addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_EXPERT, NA, NULL); @@ -7902,9 +7910,9 @@ void initrace(void) { addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL); - f = addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "club"); + f = addflag(lastrace->flags, F_STARTOBWEPSK, 100, SK_CLUBS, NA, NULL); addcondition(f, FC_NOCONDITION, 70); - addaltval(f, F_STARTOBDT, 50, DT_SLASH, NA, NULL); + addaltval(f, F_STARTOBWEPSK, 50, SK_SHORTBLADES, NA, NULL); addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "leather armour"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "bone helmet"); @@ -8020,7 +8028,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_BUTT, 8, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 50, DT_SLASH, NA, NULL); + addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_SHORTBLADES, NA, NULL); addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "panpipes"); addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "bow"); addflag(lastrace->flags, F_STARTOB, 75, NA, NA, "1-10 arrows"); @@ -8311,6 +8319,7 @@ void initrace(void) { addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "cactus fruit"); addflag(lastrace->flags, F_DOESNTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOPRINTS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4"); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); @@ -8325,6 +8334,7 @@ void initrace(void) { addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pile of sleeping powder"); addflag(lastrace->flags, F_DOESNTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOPRINTS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4"); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); @@ -8337,6 +8347,7 @@ void initrace(void) { addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DOESNTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOPRINTS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4"); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL); @@ -9078,8 +9089,9 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4+1"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL); addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL); // don't announce spellcasting - addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_MASTER, NA, NULL); + addflag(lastrace->flags, F_SPIDERCLIMB, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_S_WEB, 3, 3, "pw:1;range:4;"); + addflag(lastrace->flags, F_CANWILL, OT_A_CLIMB, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); @@ -9089,7 +9101,7 @@ void initrace(void) { addflag(lastrace->flags, F_HOMEOB, NA, NA, NA, "web"); addflag(lastrace->flags, F_HOMELEVOB, NA, NA, NA, "1-10 webs"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, ""); addrace(R_SPIDERFUNNELWEB, "giant funnelweb", 5, 'S', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Like a giant spider... but extremely venomous."); setbodytype(lastrace, BT_SPIDER); lastrace->baseid = R_SPIDER; @@ -9099,7 +9111,7 @@ void initrace(void) { addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_MASTER, NA, NULL); + addflag(lastrace->flags, F_SPIDERCLIMB, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "5d4+1"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL); @@ -9107,6 +9119,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 3, NA, NULL); // strong! addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL); // don't announce spellcasting addflag(lastrace->flags, F_CANWILL, OT_S_WEB, 3, 3, "pw:5;range:2;"); + addflag(lastrace->flags, F_CANWILL, OT_A_CLIMB, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); @@ -9116,7 +9129,7 @@ void initrace(void) { addflag(lastrace->flags, F_HOMEOB, NA, NA, NA, "web"); addflag(lastrace->flags, F_HOMELEVOB, NA, NA, NA, "20-30 webs"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, ""); addrace(R_SPIDERREDBACK, "giant redback", 5, 'S', C_RED, MT_FLESH, RC_ANIMAL, "A version of a giant spider with a highly painful bite."); setbodytype(lastrace, BT_SPIDER); lastrace->baseid = R_SPIDER; @@ -9126,7 +9139,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); - addflag(lastrace->flags, F_STARTSKILL, SK_CLIMBING, PR_MASTER, NA, NULL); + addflag(lastrace->flags, F_SPIDERCLIMB, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4+1"); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL); @@ -9134,6 +9147,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITCONFERVALS, DT_POISON, NA, NA, "1d2"); addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL); // don't announce spellcasting addflag(lastrace->flags, F_CANWILL, OT_S_WEB, 3, 3, "pw:7;range:3;"); + addflag(lastrace->flags, F_CANWILL, OT_A_CLIMB, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); @@ -9143,7 +9157,7 @@ void initrace(void) { addflag(lastrace->flags, F_HOMEOB, NA, NA, NA, "web"); addflag(lastrace->flags, F_HOMELEVOB, NA, NA, NA, "10-20 webs"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FLEEONHPPCT, 25, NA, NA, ""); addrace(R_WOLFYOUNG, "young wolf", 10, 'd', C_GREY, MT_FLESH, RC_ANIMAL, "Immature wolves."); setbodytype(lastrace, BT_QUADRAPED); addbodypart(lastrace, BP_TAIL, NULL); @@ -9928,10 +9942,9 @@ void initrace(void) { addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 5, NA, NULL); addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_STARTOBDT, 50, DT_CHOP, NA, NULL); + addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_AXES, NA, NULL); addflag(lastrace->flags, F_STARTOB, 25, NA, NA, "buckler"); addflag(lastrace->flags, F_DTVULN, DT_BASH, NA, NA, NULL); - addflag(lastrace->flags, F_DTRESIST, DT_SLASH, NA, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_PIERCE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); @@ -10413,7 +10426,7 @@ void initskills(void) { addskilldesc(SK_SS_ALLOMANCY, PR_EXPERT, "Allows you to cast Allomancy spells up to level 5.", B_FALSE); addskilldesc(SK_SS_ALLOMANCY, PR_MASTER, "Allows you to cast Allomancy spells up to level 6.", B_FALSE); addskill(SK_SS_MENTAL, "Psionics", "Boosts casting of spells from this school.", 50); - addskilldesc(SK_SS_MENTAL, PR_INEPT, "- Each rank gives you a 10%% chance to learn a new psionic ability when levelling up.", B_FALSE); + addskilldesc(SK_SS_MENTAL, PR_INEPT, "- Each rank gives you a 10% chance to learn a new psionic ability when levelling up.", B_FALSE); addskilldesc(SK_SS_MENTAL, PR_NOVICE, "Allows you to cast Psionic spells up to level 1.", B_FALSE); addskilldesc(SK_SS_MENTAL, PR_BEGINNER, "Allows you to cast Psionic spells up to level 2.", B_FALSE); addskilldesc(SK_SS_MENTAL, PR_ADEPT, "Allows you to cast Psionic spells up to level 3.", B_FALSE); diff --git a/data/hiscores.db b/data/hiscores.db index 7b814a5e9959a0bda4a6ab3df3d1bb5b671af1ac..77ed7587ffd1f1d8889358a93f4816739e4d4c02 100644 GIT binary patch delta 790 zcmYjOTS$~q5T48a>fY4#vazdf8*H|+uInXHNz)>f!qtZ`(9lxcw9@j1l!@(Hs1JtL zi82D~A$=$$lqLW<)(iJqVRWVvs#V(dFO2hdKv_IrDwr%$ym2y}y1i&UhC7 zI}^^=9H!;R!H`ilXr|eqc!t0(#p(kY;$>(`OfA~u_y9 z0YBmkoX7h(h2Q8jKg4mo$?tIpFJM2N!yfcw2e#o2(HXWc3V(7ICZhe{6|cey4H5&v zQ`IhtWbJL|8bsh*2!SD71F1p7fJey$x^~4#r-IK8mAoKW=QM5wsVf+(r0pPyY~6>1 zB+#h%HTHqzQr)p^kW}Z1$kQJqej~>8sT$>%A@Z``u8E}q2qh1YhYr#M`pTR563@xz z$R5-vkdUvNYAN1;7C;M@U^m_+2lde`edio*_$M`e%(7@d@pC(xE4tmbXO z8X0oA`IZzFiUoiLIHL^8MT4}?PT3q^L_{;B9^mQoJFKG6IVu-AV>s8S zBnw9)pb>XsGs?J3kyJo!G)eE+!d~v>DW$IpzQ~UhDnNQ*PY6(SQa+p!t;x?sg=CUr MRi%ptk0prw0qB&twg3PC delta 728 zcmXX^dq|T}6hDtm=N^@>r8d`Bm~BnXsiop9qfj%8AdIl042PCEZTYrrD=>*7=Y-6EN1EUntO;ERxIx z`b>X9gaSDVDnz5hDxWo9)W+zr2(SpJaETn$OH&k*&6W}(t`tYCHBpX3D#M;#5pL4B zEK&|xmuoFSFhVUTK8S8*rPKI_+G&haxQ1^CYl=_INLg|)r44aW>`blEyZrj_r b ? a : b) +#define OB1(o,one,many) (o->amt == 1) ? one : many +#define OBS1(o) (o->amt == 1) ? "s" : "" +#define OBNOS1(o) (o->amt == 1) ? "" : "s" // #define PRACTICETIME 15 // #attempts it takes to learn new weapon skill @@ -386,8 +389,10 @@ enum COLOUR { C_BOLDGREEN = 14, C_DARKGREY = 15, }; -#define BLUEBG 30 -#define GREENBG 50 +#define BLACKBG 0 +#define BLUEBG 16 +#define GREENBG 32 +#define REDBG 48 enum CASTTYPE { CT_NORMAL = 0, @@ -1169,6 +1174,7 @@ enum OBTYPE { OT_POT_SANCTUARY, OT_POT_SLEEP, OT_POT_SPEED, + OT_POT_SPIDERCLIMB, OT_POT_WATER, OT_POT_JUICE, // soup from recipes @@ -1368,6 +1374,7 @@ enum OBTYPE { // -- summoning OT_S_CREATEFOOD, OT_S_FLOATINGDISC, + OT_S_FRIENDS, OT_S_GLYPHWARDING, OT_S_CLEARLEVEL, OT_S_CREATEMONSTER, @@ -2369,6 +2376,10 @@ enum FLAG { // calculation F_STARTOBRND, // val0 = %chance of starting with a random ob // v1 = depth modifier. can use 'RANDOM' + F_STARTOBWEPSK, // val0 = %chance of starting with wepskill val1 + // v1 = wepskill of object + // optional val2 = addition to map depth for rarity + // calculation F_CONTAINER, // this object is a container - you can use 'o' // to take stuff out or put it in. F_HOLDING, // this container is a xxx of holding and makes objects @@ -2587,6 +2598,7 @@ enum FLAG { F_NOINJURIES, // this race cannot sustain injuries. F_NOPACK, // this race cannot hold objects F_NOSPELLS, // this race cannot cast spells + F_NOPRINTS, // this race doesn't leave footprints F_INDUCEFEAR, // causes fear when you attack it F_POISONCORPSE, // lf's corpse will be poisonous F_AUTOCREATEOB, // produces obtype 'text' wherever it walks, v0=radius @@ -2724,6 +2736,7 @@ enum FLAG { F_RISEASGHOST, // become a ghost when you die. F_SEEINDARK, // nightvis range is val0 F_SEEINVIS, // can see invisible things + F_SPIDERCLIMB, // lf can climb at 100% success rate F_SILENTMOVE, // lf makes no noise when walking/flying F_STABILITY, // doesn't slip over F_STAMREGEN, // boost stamina regeneration at 'text' per turn @@ -3394,6 +3407,11 @@ typedef struct lifeform_s { // your nightvision is increased by eyeadj / 10 // max is MAX_EYEADJ + int damlastturn; // for hp bar. not saved. + int mplastturn; // for mp bar. not saved. + float stamlastturn; // for stam bar. not saved. + int bartimer; // not saved. + // set to TRUE after lf has being created int born; @@ -3608,6 +3626,7 @@ enum BRAND { BR_SHADOWS, BR_SLOTH, BR_SPEED, + BR_SPIDERCLIMB, BR_STEALTH, BR_POWER, BR_SWIFTNESS, diff --git a/doc/add_intrinsic.txt b/doc/add_intrinsic.txt index b5313ad..be579f9 100644 --- a/doc/add_intrinsic.txt +++ b/doc/add_intrinsic.txt @@ -2,9 +2,11 @@ defs.h: add F_WHATEVER io.c: - update describeob() for when an object confers this property + update makedesc_ob() for when an object confers this property - update showlfstats() to describe the property + update showlfstats() to show temporarily gaining the property + update makedesc_race() to show the property as a racial characteristic + (strength/bonus) update announceflaggain() to describe adding it update announceflagloss() to describe losing it diff --git a/flag.c b/flag.c index a2f2811..3cab249 100644 --- a/flag.c +++ b/flag.c @@ -1108,6 +1108,9 @@ void timeeffectsflag(flag_t *f, int howlong) { case F_FLYING: warn("Your ability to fly is starting to expire..."); break; + case F_SPIDERCLIMB: + warn("Your skin is becoming less adhesive..."); more(); + break; default: // no message break; } @@ -1153,6 +1156,9 @@ void timeeffectsflag(flag_t *f, int howlong) { case F_LEVITATING: warn("Your levitation is about to expire!"); more(); break; + case F_SPIDERCLIMB: + warn("Your skin adhesion is about to expire!"); more(); + break; case F_POLYMORPHED: warn("You are about to revert to your original form!"); more(); break; diff --git a/god.c b/god.c index 024f7fc..5df9a16 100644 --- a/god.c +++ b/god.c @@ -206,7 +206,7 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { case 2: // summon undead msg("\"Destroy him, my pets!\""); - summonlfs(god, player->cell, RC_UNDEAD, SZ_ANY, AL_EVIL, 3, PERMENANT, B_FALSE); + summonlfs(god, player->cell, R_NONE, RC_UNDEAD, SZ_ANY, AL_EVIL, 3, PERMENANT, B_FALSE); break; } break; @@ -250,15 +250,14 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { o = (object_t *)poss[rnd(0,nposs-1)]; // damage it getobname(o, obname, o->amt); - msg("Your %s %s struck by divine force!", (o->amt == 1) ? "is" : "are", - noprefix(obname)); + msg("Your %s %s struck by divine force!", OB1(o, "is", "are"), noprefix(obname)); takedamage(o, roll("2d4"), DT_DIRECT); } break; case 2: // summon holy creautes msg("\"Destroy him, my pets!\""); - summonlfs(god, player->cell, RC_ANY, SZ_ANY, AL_GOOD, 3, PERMENANT, B_FALSE); + summonlfs(god, player->cell, R_NONE, RC_ANY, SZ_ANY, AL_GOOD, 3, PERMENANT, B_FALSE); break; } break; @@ -683,7 +682,7 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { addflag(o->flags, F_GODGIFT, god->race->id, NA, NA, NULL); if (haslos(player, player->cell)) { getobname(o, buf, o->amt); - msg("%s appear%s!", buf, (o->amt == 1) ? "s" : ""); + msg("%s appear%s!", buf, OBS1(o)); } else { msg("You hear something hitting the ground."); } @@ -814,7 +813,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) { if (iscursed(o) && (o->blessknown)) { char buf[BUFLEN]; getobname(o, buf, o->amt); - msg("%s explode%s in a shower of sparks!",buf, (o->amt == 1) ? "s" : ""); + msg("%s explode%s in a shower of sparks!",buf, OBS1(o)); removeob(o,ALL); donesomething = B_TRUE; } @@ -875,17 +874,19 @@ int prayto(lifeform_t *lf, lifeform_t *god) { break; case R_GODDEATH: msg("\"Behold, the power of death!\""); - for (l = lf->cell->map->lf ; l ; l = l->next) { - if ((l != lf) && haslof(lf->cell, l->cell, LOF_WALLSTOP, NULL)) { - if (isundead(l)) { - makepeaceful(l); + for (i = 1; i < lf->nlos; i++) { + lifeform_t *who; + who = lf->los[i]->lf; + if (who && !areallies(lf, who)) { + if (isundead(who)) { + makepeaceful(who); } else { - castspell(god, OT_S_PAIN, l, NULL, l->cell, NULL, NULL); + castspell(god, OT_S_PAIN, who, NULL, who->cell, NULL, NULL); + castspell(god, OT_S_DRAINLIFE, who, NULL, who->cell, NULL, NULL); } } } dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); - dospelleffects(god, OT_S_DARKNESS, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE); break; case R_GODTHIEVES: if (isinbattle(lf)) { diff --git a/io.c b/io.c index edbbdcc..715b78d 100644 --- a/io.c +++ b/io.c @@ -1702,6 +1702,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { msg("^%c%s %s",getlfcol(lf, CC_VBAD), lfname, isplayer(lf) ? "feel slow and sluggish." : "looks slow and sluggish."); donesomething = B_TRUE; break; + case F_SPIDERCLIMB: + if (isplayer(lf)) { // don't know if monsters get it + msg("Your skin becomes adhesive!"); + donesomething = B_TRUE; + } + break; case F_SPRINTING: msg("%s %s sprinting!",lfname, isplayer(lf) ? "start" : "starts"); donesomething = B_TRUE; @@ -2283,6 +2289,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) { msg("%s %s",lfname, isplayer(lf) ? "speed back up." : "speeds back up."); donesomething = B_TRUE; break; + case F_SPIDERCLIMB: + if (isplayer(lf)) { + msg("Your skin is no longet adhesive."); + donesomething = B_TRUE; + } + break; case F_SPRINTING: if (isplayer(lf)) { // don't know if monsters lose it (but you'll see them get exhausted) msg("You stop sprinting."); @@ -2395,11 +2407,11 @@ int announceobflaggain(object_t *o, flag_t *f) { switch (f->id) { case F_ONFIRE: donesomething = B_TRUE; - if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, (o->amt == 1) ? "es" : ""); + if (o->birthtime != curtime) msg("%s catch%s on fire.",prefix, OB1(o, "es", "")); break; case F_PRODUCESLIGHT: donesomething = B_TRUE; - if (o->birthtime != curtime) msg("%s start%s glowing!",prefix, (o->amt == 1) ? "s" : ""); + if (o->birthtime != curtime) msg("%s start%s glowing!",prefix, OBS1(o)); break; default: // no message break; @@ -2454,7 +2466,7 @@ void announceobflagloss(object_t *o, flag_t *f) { msg("%s %s no longer glowing.",prefix,isare); break; case F_WET: - msg("%s %s now dry.",prefix, (o->amt == 1) ? "is" : "are"); + msg("%s %s now dry.",prefix, OB1(o,"is","are")); break; default: // no message break; @@ -3279,25 +3291,29 @@ void updatestatus(void) { // returns true if view changed int updateviewfor(cell_t *cell) { int oldvx,oldvy; + int w,h; oldvx = viewx; oldvy = viewy; + + getmaxyx(gamewin, h, w); + // calculate viewport if required if ((viewx == -9999) || (viewy == -9999)) { // try to centre player - viewx = cell->x - (SCREENW/2); - viewy = cell->y - (SCREENH/2); + viewx = cell->x - (w/2); + viewy = cell->y - (h/2); } - while ((cell->x - viewx) >= ((SCREENW / 3)*2)) { + while ((cell->x - viewx) >= ((w / 3)*2)) { viewx++; } - while ((cell->y - viewy) >= ((SCREENH / 3)*2)) { + while ((cell->y - viewy) >= ((h / 3)*2)) { viewy++; } - while ((cell->x - viewx) <= (SCREENW/3)) { + while ((cell->x - viewx) <= (w/3)) { viewx--; } - while ((cell->y - viewy) <= (SCREENH/3)) { + while ((cell->y - viewy) <= (h/3)) { viewy--; } @@ -3683,6 +3699,11 @@ void docomms(lifeform_t *lf) { addchoice(&prompt, 'n', "(nothing)", NULL, NULL, NULL); ch = getchoice(&prompt); + if ((ch == 'n') || (ch == '\0')) { + msg("Cancelled."); + return; + } + switch (ch) { case 'a': snprintf(buf, BUFLEN, "Tell %s to attack who?",lfname); @@ -3698,6 +3719,12 @@ void docomms(lifeform_t *lf) { } getlfname(lf2, lfname2); msg("You say \"Attack %s!\" to %s.",isplayer(lf2) ? "me" : lfname2, lfname); + + if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) { + msg("%s doesn't respond.", lfname); + break; + } + if (lf == lf2) { // won't attack itself msg("%s looks confused at your command.", lfname); @@ -3719,6 +3746,10 @@ void docomms(lifeform_t *lf) { break; case 'c': msg("You say \"Come here!\" to %s.",lfname); + if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) { + msg("%s doesn't respond.", lfname); + break; + } // find adjacent cell c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); if (c) { @@ -3792,12 +3823,8 @@ void docomms(lifeform_t *lf) { makeknown(o->type->id); getobname(o, newobname, o->amt); msg("%s points at your pack.", lfname); - msg("Hey I recognise %s %s.", - (o->amt == 1) ? "that" : "those", - oldobname); - msg("%s %s.", - (o->amt == 1) ? "It's" : "They're", - newobname); + msg("Hey I recognise %s %s.", OB1(o, "that", "those"), oldobname); + msg("%s %s.", OB1(o, "It's", "They're"), newobname); } } else { // nothing sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL); @@ -3875,16 +3902,21 @@ void docomms(lifeform_t *lf) { // stop attacking all current targets first... killflagsofid(lf->flags, F_TARGETLF); msg("You say \"Go over there!\" to %s.", lfname); + if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) { + msg("%s doesn't respond.", lfname); + break; + } aigoto(lf, c, MR_OTHER, NULL, DEF_AIFOLLOWTIME); break; case 'j': // charisma check to see if they'll join you. msg("You say \"Join me on my quest!\" to %s.", lfname); + if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) { + msg("%s doesn't respond.", lfname); + break; + } recruit(lf); break; - case 'n': - msg("Cancelled."); - return; case 'p': // can we afford this? if (givemoney(player, lf, moneyowing)) { @@ -3924,6 +3956,11 @@ void docomms(lifeform_t *lf) { } break; case 'r': + msg("You say \"Get some rest.\" to %s.", lfname); + if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) { + msg("%s doesn't respond.", lfname); + break; + } f = isresting(lf); if (f) { stopresting(lf); @@ -3974,10 +4011,18 @@ void docomms(lifeform_t *lf) { break; case '<': msg("You say \"Stay close!\" to %s.", lfname); + if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) { + msg("%s doesn't respond.", lfname); + break; + } setfollowdistance(lf, 1, 3); break; case '>': msg("You say \"Keep your distance!\" to %s.", lfname); + if (lfhasflag(c->lf, F_RAGE) || !canhear(c->lf, player->cell, SV_SHOUT)) { + msg("%s doesn't respond.", lfname); + break; + } setfollowdistance(lf, 3, 5); break; } @@ -4135,10 +4180,8 @@ void doeat(obpile_t *op) { for (o = player->cell->obpile->first; o ; o = o->next) { if (caneat(player, o)) { getobname(o, obname, o->amt); - snprintf(buf, BUFLEN, "There %s %s here. Eat %s", - (o->amt == 1) ? "is" : "are", - obname, - (o->amt == 1) ? "it" : "one"); + snprintf(buf, BUFLEN, "There %s %s here. Eat %s", OB1(o,"is","are"), + obname, OB1(o,"it","one")); ch = askchar(buf, "yn","n", B_TRUE, B_FALSE); if (ch == 'y') { eatob = o; @@ -4298,7 +4341,7 @@ void dolook(cell_t *where, int onpurpose) { if (f) { // doens't matter if you're blind getobname(o, buf, o->amt); - msg("There %s %s here%c", (o->amt == 1) ? "is" : "are", buf, f->text[0]); + msg("There %s %s here%c", OB1(o,"is","are"), buf, f->text[0]); interrupt(player); seensomething = B_TRUE; } else { @@ -4505,11 +4548,10 @@ char *makedesc_ob(object_t *o, char *retbuf) { if (o->material->id != MT_NOTHING) { float obw; if (o->material->id == MT_FOOD) { - snprintf(buf, BUFLEN, "%s %s food product%s, ",(o->amt == 1) ? "It is a" : "They are", - getsizetext(getobsize(o)), - (o->amt == 1) ? "" : "s"); + snprintf(buf, BUFLEN, "%s %s food product%s, ", OB1(o,"It is a","They are"), + getsizetext(getobsize(o)), OBNOS1(o)); } else { - snprintf(buf, BUFLEN, "%s %s sized, made from %s, ",(o->amt == 1) ? "It is" : "They are", + snprintf(buf, BUFLEN, "%s %s sized, made from %s, ",OB1(o,"It is","They are"), getsizetext(getobsize(o)), o->material->name); } @@ -4552,7 +4594,7 @@ char *makedesc_ob(object_t *o, char *retbuf) { throwrange = getmaxthrowrange(player, o); if (throwrange >= 1) { - sprintf(buf, "@You could throw %s %d metres.",(o->amt == 1) ? "it" : "one", throwrange); + sprintf(buf, "@You could throw %s %d metres.", OB1(o,"it","one"), throwrange); } else { sprintf(buf, "@It is too heavy for you to throw."); } @@ -4565,9 +4607,9 @@ char *makedesc_ob(object_t *o, char *retbuf) { if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT)) { int dam; dam = getthrowdam(o); - sprintf(buf, "@%s good for throwing [base damage %d].",(o->amt == 1) ? "It is" : "They are", dam); + sprintf(buf, "@%s good for throwing [base damage %d].",OB1(o,"It is","They are"), dam); } else { - sprintf(buf, "@%s good for throwing.", (o->amt == 1) ? "It is" : "They are"); + sprintf(buf, "@%s good for throwing.", OB1(o,"It is","They are")); } strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, "\n", HUGEBUFLEN); } @@ -4587,15 +4629,15 @@ char *makedesc_ob(object_t *o, char *retbuf) { int basenutr; basenutr = getnutritionbase(o); sprintf(buf, "%s edible, and %s %s.\n", - (o->amt == 1) ? "It is" : "They are", - (o->amt == 1) ? "is" : "are each", + OB1(o,"It is","They are"), + OB1(o,"is","are each"), getfillingname(basenutr)); strncat(retbuf, buf, HUGEBUFLEN); if (hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL)) { // don't show "it will rot" if it's already rotten (and you know this) if (isrotting(o) && ( (getattrbracket(getattr(player, A_IQ), A_IQ, NULL) >= AT_GTAVERAGE) || getskill(player, SK_COOKING)) ) { } else { - sprintf(buf, "%s will decay and go bad over time.\n", (o->amt == 1) ? "It" : "They" ); + sprintf(buf, "%s will decay and go bad over time.\n", OB1(o,"It","They")); strncat(retbuf, buf, HUGEBUFLEN); } } @@ -5196,7 +5238,7 @@ char *makedesc_ob(object_t *o, char *retbuf) { } f = hasflag(o->flags, F_ARMOURPIERCE); if (f && f->known) { - sprintf(buf, "Armour will not reduce %s damage.\n",(o->amt == 1) ? "its" : "their"); + sprintf(buf, "Armour will not reduce %s damage.\n",OB1(o,"its","their")); strncat(retbuf, buf, HUGEBUFLEN); } f = hasflag(o->flags, F_BALANCE); @@ -5546,6 +5588,10 @@ char *makedesc_ob(object_t *o, char *retbuf) { sprintf(buf2, "%s will slow down your movement.\n", buf); strncat(retbuf, buf2, HUGEBUFLEN); break; + case F_SPIDERCLIMB: + sprintf(buf2, "%s allows you to adhere to walls.\n", buf); + strncat(retbuf, buf2, HUGEBUFLEN); + break; case F_TREMORSENSE: sprintf(buf2, "%s allows you to 'see' by sensing vibrations around you.\n", buf); strncat(retbuf, buf2, HUGEBUFLEN); @@ -5619,21 +5665,21 @@ char *makedesc_ob(object_t *o, char *retbuf) { } if (hasflag(o->flags, F_NOBLESS)) { - sprintf(buf, "%s cannot be blessed or cursed.\n", (o->amt == 1) ? "It" : "They" ); + sprintf(buf, "%s cannot be blessed or cursed.\n", OB1(o,"It","They") ); strncat(retbuf, buf, HUGEBUFLEN); } else { if (isblessknown(o)) { if (o->blessed == B_BLESSED) { sprintf(buf, "%s a blessing bestowed upon %s.\n", - (o->amt == 1) ? "It has" : "They have", - (o->amt == 1) ? "it" : "them"); + OB1(o,"It has","They have"), + OB1(o,"it","them")); strncat(retbuf, buf, HUGEBUFLEN); } else if (o->blessed == B_CURSED) { - sprintf(buf, "%s cursed.\n", (o->amt == 1) ? "It is" : "They are"); + sprintf(buf, "%s cursed.\n", OB1(o,"It is","They are")); strncat(retbuf, buf, HUGEBUFLEN); } } else { - sprintf(buf, "%s might be blessed or cursed.\n", (o->amt == 1) ? "It" : "They"); + sprintf(buf, "%s might be blessed or cursed.\n", OB1(o,"It","They")); strncat(retbuf, buf, HUGEBUFLEN); } } @@ -5648,9 +5694,9 @@ char *makedesc_ob(object_t *o, char *retbuf) { if (showcontents) { if (o->type->id == OT_SPELLBOOK) { - sprintf(buf, "\n%s contain%s the following spells:\n", (o->amt == 1) ? "It" : "They", (o->amt == 1) ? "s" : ""); + sprintf(buf, "\n%s contain%s the following spells:\n", OB1(o,"It","They"), OBS1(o)); } else { - sprintf(buf, "\n%s currently contain%s:\n", (o->amt == 1) ? "It" : "They", (o->amt == 1) ? "s" : ""); + sprintf(buf, "\n%s currently contain%s:\n", OB1(o,"It","They"), OBS1(o)); } strncat(retbuf, buf, HUGEBUFLEN); @@ -5884,8 +5930,9 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) { case F_SEEINDARK: sprintf(buf, "Darkvision (range %d)", f->val[0]); break; case F_SEEINVIS: sprintf(buf, "Can see invisible things"); break; case F_SILENTMOVE: sprintf(buf, "Moves silently"); break; + case F_SPIDERCLIMB: sprintf(buf, "Adheres to walls"); break; case F_STABILITY: sprintf(buf, "Will not fall on slippery ground."); break; - case F_STARTSKILL: sprintf(buf, "%s %s", getskillname(f->val[0]), getskilllevelname(f->val[1])); break; + case F_STARTSKILL: sprintf(buf, "%s %s", getskilllevelname(f->val[1]), getskillname(f->val[0])); break; case F_STENCH: sprintf(buf, "Emits a foul odour which affects others"); break; case F_TREMORSENSE: sprintf(buf, "Can sense vibrations (range %d)", f->val[0]); break; case F_VISRANGEMOD: if (f->val[0] > 0) sprintf(buf, "Enhanced vision range (+%d)", f->val[0]); break; @@ -6475,9 +6522,9 @@ void dooperate(obpile_t *op) { strcpy(verb, getoperateverb(o)); capitalise(verb); snprintf(buf, BUFLEN, "There %s %s here. %s %s", - (o->amt == 1) ? "is" : "are", + OB1(o,"is","are"), obname, verb, - (o->amt == 1) ? "it" : "one"); + OB1(o,"it","one")); ch = askchar(buf, "yn","n", B_TRUE, B_FALSE); if (ch == 'y') { operate(player, o, NULL); @@ -6788,10 +6835,8 @@ void doquaff(obpile_t *op) { } else { strcpy(drink, "Drink from"); } - snprintf(buf, BUFLEN, "There %s %s here. %s %s", - (o->amt == 1) ? "is" : "are", - obname, drink, - (o->amt == 1) ? "it" : "one"); + snprintf(buf, BUFLEN, "There %s %s here. %s %s", OB1(o,"is","are"), + obname, drink, OB1(o,"it","one")); ch = askchar(buf, "yn","n", B_TRUE, B_FALSE); if (ch == 'y') { liquid = o; @@ -7083,7 +7128,7 @@ void dothrow(obpile_t *op) { if (getcelldist(player->cell, where) > maxdist) { if (maxdist < 1) { - msg("%s is too heavy for you to throw!",buf, (o->amt == 1) ? "is" : "are"); + msg("%s is too heavy for you to throw!",buf, OB1(o,"is","are")); } else { msg("You can't throw %s that far!",buf); } @@ -7194,6 +7239,91 @@ void drawunviscell(cell_t *cell, int x, int y) { } */ +// draw a bar as follows, with coloured background: +// +// 0123456789 +// title:[ 11 / 23 ] +void drawbar(WINDOW *win, char *title, int cur, int max, int realmax, int lossamt, enum COLOUR textcol, enum COLOUR textcolwithbg, int barbg, int lossbg) { + float fcur, fmax,curpct,losspct = 0; + char buf[BUFLEN]; + char numbuf[BUFLEN]; + char numbuffull[BUFLEN]; + char *p; + int numpad,i; + fcur = cur; + fmax = max; + curpct = (fcur / fmax) * 100; + if ((cur > 0) && (curpct < 10)) curpct = 10; + if ((cur != max) && (curpct > 90)) curpct = 90; + if (lossamt > 0) { + losspct = ((float)lossamt / fmax) * 100; + if (losspct < 10) losspct = 10; + } + if (curpct + losspct > 100) { + losspct = 100 - curpct; + } + // construct number text to fit into 10 chars + sprintf(numbuf, "%d/%d",cur,max); + if (max != realmax) strcat(numbuf, "*"); + numpad = (10 - strlen(numbuf)) / 2; + p = numbuffull; + for ( i = 0; i < 10; i++) { + if (i < numpad) { + *p = ' '; + } else { + int idx; + idx = i - numpad; + if (idx < strlen(numbuf)) { + *p = numbuf[idx]; + } else { + *p = ' '; + } + } + p++; + } + *p = '\0'; + + // show prefix + sprintf(buf, "^n%s[",title); + textwithcol(win, buf); + + // show background bar and text + p = numbuffull; + for (i = 0; i < 10; i++){ + enum COLOUR bgcol = BLACKBG; + int thispct; + + // select bg colour... + thispct = (i+1)*10; + if (thispct <= curpct) { + bgcol = barbg; + } else if (thispct <= curpct + losspct) { + bgcol = lossbg; + } else { + bgcol = BLACKBG; + } + + // set colour + if ((cur == 0) && (max != 0)) { + setcol(win, C_ORANGE+bgcol); + } else if (bgcol == BLACKBG) { + setcol(win, textcol+bgcol); + } else { + setcol(win, textcolwithbg+bgcol); + } + // show this char + waddch(win, *p); + // inc char pointer + p++; + } + + // show suffix + setcol(win, C_GREY); + waddch(win, ']'); + waddch(win, ' '); + waddch(win, ' '); +} + void drawglyph(glyph_t *g, int x, int y) { int col; if ((gamemode == GM_GAMESTARTED) && lfhasflag(player, F_RAGE)) { @@ -7355,7 +7485,7 @@ void initgfx(void) { init_pair(C_ORANGE, COLOR_RED, COLOR_BLACK); init_pair(C_DARKGREY, COLOR_BLACK, COLOR_BLACK); - // 30 through 45 + // 16 through 31 init_pair(BLUEBG+C_BLACK, COLOR_BLACK, COLOR_BLUE); init_pair(BLUEBG+C_RED, COLOR_RED, COLOR_BLUE); init_pair(BLUEBG+C_GREEN, COLOR_GREEN, COLOR_BLUE); @@ -7373,7 +7503,7 @@ void initgfx(void) { init_pair(BLUEBG+C_BOLDGREEN, COLOR_GREEN, COLOR_BLUE); init_pair(BLUEBG+C_ORANGE, COLOR_RED, COLOR_BLUE); - // 50 through 65 + // 32 through 47 init_pair(GREENBG+C_BLACK, COLOR_BLACK, COLOR_GREEN); init_pair(GREENBG+C_RED, COLOR_RED, COLOR_GREEN); init_pair(GREENBG+C_GREEN, COLOR_GREEN, COLOR_GREEN); @@ -7390,6 +7520,23 @@ void initgfx(void) { init_pair(GREENBG+C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_GREEN); init_pair(GREENBG+C_BOLDGREEN, COLOR_GREEN, COLOR_GREEN); init_pair(GREENBG+C_ORANGE, COLOR_RED, COLOR_GREEN); + // 48 through 63 + init_pair(REDBG+C_BLACK, COLOR_BLACK, COLOR_RED); + init_pair(REDBG+C_RED, COLOR_RED, COLOR_RED); + init_pair(REDBG+C_GREEN, COLOR_GREEN, COLOR_RED); + init_pair(REDBG+C_BROWN, COLOR_YELLOW, COLOR_RED); + init_pair(REDBG+C_YELLOW, COLOR_YELLOW, COLOR_RED); + init_pair(REDBG+C_BLUE, COLOR_BLUE, COLOR_RED); + init_pair(REDBG+C_MAGENTA, COLOR_MAGENTA, COLOR_RED); + init_pair(REDBG+C_CYAN, COLOR_CYAN, COLOR_RED); + init_pair(REDBG+C_GREY, COLOR_WHITE, COLOR_RED); + init_pair(REDBG+C_YELLOW, COLOR_YELLOW, COLOR_RED); + init_pair(REDBG+C_WHITE, COLOR_WHITE, COLOR_RED); + init_pair(REDBG+C_BOLDCYAN, COLOR_CYAN, COLOR_RED); + init_pair(REDBG+C_BOLDBLUE, COLOR_BLUE, COLOR_RED); + init_pair(REDBG+C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_RED); + init_pair(REDBG+C_BOLDGREEN, COLOR_GREEN, COLOR_RED); + init_pair(REDBG+C_ORANGE, COLOR_RED, COLOR_RED); noecho(); // TODO: change back to raw mode, or make this a switch @@ -8690,6 +8837,9 @@ void msg_real(char *format, ... ) { } int needsbold(enum COLOUR col) { + if (col >= REDBG) col -= REDBG; + if (col >= GREENBG) col -= GREENBG; + if (col >= BLUEBG) col -= BLUEBG; switch (col) { case C_YELLOW: case C_WHITE: @@ -8716,7 +8866,7 @@ void drawstatus(void) { //char mpbuf[BUFLEN]; char waitbuf[BUFLEN]; //char pname[BUFLEN]; - char maxmpstr[BUFLEN]; + //char maxmpstr[BUFLEN]; flag_t *f; enum ATTRIB a; int myatt[MAXATTS]; @@ -8728,6 +8878,13 @@ void drawstatus(void) { // FIRST LINE wmove(statwin, 0, 0); + // hp + drawbar(statwin, "HP", player->hp, player->maxhp, player->maxhp, player->damlastturn, C_GREY, C_BLUE, GREENBG, REDBG); + // mp + drawbar(statwin, "MP", player->mp, getmaxmp(player), player->maxmp, player->mplastturn, C_GREY, C_GREY, BLUEBG, REDBG); + // stamina + drawbar(statwin, "SP", getstamina(player), getmaxstamina(player), getmaxstamina(player), ceil(player->stamlastturn), C_GREY, C_GREY, BLUEBG, REDBG); + // gun target ? f = hasflag(player->flags, F_GUNTARGET); if (f) { @@ -8748,6 +8905,7 @@ void drawstatus(void) { wattron(statwin, A_BOLD); wprintw(statwin, "] "); wattroff(statwin, A_BOLD); */ + /* // HP wattron(statwin, A_BOLD); wprintw(statwin, "HP:"); wattroff(statwin, A_BOLD); setcol(statwin, getpctcol(player->hp, player->maxhp)); @@ -8780,7 +8938,19 @@ void drawstatus(void) { wprintw(statwin, "%d",getstamina(player)); unsetcol(statwin, getpctcol(getstamina(player), (int)getmaxstamina(player))); wprintw(statwin, "/%d ",(int)getmaxstamina(player)); + */ + wattron(statwin, A_BOLD); wprintw(statwin, "AR:"); wattroff(statwin, A_BOLD); + snprintf(buf, BUFLEN, "%d ", getarmourrating(player, NULL, NULL, NULL)); + wprintw(statwin, buf); + + wattron(statwin, A_BOLD); wprintw(statwin, "EV:"); wattroff(statwin, A_BOLD); + wprintw(statwin, "%d ", getevasion(player)); + + + wattron(statwin, A_BOLD); wprintw(statwin, "$:"); wattroff(statwin, A_BOLD); + snprintf(buf, BUFLEN, "%d ", countmoney(player->pack)); + wprintw(statwin, buf); wattron(statwin, A_BOLD); wprintw(statwin, "Xp:"); wattroff(statwin, A_BOLD); snprintf(buf, BUFLEN, "%d", player->level); @@ -8797,9 +8967,10 @@ void drawstatus(void) { } wattron(statwin, A_BOLD); wprintw(statwin, " Trn:"); wattroff(statwin, A_BOLD); - wprintw(statwin, "%d/%d%%", player->skillpoints, + wprintw(statwin, "%d/%d%% ", player->skillpoints, (int) ((float)player->skillxp / (float)getspforpoint(player) * 100.0) ); + // blinded? if (isblind(player) && !lfhasflag(player, F_ASLEEP)) { setcol(statwin, C_RED); @@ -9062,16 +9233,6 @@ void drawstatus(void) { //redraw(); wmove(statwin, 2, 0); - wattron(statwin, A_BOLD); wprintw(statwin, "AR:"); wattroff(statwin, A_BOLD); - snprintf(buf, BUFLEN, "%d ", getarmourrating(player, NULL, NULL, NULL)); - wprintw(statwin, buf); - - wattron(statwin, A_BOLD); wprintw(statwin, "EV:"); wattroff(statwin, A_BOLD); - wprintw(statwin, "%d ", getevasion(player)); - - wattron(statwin, A_BOLD); wprintw(statwin, "$:"); wattroff(statwin, A_BOLD); - snprintf(buf, BUFLEN, "%d ", countmoney(player->pack)); - wprintw(statwin, buf); for (a = 0; a < MAXATTS; a++) { wattron(statwin, A_BOLD); wprintw(statwin, "%s:",getattrabbrev(a)); wattroff(statwin, A_BOLD); @@ -9355,7 +9516,6 @@ void showlfstats(lifeform_t *lf, int showall) { char actbuf[BUFLEN],movebuf[BUFLEN]; int h; char buf[BUFLEN],buf2[BUFLEN]; - char *descbuf = NULL; job_t *j; flag_t *f; //char *ftext= "%13s: "; @@ -9888,7 +10048,9 @@ void showlfstats(lifeform_t *lf, int showall) { y = y2 + 1; } + /* if (!isplayer(lf)) { + char *descbuf = NULL; int x=0; // description first. descbuf = malloc(HUGEBUFLEN * sizeof(char)); @@ -9899,6 +10061,7 @@ void showlfstats(lifeform_t *lf, int showall) { getyx(mainwin, y, x); } + */ // knowledge? if (lf != player) { char knowstring[BUFLEN]; @@ -10653,6 +10816,16 @@ void showlfstats(lifeform_t *lf, int showall) { mvwprintw(mainwin, y, 0, "%s can see invisible things.", you(lf)); y++; } + f = lfhasknownflag(lf, F_SPIDERCLIMB); + if (f && (f->known) && (f->lifetime != FROMRACE)) { + mvwprintw(mainwin, y, 0, "%s adhesive skin allows %s to climb walls.", your(lf), you(lf)); + y++; + } + f = lfhasknownflag(lf, F_STABILITY); + if (f && (f->known) && (f->lifetime != FROMRACE)) { + mvwprintw(mainwin, y, 0, "%s will not fall on slippery ground.", you(lf)); + y++; + } f = lfhasknownflag(lf, F_XRAYVIS); if (f && (f->known) && (f->lifetime != FROMRACE)) { mvwprintw(mainwin, y, 0, "%s can see through walls.", you(lf)); @@ -11483,6 +11656,7 @@ void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) { vsnprintf( buf, HUGEBUFLEN, format, args ); va_end(args); + if (!strlen(buf)) return; // remember the amount of spaces at the end p = buf + strlen(buf) - 1; diff --git a/io.h b/io.h index 8d4bac9..7fcbe5c 100644 --- a/io.h +++ b/io.h @@ -73,6 +73,7 @@ void dothrow(obpile_t *op); int dowear(obpile_t *op); int doweild(obpile_t *op); int downline(int *y, int h, char *heading, char *subheading, char *bottomstring, char *cmdchars, char *retchar); +void drawbar(WINDOW *win, char *title, int cur, int max, int realmax, int lossamt, enum COLOUR textcol, enum COLOUR textcolwithbg, int barbg, int lossbg); void drawglyph(glyph_t *g, int x, int y); //void drawunviscell(cell_t *cell, int x, int y); //void drawcellwithcontents(cell_t *cell, int x, int y); diff --git a/lf.c b/lf.c index 6912315..8586a43 100644 --- a/lf.c +++ b/lf.c @@ -1014,7 +1014,9 @@ int canreach(lifeform_t *lf, lifeform_t *victim, int *reachpenalty) { // harder to hit something which is climbing above you if (isclimbing(victim) && !isclimbing(lf)) { if (getskill(lf, SK_CLIMBING) != PR_MASTER) { - sizetoreach = SZ_LARGE; + if (!lfhasflag(lf, F_SPIDERCLIMB)) { + sizetoreach = SZ_LARGE; + } } } } @@ -1935,7 +1937,7 @@ int check_rest_ok(lifeform_t *lf) { msg("You cannot rest while levitating in mid-air!"); break; case E_MONSTERNEARBY: - msg("You cannot rest - there are monsters nearby!"); + msg("You cannot rest - there are monsters in view!"); break; default: msg("You cannot rest for some reason."); @@ -4304,10 +4306,6 @@ void gainhp(lifeform_t *lf, int amt) { int gained = B_FALSE; int maxed = B_FALSE; - if (isplayer(lf)) { - statdirty = B_TRUE; - } - if (lf->hp < lf->maxhp) { lf->hp += amt; gained = B_TRUE; @@ -4319,6 +4317,10 @@ void gainhp(lifeform_t *lf, int amt) { } if (isplayer(lf)) { + if (gained) { + player->damlastturn = 0; + statdirty = B_TRUE; + } if (maxed) { msg("^gYou are now fully healed."); } @@ -4422,6 +4424,7 @@ void gainmp(lifeform_t *lf, int amt) { msg("^GYour mana is now fully restored."); } if (gained) { + player->mplastturn = 0; statdirty = B_TRUE; drawstatus(); updatestatus(); @@ -4782,7 +4785,13 @@ void getwhowillfollow(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, i if (ok) { // still ok? adjally[*nadjallies] = c->lf; - if (seen) seen[*nadjallies] = cansee(lf, c->lf); + if (seen) { + if (areallies(lf, c->lf)) { + seen[*nadjallies] = B_TRUE; + } else { + seen[*nadjallies] = cansee(lf, c->lf); + } + } (*nadjallies)++; if (*nadjallies >= MAXFOLLOWLFS) return; } @@ -8269,7 +8278,7 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) { } } else if (id == SK_CLIMBING) { newf = hasflagval(lf->flags, F_CANWILL, OT_A_CLIMB, NA, NA, NULL); - if (!newf) { + if (!newf || (newf->lifetime > 0)) { newf = addflag(lf->flags, F_CANWILL, OT_A_CLIMB, NA, NA, NULL); newf->lifetime = FROMSKILL; } @@ -8648,7 +8657,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { } // if (getrandomobofsize(targmap, buf, maxobsize)) { - if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, B_TRUE, OC_NONE, DT_NONE)) { + if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE, B_TRUE, OC_NONE, DT_NONE)) { if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); o = addob(op, buf); } @@ -8660,13 +8669,13 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { snprintf(buf2, BUFLEN, "calling startobdt"); } - depthmod = val[1]; + depthmod = val[2]; switch (depthmod) { case NA: depthmod = 0; break; case RANDOM: depthmod = rnd(0,MAXDEPTH); break; default: break; } - if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, B_TRUE, OC_NONE, val[1], DT_NONE)) { + if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, SK_NONE, B_TRUE, OC_NONE, val[1], DT_NONE)) { if (db) snprintf(buf2, BUFLEN, "finished startobdt successfuly."); if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); o = addob(op, buf); @@ -8675,6 +8684,27 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { } //assert(strlen(buf) > 0); } + } else if (id == F_STARTOBWEPSK) { + if (rnd(1,100) <= val[0]) { + int depthmod; + if (db) { + snprintf(buf2, BUFLEN, "calling startobwepsk"); + } + + depthmod = val[2]; + switch (depthmod) { + case NA: depthmod = 0; break; + case RANDOM: depthmod = rnd(0,MAXDEPTH); break; + default: break; + } + if (real_getrandomob(targmap, buf, targmap->depth + depthmod, NA, maxobsize, val[1], B_TRUE, OC_NONE, DT_NONE)) { + if (db) snprintf(buf2, BUFLEN, "finished startobwepsk successfuly."); + o = addob(op, buf); + } else { + if (db) snprintf(buf2, BUFLEN, "finished startobwepsk, failed."); + } + //assert(strlen(buf) > 0); + } } else if (id == F_STARTOBCLASS) { if (rnd(1,100) <= val[0]) { int depthmod; @@ -8691,7 +8721,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { //obdb = B_TRUE; //if (getrandomobwithclass(targmap, val[1], buf, val[2])) { - if (real_getrandomob(targmap, buf, getmapdifficulty(targmap) + depthmod, NA, maxobsize, B_TRUE, + if (real_getrandomob(targmap, buf, getmapdifficulty(targmap) + depthmod, NA, maxobsize, SK_NONE, B_TRUE, val[1], OC_NONE, DT_NONE)) { if (db) snprintf(buf2, BUFLEN, "finished startobclass, success."); if (isshop && strstr(buf, "gold coin")) strcpy(buf, "potion of water"); @@ -8729,6 +8759,7 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) { killflagsofid(fp, F_STARTOB); killflagsofid(fp, F_STARTOBDT); killflagsofid(fp, F_STARTOBCLASS); + killflagsofid(fp, F_STARTOBWEPSK); // SPECIAL CASES if (lf) { @@ -10437,6 +10468,10 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) { a->alive = B_TRUE; a->lastdam = strdup("nothing"); a->lastdamtype = DT_NONE; + a->damlastturn = 0; + a->mplastturn = 0; + a->stamlastturn = 0; + a->bartimer = 0; a->killverb = strdup("Killed"); if ((gamemode == GM_GAMESTARTED) && a->prev) { a->timespent = a->prev->timespent + 1; @@ -10636,6 +10671,10 @@ object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int dos return NULL; } + if (lfhasflag(lf, F_NOPRINTS)) { + doprints = B_FALSE; + } + // footprints first if (doprints) { if (!isairborne(lf) && !lfhasflag(lf, F_NONCORPOREAL)) { @@ -11641,33 +11680,37 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml // stop hiding killflagsofid(lf->flags, F_HIDING); - // merciful weapons - if (fromob) { - f = hasflag(fromob->flags, F_MERCIFUL); - if (f && (amt >= lf->hp)) { - amt = lf->hp - 1; // ie end up at 1hp - ko = B_TRUE; - if (fromob->pile->owner && cansee(player, fromob->pile->owner)) { - f->known = B_TRUE; + // methods of knocking unconscious + if (!isundead(lf)) { + // merciful weapons + if (fromob) { + f = hasflag(fromob->flags, F_MERCIFUL); + if (f && (amt >= lf->hp)) { + amt = lf->hp - 1; // ie end up at 1hp + ko = B_TRUE; + if (fromob->pile->owner && cansee(player, fromob->pile->owner)) { + f->known = B_TRUE; + } } } - } - // bashing damage sometimes ko's - if (!ko) { - if (damtype == DT_BASH) { - int hpleftafterdam; - hpleftafterdam = lf->hp - amt; - if ((lf->hp > 1) && (hpleftafterdam >= -5) && (hpleftafterdam <= 0)) { - if (onein(2)) { - ko = B_TRUE; - amt = lf->hp - 1; // ie end up at 1hp + // bashing damage sometimes ko's + if (!ko) { + if (damtype == DT_BASH) { + int hpleftafterdam; + // if this damage would reduce the lf to between -1 and 0 hp + hpleftafterdam = lf->hp - amt; + if ((lf->hp > 1) && (hpleftafterdam >= -5) && (hpleftafterdam <= 0)) { + if (onein(2)) { + ko = B_TRUE; + amt = lf->hp - 1; // ie end up at 1hp + } } } } } - // large damage? + // large damage will be stopped by a ring of miracles if ((amt >= (lf->maxhp / 2)) && (amt >= 20)) { if (useringofmiracles(lf, 1)) { return 0; @@ -11683,6 +11726,16 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml msg("[%s takes %d dam]",lfname, amt); } + // remember the amt of damage + if (isplayer(lf)) { + if (lf->bartimer == 2) { + lf->damlastturn += amt; + } else { + lf->damlastturn = amt; + lf->bartimer = 2; + } + } + // take damage lf->hp -= amt; @@ -11908,6 +11961,14 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml } void losemp(lifeform_t *lf, int amt) { + if (isplayer(lf)) { + if (lf->bartimer == 2) { + lf->mplastturn += amt; + } else { + lf->mplastturn = amt; + lf->bartimer = 2; + } + } lf->mp -= amt; if (lf->mp < 0) { @@ -12328,6 +12389,19 @@ void modstamina(lifeform_t *lf, float howmuch) { return; } + if (isplayer(lf)) { + if (howmuch < 0) { + if (lf->bartimer == 2) { + lf->stamlastturn += fabs(howmuch); + } else { + lf->stamlastturn = fabs(howmuch); + lf->bartimer = 2; + } + } else if (howmuch > 0) { + lf->stamlastturn = 0; + } + } + orig = getstamina(lf); lf->stamina += howmuch; limitf(&(lf->stamina), 0, getmaxstamina(lf)); @@ -12711,10 +12785,10 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int want msg("You can't pick up %s!",obname); break; case E_TOOBIG: - msg("%s %s too large for you to lift.",obname, (what->amt == 1) ? "is" : "are"); + msg("%s %s too large for you to lift.",obname, OB1(what,"is","are")); break; case E_TOOHEAVY: - msg("%s %s too heavy to lift!",obname, (what->amt == 1) ? "is" : "are"); + msg("%s %s too heavy to lift!",obname, OB1(what,"is","are")); break; case E_GRAVBOOSTED: msg("The %s feels too heavy to lift!",noprefix(obname)); @@ -13167,22 +13241,25 @@ int recruit(lifeform_t *lf) { } else { int result; int difficulty; + int minmult,maxmult; difficulty = 20 + ((gethitdice(player) - gethitdice(lf))*2); if (real_skillcheck(player, A_CHA, difficulty, 0, &result)) { + minmult = 10; + maxmult = 20; // passed - askingprice = rnd(gethitdice(lf)*5, gethitdice(lf)*20 ); - addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL); } else { if (difficulty - result >= 10) { // very expensive - askingprice = rnd(gethitdice(lf)*20, gethitdice(lf)*30 ); - addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL); + minmult = 20; + maxmult = 30; } else { // expensive - askingprice = rnd(gethitdice(lf)*10, gethitdice(lf)*25 ); - addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL); + minmult = 15; + maxmult = 25; } } + askingprice = rnd(gethitdice(lf)*minmult, gethitdice(lf)*maxmult ); + addflag(lf->flags, F_HIREPRICE, askingprice, NA, NA, NULL); } if (askingprice != 0) { @@ -14482,6 +14559,11 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r othermod += f->val[0]; } } + + // autopass if we have spiderclimb skill. + if (lfhasflag(lf, F_SPIDERCLIMB)) { + othermod = diff; + } } else if (ct == SC_DODGE) { if (attrib) { // ie. -2 to 2 @@ -14826,6 +14908,8 @@ void startlfturn(lifeform_t *lf) { // update where player knows // (but without a map you will then slowly forget it) if (isplayer(lf)) { + // update line of sight if required + if (lf->losdirty) precalclos(lf); updateknowncells(); } else { // ai start of turn code @@ -14964,7 +15048,7 @@ void startlfturn(lifeform_t *lf) { case PR_MASTER: lossamt = 0; break; } if (lossamt) modstamina(lf, -lossamt); - } else if (isclimbing(lf) && isplayer(lf)) { + } else if (isclimbing(lf) && !lfhasflag(lf, F_SPIDERCLIMB)) { int lossamt; // players lose stamina based on climbing skill // monsters don't lose stamina to climb. @@ -15089,13 +15173,13 @@ void startlfturn(lifeform_t *lf) { moveob(o, c->obpile, o->amt); if (isplayer(lf)) { getobname(o, buf, o->amt); - msg("^wYour %s flies out of your hands!",noprefix(buf), (o->amt == 1) ? "flies" : "fly"); + msg("^wYour %s %s out of your hands!",noprefix(buf), OB1(o,"flies","fly")); } else if (cansee(player, lf)) { char lfname[BUFLEN]; getobname(o, buf, o->amt); getlfname(lf, lfname); msg("%s%s %s flies out of its hands!",lfname, getpossessive(lfname), - noprefix(buf), (o->amt == 1) ? "flies" : "fly"); + noprefix(buf), OB1(o,"flies","fly")); } } } @@ -15369,6 +15453,10 @@ void startlfturn(lifeform_t *lf) { } } + // if you are stunned and flying, you fall + if (isairborne(lf) && lfhasflag(lf, F_STUNNED)) { + fall_from_air(lf); + } f = hasflag(lf->flags, F_POISONED); if (f) { @@ -16248,7 +16336,9 @@ int tryclimb(lifeform_t *lf, cell_t *where, char *towhat) { msg("%s reaches %s.", towhat); } // train climbing - practice(lf, SK_CLIMBING, 1); + if (!lfhasflag(lf, F_SPIDERCLIMB)) { + practice(lf, SK_CLIMBING, 1); + } // continue... } else { // you fall. @@ -16316,8 +16406,7 @@ int touch(lifeform_t *lf, object_t *o) { if (!gloves) { if (isplayer(lf)) { msg("^bThe %s burn%s you as you touch %s!",noprefix(obname), - (o->amt == 1) ? "s" : "", - (o->amt == 1) ? "it" : "them" ); + OBS1(o), OB1(o, "it", "them") ) ; o->blessknown = B_TRUE; } else if (cansee(player, lf)) { msg("%s touches %s then recoils in pain!",lfname, obname); @@ -16937,6 +17026,15 @@ int validateraces(void) { printf("ERROR in race '%s' - F_HASATTACK with no DR\n", r->name); goterror = B_TRUE; } + } else if (f->id == F_NOFLEE) { + if (lfhasflag(lf, F_FLEEONHPPCT)) { + printf("ERROR in race '%s' - has both F_NOFLEE and F_FLEEONHPPCT.\n", r->name); + goterror = B_TRUE; + } + if (lfhasflag(lf, F_FLEEONDAM)) { + printf("ERROR in race '%s' - has both F_NOFLEE and F_FLEEONDAM.\n", r->name); + goterror = B_TRUE; + } } else if (f->id == F_STARTOB) { if (!f->text || (strlen(f->text) == 0)) { printf("ERROR in race '%s' - F_STARTOB with zero length text.\n", r->name); @@ -16990,6 +17088,11 @@ int validateraces(void) { printf("ERROR in race '%s' - has both NOSMELL and ENHANCESMELL.\n", r->name); goterror = B_TRUE; } + } else if (f->id == F_STARTOBWEPSK) { + if (!findskill(f->val[1])) { + printf("ERROR in race '%s' - STARTOBWEPSK with invalid weapon skill.\n", r->name); + goterror = B_TRUE; + } } } // end foreach flag diff --git a/map.c b/map.c index 76442dc..3d7d40a 100644 --- a/map.c +++ b/map.c @@ -472,7 +472,7 @@ object_t *addrandomob(cell_t *c) { return NULL; } - if (real_getrandomob(c->map, buf, NA, c->habitat->id, SZ_MAX, B_FALSE, OC_NONE, DT_NONE)) { + if (real_getrandomob(c->map, buf, NA, c->habitat->id, SZ_MAX, SK_NONE, B_FALSE, OC_NONE, DT_NONE)) { if (db) dblog("adding rand obj %s to cell %d,%d",buf,c->x,c->y); o = addob(c->obpile, buf); } @@ -1898,7 +1898,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ cell = getrandomcell(map); setcelltype(cell, emptycell); cell->visited = B_TRUE; - //if (db) printf("- Starting (%d,%d)\n",cell->x, cell->y); + if (db) printf("- Starting (%d,%d)\n",cell->x, cell->y); lastdir = D_UNKNOWN; done = B_FALSE; @@ -1910,7 +1910,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ dir = D_NONE; while (dir == D_NONE) { int badcount; - //if (db) printf("- At (%d,%d), moved %d, finding new direction...\n",cell->x, cell->y, moved); + if (db) printf("- At (%d,%d), moved %d, finding new direction...\n",cell->x, cell->y, moved); dir = getnewdigdir(cell, lastdir, (moved < 2) ? 0 : turnpct, &moved); @@ -1928,19 +1928,19 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ while (!isempty(cell)) { cell = getrandomcell(map); } - //if (db) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",cell->x, cell->y); + if (db) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",cell->x, cell->y); // pick a new random dir dir = getnewdigdir(cell, lastdir, turnpct, &moved); } if (!done) { - //if (db) printf("- Digging %s from (%d,%d).\n",getdirname(dir),cell->x, cell->y); + if (db) printf("- Digging %s from (%d,%d).\n",getdirname(dir),cell->x, cell->y); } } if (!done) { // move to adjacent cell in the given direction cell = getcellindir(cell, dir); - //if (db) printf("- Now at (%d,%d)\n",cell->x, cell->y); + if (db) printf("- Now at (%d,%d)\n",cell->x, cell->y); moved++; // blank it @@ -1951,7 +1951,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ cell_t *thiscell; thiscell = getcellindir(cell, d); if (thiscell) { - //if (db) printf("* Marking surrounding cell in dir %d (%d,%d) as visited.\n",d, thiscell->x, thiscell->y); + if (db) printf("* Marking surrounding cell in dir %d (%d,%d) as visited.\n",d, thiscell->x, thiscell->y); thiscell->visited = B_TRUE; } } @@ -1975,7 +1975,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ } } - //printf("%d unused cell(s)\n",unused); + if (db) dblog("%d unused cell(s)\n",unused); //dumpmap(map); //getchar(); @@ -4061,7 +4061,7 @@ void dumpmap(map_t *map, int showrooms) { int x,y; cell_t *cell; char ch; -printf("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h); +dblog("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h); // top reference row dblog_nocr(" "); @@ -4542,7 +4542,7 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) { int i; int turned = B_FALSE; cell_t *newcell; - int db = B_FALSE; + int db = B_TRUE; char err[BUFLEN]; // haven't tried any dirs yet @@ -4571,10 +4571,10 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) { } // now validate the direction - if (db) printf("--- Trying %s...\n",getdirname(dir)); + if (db) dblog("--- Trying %s...\n",getdirname(dir)); if (tried[dir] == B_TRUE) { // already found this dir to be invalid lastdir = D_UNKNOWN; - if (db) printf("--- Already know %s is invalid.\n",getdirname(dir)); + if (db) dblog("--- Already know %s is invalid.\n",getdirname(dir)); } else { // check 1 cell ahead newcell = getcellindir(cell, dir); @@ -4605,26 +4605,26 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) { } if (!isnewcellok(newcell, err)) { - if (db) printf("--- %s %s!\n",getdirname(dir), err); + if (db) dblog("--- %s %s!\n",getdirname(dir), err); tried[dir] = B_TRUE; lastdir = D_UNKNOWN; numtries++; } else if (!isnewcellok(newcell1, err)) { - if (db) printf("--- %s %s!\n",getdirname(dir), err); + if (db) dblog("--- %s %s!\n",getdirname(dir), err); tried[dir] = B_TRUE; lastdir = D_UNKNOWN; numtries++; } else if (!isnewcellok(newcell2, err)) { - if (db) printf("--- %s %s!\n",getdirname(dir), err); + if (db) dblog("--- %s %s!\n",getdirname(dir), err); tried[dir] = B_TRUE; lastdir = D_UNKNOWN; numtries++; } else { // ok - if (db) printf("--- %s %s!\n",getdirname(dir), err); + if (db) dblog("--- %s %s!\n",getdirname(dir), err); foundvaliddir = B_TRUE; } } else { - if (db) printf("--- %s %s!\n",getdirname(dir), err); + if (db) dblog("--- %s %s!\n",getdirname(dir), err); tried[dir] = B_TRUE; lastdir = D_UNKNOWN; numtries++; @@ -6078,10 +6078,11 @@ int unlinkstairsto(map_t *unlinkmap) { void updateknowncells(void) { - int x,y; - map_t *map; + //int x,y; + //map_t *map; //object_t *wep; //int seenundead = B_FALSE; + int i; // you don't remember cells when you're flying, unless you // have a magic map or photographic memory. @@ -6089,6 +6090,7 @@ void updateknowncells(void) { return; } + /* map = player->cell->map; //wep = getweapon(player); @@ -6100,15 +6102,14 @@ void updateknowncells(void) { //if ((player->cell == cell) || haslos(player, cell)) { if (haslos(player, cell)) { setcellknown(cell, B_FALSE); - /* - if (cell->lf && lfhasflag(cell->lf, F_UNDEAD)) { - seenundead = B_TRUE; - } - */ } } } } + */ + for (i = 0; i < player->nlos; i++) { + setcellknown(player->los[i], B_FALSE); + } } int validateregions(void) { diff --git a/move.c b/move.c index 9b2f14c..7676fbc 100644 --- a/move.c +++ b/move.c @@ -1298,9 +1298,9 @@ int movelf(lifeform_t *lf, cell_t *newcell) { char obname[BUFLEN]; getobname(o,obname,o->amt); if (isplayer(lf)) { - msg("%s grab%s you!",obname,(o->amt == 1) ? "s" : ""); + msg("%s grab%s you!",obname,OBS1(o)); } else if (cansee(player, lf)) { - msg("%s grab%s %s!",obname, (o->amt == 1) ? "s" : "", lfname); + msg("%s grab%s %s!",obname, OBS1(o), lfname); } } } // end foreach object in cell diff --git a/nexus.c b/nexus.c index 0af521e..59021e0 100644 --- a/nexus.c +++ b/nexus.c @@ -875,6 +875,16 @@ void donextturn(map_t *map) { drawcursor(); // find out what player wants to do handleinput(); + if (who->bartimer) { + who->bartimer--; + if (who->bartimer == 0) { + who->damlastturn = 0; + who->mplastturn = 0; + who->stamlastturn = 0; + statdirty = B_TRUE; + drawstatus(); + } + } } else { //char lfname[BUFLEN]; //char buf[BUFLEN]; @@ -1046,6 +1056,11 @@ int init(void) { initjobs(); initrace(); + // open log file (want to do this before digging the first map) + logfile = fopen("log.txt","wt"); + fprintf(logfile, "\n\n\n====== NEW LOGFILE ====\n"); + + // create the dungeon layout initmap(); gamemode = GM_VALIDATION; @@ -1056,9 +1071,6 @@ int init(void) { return B_TRUE; } - // open log file - logfile = fopen("log.txt","wt"); - fprintf(logfile, "\n\n\n====== NEW LOGFILE ====\n"); // load in vaults loadvaults(); diff --git a/objects.c b/objects.c index 3ab51ee..75a02de 100644 --- a/objects.c +++ b/objects.c @@ -2474,6 +2474,11 @@ int changemat(object_t *o, enum MATERIAL mat) { // inherit flags from new material copyflags(o->flags, m->flags, FROMMAT); + // other stuff... + if (mat != MT_FLESH) { + killflagsofid(o->flags, F_ISMEAT); + } + if (mat == MT_ICE) { obmod_t *om; // if it turned to ice.. @@ -2744,10 +2749,10 @@ int doobdieconvert(object_t *o, int wantannounce) { } else if (oblastdamtype(o) == DT_DECAY) { // don't announce devay death while traning if (!lfhasflag(player, F_TRAINING)) { - snprintf(desc, BUFLEN, "%s completed rotted away", (o->amt == 1) ? "has" : "have"); + snprintf(desc, BUFLEN, "%s completed rotted away", OB1(o,"has","have")); } } else { - snprintf(desc, BUFLEN, "%s destroyed", (o->amt == 1) ? "is" : "are"); + snprintf(desc, BUFLEN, "%s destroyed", OB1(o,"is","are")); } if (strstr(o->type->name, "stain") || (o->type->id == OT_ROASTMEAT)) { assert(0 == 1); @@ -2865,14 +2870,14 @@ void explodeob(object_t *o, flag_t *f, int bigness) { // announce if (o->pile->owner) { if (isplayer(o->pile->owner)) { - msg("Your %s explode%s!", noprefix(obname), (o->amt == 1) ? "s" : ""); + msg("Your %s explode%s!", noprefix(obname),OBS1(o)); } else if (cansee(player, o->pile->owner)) { char lfname[BUFLEN]; getlfname(o->pile->owner, lfname); - msg("%s%s %s explode%s!", lfname, getpossessive(lfname), noprefix(obname), (o->amt == 1) ? "s" : ""); + msg("%s%s %s explode%s!", lfname, getpossessive(lfname), noprefix(obname),OBS1(o)); } } else if (haslos(player, c)) { - msg("%s explode%s!", obname, (o->amt == 1) ? "s" : ""); + msg("%s explode%s!", obname,OBS1(o)); } explodecells(c, dam * o->amt, bigness ? B_TRUE : B_FALSE, o, bigness ? 1 : 0, DT_COMPASS, B_FALSE); @@ -2889,17 +2894,17 @@ void extinguish(object_t *o) { if (o->pile->owner) { if (isplayer(o->pile->owner)) { msg("Your %s %s extinguished.", noprefix(obname), - (o->amt == 1) ? "is" : "are"); + OB1(o,"is","are")); } else if (cansee(player, o->pile->owner)) { char lfname[BUFLEN]; getlfname(o->pile->owner, lfname); msg("%s%s %s %s extinguished.", lfname, getpossessive(lfname), noprefix(obname), - (o->amt == 1) ? "is" : "are"); + OB1(o,"is","are")); } } else if (o->pile->where && haslos(player, o->pile->where)) { getobname(o, obname, o->amt); msg("%s %s extinguished.", obname, - (o->amt == 1) ? "is" : "are"); + OB1(o,"is","are")); } killflag(f); } @@ -4806,7 +4811,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan case OT_RING_STR: f = hasflag(o->flags, F_EQUIPCONFER); if (f) { - snprintf(buf2, BUFLENSMALL, "+%d ",f->val[2]); + snprintf(buf2, BUFLENSMALL, "%s%d ",(f->val[2] < 0) ? "-" : "+", abs(f->val[2])); strcat(localbuf, buf2); } break; @@ -5167,10 +5172,11 @@ objecttype_t *getoppositestairs(objecttype_t *ot) { return findot(f->val[0]); } -//char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth, int forcehabitat, enum LFSIZE maxsize) { -// varargs are: -// OC_CLASS1, OC_CLAS2, OC_NONE, ..., DT_DAMTYPE1, DT_DAMTYPE2, .., DT_NONE -char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, int forpickup, ... ) { +// varargs are: +// OC_CLASS1, OC_CLAS2, OC_NONE, ..., DT_DAMTYPE1, DT_DAMTYPE2, .., DT_NONE +// +// no objectclass given then it will be picked randomly, or (if wepsk isn't sk_none) set to oc_weapon. +char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, enum SKILL wepsk, int forpickup, ... ) { va_list args; objecttype_t *ot; objecttype_t *poss[MAXRANDOMOBCANDIDATES]; @@ -5199,6 +5205,7 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, habitat_t *hab; char habname[BUFLEN]; int rrmoddir = -1; + skill_t *wantsk = NULL; if (!db) db = obdb; @@ -5216,6 +5223,10 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, } va_end(args); + if (wepsk) { + wantsk = findskill(wepsk); + } + if (forcehabitat != NA) { hab = findhabitat(forcehabitat); } else if (map) { @@ -5245,7 +5256,11 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, // no obclass given? pick one randomly. if (!nwantclass) { - wantclass[0] = getrandomobclass(hab->id); + if (wantsk) { + wantclass[0] = OC_WEAPON; + } else { + wantclass[0] = getrandomobclass(hab->id); + } nwantclass = 1; } @@ -5254,6 +5269,10 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, raritymin,raritymax,wantrr, habname); if (db || partdb) { char dbuf[BUFLEN]; + if (wantsk) { + sprintf(dbuf, " must have wepskill: %s", wantsk->name); + dblog("%s", dbuf); + } if (nwantclass) { objectclass_t *oc = NULL; sprintf(dbuf, " must have obclass: "); @@ -5353,6 +5372,17 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, } } + // matches wanted weapon skill? + if (wantsk) { + if (ot->id == OT_QUICKBLADE) { + dblog("xxx"); + } + if (!hasflagval(ot->flags, F_USESSKILL, wantsk->id, NA, NA, NULL)) { + condok = B_FALSE; + if (db) dblog(" %s doesn't use correct weapon skill.", ot->name); + } + } + if (forpickup) { if (hasflag(ot->flags, F_NOPICKUP)) { condok = B_FALSE; @@ -5518,21 +5548,21 @@ char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, } char *getrandomob(map_t *map, char *buf) { - return real_getrandomob(map, buf, NA, NA, SZ_MAX, B_FALSE, OC_NONE, DT_NONE); + return real_getrandomob(map, buf, NA, NA, SZ_MAX, SK_NONE, B_FALSE, OC_NONE, DT_NONE); } char *getrandomobofsize(map_t *map, char *buf, enum LFSIZE maxsize) { - return real_getrandomob(map, buf, NA, NA, maxsize, B_FALSE, OC_NONE, DT_NONE); + return real_getrandomob(map, buf, NA, NA, maxsize, SK_NONE, B_FALSE, OC_NONE, DT_NONE); } char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf) { - return real_getrandomob(map, buf, NA, NA, SZ_MAX, B_TRUE, OC_NONE, damtype, DT_NONE); + return real_getrandomob(map, buf, NA, NA, SZ_MAX, SK_NONE, B_TRUE, OC_NONE, damtype, DT_NONE); } char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod) { //return real_getrandomob(map, buf, RO_OBCLASS, cid, map->depth + depthmod); if (depthmod == NA) depthmod = 0; - return real_getrandomob(map, buf, getmapdifficulty(map) + depthmod, NA, SZ_MAX, B_FALSE, cid, OC_NONE, DT_NONE); + return real_getrandomob(map, buf, getmapdifficulty(map) + depthmod, NA, SZ_MAX, SK_NONE, B_FALSE, cid, OC_NONE, DT_NONE); } enum OBCLASS getrandomobclass(enum HABITAT hab) { @@ -7017,7 +7047,7 @@ void makewet(object_t *o, int amt) { } else { // rust if (haslos(player, loc) && !isdead(player)) { - msg("%s rust%s.",obnamefull, (o->amt == 1) ? "s" : ""); + msg("%s rust%s.",obnamefull,OBS1(o)); } f = addflag(o->flags, F_RUSTED, amt, NA, NA, NULL); } @@ -7031,7 +7061,7 @@ void makewet(object_t *o, int amt) { // make wetter /* if (haslos(player, loc)) { - msg("%s get%s wetter.",obnamefull, (o->amt == 1) ? "s" : ""); + msg("%s get%s wetter.",obnamefull,OBS1(o)); } */ f->val[0] += amt; @@ -7052,7 +7082,7 @@ void makewet(object_t *o, int amt) { } if (doannounce) { - msg("%s get%s wet.",obnamefull, (o->amt == 1) ? "s" : ""); + msg("%s get%s wet.",obnamefull,OBS1(o)); } } f = addflag(o->flags, F_WET, amt, TM_WETTIME, NA, NULL); @@ -7093,7 +7123,7 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) { getobname(src, obname, src->amt); getobname(pit, pitname, 1); - msg("%s fall%s down %s.", obname, (src->amt == 1) ? "s" : "", pitname); + msg("%s fall%s down %s.", obname, OBS1(src), pitname); } dst = newcell->obpile; } @@ -7348,10 +7378,10 @@ void obdie(object_t *o) { snprintf(desc, BUFLEN, "%s", f->text); } else if (oblastdamtype(o) == DT_DECAY) { if (!lfhasflag(player, F_TRAINING)) { - snprintf(desc, BUFLEN, "%s completely rotted away", (o->amt == 1) ? "has" : "have" ); + snprintf(desc, BUFLEN, "%s completely rotted away", OB1(o,"has","have") ); } } else { - snprintf(desc, BUFLEN, "%s destroyed", (o->amt == 1) ? "is" : "are"); + snprintf(desc, BUFLEN, "%s destroyed", OB1(o,"is","are")); } if (strlen(desc)) { @@ -7645,8 +7675,7 @@ int obsfallthrough(cell_t *c, object_t *pit) { if (haslos(player, c)) { // player can see the top of the hole getobname(oo,obname, oo->amt); - msg("%s %s%s through %s.", obname, verb, - (oo->amt == 1) ? "s" : "", + msg("%s %s%s through %s.", obname, verb, OBS1(oo), downholename); } @@ -7663,9 +7692,7 @@ int obsfallthrough(cell_t *c, object_t *pit) { if (haslos(player, belowcell)) { // player can see the bottom of the hole getobname(oo,obname, oo->amt); - msg("%s %s%s through %s.", obname, verb, - (oo->amt == 1) ? "s" : "", - upholename); + msg("%s %s%s through %s.", obname, verb, OBS1(oo), upholename); } // does the object hit anyone? @@ -7678,9 +7705,7 @@ int obsfallthrough(cell_t *c, object_t *pit) { char lfname[BUFLEN]; getobname(oo,obname, oo->amt); getlfname(lf, lfname); - msg("%s hit%s %s!", obname, - (oo->amt == 1) ? "s" : "", - lfname); + msg("%s hit%s %s!", obname, OBS1(oo), lfname); } snprintf(dambuf, BUFLEN, "a falling %s", oo->type->name); losehp(lf, getthrowdam(oo) * 6, DT_PROJECTILE, NULL, dambuf); @@ -8244,7 +8269,8 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { removeob(oo, 1); break; case OT_FOUNTAIN: - if (onein(ONEIN_FOUNTAINDRYUP)) { + if (hasflagval(oo->flags, F_LINKOB, OT_POT_EXPERIENCE, NA, NA, NULL) || + onein(ONEIN_FOUNTAINDRYUP)) { cell_t *loc; loc = getoblocation(oo); if (haslos(player, loc)) { @@ -9357,6 +9383,13 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE } if (seen) *seen = B_TRUE; break; + case OT_POT_SPIDERCLIMB: + i = geteffecttime(20,50,potblessed); + addtempflag(lf->flags, F_SPIDERCLIMB, B_TRUE, NA, NA, NULL, i); + if (!lfhasflagval(lf, F_CANWILL, OT_A_CLIMB, NA, NA, NULL)) { + addtempflag(lf->flags, F_CANWILL, OT_A_CLIMB, NA, NA, NULL, i); + } + break; case OT_POT_WATER: switch (potblessed) { case B_BLESSED: @@ -9541,10 +9574,8 @@ int readsomething(lifeform_t *lf, object_t *o) { if (o->type->obclass->id == OC_BOOK) { // is this a spellbook? if (o->type->id == OT_SPELLBOOK) { - // if so, always id it. - // note though that we can only actually LEARN - // the spell if we are skilled in that school. - willid = B_TRUE; + // if so, only id it if we can understand it. + willid = B_FALSE; } else { // ie. a manual willid = B_TRUE; @@ -9928,6 +9959,17 @@ int readsomething(lifeform_t *lf, object_t *o) { return B_FALSE; } + // player now knows what it is - id it! + if (isplayer(lf) && !isknown(o)) { + identify(o); + o->blessknown = B_TRUE; + real_getobname(o, obname, 1, B_FALSE, B_TRUE, B_FALSE, B_TRUE, B_FALSE); // don't adjust for blindness + // tell the player + msg("This is %s!",obname); + more(); + drawmsg(); + } + // we are skilled in the right school. now ask which spell to learn. initprompt(&prompt, "Which spell will you try to learn?"); for (oo = o->contents->first ;oo ; oo = oo->next) { @@ -10271,8 +10313,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) { strcpy(prefix, ""); } - msg("%s%s shatter%s!",prefix, strlen(prefix) ? noprefix(obname) : obname, - (o->amt == 1) ? "s" : ""); + msg("%s%s shatter%s!",prefix, strlen(prefix) ? noprefix(obname) : obname, OBS1(o)); seen = B_TRUE; } else { @@ -10592,7 +10633,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) { if (haslos(player, c)) { char buf[BUFLEN]; getobname(o, buf, o->amt); - msg("%s %s lit.", buf, (o->amt == 1) ? "is" : "are"); + msg("%s %s lit.", buf, OB1(o,"is","are")); } turnon(NULL, o); @@ -10627,7 +10668,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) { // announce getobname(o, obname, o->amt); if (isplayer(owner)) { - msg("Your %s burn%s you!", noprefix(obname), (o->amt == 1) ? "s" : ""); + msg("Your %s burn%s you!", noprefix(obname),OBS1(o)); } else if (cansee(player, owner)) { char lfname[BUFLEN]; getlfname(owner, lfname); @@ -11706,10 +11747,10 @@ void timeeffectsob(object_t *o) { // object can't go anywhere - it disintegrates. if (owner && cansee(player, owner)) { msg("%s%s vanish%s in a surge of %s power!", ownername, getpossessive(ownername), - obname, (o->amt == 1) ? "es" : "", + obname, OB1(o,"es",""), (o->blessed = B_CURSED) ? "holy" : "evil"); } else if (haslos(player, location)) { - msg("%s vanish%s in a surge of %s power!", obname, (o->amt == 1) ? "es" : "", + msg("%s vanish%s in a surge of %s power!", obname, OB1(o,"es",""), (o->blessed = B_CURSED) ? "holy" : "evil"); } removeob(o, o->amt); @@ -11778,7 +11819,7 @@ void timeeffectsob(object_t *o) { if (willvanish) { // vanish. if (haslos(player, location)) { - msg("%s vanish%s.", obname, (o->amt == 1) ? "es" : ""); + msg("%s vanish%s.", obname, OB1(o,"es","")); } killob(o); return; diff --git a/objects.h b/objects.h index c44cf8e..ae1cee4 100644 --- a/objects.h +++ b/objects.h @@ -127,7 +127,7 @@ char *getobhurtname(object_t *o, enum DAMTYPE damtype); float getobweight(object_t *o); float getobunitweight(object_t *o); objecttype_t *getoppositestairs(objecttype_t *ot); -char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, int forpickup, ... ); +char *real_getrandomob(map_t *map, char *buf, int forcedepth, int forcehabitat, enum LFSIZE maxsize, enum SKILL wepsk, int forpickup, ... ); char *getrandomob(map_t *map, char *buf); char *getrandomobofsize(map_t *map, char *buf, enum LFSIZE maxsize); char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf); diff --git a/shops.c b/shops.c index 11b22d0..e28a323 100644 --- a/shops.c +++ b/shops.c @@ -318,7 +318,7 @@ enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *topte case OT_TEMPLE: wantflag = F_NONE; wantoc = OC_MONEY; break; default: wantflag = F_NONE; wantoc = OC_NONE; break; } - o = doaskobject(lf->pack, "What will you donate?", &count, B_FALSE, B_FALSE, AO_NONE, wantflag, F_NONE); + o = doaskobject(lf->pack, "What will you donate?", &count, B_TRUE, B_FALSE, B_FALSE, '\0', AO_NONE, wantflag, F_NONE); // validate it if (o) { @@ -329,21 +329,55 @@ enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *topte return SR_CONTINUE; } } + + // confirm count for gold + if (o->type->obclass->id == OC_MONEY) { + char answer[BUFLEN],buf[BUFLEN]; + sprintf(buf, "How much money will you donate (you have $%d)?", o->amt); + askstring(buf, '?', answer, BUFLEN, NULL); + count = atoi(answer); + if (count <= 0) { + return SR_CONTINUE; + } + 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(); } else { - object_t *newob; - char let; - if (vm->contents->first) { - let = vm->contents->last->letter + 1; + int goldgiven = 0; + if (o->type->id == OT_GOLD) { + givemoney(lf, NULL, count); + (*ndonated)++; + goldgiven += count; } else { - let = 'a'; + 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)++; + } + + 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."); + } + } else { + msg("Thanks!"); more(); } - newob = moveob(o, vm->contents, count); - newob->letter = let; - (*ndonated)++; - msg("Thanks!"); more(); } } else { return SR_BACK; @@ -524,7 +558,13 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top for (o = vm->contents->first ; o ; o = o->next) { char obname[BUFLEN]; // get the name of the object - real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_TRUE); + if (gettechlevel(o->type->id) > getskill(player, SK_TECHUSAGE)) { + // unidentifie tech - hide the name + real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_FALSE); + } else { + // anything else - show the real name + real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_TRUE, B_TRUE, B_TRUE); + } snprintf(buf, BUFLEN, "%c - %s", o->letter, obname); snprintf(buf2, BUFLEN, "%-60s$%d",buf,(int)getshopprice(o, player)); mvwprintw(mainwin, y, 0, "%s", buf2); diff --git a/spell.c b/spell.c index 3aef41e..be185c4 100644 --- a/spell.c +++ b/spell.c @@ -609,7 +609,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef char yn; char ques[BUFLEN]; getobname(o, obname, o->amt); - sprintf(ques, "There %s %s here. Cook it?", (o->amt == 1) ? "is" : "are",obname); + sprintf(ques, "There %s %s here. Cook it?", OB1(o,"is","are"),obname); yn = askchar(ques, "yn","n", B_TRUE, B_FALSE); if (yn == 'y') { corpse = o; @@ -1075,7 +1075,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } return B_TRUE; } else if (!isdualweilding(user)) { - if (isplayer(user)) msg("You need two be dual-weilding to perform an attack flurry!"); + if (isplayer(user)) msg("You need to be dual-weilding to perform an attack flurry!"); return B_TRUE; } @@ -2873,6 +2873,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } } addchoice(&prompt, '-', "(nothing)", NULL, NULL, NULL); + prompt.maycancel = B_TRUE; if (prompt.nchoices == 1) { msg("You don't have anything which you can inspect."); @@ -3035,7 +3036,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (haslos(player, caster->cell)) { msg("The pentagram pulses red."); } - if (summonlfs(caster, caster->cell, RC_DEMON, SZ_ANY, AL_NONE, 1, PERMENANT, B_FALSE)) { + if (summonlfs(caster, caster->cell, R_NONE, RC_DEMON, SZ_ANY, AL_NONE, 1, PERMENANT, B_FALSE)) { if (isplayer(caster) || cansee(player, caster)) { msg("An other-worldly demon appears!"); } @@ -3641,21 +3642,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (target) { if (isplayer(target)) { getobname(targob, obname, targob->amt); - msg("^%cYour %s vanish%s!", getlfcol(target, CC_VBAD), noprefix(obname), (targob->amt == 1) ? "es" : ""); + msg("^%cYour %s vanish%s!", getlfcol(target, CC_VBAD), noprefix(obname), OB1(targob,"es","")); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (isplayer(caster)) { char targname[BUFLEN]; getlfname(target, targname); getobname(targob, obname, targob->amt); msg("%s%s %s appear%s in your pack!", targname, getpossessive(targname), - noprefix(obname), (targob->amt == 1) ? "es" : ""); + noprefix(obname), OB1(targob,"es","")); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { char targname[BUFLEN]; getlfname(target, targname); getobname(targob, obname, targob->amt); msg("^%c%s%s %s vanish%s!", getlfcol(target, CC_VBAD), targname, getpossessive(targname), noprefix(obname), - (targob->amt == 1) ? "es" : ""); + OB1(targob,"es","")); if (seenbyplayer) *seenbyplayer = B_TRUE; } } @@ -4548,7 +4549,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenthiscell) { if (!hasflag(o->flags, F_OBDIETEXT)) { getobname(o, obname, o->amt); - msg("%s crumble%s to dust!", obname, (o->amt == 1) ? "s" : ""); + msg("%s crumble%s to dust!", obname, OBS1(o)); } if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -4665,7 +4666,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ (o->type->id == OT_TRAPGAS)) { char obname[BUFLEN]; getobname(o, obname, o->amt); - msg("%s %s revealed!", obname, (o->amt == 1) ? "is" : "are"); + msg("%s %s revealed!", obname, OB1(o,"is","are")); npoisoned++; killflagsofid(o->flags, F_SECRET); } else { @@ -4698,7 +4699,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (ispoisoned || isdecayed) { char obname[BUFLEN]; getobname(o, obname, o->amt); - msg("%s %s %s!", obname, (o->amt == 1) ? "is" : "are", + msg("%s %s %s!", obname, OB1(o,"is","are"), ispoisoned ? "poisoned" : "rotted"); npoisoned++; } @@ -4854,13 +4855,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (haslos(player, targcell) && canseeob(player, o)) { - msg("%s disappear%s!", buf, (o->amt == 1) ? "s" : ""); + msg("%s disappear%s!", buf, OBS1(o)); if (seenbyplayer) *seenbyplayer = B_TRUE; donesomething = B_TRUE; } moveob(o, c->obpile, o->amt); if (haslos(player, c) && canseeob(player, o)) { - msg("%s appear%s nearby!", buf, (o->amt == 1) ? "s" : ""); + msg("%s appear%s nearby!", buf, OBS1(o)); } } if (isplayer(caster) && !donesomething) { @@ -5505,7 +5506,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("%s %s start%s glowing bright blue!", (o->pile->owner == caster) ? "Your" : "", (o->pile->owner == caster) ? noprefix(obname) : obname, - (o->amt == 1) ? "s" : ""); + OBS1(o)); more(); ch = askchar("Abort your spell?", "yn","y", B_TRUE, B_FALSE); if (ch == 'y') { @@ -5548,7 +5549,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("%s %s freeze%s some more.", (o->pile->owner == caster) ? "Your" : "", (o->pile->owner == caster) ? noprefix(obname) : obname, - (o->amt == 1) ? "s" : ""); + OBS1(o)); } // restore it f = hasflag(o->flags, F_OBHP); @@ -5585,7 +5586,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { if (o->pile->owner) { if (isplayer(o->pile->owner)) { - msg("Your %s turn%s to ice!",noprefix(buf), (o->amt == 1) ? "s" : ""); + msg("Your %s turn%s to ice!",noprefix(buf), OBS1(o)); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (haslos(player, o->pile->owner->cell)) { getlfname(o->pile->owner, buf); @@ -5787,15 +5788,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // severed body parts getflags(target->flags, retflag, &nretflags, F_INJURY, F_NOBODYPART, F_NONE); for (i = 0; i < nretflags; i++) { + enum BODYPART bpgone = BP_NONE; if ((retflag[i]->id == F_NOBODYPART) && (retflag[i]->val[1] == B_FROMINJURY)) { + bpgone = retflag[i]->val[0]; + } else if ((retflag[i]->id == F_INJURY) && (retflag[i]->lifetime == PERMENANT)) { // permenant injury + bpgone = retflag[i]->val[1]; + } + if (bpgone != BP_NONE) { if (isplayer(target)) { - msg("Your %s grows back!", getbodypartname(target, retflag[i]->val[0])); + msg("Your %s grows back!", getbodypartname(target, bpgone)); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { char targname[BUFLEN]; getlfname(target, targname); msg("%s%s %s grows back!", targname, getpossessive(targname), - getbodypartname(target, retflag[i]->val[0])); + getbodypartname(target, bpgone)); if (seenbyplayer) *seenbyplayer = B_TRUE; } killflag(retflag[i]); @@ -5927,7 +5934,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ getobname(o, obname, o->amt); getlfname(target, lfname); msg("%s%s %s glow%s red hot!", lfname, getpossessive(lfname), - noprefix(obname), (o->amt == 1) ? "s" : ""); + noprefix(obname), OBS1(o)); if (seenbyplayer) *seenbyplayer = B_TRUE; } takedamage(o, rnd(1,4), DT_HEAT); @@ -5959,7 +5966,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (haslos(player, targcell)) { char obname[BUFLEN]; getobname(o, obname, o->amt); - msg("%s glow%s red hot!", obname, (o->amt == 1) ? "s" : ""); + msg("%s glow%s red hot!", obname, OBS1(o)); if (seenbyplayer) *seenbyplayer = B_TRUE; donesomething = B_FALSE; } @@ -6503,7 +6510,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (spellresisted(target, caster, spellid, power, seenbyplayer, B_FALSE)) { failed = B_TRUE; - } else if (skillcheck(target, SC_CON, 20 + power, 0)) { + } else if (skillcheck(target, SC_CON, 20 + (power*2), 0)) { failed = B_TRUE; } @@ -7802,7 +7809,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (haslos(player, targcell)) { char obname[BUFLEN]; getobname(retob[n], obname, retob[n]->amt); - msg("%s flare%s up!", obname, (retob[n]->amt == 1) ? "s" : ""); + msg("%s flare%s up!", obname, OBS1(retob[n])); if (seenbyplayer) *seenbyplayer = B_TRUE; } } // end foreach flaming ob @@ -9012,14 +9019,27 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if ((spellid == OT_S_SUMMONANIMALSSM) || (spellid == OT_S_SUMMONANIMALSMD) || (spellid == OT_S_SUMMONANIMALSLG) || + (spellid == OT_S_FRIENDS) || (spellid == OT_S_SUMMONDEMON)) { int lifetime, nwant,ngot,successrate; enum LFSIZE wantsize; enum RACECLASS wantrc; + enum RACE wantrace = R_NONE; int friendly; lifetime = (power * 9) + rnd(1,power*2); switch (spellid) { + case OT_S_FRIENDS: + switch (rnd(1,2)) { + case 1: wantrace = R_CHICKEN; break; + case 2: wantrace = R_BUTTERFLY; break; + } + wantrc = RC_ANY; + wantsize = SZ_ANY; + nwant = 8; + successrate = 100; + friendly = B_FALSE; + break; case OT_S_SUMMONDEMON: wantrc = RC_DEMON; wantsize = SZ_ANY; @@ -9065,19 +9085,29 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } - ngot = summonlfs(caster, caster->cell, wantrc, wantsize, AL_NONE, nwant, lifetime, friendly); + ngot = summonlfs(caster, caster->cell, wantrace, wantrc, wantsize, AL_NONE, nwant, lifetime, friendly); if (!ngot) { fizzle(caster); return B_TRUE; } else { if (haslos(player, caster->cell)) { // intentionally not using cansee - raceclass_t *rc; - rc = findraceclass(wantrc); if (seenbyplayer) *seenbyplayer = B_TRUE; - if (ngot == 1) { - msg("%s %s appears near %s!", needan(rc->name) ? "An" : "A", rc->name, castername); + if (wantrace) { + race_t *r; + r = findrace(wantrace); + if (ngot == 1) { + msg("%s %s appears near %s!", needan(r->name) ? "An" : "A", r->name, castername); + } else { + msg("%s appear around %s!", makeplural(r->name), castername); + } } else { - msg("%s appear around %s!", makeplural(rc->name), castername); + raceclass_t *rc; + rc = findraceclass(wantrc); + if (ngot == 1) { + msg("%s %s appears near %s!", needan(rc->name) ? "An" : "A", rc->name, castername); + } else { + msg("%s appear around %s!", makeplural(rc->name), castername); + } } } } @@ -9679,7 +9709,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (o) { noise(caster->cell, NULL, NC_OTHER, 1, "something hitting the ground.", NULL); if (!isblind(caster)) { - msg("%s appear%s on the ground!", obname, (o->amt == 1) ? "s" : ""); + msg("%s appear%s on the ground!", obname, OBS1(o)); } } else { // ob exists but couldn't make it appear @@ -10438,8 +10468,7 @@ void pullobto(object_t *o, lifeform_t *lf) { getobname(o, obname, o->amt); getlfname(lf, lfname); if (isplayer(lf) || haslos(player, lf->cell)) { - msg("%s %s towards %s!", obname, (o->amt == 1) ? "flies" : "fly", - lfname); + msg("%s %s towards %s!", obname, OB1(o,"flies","fly"), lfname); } // can we pick up the object? @@ -10451,7 +10480,7 @@ void pullobto(object_t *o, lifeform_t *lf) { snprintf(buf, BUFLEN, "a flying %s", noprefix(obname)); if (isplayer(lf) || haslos(player, lf->cell)) { - msg("%s %s into %s!", obname, (o->amt == 1) ? "slams" : "slam", lfname); + msg("%s %s into %s!", obname, OB1(o,"slams","slam"), lfname); } // where does it end up? obloc = getoblocation(o); @@ -10661,7 +10690,8 @@ void stopspell(lifeform_t *caster, enum OBTYPE spellid) { // returns # created -int summonlfs(lifeform_t *caster, cell_t *where, enum RACECLASS wantrc, enum LFSIZE wantsize, enum ALIGNMENT wantalign, int howmany, int lifetime, int friendly) { +// pass EITHER wantrace OR wantrc + wantsize + wantalign +int summonlfs(lifeform_t *caster, cell_t *where, enum RACE wantrace, enum RACECLASS wantrc, enum LFSIZE wantsize, enum ALIGNMENT wantalign, int howmany, int lifetime, int friendly) { lifeform_t *newlf; race_t *r = NULL; enum RACE poss[MAXCANDIDATES]; @@ -10670,30 +10700,35 @@ int summonlfs(lifeform_t *caster, cell_t *where, enum RACECLASS wantrc, enum LFS int ncreated = 0; cell_t *c; - // determine possible types of race - for (r = firstrace ; r; r = r->next) { - int ok = B_TRUE; - if ((wantrc != RC_ANY) && (r->raceclass->id != wantrc)) { - ok = B_FALSE; - } - - if (wantsize != SZ_ANY) { - flag_t *f; - f = hasflag(r->flags, F_SIZE); - if (f && (f->val[0] != wantsize)) { + if (wantrace) { + poss[0] = wantrace; + nposs = 1; + } else { + // determine possible types of race + for (r = firstrace ; r; r = r->next) { + int ok = B_TRUE; + if ((wantrc != RC_ANY) && (r->raceclass->id != wantrc)) { ok = B_FALSE; } - } - if (wantalign != AL_NONE) { - flag_t *f; - f = hasflag(r->flags, F_ALIGNMENT); - if (f && (f->val[0] != wantalign)) { - ok = B_FALSE; + if (wantsize != SZ_ANY) { + flag_t *f; + f = hasflag(r->flags, F_SIZE); + if (f && (f->val[0] != wantsize)) { + ok = B_FALSE; + } + } + + if (wantalign != AL_NONE) { + flag_t *f; + f = hasflag(r->flags, F_ALIGNMENT); + if (f && (f->val[0] != wantalign)) { + ok = B_FALSE; + } + } + if (ok) { + poss[nposs++] = r->id; } - } - if (ok) { - poss[nposs++] = r->id; } } diff --git a/spell.h b/spell.h index b2e165a..c17494f 100644 --- a/spell.h +++ b/spell.h @@ -38,7 +38,7 @@ int spellresisted(lifeform_t *target, lifeform_t *caster, int spellid, int power void stopspell(lifeform_t *caster, enum OBTYPE spellid); void stopallspells(lifeform_t *lf); void stopallspellsexcept(lifeform_t *lf, ...); -int summonlfs(lifeform_t *caster, cell_t *where, enum RACECLASS wantrc, enum LFSIZE wantsize, enum ALIGNMENT wantalign, int howmany, int lifetime, int friendly); +int summonlfs(lifeform_t *caster, cell_t *where, enum RACE wantrace, enum RACECLASS wantrc, enum LFSIZE wantsize, enum ALIGNMENT wantalign, int howmany, int lifetime, int friendly); lifeform_t *validateabillf(lifeform_t *user, enum OBTYPE aid, lifeform_t **target); cell_t *validatespellcell(lifeform_t *caster, cell_t **targcell, int targtype, enum OBTYPE spellid, int power, int frompot); //lifeform_t *validatespelllf(lifeform_t *caster, lifeform_t **lf); diff --git a/text.c b/text.c index bb7e270..3d73552 100644 --- a/text.c +++ b/text.c @@ -1091,7 +1091,7 @@ void makegunaimstring(lifeform_t *lf, int lfid, char *retbuf) { makethrowaccstring(lf, targ->cell, f, accbuf); killflagsofid(lf->flags, F_THROWING); - sprintf(retbuf, "%s %s", noprefix(targname), accbuf); + sprintf(retbuf, "%s%s", noprefix(targname), accbuf); } char *makekillertext(char *retbuf, char *killverb, char *lastdam, int wantextra) {