diff --git a/data.c b/data.c index 2f83dab..466742d 100644 --- a/data.c +++ b/data.c @@ -425,6 +425,7 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STEALTH, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_TECHUSAGE, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_TWOWEAPON, NA, NA, NULL); @@ -3081,6 +3082,9 @@ void initobjects(void) { addflag(lastot->flags, F_NEEDSGRAB, B_TRUE, NA, NA, NULL); addot(OT_A_CHECKSTAIRS, "check stairs", "Attempt to determine what lies on the other end of a staircase.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addot(OT_A_CLIMB, "climb wall", "Climb up a wall to escape your enemies.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); + addflag(lastot->flags, F_STAMCOST, 2, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_COOK, "cook", "Combine food and water into a healthy meals.", 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); @@ -4937,6 +4941,13 @@ void initobjects(void) { addflag(lastot->flags, F_HITCONFER, F_ASLEEP, SC_CON, 27, "20-30"); addflag(lastot->flags, F_HITCONFERVALS, B_TRUE, ST_ASLEEP, NA, NULL); + addot(OT_MANRIKI, "manriki", "A pair of weights on the end of a metal chain, designed to entangle those at whom it is thrown.", MT_METAL, 0.1, OC_MISSILE, SZ_SMALL); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_MISSILEDAM, 0, NA, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL); + addflag(lastot->flags, F_TANGLEMISSILE, 26, 21, B_FALSE, NULL); + addot(OT_NEEDLE, "needle", "A tiny pointed needle.", MT_METAL, 0.02, OC_MISSILE, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "It makes sewing easier."); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); @@ -4947,6 +4958,17 @@ void initobjects(void) { addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 25, NA, NULL); addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); + addot(OT_NET, "throwing net", "A grid of strong cords, weighted at the edges. Made for throwing over a target.", MT_CLOTH, 3, OC_MISSILE, SZ_MEDIUM); + addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_MISSILEDAM, 0, NA, NA, NULL); + addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL); + addflag(lastot->flags, F_NUMAPPEAR, 1, 2, NA, NULL); + addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); + addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_TANGLEMISSILE, 33, 30, B_TRUE, NULL); + addot(OT_JAVELIN, "javelin", "A long, sharp missile weapon.", MT_METAL, 6, OC_MISSILE, SZ_MEDIUM); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, ""); @@ -6704,7 +6726,7 @@ void initrace(void) { addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 95, NA, NULL); - addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NUMAPPEAR, 1, 3, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4"); @@ -6731,7 +6753,7 @@ void initrace(void) { addrace(R_TROGLODYTE, "troglodyte", 20, 'z', C_GREY, MT_FLESH, RC_HUMANOID, "Troglodytes are smaller, stunted lizardmen who at outcast at birth. They linger on the outskirts of society, scavenging garbage and living in their own filth."); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 78, NA, NULL); @@ -7064,7 +7086,8 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "hisses^a hiss"); addflag(lastrace->flags, F_SEEINDARK, 8, NA, NA, NULL); addflag(lastrace->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL); - addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "cloud of smoke"); + addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "puff of smoke"); + addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, "puff of smoke"); addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); @@ -8180,7 +8203,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOMEOB, NA, NA, NA, "web"); addflag(lastrace->flags, F_HOMELEVOB, NA, NA, NA, "1-10 webs"); addflag(lastrace->flags, F_BODYPARTNAME, BP_HEAD, NA, NA, "cephalothorax"); @@ -8210,7 +8233,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOMEOB, NA, NA, NA, "web"); addflag(lastrace->flags, F_HOMELEVOB, NA, NA, NA, "20-30 webs"); addflag(lastrace->flags, F_BODYPARTNAME, BP_HEAD, NA, NA, "cephalothorax"); @@ -8240,7 +8263,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_POISONOUS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOMEOB, NA, NA, NA, "web"); addflag(lastrace->flags, F_HOMELEVOB, NA, NA, NA, "10-20 webs"); addflag(lastrace->flags, F_BODYPARTNAME, BP_HEAD, NA, NA, "cephalothorax"); @@ -8323,6 +8346,7 @@ void initrace(void) { lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); @@ -8351,6 +8375,7 @@ void initrace(void) { addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); + addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "giant fly corpse"); addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); diff --git a/data/hiscores.db b/data/hiscores.db index 25bca16..e017819 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/defs.h b/defs.h index 6d6d26c..f08cf7f 100644 --- a/defs.h +++ b/defs.h @@ -1305,6 +1305,7 @@ enum OBTYPE { // abilities OT_A_AIMEDSTRIKE, OT_A_CHECKSTAIRS, + OT_A_CLIMB, OT_A_COOK, OT_A_DARKWALK, OT_A_DISARM, // disarm a trap @@ -1569,7 +1570,9 @@ enum OBTYPE { OT_DART, OT_DARTNANO, OT_DARTTRANQ, + OT_MANRIKI, OT_NEEDLE, + OT_NET, OT_JAVELIN, OT_BULLET, OT_RUBBERBULLET, @@ -2020,6 +2023,11 @@ enum FLAG { F_DAM, // v0 = damtype, // v1=DR (this takes precedence) F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier) + F_TANGLEMISSILE, // this object will trip anyone it is thrown at + // (if it hits), unless they pass a SC_SLIP + // check of difficulty v0 + // if V1/V2 are set, then F_RESTRICTMOVEMENT + // v1->v0, v2->v1 is added to this object after it hits. F_ACCURACY, // 100 - val0 = modify to tohit% (ie. higher is better) F_UNARMEDWEP, // this is not a real weapon, ie. claws, teeth etc F_ARMOURPIERCE, // goes through armour @@ -2124,6 +2132,7 @@ enum FLAG { F_PRAYEDTO, // player has prayed to this god before. F_GAVEMONEY, // v0 tracks how much money we gave away this turn // used for r_godgreed anger effects. + F_CLIMBING, // lf is currently climbing a wall F_COUNTER, // generic counter flag for race abilities. F_DEBUG, // debugging enabled F_ACCURACYMOD, // modify your accuracy by val0 @@ -2385,7 +2394,7 @@ enum FLAG { F_NOPACK, // this race cannot hold objects F_NOSPELLS, // this race cannot cast spells F_INDUCEFEAR, // causes fear when you attack it - F_POISONOUS, // lf's corpse will be poisonous + F_POISONCORPSE, // lf's corpse will be poisonous F_AUTOCREATEOB, // produces obtype 'text' wherever it walks, v0=radius // (only if ob of that type not already there) F_PACKATTACK, // deal v0 extra damage of type v1 if there are @@ -2732,6 +2741,7 @@ enum ERROR { E_NOUNARMEDATTACK, E_NOTEQUIPPED, E_NOPICKUP, + E_STUCK, E_MONSTERNEARBY, E_NOEFFECT, E_FAILED, diff --git a/io.c b/io.c index b943d4c..7ed86ad 100644 --- a/io.c +++ b/io.c @@ -641,7 +641,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src if (cansee(player, c->lf)) { flag_t *f; object_t *wep,*o; - char extrainfo[BUFLEN]; + char extrainfo[BIGBUFLEN]; strcpy(extrainfo, ""); getlfnamea(c->lf, buf); if (lfhasflag(c->lf, F_NAME)) { @@ -733,6 +733,11 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src } } + if (lfhasflag(c->lf, F_CLIMBING)) { + if (strlen(extrainfo)) strcat(extrainfo, ", "); + strcat(extrainfo, "climbing"); + } + f = lfhasflag(c->lf, F_ATTACHEDTO); if (lfhasflag(c->lf, F_ATTACHEDTO)) { lifeform_t *alf; @@ -747,6 +752,16 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src } } + o = isstuck(c->lf); + if (o) { + char obname[BUFLEN]; + char buf2[BUFLEN]; + real_getobname(o, obname, o->amt, B_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); + if (strlen(extrainfo)) strcat(extrainfo, ", "); + snprintf(buf2, BUFLEN, "stuck in %s",obname); + strcat(extrainfo, buf2); + } + if ((getallegiance(c->lf) == AL_HOSTILE) && (getlorelevel(player, c->lf->race->raceclass->id) >= PR_ADEPT)) { char dangerbuf[BUFLEN]; @@ -773,32 +788,24 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src strcat(extrainfo, dangerbuf); } - o = isstuck(c->lf); - if (o) { - char buf2[BUFLEN]; - char obname[BUFLEN]; - - if (strlen(extrainfo)) strcat(extrainfo, ", "); - getobname(o, obname, o->amt); - snprintf(buf2, BUFLEN, "stuck in %s", obname); - strcat(extrainfo, buf2); - } // hp - if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) || - (getlorelevel(player, c->lf->race->raceclass->id) >= PR_SKILLED) - ) { - char buf2[BUFLEN]; - // show actual hp - snprintf(buf2, BUFLEN, "hp %d/%d",c->lf->hp, c->lf->maxhp); - if (strlen(extrainfo)) strcat(extrainfo, ", "); - strcat(extrainfo, buf2); - } else { - char buf2[BUFLEN]; - // show condition name - snprintf(buf2, BUFLEN, "%s",getseenlfconditionname(c->lf, player)); - if (strlen(buf2)) { + if (!isplayer(c->lf)) { + if (isgenius(player) || (getseenlfconditioncutoff(player) == C_HEALTHY) || + (getlorelevel(player, c->lf->race->raceclass->id) >= PR_SKILLED) + ) { + char buf2[BUFLEN]; + // show actual hp + snprintf(buf2, BUFLEN, "hp %d/%d",c->lf->hp, c->lf->maxhp); if (strlen(extrainfo)) strcat(extrainfo, ", "); strcat(extrainfo, buf2); + } else { + char buf2[BUFLEN]; + // show condition name + snprintf(buf2, BUFLEN, "%s",getseenlfconditionname(c->lf, player)); + if (strlen(buf2)) { + if (strlen(extrainfo)) strcat(extrainfo, ", "); + strcat(extrainfo, buf2); + } } } @@ -9455,6 +9462,10 @@ void showlfstats(lifeform_t *lf, int showall) { snprintf(buf, BUFLEN,"%s %s attached to %s.",you(lf), is(lf), grabeename); wrapprint(mainwin, &y, &x, "%s ", buf); } + f = lfhasknownflag(lf, F_CLIMBING); + if (f && (f->known)) { + wrapprint(mainwin, &y, &x, "%s %s climbing on a wall. ", you(lf), is(lf)); + } f = lfhasknownflag(lf, F_FASTMETAB); if (f && (f->known)) { wrapprint(mainwin, &y, &x, "%s metabolic rate has been increased. ", your(lf), getpossessive(you(lf))); @@ -9697,42 +9708,19 @@ void showlfstats(lifeform_t *lf, int showall) { } else if (mode == 's') { char skilltitle[BUFLEN]; - flag_t *known[MAXSKILLS], *available[MAXSKILLS]; - int numknown = 0, numavailable = 0; - int n; enum SKILLLEVEL slev; skill_t *sk; int finished = B_FALSE,dounknown; centre(mainwin, C_WHITE, 0, "SKILLS"); - /* - // get available skills - for (f = lf->flags->first ; f ; f = f->next) { - if (f->id == F_CANLEARN) { - if (!getskill(lf, f->val[0])) { - available[numavailable++] = f; - } - } - } - // get known skills, in order - for (slev = PR_MASTER ; slev >= PR_NOVICE; slev--) { - for (f = lf->flags->first ; f ; f = f->next) { - if ((f->id == F_HASSKILL) && (f->val[1] == slev)) { - known[numknown++] = f; - } - } - } - */ - - y = 2; snprintf(skilltitle, BUFLEN, "%-21s"," "); for (i = PR_NOVICE; i <= PR_MASTER; i++) { char toadd[BUFLEN], *sn; int prepad,postpad,n; - // construct "|xxxxxxxx" + // construct: "|xxxxxxxx" // ie "|Beginner" // ie "| Inept " sn = getskilllevelname(i); @@ -9757,7 +9745,9 @@ void showlfstats(lifeform_t *lf, int showall) { slev = getskill(lf, sk->id); if (!dounknown && (slev != PR_INEPT)) { // known skill - sprintf(thisline, "%-21s[^%d", sk->name, getskilllevelcolour(slev)); + sprintf(thisline, "^%c%-21s^n[^%d", + ismaxedskill(lf, sk->id) ? 'h' : 'n', + sk->name, getskilllevelcolour(slev)); for (i = PR_NOVICE; i <= PR_MASTER; i++) { char toadd[BUFLEN]; @@ -9815,7 +9805,6 @@ void showlfstats(lifeform_t *lf, int showall) { centre(mainwin, C_WHITE, y, "MAGIC"); y += 2; doheading(mainwin, &y, 0, subheading); - //if (!isplayer(lf)) { // show spells monster can cast using mp for (lev = 0; (lev <= 9) && !exitnow; lev++) { for (ot = objecttype ; ot && !exitnow ; ot = ot->next) { diff --git a/lf.c b/lf.c index a358825..a3ef641 100644 --- a/lf.c +++ b/lf.c @@ -792,6 +792,10 @@ int canpickup(lifeform_t *lf, object_t *o, int amt) { return B_FALSE; } if (lf) { + if (isstuck(lf) == o) { + reason = E_STUCK; + return B_FALSE; + } if (getobsize(o) > getlfsize(lf)) { reason = E_TOOBIG; return B_FALSE; @@ -1561,8 +1565,8 @@ int celltransparentfor(lifeform_t *lf, cell_t *c, int *xray, int *rangemod) { if (rangemod) *rangemod = 0; - // solid cells stop los - if (!c->type->transparent) { + // solid cells stop los (unless it's your own cell) + if (!c->type->transparent && (c != lf->cell)) { if (xray && *xray) { (*xray)--; } else return B_FALSE; @@ -2193,7 +2197,7 @@ void die(lifeform_t *lf) { } // tainted? - if ((lf->lastdamtype == DT_POISONGAS) || lfhasflag(lf, F_POISONOUS) || lfhasflag(lf, F_POISONED)) { + if ((lf->lastdamtype == DT_POISONGAS) || lfhasflag(lf, F_POISONCORPSE) || lfhasflag(lf, F_POISONED)) { addflag(corpse->flags, F_TAINTED, B_TRUE, NA, NA, NULL); } @@ -3281,8 +3285,10 @@ void enhanceskills(lifeform_t *lf) { } else if (f->id == F_LEVSPELLSCHOOL) { // select a spell from school if (isplayer(lf)) { int done = B_FALSE; + char qbuf[BUFLEN]; + sprintf(qbuf, "Learn which new spell (maxmp=%d):", getmaxmp(player)); while (!done) { - makespellchoicelist(&prompt, player, "Learn which new spell:","Describe which spell:", f->val[1], B_TRUE, B_FALSE, B_FALSE, player->maxmp); + makespellchoicelist(&prompt, player, qbuf, "Describe which spell:", f->val[1], B_TRUE, B_FALSE, B_FALSE, player->maxmp); if (prompt.nchoices > 0) { objecttype_t *ot; getchoicestr(&prompt, B_TRUE, B_TRUE); @@ -3415,8 +3421,10 @@ void enhanceskills(lifeform_t *lf) { // psionics sometimes lets you learn spells slev = getskill(lf, SK_SS_MENTAL); if (pctchance(slev*20)) { + char qbuf[BUFLEN]; + sprintf(qbuf, "Learn which psionic power (maxmp=%d):", getmaxmp(player)); // construct list of castable mental spells - makespellchoicelist(&prompt, lf, "Learn which new psionic power:","Describe which psionic power:", SS_MENTAL, B_TRUE, B_FALSE, B_FALSE, player->maxmp); + makespellchoicelist(&prompt, lf, qbuf, "Describe which psionic power:", SS_MENTAL, B_TRUE, B_FALSE, B_FALSE, player->maxmp); if (prompt.nchoices > 0) { objecttype_t *ot; msg("Your brain has unlocked a new psionic power!"); more(); @@ -7726,6 +7734,12 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) { newf = addflag(lf->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); newf->lifetime = FROMSKILL; } + } else if (id == SK_CLIMBING) { + newf = hasflagval(lf->flags, F_CANWILL, OT_A_CLIMB, NA, NA, NULL); + if (!newf) { + newf = addflag(lf->flags, F_CANWILL, OT_A_CLIMB, NA, NA, NULL); + newf->lifetime = FROMSKILL; + } } else if (id == SK_COOKING) { if (isplayer(lf)) { makeknown(OT_POT_WATER); @@ -8902,7 +8916,8 @@ int haslos(lifeform_t *viewer, cell_t *dest) { // can't see when you're dead UNLESS you are the player. this is // to prevent the screen from going black when "You die" appears. - if (isdead(viewer) && !isplayer(viewer)) return B_FALSE; + //if (isdead(viewer) && !isplayer(viewer)) return B_FALSE; + if (lfhasflag(viewer, F_DEAD) && !isplayer(viewer)) return B_FALSE; if (viewer->losdirty) { @@ -9106,6 +9121,13 @@ int ischarmable(lifeform_t *lf) { return B_TRUE; } +int isclimbing(lifeform_t *lf) { + if (hasflag(lf->flags, F_CLIMBING)) { + return B_TRUE; + } + return B_FALSE; +} + int isdead(lifeform_t *lf) { if (!lf->alive) return B_TRUE; if (lf->hp <= 0) return B_TRUE; @@ -11688,6 +11710,9 @@ int pickup(lifeform_t *lf, object_t *what, int howmany, int fromground, int want case E_NOPACK: msg("You lack the ability to carry things!"); break; + case E_STUCK: + msg("You can't pick up %s while caught in it!",obname); + break; case E_NOPICKUP: msg("You can't pick up %s!",obname); break; @@ -12253,7 +12278,15 @@ void relinklf(lifeform_t *src, map_t *dst) { sortlf(dst, src); } -// strat resting... +int startclimbing(lifeform_t *lf, cell_t *where) { + int dir; + dir = getdirtowards(lf->cell, where, lf, B_FALSE, DT_ORTH); + movelf(lf, where); + setfacing(lf, diropposite(dir)); + addflag(lf->flags, F_CLIMBING, B_TRUE, NA, NA, NULL); + return B_FALSE; +} + int startresting(lifeform_t *lf, int willtrain) { int traincounter; @@ -12649,8 +12682,8 @@ void setattr(lifeform_t *lf, enum ATTRIB attr, int val) { } int setfacing(lifeform_t *lf, int dir) { - if (dir == D_NONE) { - dblog("xxx"); + if (isclimbing(lf)) { // can't change dir while climbing + return B_TRUE; } if (lf->facing == dir) { // already facing that way return B_TRUE; @@ -13533,7 +13566,7 @@ void startlfturn(lifeform_t *lf) { // stuck inside solid cells? if (!cellwalkable(lf, lf->cell, &error)) { - if (error == E_WALLINWAY) { + if ((error == E_WALLINWAY) && !isclimbing(lf)) { if (isplayer(lf)) { msg("You reintegrate inside a solid object!"); } @@ -14174,7 +14207,7 @@ void startlfturn(lifeform_t *lf) { if (isdead(lf)) return; - getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_FLEEFROM, + getflags(lf->flags, retflag, &nretflags, F_ATTACHEDTO, F_CANWILL, F_CHARMEDBY, F_CLIMBING, F_FLEEFROM, F_GRABBEDBY, F_GRABBING, F_BOOSTSPELL, F_FEIGNINGDEATH, F_INJURY, F_NOFLEEFROM, F_PETOF, F_SPOTTED, F_STABBEDBY, F_TARGETCELL, F_TARGETLF, F_NONE); for (i = 0; i < nretflags; i++) { @@ -14251,6 +14284,12 @@ void startlfturn(lifeform_t *lf) { continue; } } + + if (f->id == F_CLIMBING) { + if (!lf->cell->type->solid) { + killflag(f); + } + } if ((f->id == F_CHARMEDBY) || (f->id == F_PETOF) || @@ -14462,6 +14501,42 @@ void stopeating(lifeform_t *lf) { } +int stopclimbing(lifeform_t *lf, int onpurpose) { + cell_t *c; + char lfname[BUFLEN]; + getlfname(lf, lfname); + if (!onpurpose) { + if (isplayer(lf)) { + msg("You fall off %s!", lf->cell->type->name); + } else if (cansee(player, lf)) { + msg("%s falls off %s!", lfname, lf->cell->type->name); + } + } + c = getcellindir(lf->cell, lf->facing); + if (!cellwalkable(lf, c, NULL)) { + if (onpurpose) { + if (isplayer(lf)) { + msg("There is no room for you to stop climbing!"); + } + return B_TRUE; + } + // if not on purpose, try to find another cell + c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND); + if (!c) { + if (isplayer(lf)) { + msg("Luckily, there is no room for you to fall."); + } + return B_TRUE; + } + } + movelf(lf, c); + killflagsofid(lf->flags, F_CLIMBING); + if (!onpurpose) { + fall(lf, NULL, B_TRUE); + } + return B_FALSE; +} + void stopresting(lifeform_t *lf) { flag_t *f; diff --git a/lf.h b/lf.h index 6ff0539..9343960 100644 --- a/lf.h +++ b/lf.h @@ -261,6 +261,7 @@ int isbleeding(lifeform_t *lf); int isblind(lifeform_t *lf); enum BURDENED isburdened(lifeform_t *lf); int ischarmable(lifeform_t *lf); +int isclimbing(lifeform_t *lf); int isdead(lifeform_t *lf); int isdeaf(lifeform_t *lf); object_t *isdualweilding(lifeform_t *lf); @@ -339,6 +340,7 @@ int recruit(lifeform_t *lf); void refreshlevelabilities(lifeform_t *lf); void relinklf(lifeform_t *src, map_t *dst); int rest(lifeform_t *lf, int onpurpose); +int startclimbing(lifeform_t *lf, cell_t *where); int startresting(lifeform_t *lf, int willtrain); int rollattr(enum ATTRBRACKET bracket); int rollstat(lifeform_t *lf, enum ATTRIB attr); @@ -367,6 +369,7 @@ void sortlf(map_t *map, lifeform_t *lf); void startlfturn(lifeform_t *lf); int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag); int stone(lifeform_t *lf); +int stopclimbing(lifeform_t *lf, int onpurpose); void stopeating(lifeform_t *lf); void stopresting(lifeform_t *lf); void stoprunning(lifeform_t *lf); diff --git a/move.c b/move.c index 659bd4e..6fb95c3 100644 --- a/move.c +++ b/move.c @@ -2059,7 +2059,7 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) { } getlfname(lf,lfname); - getobname(o, buf, o->amt); + real_getobname(o, buf, o->amt, B_FALSE, B_FALSE, B_TRUE, B_FALSE, B_FALSE); // for stacks of sticky objects, each one after the first adds // quarter its difficuly. ie: @@ -2341,6 +2341,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { reldir = getrelativedir(lf, dir); + if (isclimbing(lf)) strafe = B_TRUE; if (onpurpose) { if (isplayer(lf)) { diff --git a/objects.c b/objects.c index c6d5b10..5a76b0c 100644 --- a/objects.c +++ b/objects.c @@ -6612,8 +6612,17 @@ void makewet(object_t *o, int amt) { } else { // get wet - if (haslos(player, loc) && !isdead(player)) { - msg("%s get%s wet.",obnamefull, (o->amt == 1) ? "s" : ""); + if (!isdead(player)) { + int doannounce = B_FALSE; + if (owner) { + if (cansee(player, owner)) doannounce = B_TRUE; + } else { + if (haslos(player, loc)) doannounce = B_TRUE; + } + + if (doannounce) { + msg("%s get%s wet.",obnamefull, (o->amt == 1) ? "s" : ""); + } } f = addflag(o->flags, F_WET, amt, TM_WETTIME, NA, NULL); } @@ -10263,7 +10272,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, char throwverbpres[BUFLEN]; int acc,myroll; int youhit = B_FALSE; - int missiledam = 0; + int missiledam = 0; // how much damage the missile itself will take object_t *newob = NULL; cell_t *newloc; int db = B_TRUE; @@ -10671,7 +10680,16 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, } else if (!lfhasflag(target, F_CASTINGSPELL) && skillcheck(target, SC_DODGE, 7*speed, dodgemod)) { // then check if we dodge it... if (db) dblog("target passed dodge check."); + youhit = B_FALSE; + if (seen) { + if (isplayer(target)) { + msg("You dodge %s.", obname); + } else { + msg("%s dodges %s.", targetname, obname); + } + announcedmiss = B_TRUE; + } } } } @@ -10712,7 +10730,9 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, int dam = 0; char damstring[BUFLEN]; int reduceamt = 0; + int willtangle = B_FALSE; int throwdam; + flag_t *f; op = addobpile(NOOWNER, NOLOC, NULL); @@ -10739,10 +10759,24 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, shattered = B_TRUE; } + // will the missile trip them over? + f = hasflag(o->flags, F_TANGLEMISSILE); + if (f) { + if (isairborne(target) || !skillcheck(target, SC_SLIP, f->val[0], 0)) { + willtangle = B_TRUE; + } + } + // announce if (seen) { char buf2[BUFLEN]; - snprintf(buf2, BUFLEN, "%s hit%s %s.",obname,(amt == 1) ? "s" : "", targetname); + char verb[BUFLEN]; + if (willtangle) { + sprintf(verb, "wrap%s around", (amt == 1) ? "s" : ""); + } else { + sprintf(verb, "hit%s", (amt == 1) ? "s" : ""); + } + snprintf(buf2, BUFLEN, "%s %s %s.",obname, verb, targetname); if (lfhasflag(player, F_EXTRAINFO)) { char damstring[BUFLEN]; snprintf(damstring, BUFLEN, " [%d dmg]",dam); @@ -10774,6 +10808,32 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, missiledam += ((speed*2)+1); + if (willtangle) { + missiledam = 0; // don't damage the misisle + + fall(target, NULL, B_TRUE); + taketime(target, getactspeed(target)); + + if (f->val[1] != NA) { + addflag(o->flags, F_RESTRICTMOVEMENT, f->val[1], f->val[2], B_FALSE, NULL); + } + } + + + f = hasflag(o->flags, F_TANGLEMISSILE); + if (f) { + missiledam = 0; + if (isairborne(target) || !skillcheck(target, SC_SLIP, f->val[0], 0)) { + fall(target, NULL, B_TRUE); + taketime(target, getactspeed(target)*2); + + if (f->val[1] != NA) { + addflag(o->flags, F_RESTRICTMOVEMENT, f->val[1], f->val[2], B_FALSE, NULL); + } + } + } + + if (thrower) { if (firearm) { practice(thrower, SK_THROWING, 1); @@ -10981,6 +11041,14 @@ void timeeffectsob(object_t *o) { } } + if (hasflag(o->flags, F_TANGLEMISSILE)) { + if (!location || !location->lf) { + // thrown entangling weapons lose their "stickiness" + // once the target escapes + killflagsofid(o->flags, F_RESTRICTMOVEMENT); + } + } + if (location) { // does object's material change cell type? @@ -11004,7 +11072,6 @@ void timeeffectsob(object_t *o) { } } - // checks based on object if (o->type->id == OT_VINE) { lifeform_t *creator; @@ -11969,11 +12036,11 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob // ie. inept = -30%, adept = 0%, master = +30% acc += ((slev - PR_ADEPT) * 10); } else { - slev = getskill(thrower, whichskill); acc = 60; - // ie. inept = -30%, adept = 0%, master = +30% - acc += ((slev - PR_ADEPT) * 10); - // acc will now be 10 - 70 + // ie. inept = -45%, adept = 0%, master = +45% + slev = getskill(thrower, whichskill); + acc += ((slev - PR_ADEPT) * 15); + // acc will now be 25 - 115 } // adjust for range diff --git a/save.c b/save.c index ff232ae..6dc501e 100644 --- a/save.c +++ b/save.c @@ -503,7 +503,6 @@ map_t *loadmap(char *basefile) { // successful load - kill the map now unlink(filename); - return m; } diff --git a/spell.c b/spell.c index 3aa1f73..6425f9e 100644 --- a/spell.c +++ b/spell.c @@ -554,6 +554,49 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } taketime(user, getactspeed(user)*2); + } else if (abilid == OT_A_CLIMB) { + if (lfhasflag(user, F_CLIMBING)) { + // stop climbing + stopclimbing(user, B_TRUE); + taketime(user, getmovespeed(user)); + return B_FALSE; + } + + if (isprone(user)) { + if (isplayer(user)) msg("You will need to stand up first!"); + return B_TRUE; + } + // ask for direction + if (!targcell) { + int dirch,dir; + dirch = askchar("Climb wall in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE, B_TRUE); + if ((dirch == '-') || !dirch) { + if (isplayer(user)) msg("Cancelled."); + return B_TRUE; + } + dir = chartodir(dirch); + if (dir == D_NONE) { + targcell = user->cell; + } else { + targcell = getcellindir(user->cell, dir); + } + } + if (!targcell) { + if (isplayer(user)) msg("Cancelled."); + return B_TRUE; + } + + if (!targcell->type->solid) { + if (isplayer(user)) msg("There is no wall there!"); + return B_TRUE; + } + if (targcell->lf) { + if (isplayer(user)) msg("There is no wall there!"); + return B_TRUE; + } + + startclimbing(user, targcell); + taketime(user, getmovespeed(user)); } else if (abilid == OT_A_COOK) { object_t *water,*o; race_t *r = NULL; @@ -1535,6 +1578,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } else if (abilid == OT_A_SPRINT) { flag_t *f; + f = lfhasflag(user, F_SPRINTING); + if (f) { + // stop sprinting. + killflag(f); + return B_FALSE; + } + if (lfhasflagval(user, F_INJURY, IJ_WINDPIPECRUSHED, NA, NA, NULL)) { if (isplayer(user)) msg("You can't sprint with a crushed windpipe."); return B_TRUE; @@ -1545,13 +1595,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef return B_TRUE; } - f = lfhasflag(user, F_SPRINTING); - if (f) { - if (isplayer(user)) { - msg("You are already sprinting!"); - } - return B_TRUE; - } if (isburdened(user)) { if (isplayer(user)) { msg("You cannot sprint while burdened.");