- [+] bug: shouldn't be able to pay with gems without beginner

psychology
- [+] plauge rat should have poison corpse
- [+] bjorn should only get mad when you flee from armed foes.
- [+] Strengths: should include poisonous bite at beginner level, not
      adept.
- [+] show behaviour flags in description
    - [+] territorial (insane)
    - [+] fleeondam (timid)
    - [+] noflee (drugged)
    - [+] followtime (detemrined / lazy)
    - [+] muscled/scrawny
- [+] should be able to pay potion stores to id stuff.
    - [+] update make_basic_shop
    - [+] use shopacceptsflag
    - [+] id function...
- [+] bug: scroll of wishing, Protection. keeps giving me 'sun hat.
    - [+] limit possible body parts to certain ones.
- [+] when wearing armour of the spider, you should never get exhausted
      from climbing
- [+] show "Threat Assessment" text on @@
- [+] only warn about pentagrams with gtaverage iq
* [+] new playable race: Wyrmspawn
This commit is contained in:
Rob Pearce 2012-05-22 06:10:49 +00:00
parent 1605501866
commit cd9b6cd40a
13 changed files with 338 additions and 83 deletions

2
ai.c
View File

@ -1991,7 +1991,7 @@ int aipickupok(lifeform_t *lf, object_t *o) {
*/
if (isedible(o)) {
if (caneat(lf, o) && !isinbattle(lf, B_FALSE)) {
if (caneat(lf, o) && !isinbattle(lf, B_NODISTANT, B_FALSE)) {
ok = B_TRUE;
}
} else if (canpickup(lf, o, 1)) {

69
data.c
View File

@ -1814,7 +1814,9 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_VERYRARE, NULL);
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_HASHIDDENNAME, NA, OC_SCROLL, NULL);
addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_HASHIDDENNAME, NA, OC_BOOK, NULL);
make_basic_shop(lastot->flags, B_ALLOWID);
for (i = 0; i < 10; i++) {
f = addflag(lastot->flags, F_STARTOBCLASS, 100, OC_BOOK, RANDOM, NULL);
addcondition(f, FC_NOCONDITION, 33);
@ -1824,7 +1826,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL);
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
make_basic_shop(lastot->flags, B_NOID);
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_FOOD, RANDOM, NULL);
}
@ -1832,7 +1834,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
make_basic_shop(lastot->flags, B_NOID);
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL);
}
@ -1840,7 +1842,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
make_basic_shop(lastot->flags, B_NOID);
for (i = 0; i < 10; i++) {
f = addflag(lastot->flags, F_STARTOBCLASS, 100, OC_TOOLS, RANDOM, NULL);
addcondition(f, FC_NOCONDITION, 50);
@ -1849,8 +1851,9 @@ void initobjects(void) {
addot(OT_SHOPPOTION, "potion store", "A small kiosk dealing in liqour and potions.", MT_METAL, 500, OC_BUILDING, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL);
addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_DRINKABLE, NA, OC_POTION, NULL);
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
make_basic_shop(lastot->flags);
make_basic_shop(lastot->flags, B_ALLOWID);
for (i = 0; i < 10; i++) {
addflag(lastot->flags, F_STARTOBCLASS, 100, OC_POTION, RANDOM, NULL);
}
@ -1859,9 +1862,11 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_VERYRARE, NULL);
addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_GEM, 75, NA, NULL);
addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_HASHIDDENNAME, NA, OC_RING, NULL); // ID only, not sell.
addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something");
addflag(lastot->flags, F_SHOPMENU, 1, MA_GOTOMENU, SM_SELLITEMS, "b:sell gems");
addflag(lastot->flags, F_SHOPMENU, 2, MA_QUIT, NA, "q:leave");
addflag(lastot->flags, F_SHOPMENU, 2, MA_GOTOMENU, SM_ID, "i:inspect items");
addflag(lastot->flags, F_SHOPMENU, 3, MA_QUIT, NA, "q:leave");
addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "a cash register chiming.");
for (i = 0; i < 10; i++) {
if (onein(3)) {
@ -9034,6 +9039,43 @@ void initrace(void) {
addflag(lastrace->flags, F_TAMABLE, 25, NA, NA, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, "gne");
addrace(R_WYRMSPAWN, "wyrmspawn", 150, '@', C_MAGENTA, MT_FLESH, RC_HUMANOID, "In the rare occasion that a wyrm mates with a human, the result is a wyrmspawn - half-human, half-wyrm. Their scaled skin protects against slashing damage, and those who live long enough gain powerful breath weapons. On the other hand, their innate ego precludes the worship of any god and limits their rate of learning.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_WINGS, NULL);
addflag(lastrace->flags, F_PLAYABLE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 1, 4, NA, NULL);
addflag(lastrace->flags, F_TR, 3, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 4, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 65, OC_WEAPON, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_POTION, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_SCROLL, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_SCROLL, NA, NULL);
addflag(lastrace->flags, F_STARTOBCLASS, 30, OC_SCROLL, NA, NULL);
addflag(lastrace->flags, F_STARTJOB, 75, J_RANDOM, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "roars^a roars");
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOFLEE, NA, NA, NA, NULL);
// bonuses
addflag(lastrace->flags, F_DTRESIST, DT_SLASH, NA, NA, NULL);
addflag(lastrace->flags, F_LEVABIL, 7, OT_S_FLIGHT, NA, NULL);
addflag(lastrace->flags, F_LEVABIL, 10, OT_S_FIREBALL, 80, "pw:10;");
addflag(lastrace->flags, F_STARTSKILL, SK_LORE_DRAGONS, PR_SKILLED, NA, NULL);
// penalties
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_LEARNBOOST, -30, NA, NA, NULL);
addflag(lastrace->flags, F_NOPRAY, NA, NA, NA, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, "ne");
// robots
@ -9507,7 +9549,7 @@ void initrace(void) {
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "prolonged peace");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of magic");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "cowardice");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "fleeing from armed foes");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "dishonourable combat");
// sacrifices
addflag(lastrace->flags, F_SACRIFICEOBWITHFLAG, F_BATTLESPOILS, NA, 3, "OB explode#S into a shower of blood!");
@ -14284,7 +14326,7 @@ void initrace(void) {
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:4;");
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:2;");
addflag(lastrace->flags, F_CANWILL, OT_A_SUCKBLOOD, NA, NA, "dam:0d1+4;");
addflag(lastrace->flags, F_WANTS, OT_BLOODSPLASH, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_WANTS, OT_BLOODPOOL, B_COVETS, NA, NULL);
@ -14464,6 +14506,7 @@ void initrace(void) {
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "scuttle");
addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL);
addrace(R_ROC, "roc", 1, 'A', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Rocs are unbelievably gargantuan birds or prey, large enough to carry a fully-grown elephant. They are generally peaceful, but deadly once provoked."); // 'A' for Avian
setbodytype(lastrace, BT_BIRD);
@ -17644,9 +17687,13 @@ void killcommand(command_t *cmd) {
}
}
void make_basic_shop(flagpile_t *fp) {
addflag(fp, F_SHOPMENU, 0, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something");
addflag(fp, F_SHOPMENU, 1, MA_QUIT, NA, "q:leave");
void make_basic_shop(flagpile_t *fp, int includeid) {
int idx = 0;
addflag(fp, F_SHOPMENU, idx++, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something");
if (includeid) {
addflag(fp, F_SHOPMENU, idx++, MA_GOTOMENU, SM_ID, "i:inspect items");
}
addflag(fp, F_SHOPMENU, idx++, MA_QUIT, NA, "q:leave");
addflag(fp, F_MAKESNOISE, 33, 3, NA, "a cash register chiming.");
}

2
data.h
View File

@ -14,5 +14,5 @@ void initskills(void);
void killbehaviour(behaviour_t *b);
void killcommand(command_t *cmd);
void killoption(option_t *o);
void make_basic_shop(flagpile_t *fp);
void make_basic_shop(flagpile_t *fp, int includeid);
void sortcommands(void);

Binary file not shown.

20
defs.h
View File

@ -78,6 +78,13 @@
#define B_TRUE (-1)
#define B_MAYBE (-2)
#define B_ALLOWID (-1)
#define B_NOID (0)
#define B_ONLYIFARMED (-1)
#define B_INCLUDEDISTANT (-1)
#define B_NODISTANT (0)
#define B_MAYCHASE (-1)
#define B_ONLYEXTERNAL (-1)
#define B_FORCE (-2)
@ -368,6 +375,7 @@ enum TRADEINFOTYPE {
enum SHOPACTION {
SA_BUY,
SA_SELL,
SA_ID,
};
///////////////////////////////////////
@ -997,6 +1005,7 @@ enum RACE {
R_ELF,
R_HUMAN,
R_MAMMOAN,
R_WYRMSPAWN,
// robots
R_ANDROID,
R_BOTRIOT,
@ -2688,8 +2697,9 @@ enum FLAG {
F_BANNEDLF, // lfid v0 is not allowed to enter this shop
F_SHOP, // this object is a shop
F_SHOPDONATED, // v0 = how much gold worth you have donated
F_SHOPACCEPTSFLAG, // v0 = can sell items with flag v0 to this shop, for
// v1 percent of full value.
F_SHOPACCEPTSFLAG, // v0 = can sell/id items with flag v0 to this shop, for
// v1 percent of full value you can sell for
// NA means 'you can't sell it' (ie. id only)
// v2 = must be this objectclass (or NA)
F_SHOPMENU, // defines a menu for interaction with a shop
// v0 = (menuid*100) + itemorder
@ -3244,6 +3254,7 @@ enum FLAG {
F_FLEEONDAM, // lf will run away instead of counterattacking
F_FLEEONHPPCT, // lf will run away if its hp drop to v0% or lower
F_NOFLEE, // lf will not run away
F_NOPRAY, // lf cannor pray
F_ATTACKRANGE, // v0/v1 = min/max celldist to stay away
// from f_targetlf (ie. lf we are attacking)
F_FOLLOWRANGE, // v0/v1 = min/max celldist to stay away
@ -3565,7 +3576,8 @@ 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_SPIDERCLIMB, // lf can climb at 100% success rate, and climbing
// does not drain their stamina.
F_SILENTMOVE, // lf makes no noise when walking/flying
F_SIXTHSENSE, // warned about nearby enemies. v0 = power.
F_STABILITY, // doesn't slip over
@ -4717,6 +4729,8 @@ enum SHOPMENU {
// weapon/armour shops
SM_RESIZE = -9,
SM_REPAIR = -10,
// various shops
SM_ID = -11,
};
enum SHOPRETURN {

12
god.c
View File

@ -1779,7 +1779,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
cell_t *c;
object_t *o;
case R_GODBATTLE:
if (isinbattle(player, B_TRUE)) {
if (isinbattle(player, B_INCLUDEDISTANT, B_FALSE)) {
int redo = B_TRUE;
object_t *o;
@ -1886,7 +1886,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
dospelleffects(god, OT_S_CUREPOISON, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE, NULL);
}
if (isinbattle(lf, B_TRUE)) {
if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) {
int i,nretflags;
flag_t *retflag[MAXCANDIDATES];
// smite evil
@ -2064,7 +2064,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
donesomething = B_TRUE;
statdirty = B_TRUE;
}
if (isinbattle(lf, B_TRUE)) {
if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) {
if (plev >= PL_INDIFFERENT) {
dospelleffects(NULL, OT_S_HEAVENARM, plev+1, player, NULL, player->cell, B_UNCURSED, NULL, B_FALSE, NULL);
donesomething = B_TRUE;
@ -2088,7 +2088,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
}
break;
case R_GODTHIEVES:
if (isinbattle(lf, B_TRUE)) {
if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) {
lifeform_t *l;
int donesomething = B_FALSE;
if (islowhp(lf)) {
@ -2240,7 +2240,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
}
break;
case R_GODMERCY:
if (isinbattle(lf, B_TRUE)) {
if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) {
lifeform_t *l;
int donesomething = B_FALSE;
int preventstoning = B_FALSE;
@ -2304,7 +2304,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
uncurse_one_equipped(lf, "\"Let thy curse be ended!\"");
break;
case R_GODNATURE:
if (isinbattle(lf, B_TRUE)) {
if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) {
lifeform_t *l;
int donesomething = B_FALSE;
int redo = B_TRUE;

93
io.c
View File

@ -2985,7 +2985,7 @@ void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int fi
char pricebuf[BUFLEN];
int markdownpct;
for (n = 0; n < nsellflags; n++) {
if (obmatchessellflag(mylist[i], sellflag[n])) {
if (obmatchessellflag(mylist[i], sellflag[n], SA_SELL)) {
curflag = sellflag[n];
break;
}
@ -7272,7 +7272,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
case F_FLYING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can fly at will"); break;
case F_HEAVYBLOW: if (lorelev >= PR_ADEPT) sprintf(buf, "Attacks will knock enemies backwards"); break;
case F_HITCONFER:
if (lorelev >= PR_ADEPT) {
if (lorelev >= PR_BEGINNER) {
if (f->val[0] == F_POISONED) {
poisontype_t *pt;
pt = findpoisontype(f->val[1]);
@ -7281,6 +7281,11 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
}
break;
case F_HUMANOID: if (!forplayersel) sprintf(buf, "Can use weapons and armour."); break;
case F_LEARNBOOST:
if ((lorelev >= PR_BEGINNER) && (f->val[0] >= 0)) {
sprintf(buf, "Gains XP %d%% faster.", f->val[0]);
}
break;
case F_LEVITATING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can levitate at will"); break;
case F_MEDITATES: if (lorelev >= PR_ADEPT) sprintf(buf, "Meditates to retain awareness while sleeping."); break;
case F_MPMOD: if (f->val[0] > 0) sprintf(buf, "+%d Mana", f->val[0]); break;
@ -7374,6 +7379,11 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
}
break;
case F_FASTMETAB: if (lorelev >= PR_BEGINNER) sprintf(buf, "Fast metabolism (needs to eat often)"); break;
case F_LEARNBOOST:
if ((lorelev >= PR_BEGINNER) && (f->val[0] < 0)) {
sprintf(buf, "Gains XP %d%% slower.", abs(f->val[0]));
}
break;
case F_MATVULN:
if (lorelev >= PR_ADEPT) {
mt = findmaterial(f->val[0]);
@ -7382,6 +7392,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
break;
case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break;
case F_NEEDSWATER: if (lorelev >= PR_NOVICE) sprintf(buf, "Will suffocate without water"); break;
case F_NOPRAY: if (lorelev >= PR_BEGINNER) sprintf(buf, "Cannot worship gods."); break;
case F_NOSMELL: if ((lorelev >= PR_NOVICE) ) sprintf(buf, "No sense of smell."); break;
case F_NOCTURNAL: if ((lorelev >= PR_BEGINNER) && !forplayersel) sprintf(buf, "Sleeps during the day."); break;
case F_NOSPELLS: if (lorelev >= PR_NOVICE) sprintf(buf, "Cannot use magic."); break;
@ -11210,6 +11221,7 @@ void showlfarmour(lifeform_t *lf) {
void showlfstats(lifeform_t *lf, int showall) {
int y = 0, y2 = 0, x2 = 40;
int starty;
int x;
int arating, evasion;
int acc;
@ -11294,11 +11306,13 @@ void showlfstats(lifeform_t *lf, int showall) {
y = 0;
ch = '\0';
if (mode == '@') {
wattron(mainwin, A_UNDERLINE);
if (isplayer(lf)) {
centre(mainwin, C_WHITE, 0, "CHARACTER DETAILS");
} else{
centre(mainwin, C_WHITE, 0, "MONSTER DETAILS");
}
wattroff(mainwin, A_UNDERLINE);
x = 0;
centre(mainwin, C_MAGENTA, 1, "[Press ? for a full description]");
@ -11794,6 +11808,12 @@ void showlfstats(lifeform_t *lf, int showall) {
y = y2 + 1;
}
wattron(mainwin, A_UNDERLINE);
centre(mainwin, C_WHITE, y, "THREAT ASSESSMENT");
wattroff(mainwin, A_UNDERLINE);
y++;
starty = y;
/*
if (!isplayer(lf)) {
char *descbuf = NULL;
@ -11852,6 +11872,49 @@ void showlfstats(lifeform_t *lf, int showall) {
// extra info from lore?
if (lorelev >= PR_SKILLED) {
int hitstokillyou,hitstokillit;
// append behaviour text
f = lfhasflag(lf, F_BEHAVIOUR);
if (f) {
behaviour_t *b;
b = findbehaviour(f->val[0]);
if (b) {
char bhtext[BUFLEN];
switch (b->id) {
case BH_INSANE:
sprintf(bhtext, "It is insane, and will attack anyone who comes close. ");
break;
case BH_TIMID:
sprintf(bhtext, "It is timid, and will flee upon taking damage. ");
break;
case BH_DRUGGED:
sprintf(bhtext, "It is drugged, and will never flee. ");
break;
case BH_DETERMINED:
sprintf(bhtext, "It is determined, and will chase you for longer. ");
break;
case BH_LAZY:
sprintf(bhtext, "It is lazy, and won't chase you very far. ");
break;
case BH_MUSCLED:
sprintf(bhtext, "It is muscled, and has extra hit points. ");
break;
case BH_SCRAWNY:
sprintf(bhtext, "It is scrawy, and has lowered hit points. ");
break;
default:
strcpy(bhtext, "");
break;
}
if (strlen(bhtext)) {
setcol(mainwin, lorecol);
wrapprint(mainwin, &y, &x, 0, "%s", bhtext);
unsetcol(mainwin, lorecol);
}
}
}
hitstokillit = gethitstokill(player, lf, B_TRUE, B_TRUE);
hitstokillyou = gethitstokill(lf, player, B_TRUE, B_TRUE);
if (hitstokillit == hitstokillyou) {
@ -11952,10 +12015,6 @@ void showlfstats(lifeform_t *lf, int showall) {
if (f && (f->known)) {
wrapprint(mainwin, &y, &x, 0, "%s %s climbing on a wall. ", you(lf), is(lf));
}
f = lfhasknownflag(lf, F_FASTMETAB);
if (f && (f->known)) {
wrapprint(mainwin, &y, &x, 0, "%s metabolic rate has been increased. ", your(lf), getpossessive(you(lf)));
}
f = lfhasknownflag(lf, F_FEIGNINGDEATH);
if (f && (f->known)) {
wrapprint(mainwin, &y, &x, 0, "%s %s pretending to be dead. ", you(lf), is(lf));
@ -12143,8 +12202,14 @@ void showlfstats(lifeform_t *lf, int showall) {
mt = findmaterial(getlfmaterial(lf));
wrapprint(mainwin, &y, &x, 0, "%s %s made out of %s. ",you(lf), is(lf), mt->name);
}
if (y == starty) {
wrapprint(mainwin, &y, &x, 0, "Nothing obvious.");
}
} else if (mode == 'a') {
wattron(mainwin, A_UNDERLINE);
centre(mainwin, C_WHITE, 0, "ABILITIES");
wattroff(mainwin, A_UNDERLINE);
y = 2;
for (ot = objecttype ; ot ; ot = ot->next) {
@ -12204,7 +12269,9 @@ void showlfstats(lifeform_t *lf, int showall) {
skill_t *sk;
int finished = B_FALSE,dounknown;
wattron(mainwin, A_UNDERLINE);
centre(mainwin, C_WHITE, 0, "SKILLS");
wattroff(mainwin, A_UNDERLINE);
y = 2;
@ -12321,7 +12388,9 @@ void showlfstats(lifeform_t *lf, int showall) {
snprintf(subheading, BUFLEN, " %-4s%-26s%-15s%-13s%s","Lv","Spell", "School", "Power", "Cost");
wattron(mainwin, A_UNDERLINE);
centre(mainwin, C_WHITE, y, "MAGIC"); y += 2;
wattroff(mainwin, A_UNDERLINE);
doheading(mainwin, &y, 0, subheading);
// show spells monster can cast using mp
for (lev = 0; (lev <= 9) && !exitnow; lev++) {
@ -12403,7 +12472,9 @@ void showlfstats(lifeform_t *lf, int showall) {
enum LFSIZE racesize,cursize;
x = 0; // override
// down a line.
wattron(mainwin, A_UNDERLINE);
centre(mainwin, C_WHITE, y, "EFFECTS");
wattroff(mainwin, A_UNDERLINE);
y += 2;
@ -12662,6 +12733,12 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s %s %s resistant to magic.", you(lf), is(lf), adjective);
y++;
}
f = hasflag_real(lf->flags, F_FASTMETAB, B_TRUE, NULL, FROMRACE);
if (f) {
wrapprint(mainwin, &y, &x, 0, "%s metabolic rate has been increased. ", your(lf), getpossessive(you(lf)));
}
f = hasflag_real(lf->flags, F_TREMORSENSE, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s can 'see' by sensing vibrations around %s.", you(lf), you(lf));
@ -13294,11 +13371,13 @@ void showlfstats(lifeform_t *lf, int showall) {
} else if (mode == 'i') {
object_t *o;
cls();
wattron(mainwin, A_UNDERLINE);
if (lf == player) { // mindscanning it
centre(mainwin, C_WHITE, 0, "INVENTORY");
} else { // not mindscanning
centre(mainwin, C_WHITE, 0, "INVENTORY (equipped items only)");
}
wattroff(mainwin, A_UNDERLINE);
y = 2;
if ((lf == player) && lfhasflag(lf, F_NOPACK)) {
@ -13336,7 +13415,9 @@ void showlfstats(lifeform_t *lf, int showall) {
int i;
char line[BUFLEN];
cls();
wattron(mainwin, A_UNDERLINE);
centre(mainwin, C_WHITE, 0, "GODS");
wattroff(mainwin, A_UNDERLINE);
y = 2;
snprintf(line, BUFLEN, "%-30s Prayed? %-22s %s","God","Piety", "Happiness");

14
lf.c
View File

@ -13104,13 +13104,15 @@ flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp) {
}
int isinbattle(lifeform_t *lf, int includedistant) {
int isinbattle(lifeform_t *lf, int includedistant, int onlyarmed) {
if (includedistant) {
lifeform_t *l;
for (l = lf->cell->map->lf ; l ;l = l->next) {
if ((l != lf) && areenemies(l, lf) && cansee(lf, l)) {
if (!lfhasflag(l, F_DOESNTMOVE)) {
return B_TRUE;
if (!onlyarmed || getweapon(l)) {
return B_TRUE;
}
}
}
}
@ -13121,7 +13123,9 @@ int isinbattle(lifeform_t *lf, int includedistant) {
c = getcellindir(lf->cell, dir);
if (c && c->lf && areenemies(lf, c->lf) && cansee(lf, c->lf)) {
if (!lfhasflag(c->lf, F_DOESNTMOVE)) {
return B_TRUE;
if (!onlyarmed || getweapon(c->lf)) {
return B_TRUE;
}
}
}
}
@ -19971,7 +19975,7 @@ void startlfturn(lifeform_t *lf) {
// they are hiding, and you haven't spotted them yet
f = ishidingfrom(l, lf);
if (f && !isinbattle(lf, B_FALSE)) {
if (f && !isinbattle(lf, B_NODISTANT, B_FALSE)) {
// can you see their cell?
if (!lfhasflag(lf, F_TRAINING) && haslos(lf, l->cell)) {
int bonus = 0;
@ -19995,7 +19999,7 @@ void startlfturn(lifeform_t *lf) {
}
// secret doors, traps, etc?
if (isplayer(lf) && !isinbattle(lf, B_TRUE) && !isblind(lf) && !lfhasflag(lf, F_TRAINING)) {
if (isplayer(lf) && !isinbattle(lf, B_INCLUDEDISTANT, B_FALSE) && !isblind(lf) && !lfhasflag(lf, F_TRAINING)) {
for (i = 0; i < lf->nlos; i++) {
if (!lf->los[i]->lf || (lf->los[i]->lf == lf)) {
object_t *o;

2
lf.h
View File

@ -338,7 +338,7 @@ flag_t *ishidingfrom(lifeform_t *hider, lifeform_t *seeker);
int ishirable(lifeform_t *lf);
int isimmobile(lifeform_t *lf);
flag_t *isimmuneto(flagpile_t *fp, enum DAMTYPE dt, int onlytemp);
int isinbattle(lifeform_t *lf, int includedistant);
int isinbattle(lifeform_t *lf, int includedistant, int onlyarmed);
int isingunrange(lifeform_t *lf, cell_t *where);
int isliving(lifeform_t *lf);
int isloreskill(enum SKILL skid);

22
move.c
View File

@ -139,7 +139,7 @@ int canswapwith(lifeform_t *lf, lifeform_t *lf2) {
}
if (isplayer(lf) && !areenemies(lf, lf2)) {
if (isknownpeaceful(lf2)) {
// player can swap with peaceful lgs
// player can swap with peaceful lfs
// if they are a lot smaller
if (getlfsize(lf) - getlfsize(lf2) >= 2) {
return B_TRUE;
@ -198,8 +198,9 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err
return B_TRUE;
}
if (o->type->id == OT_PENTAGRAM) {
// this is only dangerous for the player
if (isplayer(lf)) {
// this is only dangerous for the player, and only if they have
// above average wisdom
if (isplayer(lf) && (wis >= AT_GTAVERAGE)) {
object_t *oo;
// any blessed objects in your pack?
for (oo = lf->pack->first ; oo ; oo = oo->next) {
@ -2335,7 +2336,9 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int onpurpose, int *didmsg) {
reason = E_OK;
return B_TRUE;
}
modstamina(lf, -1);
if (!lfhasflag(lf, F_SPIDERCLIMB)) {
modstamina(lf, -1);
}
}
}
}
@ -2778,9 +2781,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
int reldir;
int srcmoney = 0;
int prebattle = B_FALSE;
int prebattlearmed = B_FALSE;
flag_t *f;
// are we next to an enemy who we can see?
prebattle = isinbattle(lf, B_FALSE);
prebattle = isinbattle(lf, B_NODISTANT, B_FALSE);
if (isplayer(lf)) {
// only care about this for players
prebattlearmed = isinbattle(lf, B_NODISTANT, B_ONLYIFARMED);
}
howlong = getmovespeed(lf);
@ -2809,7 +2817,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
}
// check for fleeing...
if (isplayer(lf) && !isdead(lf)) {
if (prebattle && !isinbattle(lf, B_FALSE) && onpurpose) {
if (prebattlearmed && !isinbattle(lf, B_NODISTANT, B_ONLYIFARMED) && onpurpose) {
angergodmaybe(R_GODBATTLE, 5, GA_COWARD);
}
}
@ -3317,7 +3325,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
// check for fleeing...
if (isplayer(lf) && !isdead(lf)) {
if (prebattle && !isinbattle(lf, B_FALSE) && onpurpose) {
if (prebattlearmed && !isinbattle(lf, B_NODISTANT, B_ONLYIFARMED) && onpurpose) {
angergodmaybe(R_GODBATTLE, 10, GA_COWARD);
}
}

110
shops.c
View File

@ -20,6 +20,7 @@
#define DEF_REMCURSECOST 60
#define DEF_BLESSCOST 50
#define DEF_IDCOST 50
#define DEF_SURCHARGE 15
#define DEF_RESIZECOST 80
#define DEF_REPAIRCOSTPERHP 2
@ -118,10 +119,13 @@ int getshopblessprice(object_t *o, object_t *shop) {
return cost;
}
int obmatchessellflag(object_t *o, flag_t *f) {
int obmatchessellflag(object_t *o, flag_t *f, enum SHOPACTION action) {
if ((f->val[0] == F_NONE) || hasflag(o->flags, f->val[0])) {
if ((f->val[2] == NA) || (o->type->obclass->id == f->val[2])) {
return B_TRUE;
if ((action == SA_SELL) && (f->val[1] == NA)) {
} else {
return B_TRUE;
}
}
}
return B_FALSE;
@ -217,6 +221,9 @@ void shop(lifeform_t *lf, object_t *vm) {
} else if (curmenu == SM_DONATE) {
shopfunc = shopdonate;
shoparg = &ngiven;
} else if (curmenu == SM_ID) {
shopfunc = shopid;
shoparg = &ngiven;
} else if (curmenu == SM_REST) {
shopfunc = shoprest;
shoparg = &ngiven;
@ -629,6 +636,84 @@ enum SHOPRETURN shopbless(lifeform_t *lf, object_t *vm, int starty, char *toptex
return SR_CONTINUE;
}
enum SHOPRETURN shopid(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *nid) {
flag_t *sellflag[MAXCANDIDATES];
char buf[BUFLEN],obname[BUFLEN];
int nsellflags;
object_t *o;
int y,ch,i;
int cost = DEF_IDCOST;
y = starty;
cost = applyshoppricemod(DEF_IDCOST,lf, vm, SA_ID);
*nid = 0;
mvwprintw(mainwin, y, 0, "We can help inspect your items for a small fee."); y += 2;
mvwprintw(mainwin, y, 0, "For just $%d per item we can reveal their general purpose,", cost); y++;
mvwprintw(mainwin, y, 0, "however please note that we are unable to detect magical"); y++;
mvwprintw(mainwin, y, 0, "enchantments or blessings.", cost); y += 2;
mvwprintw(mainwin, y, 0, "Identify items [y/n]? ", countmoney(lf->pack));
ch = getch();
if (ch != 'y') {
return SR_BACK;
}
getflags(vm->flags, sellflag, &nsellflags, F_SHOPACCEPTSFLAG, F_NONE);
// ask what to sell
sprintf(buf, "What would you like to inspect (you have $%d)?", countmoney(lf->pack));
initprompt(&prompt, buf);
prompt.maycancel = B_TRUE;
for (o = player->pack->first ; o ; o = o->next) {
int ok = B_FALSE;
for (i = 0; i < nsellflags; i++) {
if (obmatchessellflag(o, sellflag[i], SA_ID)) {
if (!isknown(o)) {
ok = B_TRUE;
break;
}
}
}
if (ok) {
char costbuf[BUFLEN];
getobname(o, buf, o->amt);
sprintf(costbuf, "%-60s($%d)", buf, cost);
addchoice(&prompt, o->letter, costbuf, costbuf, o, NULL);
}
}
addchoice(&prompt, '-', "(nothing)", NULL, NULL, NULL);
ch = getchoice(&prompt);
o = (object_t *)prompt.result;
if (!o) {
return SR_BACK;
}
// confirm
getobname(o, obname, o->amt);
if (countmoney(player->pack) < cost) {
msg("You cannot afford the $%d inspection fee.", cost);
more();
} else {
// pay.
msg("You hand over $%d.", cost); more();
givemoney(player, NULL, cost);
// id it.
makeknown(o->type->id);
// get name again
getobname(o, obname, o->amt);
// tell the player
msg("\"%s %s.\"",(o->amt == 1) ? "That is" : "Those are", obname);
more();
}
return SR_CONTINUE;
}
enum SHOPRETURN shopmiracle(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated) {
char ch;
@ -788,16 +873,19 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
// only list gold if you have enough
if (getobvalue(oo) >= value) valid = B_TRUE;
strcpy(fullname, moneyname);
} else if ((slev >= PR_BEGINNER) && hasflag(oo->flags, F_GEM)) {
// only list gems which are worth enough
int thisval;
thisval = applyshoppricemod(getobvalue(oo), player, vm, SA_SELL);
if (thisval >= value) {
valid = B_TRUE;
sprintf(fullname, "%s (worth $%d)", moneyname, thisval);
} else if (hasflag(oo->flags, F_GEM)) {
// gems are only valid if our psychology skill is high
// enough to convince the shopkeeper to accept them.
if (slev >= PR_BEGINNER) {
int thisval;
thisval = applyshoppricemod(getobvalue(oo), player, vm, SA_SELL);
if (thisval >= value) {
valid = B_TRUE;
sprintf(fullname, "%s (worth $%d)", moneyname, thisval);
}
}
} else {
// always list cards
// always list anything else (credit cards)
valid = B_TRUE;
strcpy(fullname, moneyname);
}
@ -1165,7 +1253,7 @@ enum SHOPRETURN shopsell(lifeform_t *lf, object_t *vm, int starty, char *toptext
// get matching sell flag
curflag = NULL;
for (i = 0; i < nsellflags; i++) {
if (obmatchessellflag(o, sellflag[i])) {
if (obmatchessellflag(o, sellflag[i], SA_SELL)) {
curflag = sellflag[i];
break;
}

View File

@ -4,12 +4,13 @@ int apply_shopob_restrictions(char *buf);
float applyshoppricemod(float origprice, lifeform_t *lf, object_t *shop, enum SHOPACTION action);
int canafford(lifeform_t *lf, int amt);
int getshopblessprice(object_t *o, object_t *shop);
int obmatchessellflag(object_t *o, flag_t *f);
int obmatchessellflag(object_t *o, flag_t *f, enum SHOPACTION action);
void shop(lifeform_t *lf, object_t *vm);
enum SHOPRETURN shopabsolve(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated);
enum SHOPRETURN shopbless(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *ndonated);
enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
enum SHOPRETURN shopdetectcurse(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
enum SHOPRETURN shopid(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *nid);
enum SHOPRETURN shopmiracle(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);
enum SHOPRETURN shoprepair(lifeform_t *lf, object_t *vm, int starty, char *toptext, int *npurchased);

72
spell.c
View File

@ -2601,6 +2601,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
lifeform_t *god;
if (!isplayer(user)) return B_FALSE;
if (lfhasflag(player, F_NOPRAY)) {
if (isplayer(user)) {
msg("Your pride prevents you from worshipping another being.");
}
return B_TRUE;
}
// ask for which god
initprompt(&prompt, "To whom will you pray?");
prompt.maycancel = B_TRUE;
@ -12445,50 +12452,55 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (ch == 'a') { // wealth (gold, bad: goldtouch)
snprintf(buf, BUFLEN, "1000-2000 gold coins");
} else if (ch == 'b') { // power (weapons, bad: battery)
skill_t *sk,*poss[MAXSKILLS];
int nposs = 0;
// get a list of all valid weapon skills
for (sk = firstskill ; sk ; sk = sk->next) {
if (isweaponskill(sk->id) && getskill(target, sk->id)) {
poss[nposs++] = sk;
}
}
if (nposs) {
int nweps = 0;
objecttype_t *ot;
// pick a random one
sk = poss[rnd(0,nposs-1)];
// find all associated weapons
for (ot = objecttype ; ot ; ot = ot->next) {
if (hasflagval(ot->flags, F_USESSKILL, sk->id, NA, NA, NULL)) {
nweps++;
if (blessed == B_CURSED) {
snprintf(buf, BUFLEN, "battery");
} else {
skill_t *sk,*poss[MAXSKILLS];
int nposs = 0;
// get a list of all valid weapon skills
for (sk = firstskill ; sk ; sk = sk->next) {
if (isweaponskill(sk->id) && getskill(target, sk->id)) {
poss[nposs++] = sk;
}
}
if (nweps) {
int sel,n = 0;
sel = rnd(0,nweps-1);
if (nposs) {
int nweps = 0;
objecttype_t *ot;
// pick a random one
sk = poss[rnd(0,nposs-1)];
// find all associated weapons
for (ot = objecttype ; ot ; ot = ot->next) {
if (hasflagval(ot->flags, F_USESSKILL, sk->id, NA, NA, NULL)) {
if (n == sel) break;
n++;
nweps++;
}
}
snprintf(buf, BUFLEN, "excellent branded %s", ot->name);
if (nweps) {
int sel,n = 0;
sel = rnd(0,nweps-1);
for (ot = objecttype ; ot ; ot = ot->next) {
if (hasflagval(ot->flags, F_USESSKILL, sk->id, NA, NA, NULL)) {
if (n == sel) break;
n++;
}
}
snprintf(buf, BUFLEN, "excellent branded %s", ot->name);
} else {
snprintf(buf, BUFLEN, "stick");
}
} else {
snprintf(buf, BUFLEN, "stick");
}
} else {
snprintf(buf, BUFLEN, "stick");
}
} else if (ch == 'c') { // protection. bad: turn to stone
enum BODYPART bp,poss[MAXBODYPARTS];
int nposs = 0;
// get a list of all valid body parts
for (bp = 0; bp <= MAXBODYPARTS; bp++) {
if (!lfhasflagval(target, F_NOBODYPART, bp, NA, NA, NULL)) {
poss[nposs++] = bp;
}
}
if (hasbp(target, BP_HEAD)) poss[nposs++] = BP_HEAD;
if (hasbp(target, BP_SHOULDERS)) poss[nposs++] = BP_SHOULDERS;
if (hasbp(target, BP_BODY)) poss[nposs++] = BP_BODY;
if (hasbp(target, BP_LEGS)) poss[nposs++] = BP_LEGS;
if (hasbp(target, BP_FEET)) poss[nposs++] = BP_FEET;
if (hasbp(target, BP_HANDS)) poss[nposs++] = BP_HANDS;
if (nposs) {
int narms = 0;
objecttype_t *ot;