diff --git a/attack.c b/attack.c index 70cb07d..2e3b800 100644 --- a/attack.c +++ b/attack.c @@ -2008,7 +2008,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) { object_t *oo; f = hasflag(o->flags, F_TRAPPED); if (f && pctchance(75)) { - doobtraps(o, lf); + triggerattachedtraps(o, lf); } else { // if a trap didn't go off, you might break the lock f = hasflag(o->flags, F_LOCKED); diff --git a/data.c b/data.c index 3621468..34876c4 100644 --- a/data.c +++ b/data.c @@ -183,16 +183,16 @@ void initcommands(void) { //addcommand(CMD_DROP, 'd', "Drop an item."); addcommand(CMD_DROPMULTI, 'd', "Drop one or more items."); addcommand(CMD_EAT, 'e', "Eat something."); - addcommand(CMD_INTERACT, 'I', "Interact with adjacent objects."); + addcommand(CMD_INTERACT, 'I', "Interact with a nearby object."); addcommand(CMD_MAGIC, 'm', "Use magic or abilities."); addcommand(CMD_MEMMAGIC, 'M', "Memorise a hotkey for magic or abilities."); addcommand(CMD_OFFER, 'O', "Offer a sacrifice to the gods."); - addcommand(CMD_OPERATE, 'o', "Operate a tool/wand/device, or fill a flask."); + addcommand(CMD_OPERATE, 'o', "Operate a held tool/wand/device, or fill a flask."); addcommand(CMD_POUR, 'P', "Pour a potion onto something."); addcommand(CMD_QUAFF, 'q', "Quaff (drink) a potion."); addcommand(CMD_READ, 'r', "Read a scroll/book."); addcommand(CMD_RESTFULL, 'R', "Rest until healed, or train your skills."); - addcommand(CMD_CLOSE, 's', "Shut a door."); + //addcommand(CMD_CLOSE, 's', "Shut a door."); addcommand(CMD_THROW, 't', "Throw an object."); addcommand(CMD_TAKEOFF, 'T', "Take off an item of clothing/jewelery."); addcommand(CMD_WEILD, 'w', "Weild a weapon."); @@ -2923,6 +2923,14 @@ void initobjects(void) { addflag(lastot->flags, F_SECRET, 70, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addot(OT_TRAPNOISE, "noise trap", "A hinge which squeaks loudly, attracting attention.", MT_NOTHING, 0, OC_TRAP, SZ_SMALL); + addflag(lastot->flags, F_OBJECTTRAP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_TRAP, 50, B_FALSE, NA, NULL); + addflag(lastot->flags, F_GLYPH, C_GREY, '^', NA, NULL); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + + addot(OT_TRAPGAS, "gas trap", "A trap which releases poisonous gas.", MT_NOTHING, 0, OC_TRAP, SZ_SMALL); addflag(lastot->flags, F_TRAP, 70, B_TRUE, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 69, RR_UNCOMMON, NULL); @@ -6495,6 +6503,7 @@ void initobjects(void) { addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDDIR, B_TRUE, NA, NA, "Use your spanner in which direction"); + addflag(lastot->flags, F_OPERNEEDSKILL, SK_TECHUSAGE, PR_NOVICE, NA, NULL); addflag(lastot->flags, F_HELPSDISARM, 5, NA, NA, NULL); addflag(lastot->flags, F_HELPSREPAIR, MT_METAL, 2, 15, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); diff --git a/defs.h b/defs.h index 21fff9d..0c85f6a 100644 --- a/defs.h +++ b/defs.h @@ -484,6 +484,7 @@ enum CELLCONDITION { CC_EDIBLE, CC_KNOWN, CC_IDENTIFIED, + CC_INTERACTABLE, CC_MINAR, // arg CC_MAXAR, // arg CC_MINDR, // arg @@ -1747,6 +1748,7 @@ enum OBTYPE { OT_TRAPLIGHTNING, OT_TRAPMINE, OT_TRAPNEEDLEP, + OT_TRAPNOISE, OT_TRAPPIT, OT_TRAPROCK, OT_TRAPSUMMON, @@ -3122,6 +3124,11 @@ enum FLAG { // v0 = B_IFNOTBLESSED (only targets an ob if unblessed) F_OPERONOFF, // operating this will just turn it on/off F_OPERUSECHARGE, // operating this will use 1 charge + F_OPERNEEDSKILL, // you need a certain skill to operate this. + // eg. you know what a spanner is without any tech skill, but you + // need skill to actually use it. + // v0 = skill that you need + // v1 = skill level you need it at F_OPERNEEDTARGET, // need to ask for a target of type val0 when opering // v1 is bitmask of: // TR_NEEDLOS, TR_NEEDLOF, TR_NONE @@ -3219,7 +3226,7 @@ enum FLAG { // check. // v2 = sc_dodge difficulty // if text == "ground", then this trap only goes off - // if you're on the ground (ie not flying) + // if you're on the ground (ie not flying) - ie. a pressure plate F_OBJECTTRAP, // this trap can go onto an object (door, chest, etc) F_DOORTRAPONLY, // this trap can only go on to doors F_DOORFALLOB, // if this object is trapped with OT_TRAPDOORFALL, @@ -4598,6 +4605,7 @@ enum ERROR { E_NOABIL, E_NOMP, E_NOSTAM, + E_NOSKILL, E_NOSPELLS, E_AVOIDOB, E_FROZEN, @@ -4678,7 +4686,7 @@ enum COMMAND { // CMD_AGAIN, CMD_AIM, - CMD_CLOSE, + //CMD_CLOSE, CMD_COMMS, CMD_COMMSALL, CMD_DOWN, diff --git a/io.c b/io.c index 007aed5..921efe4 100644 --- a/io.c +++ b/io.c @@ -4495,6 +4495,7 @@ void doattackcell(int dir) { } } +/* void doclose(void) { int failed = B_TRUE; // default is to fail int dir; @@ -4545,6 +4546,7 @@ void doclose(void) { } } } +*/ void docommslf(lifeform_t *lf, char ch, lifeform_t *lf2, cell_t *targc) { char lfname[BUFLEN], lfname2[BUFLEN]; @@ -7025,6 +7027,18 @@ char *makedesc_ob(object_t *o, char *retbuf) { strncat(retbuf, buf, HUGEBUFLEN); } + f = hasflag(o->flags, F_OPERABLE); + if (f) { + flag_t *f2; + f2 = hasflag(o->flags, F_OPERNEEDSKILL); + if (f2) { + sprintf(buf, "It requires %s %s skill to operate.\n", getskilllevelname(f2->val[1]), getskillname(f2->val[0])); + } else { + sprintf(buf, "It can be operated.\n"); + } + strncat(retbuf, buf, HUGEBUFLEN); + } + // other weapon properties... getflags(o->flags, retflag, &nretflags, F_CANBLOCK, F_NONE); for (i = 0; i < nretflags; i++) { @@ -9109,6 +9123,8 @@ void dohelp(char helpmode) { restoregamewindows(); } + + void dointeract(void) { cell_t *c; object_t *o; @@ -9121,7 +9137,7 @@ void dointeract(void) { // operable objects here? for (o = player->cell->obpile->first; o ; o = o->next) { - if (isoperable(o)) { + if (isinteractable(o) && !isdoor(o, NULL)) { // can't open/close doors you're on top of char obname[BUFLEN],buf[BUFLEN]; char verb[BUFLEN]; int ch; @@ -9146,6 +9162,14 @@ void dointeract(void) { msg("Cancelled."); return; } + + + // can only interact with things we're facing + if (getrelativedir(player, dir) != RD_FORWARDS) { + msg("You can only interact with things in front of you."); + return; + } + c = getcellindir(player->cell, dir); if (!c) { msg("Cancelled."); @@ -9157,21 +9181,14 @@ void dointeract(void) { // get adjacent cells // anything operable and impasssble? + /* initcondv(&cs, CC_HASFLAG, B_TRUE, F_IMPASSABLE, CC_OPERABLE, B_TRUE, NA, CC_NONE); - getobs(c->obpile, &cs, ob, &nobs); - for (n = 0; n < nobs; n++) { - char obname[BUFLEN]; - getobname(ob[n], obname, ob[n]->amt); - addchoice(&prompt, ch, obname, NULL, ob[n], NULL); - if (ch == 'z') ch = 'A'; - else ch++; - } - - // open doors - initcondv(&cs, CC_HASFLAG, B_TRUE, F_DOOR, + */ + initcondv(&cs, CC_INTERACTABLE, B_TRUE, NA, CC_NONE); + getobs(c->obpile, &cs, ob, &nobs); for (n = 0; n < nobs; n++) { char obname[BUFLEN]; @@ -9180,7 +9197,6 @@ void dointeract(void) { if (ch == 'z') ch = 'A'; else ch++; } - o = NULL; if (!prompt.nchoices) { @@ -11123,17 +11139,19 @@ void handleinput(void) { case CMD_NEXTTARGET: donextguntarget(); break; - // object functions + /* case CMD_CLOSE: // close addflag(player->flags, F_LASTCMD, NA, NA, NA, temp); doclose(); break; + */ case CMD_COMMS: // communicate docomms(NULL); break; case CMD_COMMSALL: // communicate docommsmulti(); break; + // object functions case CMD_EAT: // eat doeat(player->pack); break; diff --git a/lf.c b/lf.c index 2ad14e7..e6b38ea 100644 --- a/lf.c +++ b/lf.c @@ -1179,6 +1179,8 @@ int canopendoors(lifeform_t *lf) { } int canoperate(lifeform_t *lf, object_t *o, enum ERROR *why) { + flag_t *f; + if (why) *why = E_OK; if (lfhasflag(lf, F_RAGE)) { if (why) *why = E_RAGE; @@ -1194,6 +1196,14 @@ int canoperate(lifeform_t *lf, object_t *o, enum ERROR *why) { return B_FALSE; } } + + f = hasflag(o->flags, F_OPERNEEDSKILL); + if (f) { + if (getskill(lf, f->val[0]) < f->val[1]) { + if (why) *why = E_NOSKILL; + return B_FALSE; + } + } return B_TRUE; } diff --git a/move.c b/move.c index 4c2e7b0..5254f56 100644 --- a/move.c +++ b/move.c @@ -1968,6 +1968,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) { for (o = newcell->obpile->first ; o ; o = nexto ) { flag_t *f; nexto = o->next; + f = hasflag(o->flags, F_TRAP); if (f) { if (strstr(f->text, "ground") && isairborne(lf, NULL)) { @@ -2174,7 +2175,7 @@ int opendoor(lifeform_t *lf, object_t *o) { // trapped? if (lf && hasflag(o->flags, F_TRAPPED)) { - if (doobtraps(o, lf)) { + if (triggerattachedtraps(o, lf)) { if (isplayer(lf)) stoppathfinding(lf); return B_TRUE; } @@ -2918,6 +2919,7 @@ int teleportto(lifeform_t *lf, cell_t *c, int wantsmoke) { return B_FALSE; } +// trigger an actual trap object (ie. OC_TRAP) void triggertrap(lifeform_t *lf, object_t *o, object_t *trapob, cell_t *where) { char triggerer[BUFLEN]; char trapname[BUFLEN]; diff --git a/nexus.c b/nexus.c index f468e59..693c08a 100644 --- a/nexus.c +++ b/nexus.c @@ -1684,6 +1684,19 @@ void initcondv(condset_t *cs, ...) { va_end(args); } +char incletter(char *ch) { + int newchar; + if (*ch == '\0') { + newchar = 'a'; + } else if (*ch == 'z') { + newchar = 'A'; + } else { + newchar = (*ch) + 1; + } + + *ch = newchar; + return *ch; +} void inctime(long nunits) { curtime += (nunits*(TIMECONST)); diff --git a/nexus.h b/nexus.h index 3d313ac..7095ed4 100644 --- a/nexus.h +++ b/nexus.h @@ -24,6 +24,7 @@ char getpctletter(float num, float max); int init(void); void initcond(condset_t *cs); void initcondv(condset_t *cs, ...); +char incletter(char *ch); void inctime(long nunits); void calcbresnham(map_t *m, int x1, int y1, int x2, int y2, cell_t **retcell, int *numpixels); void initbresnham(int x1, int y1, int x2, int y2, int *xinc1, int *yinc1, int *dinc1, int *xinc2, int *yinc2, int *dinc2, int *numpixels, int *d); diff --git a/objects.c b/objects.c index a7a1db3..c538399 100644 --- a/objects.c +++ b/objects.c @@ -3491,6 +3491,23 @@ void colourmatchob(object_t *o, lifeform_t *lf) { } } +// returns TRUE if user chose to cancel the action +int confirmknowntraps(object_t *o) { + if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) { + if (getattrbracket(getattr(player, A_WIS), A_WIS, NULL) >= AT_AVERAGE) { + char ch; + char buf[BUFLEN],obname[BUFLEN]; + getobname(o, obname, o->amt); + snprintf(buf, BUFLEN,"Really operate %s?", obname); + ch = askchar(buf,"yn","n", B_TRUE, B_FALSE); + if (ch != 'y') { + return B_TRUE; + } + } + } + return B_FALSE; +} + void copyobprops(object_t *dst, object_t *src) { dst->material = src->material; dst->weight = src->weight; @@ -3790,7 +3807,8 @@ int doobdieconvert(object_t *o, int wantannounce) { } -int doobtraps(object_t *o, lifeform_t *lf) { +// trigger any traps attached to a regular object (ie. a door with a trap) +int triggerattachedtraps(object_t *o, lifeform_t *lf) { flag_t *f; f = hasflag(o->flags, F_TRAPPED); if (f) { @@ -4768,7 +4786,7 @@ lifeform_t *getobcreatedby(object_t *o) { } int getobjamdiff(int depth) { - return 100 + rnd(1,100); + return 50 + rnd(0,depth*5); } // returns the amount to adjust a skillcheck roll if you give object 'o' to lifeform 'lf' @@ -7627,6 +7645,18 @@ object_t *hasequippedobidon(obpile_t *op, enum OBTYPE oid, enum BODYPART bp) { return NULL; } +int hasinteractableflags(flagpile_t *fp) { + if (hasflag(fp, F_IMPASSABLE)) { + return B_TRUE; + } else if (hasflag(fp, F_DOOR)) { + return B_TRUE; + } else if (hasflag(fp, F_CONTAINER)) { + return B_TRUE; + } + return B_FALSE; +} + + object_t *hasknownob(obpile_t *op, enum OBTYPE oid) { object_t *o; for (o = op->first ; o ; o = o->next) { @@ -8203,6 +8233,21 @@ int isimpassableob(object_t *o, lifeform_t *lf, enum LFSIZE forcesize) { return B_FALSE; } +// 'Interacting' is using things without holding them. +// +// It's fine to interact with a computer, door or treasure chest. +// It's NOT fine to interact with a wand, even though it is operable. +// +int isinteractable(object_t *o) { + if (isoperable(o) && hasinteractableflags(o->flags)) { + return B_TRUE; + } else if (isdoor(o, NULL)) { + return B_TRUE; + } + return B_FALSE; +} + + int ismagicalobtype(objecttype_t *ot) { switch (ot->obclass->id) { case OC_SCROLL: @@ -10103,6 +10148,9 @@ int obmeetscondition(object_t *o, enum CELLCONDITION cond, int arg, int value) { case CC_OPERABLE: if (isoperable(o)) check = B_TRUE; break; + case CC_INTERACTABLE: + if (isinteractable(o)) check = B_TRUE; + break; case CC_POURABLE: if (ispourable(o)) check = B_TRUE; break; @@ -10268,6 +10316,9 @@ int otmeetscondition(objecttype_t *ot, enum CELLCONDITION cond, int arg, int val case CC_OPERABLE: if (hasflag(ot->flags, F_OPERABLE)) check = B_TRUE; break; + case CC_INTERACTABLE: + if (hasinteractableflags(ot->flags)) check = B_TRUE; + break; case CC_POURABLE: if (hasflag(ot->flags, F_POURABLE)) check = B_TRUE; break; @@ -10524,20 +10575,21 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { } } + getobname(o, obname, 1); + if (!canoperate(lf, o, &why)) { if (isplayer(lf)) { switch (why) { - case E_NOHANDS: msg("You lack the manual dexterity to operate this."); break; + case E_NOHANDS: msg("You lack the manual dexterity to operate %s.", obname); break; case E_RAGE: msg("You are too enraged to operate anything!"); break; case E_STUNNED: msg("You cannot operate anything while stunned."); break; - default: msg("For some reason, you can't operate this."); break; + case E_NOSKILL: msg("You lack the skill to operate %s.", obname); break; + default: msg("For some reason, you can't operate %s.", obname); break; } return B_TRUE; } } - getobname(o, obname, 1); - if ((isplayer(lf)) || cansee(player, lf)) { playercansee = B_TRUE; } else { @@ -10575,16 +10627,9 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { // has known trap? if (isplayer(lf)) { - if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) { - if (getattrbracket(getattr(lf, A_WIS), A_WIS, NULL) >= AT_AVERAGE) { - char ch; - snprintf(buf, BUFLEN,"Really operate %s?", obname); - ch = askchar(buf,"yn","n", B_TRUE, B_FALSE); - if (ch != 'y') { - msg("Cancelled."); - return B_TRUE; - } - } + if (confirmknowntraps(o)) { + msg("Cancelled."); + return B_TRUE; } } @@ -10680,13 +10725,17 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { char ch; int dir; // ask direction - ch = askchar(f->text, "yuhjklbn-","-", B_FALSE, B_TRUE); + ch = askchar(f->text, "yuhjklbn.-","-", B_FALSE, B_TRUE); if ((ch == '-') || !ch) { msg("Cancelled."); return B_TRUE; } else { dir = chartodir(ch); - where = getcellindir(lf->cell, dir); + if (dir == D_NONE) { + where = lf->cell; + } else { + where = getcellindir(lf->cell, dir); + } } } @@ -10792,7 +10841,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { if (isplayer(lf)) maketried(o->type->id, NULL); // trapped? - if (doobtraps(o, lf)) { + if (triggerattachedtraps(o, lf)) { return B_TRUE; } @@ -11913,59 +11962,134 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { int donesomething = B_FALSE; if (!where) { if (isplayer(lf)) msg("There is nothing to use your spanner on there!"); - } else if (where->lf) { + } else if (where->lf && (where->lf != lf)) { if (isplayer(lf)) msg("There is someone in your way!"); } else { - object_t *o; - char ch; + int isopen; + object_t *o2; + char ch = '\0',qbuf[BUFLEN],spannername[BUFLEN]; flag_t *f; - for (o = where->obpile->first ; o ; o = o->next) { - int isopen; - // jammed doors - if (isdoor(o, &isopen)) { - if (!isopen) { // ie. if closed. - f = hasflag(o->flags, F_JAMMED); - if (f) { - ch = askchar("The hinges seem jammed. Loosen them", "yn", "y", B_TRUE, B_FALSE); - if (ch == 'y') { - char obname[BUFLEN]; - getobname(o, obname, 1); - msg("You loosen the hinges on %s.", obname); - killflag(f); - taketime(lf, getactspeed(lf)); - donesomething = B_TRUE; - } - } else { - char obname[BUFLEN]; - getobname(o, obname, 1); - snprintf(buf, BUFLEN, "Tighten the hinges on %s",obname); - ch = askchar(buf, "yn", "y", B_TRUE, B_FALSE); - if (ch == 'y') { - msg("You tighten the hinges on %s.", obname); - addflag(o->flags, F_JAMMED, 2, B_TRUE, 150, NULL); - taketime(lf, getactspeed(lf)); - donesomething = B_TRUE; - } - } - } - } - // gratings - if ((o->type->id == OT_GRATINGFLOOR) && hasflag(o->flags, F_LOCKED)) { - char obname[BUFLEN]; - getobname(o, obname, 1); - ch = askchar("It looks like you could remove the bolts. Do so", "yn", "y", B_TRUE, B_FALSE); - if (ch == 'y') { - msg("You remove the cover from %s.", obname); - killflagsofid(o->flags, F_LOCKED); - killflagsofid(o->flags, F_LOCKABLE); - taketime(lf, getactspeed(lf)); - donesomething = B_TRUE; - } + + getobname(o, spannername, 1); + + snprintf(qbuf, BUFLEN, "What will you use %s on?", spannername); + initprompt(&prompt, qbuf); + for (o2 = where->obpile->first ; o2 ; o2 = o2->next) { + // can use the spanner on... + if (isdoor(o2, &isopen)) { // doors + getobname(o2, obname, 1); + addchoice(&prompt, incletter(&ch), obname, NULL, o2 , NULL); + } else if (hasflag(o2->flags, F_LOCKABLE)) { + getobname(o2, obname, 1); + addchoice(&prompt, incletter(&ch), obname, NULL, o2 , NULL); } } - } - if (!donesomething) { - if (isplayer(lf)) msg("There is nothing to use your spanner on there!"); + + if (prompt.nchoices >= 1) { + int isopen; + if (prompt.nchoices == 1) { + o2 = (object_t *)prompt.choice[0].data; + } else { + prompt.maycancel = B_TRUE; + getchoice(&prompt); + o2 = (object_t *) prompt.result; + } + + if (o2) { + if (isplayer(lf)) { + if (confirmknowntraps(o2)) { + msg("Cancelled."); + return B_TRUE; + } + } + + snprintf(qbuf, BUFLEN, "What will you do to %s?", obname); + initprompt(&prompt, qbuf); + + // figure out what you can do to the object + if (isdoor(o2, &isopen) && !isopen) { + getobname(o2, obname, 1); + + f = hasflagknown(o2->flags, F_JAMMED); + if (f) { + // you know it's jammed... + snprintf(qbuf, BUFLEN, "Unjam it"); + addchoice(&prompt, 'j', qbuf, NULL, o2 , NULL); + } else { + // you don't _think_ it's jammed... + snprintf(qbuf, BUFLEN, "Jam it"); + addchoice(&prompt, 'j', qbuf, NULL, o2 , NULL); + } + } + f = hasflag(o2->flags, F_LOCKABLE); + if (f) { + snprintf(qbuf, BUFLEN, "Dismantle the lock"); + addchoice(&prompt, 'l', qbuf, NULL, o2 , NULL); + } + + if (prompt.nchoices >= 1) { + prompt.maycancel = B_TRUE; + ch = getchoice(&prompt); + + if (ch != '\0') { + // traps go off + if (triggerattachedtraps(o2, lf)) { + return B_TRUE; + } + } + + switch (ch) { + case 'j': + f = hasflagknown(o2->flags, F_JAMMED); + if (f) { + // unjam it + msg("You loosen the hinges on %s.", obname); + killflag(f); + taketime(lf, getactspeed(lf)); + donesomething = B_TRUE; + } else { + // you don't _think_ it's jammed... + // try to jam it. + if (hasflag(o2->flags, F_JAMMED)) { + msg("The hinges on %s cannot be tightened any more.", obname); + f->known = B_TRUE; + taketime(lf, getactspeed(lf)); + donesomething = B_TRUE; + } else { + msg("You tighten the hinges on %s.", obname); + addflag(o2->flags, F_JAMMED, 2, B_TRUE, 120, NULL); // very tight + taketime(lf, getactspeed(lf)); + donesomething = B_TRUE; + } + } + break; + case 'l': + f = hasflagknown(o2->flags, F_LOCKED); + if (f) { + msg("You remove the locking bolts from %s.", obname); + killflagsofid(o2->flags, F_LOCKED); + killflagsofid(o2->flags, F_LOCKABLE); + taketime(lf, getactspeed(lf)); + donesomething = B_TRUE; + } else { + // should never happen. + msg("%s is already unlocked.",obname); + } + break; + default: + msg("Cancelled."); + return B_TRUE; + } + } else { + msg("There doesn't seem to be much you can do to %s.",obname); + } + } else { + msg("Cancelled."); + return B_TRUE; + } + } else { + msg("There is nothing to use your spanner on there!"); + } } } else if (o->type->id == OT_STYPTIC) { flag_t *retflag[MAXCANDIDATES]; @@ -12690,9 +12814,9 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE break; } if (potblessed == B_CURSED) { - amt = -1; + amt = -5; } else { - amt = 1; + amt = 5; } // select a random attribute if (potblessed == B_BLESSED) { @@ -16949,7 +17073,10 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c, object_t *trapped } } } else if (oid == OT_TRAPALARM) { + // 50 is stupidly loud, intentionally noise(c, NULL, NC_OTHER, 50, "a blaring siren!", "A blaring siren goes off!"); + } else if (oid == OT_TRAPNOISE) { + noise(c, NULL, NC_OTHER, 3, "a loud squeak!", "The hinges squeak loudly!"); } else if ((oid == OT_TRAPARROW) || (oid == OT_TRAPARROWP)) { int dir,bestdir = D_NONE; cell_t *src = NULL; diff --git a/objects.h b/objects.h index dd083b4..bd2da9d 100644 --- a/objects.h +++ b/objects.h @@ -2,6 +2,7 @@ #define __OBJECTS_H #include "defs.h" + brand_t *addbrand(enum BRAND id, char *suffix, enum BODYPART bp, enum BLESSTYPE blessed, int blesschance); object_t *addemptyob(obpile_t *where, object_t *o); hiddenname_t *addhiddenname(enum OBCLASS obclass, char *text); @@ -40,6 +41,7 @@ int chargesknown(object_t *o); int getcritprotection(object_t *o); int checkobnames(char *haystack, char *needle); void colourmatchob(object_t *o, lifeform_t *lf); +int confirmknowntraps(object_t *o); void copyobprops(object_t *dst, object_t *src); int counthiddennames(enum OBCLASS ocid, char *text); int countmoney(obpile_t *op); @@ -54,7 +56,7 @@ int curseob(object_t *o); void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype, lifeform_t *srclf); void dodecay(object_t *o); int doobdieconvert(object_t *o, int wantannounce); -int doobtraps(object_t *o, lifeform_t *lf); +int triggerattachedtraps(object_t *o, lifeform_t *lf); void dumpobs(int ntogen); void dumpobrarity(void); void explodeob(object_t *o, flag_t *f, int bigness, lifeform_t *causedby); @@ -172,6 +174,7 @@ enum BODYPART getweildloc(object_t *o, lifeform_t *lf, enum BODYPART *otherloc, int hasedibleob(obpile_t *op); object_t *hasequippedobid(obpile_t *op, enum OBTYPE oid); object_t *hasequippedobidon(obpile_t *op, enum OBTYPE oid, enum BODYPART bp); +int hasinteractableflags(flagpile_t *fp); object_t *hasknownob(obpile_t *op, enum OBTYPE oid); object_t *hasob(obpile_t *op, enum OBTYPE oid); object_t *hasobletter(obpile_t *op, char letter); @@ -213,6 +216,7 @@ int isknownot(objecttype_t *ot); int isheavyweapon(object_t *o); int isidentified(object_t *o); int isimpassableob(object_t *o, lifeform_t *lf, enum LFSIZE forcesize); +int isinteractable(object_t *o); int ismagicalobtype(objecttype_t *ot); int ismagical(object_t *o); int ismeleeweapon(object_t *o);