/* * Split obj so that it gets size gets reduced by num. The quantity num is * put in the object structure delivered by this call. The returned object * has its wornmask cleared and is positioned just following the original * in the nobj chain (and nexthere chain when on the floor). */ struct obj * splitobj(struct obj *obj, long int num) { struct obj *otmp; if (obj->cobj || num <= 0L || obj->quan <= num) panic("splitobj"); /* can't split containers */ otmp = newobj(obj->oxlth + obj->onamelth); *otmp = *obj; /* copies whole structure */ otmp->o_id = flags.ident++; if (!otmp->o_id) otmp->o_id = flags.ident++; /* ident overflowed */ otmp->timed = 0; /* not timed, yet */ otmp->lamplit = 0; /* ditto */ otmp->owornmask = 0L; /* new object isn't worn */ obj->quan -= num; obj->owt = weight(obj); otmp->quan = num; otmp->owt = weight(otmp); /* -= obj->owt ? */ obj->nobj = otmp; /* Only set nexthere when on the floor, nexthere is also used */ /* as a back pointer to the container object when contained. */ if (obj->where == OBJ_FLOOR) obj->nexthere = otmp; if (obj->oxlth) (void)memcpy((genericptr_t)otmp->oextra, (genericptr_t)obj->oextra, obj->oxlth); if (obj->onamelth) (void)strncpy(ONAME(otmp), ONAME(obj), (int)obj->onamelth); if (obj->unpaid) splitbill(obj,otmp); if (obj->timed) obj_split_timers(obj, otmp); if (obj_sheds_light(obj)) obj_split_light_source(obj, otmp); return otmp; }
struct obj *oname(struct obj *obj, const char *name) { int lth; char buf[PL_PSIZ]; lth = *name ? (int)(strlen(name) + 1) : 0; if (lth > PL_PSIZ) { lth = PL_PSIZ; name = strncpy(buf, name, PL_PSIZ - 1); buf[PL_PSIZ - 1] = '\0'; } /* If named artifact exists in the game, do not create another. * Also trying to create an artifact shouldn't de-artifact * it (e.g. Excalibur from prayer). In this case the object * will retain its current name. */ if (obj->oartifact || (lth && exist_artifact(obj->otyp, name))) return obj; if (lth == obj->onamelth) { /* no need to replace entire object */ if (lth) strcpy(ONAME(obj), name); } else { obj = realloc_obj(obj, obj->oxlth, obj->oextra, lth, name); } if (lth) artifact_exists(obj, name, TRUE); if (obj->oartifact) { /* can't dual-wield with artifact as secondary weapon */ if (obj == uswapwep) untwoweapon(); /* activate warning if you've just named your weapon "Sting" */ if (obj == uwep) set_artifact_intrinsic(obj, TRUE, W_WEP); } if (carried(obj)) update_inventory(); return obj; }
/* * Attach a monster id to an object, to provide * a lasting association between the two. */ struct obj *obj_attach_mid(struct obj *obj, unsigned mid) { struct obj *otmp; int lth, namelth; if (!mid || !obj) return NULL; lth = sizeof(mid); namelth = obj->onamelth ? strlen(ONAME(obj)) + 1 : 0; if (namelth) otmp = realloc_obj(obj, lth, &mid, namelth, ONAME(obj)); else { otmp = obj; otmp->oxlth = sizeof(mid); memcpy(otmp->oextra, (void *)&mid, sizeof(mid)); } if (otmp && otmp->oxlth) otmp->oattached = OATTACHED_M_ID; /* mark it */ return otmp; }
static struct obj *save_mtraits(struct obj *obj, struct monst *mtmp) { struct obj *otmp; int lth, namelth; lth = sizeof(struct monst) + mtmp->mxlth + mtmp->mnamelth; namelth = obj->onamelth ? strlen(ONAME(obj)) + 1 : 0; otmp = realloc_obj(obj, lth, mtmp, namelth, ONAME(obj)); if (otmp && otmp->oxlth) { struct monst *mtmp2 = (struct monst *)otmp->oextra; if (mtmp->data) mtmp2->mnum = monsndx(mtmp->data); /* invalidate pointers */ /* m_id is needed to know if this is a revived quest leader */ /* but m_id must be cleared when loading bones */ mtmp2->nmon = NULL; mtmp2->data = NULL; mtmp2->minvent = NULL; otmp->oattached = OATTACHED_MONST; /* mark it */ } return otmp; }
/* * Create a dummy duplicate to put on shop bill. The duplicate exists * only in the billobjs chain. This function is used when a shop object * is being altered, and a copy of the original is needed for billing * purposes. For example, when eating, where an interruption will yield * an object which is different from what it started out as; the "I x" * command needs to display the original object. * * The caller is responsible for checking otmp->unpaid and * costly_spot(u.ux, u.uy). This function will make otmp no charge. * * Note that check_unpaid_usage() should be used instead for partial * usage of an object. */ void bill_dummy_object(struct obj *otmp) { struct obj *dummy; if (otmp->unpaid) subfrombill(otmp, shop_keeper(level, *u.ushops)); dummy = newobj(otmp->oxlth + otmp->onamelth); *dummy = *otmp; dummy->where = OBJ_FREE; dummy->o_id = flags.ident++; if (!dummy->o_id) dummy->o_id = flags.ident++; /* ident overflowed */ dummy->timed = 0; if (otmp->oxlth) memcpy(dummy->oextra, otmp->oextra, otmp->oxlth); if (otmp->onamelth) strncpy(ONAME(dummy), ONAME(otmp), (int)otmp->onamelth); if (Is_candle(dummy)) dummy->lamplit = 0; addtobill(dummy, FALSE, TRUE, TRUE); otmp->no_charge = 1; otmp->unpaid = 0; return; }
/*ARGSUSED*/ STATIC_OVL void newmail(struct mail_info *info) { struct monst *md; coord start, stop; boolean message_seen = FALSE; /* Try to find good starting and stopping places. */ if (!md_start(&start) || !md_stop(&stop,&start)) goto give_up; /* Make the daemon. Have it rush towards the hero. */ if (!(md = makemon(&mons[PM_MAIL_DAEMON], start.x, start.y, NO_MM_FLAGS))) goto give_up; if (!md_rush(md, stop.x, stop.y)) goto go_back; message_seen = TRUE; verbalize("%s, %s! %s.", Hello(md), plname, info->display_txt); if (info->message_typ) { struct obj *obj = mksobj(SCR_MAIL, FALSE, FALSE); if (info->message_typ == MSG_HINT) obj->spe = MAIL_HINT; if (distu(md->mx,md->my) > 2) verbalize("Catch!"); display_nhwindow(WIN_MESSAGE, FALSE); if (info->object_nam) { obj = oname(obj, info->object_nam); if (info->response_cmd) { /*(hide extension of the obj name)*/ int namelth = info->response_cmd - info->object_nam - 1; if ( namelth <= 0 || namelth >= (int) obj->onamelth ) warning("mail delivery screwed up"); else *(ONAME(obj) + namelth) = '\0'; /* Note: renaming object will discard the hidden command. */ } } obj = hold_another_object(obj, "Oops!", (const char *)0, (const char *)0); } /* zip back to starting location */ go_back: (void) md_rush(md, start.x, start.y); mongone(md); /* deliver some classes of messages even if no daemon ever shows up */ give_up: if (!message_seen && info->message_typ == MSG_OTHER) pline("Hark! \"%s.\"", info->display_txt); }
void save_obj(struct memfile *mf, struct obj *obj) { unsigned int oflags; oflags = (obj->cursed << 31) | (obj->blessed << 30) | (obj->unpaid << 29) | (obj->no_charge << 28) | (obj->known << 27) | (obj->dknown << 26) | (obj->bknown << 25) | (obj->rknown << 24) | (obj->oeroded << 22) | (obj->oeroded2 << 20) | (obj->oerodeproof << 19) | (obj->olocked << 18) | (obj->obroken << 17) | (obj->otrapped << 16) | (obj->recharged << 13) | (obj->lamplit << 12) | (obj->greased << 11) | (obj->oattached << 9) | (obj->in_use << 8) | (obj->was_thrown << 7) | (obj->bypass << 6); mfmagic_set(mf, OBJ_MAGIC); mwrite32(mf, obj->onamelth); mwrite32(mf, obj->o_id); mwrite32(mf, obj->owt); mwrite32(mf, obj->quan); mwrite32(mf, obj->corpsenm); mwrite32(mf, obj->oeaten); mwrite32(mf, obj->age); mwrite32(mf, obj->owornmask); mwrite32(mf, oflags); mwrite16(mf, obj->otyp); mwrite8(mf, obj->ox); mwrite8(mf, obj->oy); mwrite8(mf, obj->spe); mwrite8(mf, obj->oclass); mwrite8(mf, obj->invlet); mwrite8(mf, obj->oartifact); mwrite8(mf, obj->where); mwrite8(mf, obj->timed); /* no need to save the value of the cobj pointer, but we will need to know * if there is something in here that needs to be restored */ mwrite8(mf, obj->cobj ? 1 : 0); if (obj->onamelth) mwrite(mf, ONAME(obj), obj->onamelth); if (obj->oattached == OATTACHED_MONST) save_mon(mf, (struct monst*)obj->oextra); else if (obj->oattached == OATTACHED_M_ID) mwrite32(mf, *(unsigned int*)obj->oextra); }
char *xname(struct obj *obj) { static char bufr[BUFSZ]; /* Leave room for "17 -3 " */ char *buf = &(bufr[PREFIX]); int nn = objects[obj->otyp].oc_name_known; char *an = objects[obj->otyp].oc_name; char *dn = objects[obj->otyp].oc_descr; char *un = objects[obj->otyp].oc_uname; int pl = 0; if(obj->quan != 0) { pl = 1; } if((obj->dknown == 0) && (Blind == 0)) { /* %% Doesn't belong here */ obj->dknown = 1; } switch(obj->olet) { case AMULET_SYM: if((obj->spe < 0) && (obj->known != 0)) { strcpy(buf, "cheap plastic imitation of the "); } else { strcpy(buf, ""); } strcat(buf, "Amulet of Yendor"); break; case TOOL_SYM: if(nn == 0) { strcpy(buf, dn); break; } strcpy(buf, an); break; case FOOD_SYM: if((obj->otyp == CLOVE_OF_GARLIC) && (pl != 0)) { pl = 0; strcpy(buf, "cloves of garlic"); break; } if((obj->otyp == DEAD_HOMUNCULUS) && (pl != 0)) { pl = 0; strcpy(buf, "dead homunculi"); break; } /* Fungis ? */ /* Fall into next case */ case WEAPON_SYM: if((obj->otyp == WORM_TOOTH) && (pl != 0)) { pl = 0; strcpy(buf, "worm teeth"); break; } if((obj->otyp == CRYSKNIFE) && (pl != 0)) { pl = 0; strcpy(buf, "crysknifes"); break; } /* Fall into next case */ case ARMOR_SYM: case CHAIN_SYM: case ROCK_SYM: strcpy(buf, an); break; case BALL_SYM: if(obj->owt > objects[obj->otyp].oc_weight) { sprintf(buf, "%sheavy iron ball", "very "); } else { sprintf(buf, "%sheavy iron ball", ""); } break; case POTION_SYM: if((nn != 0) || (un != 0) || (obj->dknown == 0)) { strcpy(buf, "potion"); if(pl != 0) { pl = 0; strcat(buf, "s"); } if(obj->dknown == 0) { break; } if(un != 0) { strcat(buf, " called "); strcat(buf, un); } else { strcat(buf, " of "); strcat(buf, an); } } else { strcpy(buf, dn); strcat(buf, " potion"); } break; case SCROLL_SYM: strcpy(buf, "scroll"); if(pl != 0) { pl = 0; strcat(buf, "s"); } if(obj->dknown == 0) { break; } if(nn != 0) { strcat(buf, " of "); strcat(buf, an); } else if(un != 0) { strcat(buf, " called "); strcat(buf, un); } else { strcat(buf, " labeled "); strcat(buf, dn); } break; case WAND_SYM: if(obj->dknown == 0) { sprintf(buf, "wand"); } else if(nn != 0) { sprintf(buf, "wand of %s", an); } else if(un != 0) { sprintf(buf, "wand called %s", un); } else { sprintf(buf, "%s wand", dn); } break; case RING_SYM: if(obj->dknown == 0) { sprintf(buf, "ring"); } else if(nn != 0) { sprintf(buf, "ring of %s", an); } else if(un != 0) { sprintf(buf, "ring called %s", un); } else { sprintf(buf, "%s ring", dn); } break; case GEM_SYM: if(obj->dknown == 0) { strcpy(buf, "gem"); break; } if(nn == 0) { sprintf(buf, "%s gem", dn); break; } if((pl != 0) && (strncmp("worthless piece", an, 15) == 0)) { pl = 0; sprintf(buf, "worthless pieces%s", an + 15); break; } strcpy(buf, an); if((obj->otyp >= TURQUOISE) && (obj->otyp <= JADE)) { strcat(buf, " stone"); } break; default: sprintf(buf, "glorkum %c (0%o) %d %d", obj->olet, obj->olet, obj->otyp, obj->spe); } if(pl != 0) { char *p = eos(buf) - 1; if((*p == 's') || (*p == 'z') || (*p == 'x') || ((*p == 'h') && p[-1] == 's')) { /* Boxes */ strcat(buf, "es"); } else if((*p == 'y') && (index(vowels, p[-1]) == 0)) { /* Rubies, zruties */ strcpy(p, "ies"); } else { strcat(buf, "s"); } } if(obj->onamelth) { strcat(buf, " named "); strcat(buf, ONAME(obj)); } return buf; }
/* return TRUE if mon still alive */ bool hmon(struct monst *mon, struct obj *obj, int thrown) { int tmp; bool hittxt = FALSE; if (!obj) { tmp = rnd(2); /* attack with bare hands */ if (mon->data->mlet == 'c' && !uarmg) { pline("You hit the cockatrice with your bare hands."); pline("You turn to stone ..."); done_in_by(mon); } } else if (obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE) { if (obj == uwep && (obj->otyp > SPEAR || obj->otyp < BOOMERANG)) tmp = rnd(2); else { if (strchr(mlarge, mon->data->mlet)) { tmp = rnd(objects[obj->otyp].wldam); if (obj->otyp == TWO_HANDED_SWORD) tmp += d(2, 6); else if (obj->otyp == FLAIL) tmp += rnd(4); } else tmp = rnd(objects[obj->otyp].wsdam); tmp += obj->spe; if (!thrown && obj == uwep && obj->otyp == BOOMERANG && !rn2(3)) { pline("As you hit %s, the boomerang breaks into splinters.", monnam(mon)); freeinv(obj); setworn(NULL, obj->owornmask); obfree(obj, NULL); tmp++; } } if (mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD && !strcmp(ONAME(obj), "Orcrist")) tmp += rnd(10); } else switch (obj->otyp) { case HEAVY_IRON_BALL: tmp = rnd(25); break; case EXPENSIVE_CAMERA: pline("You succeed in destroying your camera. Congratulations!"); freeinv(obj); if (obj->owornmask) setworn(NULL, obj->owornmask); obfree(obj, NULL); return (TRUE); case DEAD_COCKATRICE: pline("You hit %s with the cockatrice corpse.", monnam(mon)); if (mon->data->mlet == 'c') { tmp = 1; hittxt = TRUE; break; } pline("%s is turned to stone!", Monnam(mon)); killed(mon); return (FALSE); case CLOVE_OF_GARLIC: /* no effect against demons */ if (strchr(UNDEAD, mon->data->mlet)) mon->mflee = 1; tmp = 1; break; default: /* non-weapons can damage because of their weight */ /* (but not too much) */ tmp = obj->owt / 10; if (tmp < 1) tmp = 1; else tmp = rnd(tmp); if (tmp > 6) tmp = 6; } /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */ tmp += u.udaminc + dbon(); if (u.uswallow) { if ((tmp -= u.uswldtim) <= 0) { pline("Your arms are no longer able to hit."); return (TRUE); } } if (tmp < 1) tmp = 1; mon->mhp -= tmp; if (mon->mhp < 1) { killed(mon); return (FALSE); } if (mon->mtame && (!mon->mflee || mon->mfleetim)) { mon->mflee = 1; /* Rick Richardson */ mon->mfleetim += 10 * rnd(tmp); } if (!hittxt) { if (thrown) { /* this assumes that we cannot throw plural things */ hit(xname(obj) /* or: objects[obj->otyp].oc_name */, mon, exclam(tmp)); } else if (Blind) pline("You hit it."); else pline("You hit %s%s", monnam(mon), exclam(tmp)); } if (u.umconf && !thrown) { if (!Blind) { pline("Your hands stop glowing blue."); if (!mon->mfroz && !mon->msleep) pline("%s appears confused.", Monnam(mon)); } mon->mconf = 1; u.umconf = 0; } return (TRUE); /* mon still alive */ }
struct obj *restore_obj(struct memfile *mf) { unsigned int oflags; char namelen; struct obj *otmp; mfmagic_check(mf, OBJ_MAGIC); namelen = mread32(mf); otmp = newobj(namelen); memset(otmp, 0, namelen + sizeof(struct obj)); otmp->o_id = mread32(mf); otmp->owt = mread32(mf); otmp->quan = mread32(mf); otmp->corpsenm = mread32(mf); otmp->oeaten = mread32(mf); otmp->age = mread32(mf); otmp->owornmask = mread32(mf); oflags = mread32(mf); otmp->otyp = mread16(mf); otmp->ox = mread8(mf); otmp->oy = mread8(mf); otmp->spe = mread8(mf); otmp->oclass = mread8(mf); otmp->invlet = mread8(mf); otmp->oartifact = mread8(mf); otmp->where = mread8(mf); otmp->timed = mread8(mf); otmp->cobj = mread8(mf) ? (void*)1 : NULL; /* set the pointer to 1 if there will be contents */ otmp->onamelth = namelen; otmp->cursed = (oflags >> 31) & 1; otmp->blessed = (oflags >> 30) & 1; otmp->unpaid = (oflags >> 29) & 1; otmp->no_charge = (oflags >> 28) & 1; otmp->known = (oflags >> 27) & 1; otmp->dknown = (oflags >> 26) & 1; otmp->bknown = (oflags >> 25) & 1; otmp->rknown = (oflags >> 24) & 1; otmp->oeroded = (oflags >> 22) & 3; otmp->oeroded2 = (oflags >> 20) & 3; otmp->oerodeproof = (oflags >> 19) & 1; otmp->olocked = (oflags >> 18) & 1; otmp->obroken = (oflags >> 17) & 1; otmp->otrapped = (oflags >> 16) & 1; otmp->recharged = (oflags >> 13) & 7; otmp->lamplit = (oflags >> 12) & 1; otmp->greased = (oflags >> 11) & 1; otmp->oattached = (oflags >> 9) & 3; otmp->in_use = (oflags >> 8) & 1; otmp->was_thrown = (oflags >> 7) & 1; otmp->bypass = (oflags >> 6) & 1; if (otmp->onamelth) mread(mf, ONAME(otmp), otmp->onamelth); if (otmp->oattached == OATTACHED_MONST) { struct monst *mtmp = restore_mon(mf); int monlen = sizeof(struct monst) + mtmp->mnamelth + mtmp->mxlth; otmp = realloc_obj(otmp, monlen, mtmp, otmp->onamelth, ONAME(otmp)); dealloc_monst(mtmp); } else if (otmp->oattached == OATTACHED_M_ID) { unsigned int mid = mread32(mf); otmp = obj_attach_mid(otmp, mid); } return otmp; }
int chwepon(struct obj *otmp, int amount) { const char *color = hcolor((amount < 0) ? "black" : "blue"); const char *xtime; int otyp = STRANGE_OBJECT; if (!uwep || (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))) { char buf[BUFSZ]; sprintf(buf, "Your %s %s.", makeplural(body_part(HAND)), (amount >= 0) ? "twitch" : "itch"); strange_feeling(otmp, buf); exercise(A_DEX, (boolean) (amount >= 0)); return 0; } if (otmp && otmp->oclass == SCROLL_CLASS) otyp = otmp->otyp; if (uwep->otyp == WORM_TOOTH && amount >= 0) { uwep->otyp = CRYSKNIFE; uwep->oerodeproof = 0; pline("Your weapon seems sharper now."); uwep->cursed = 0; if (otyp != STRANGE_OBJECT) makeknown(otyp); return 1; } if (uwep->otyp == CRYSKNIFE && amount < 0) { uwep->otyp = WORM_TOOTH; uwep->oerodeproof = 0; pline("Your weapon seems duller now."); if (otyp != STRANGE_OBJECT && otmp->bknown) makeknown(otyp); return 1; } if (amount < 0 && uwep->oartifact && restrict_name(uwep, ONAME(uwep))) { if (!Blind) pline("Your %s %s.", aobjnam(uwep, "faintly glow"), color); return 1; } /* there is a (soft) upper and lower limit to uwep->spe */ if (((uwep->spe > 5 && amount >= 0) || (uwep->spe < -5 && amount < 0)) && rn2(3)) { if (!Blind) pline("Your %s %s for a while and then %s.", aobjnam(uwep, "violently glow"), color, otense(uwep, "evaporate")); else pline("Your %s.", aobjnam(uwep, "evaporate")); useupall(uwep); /* let all of them disappear */ return 1; } if (!Blind) { xtime = (amount*amount == 1) ? "moment" : "while"; pline("Your %s %s for a %s.", aobjnam(uwep, amount == 0 ? "violently glow" : "glow"), color, xtime); if (otyp != STRANGE_OBJECT && uwep->known && (amount > 0 || (amount < 0 && otmp->bknown))) makeknown(otyp); } uwep->spe += amount; if (amount > 0) uwep->cursed = 0; /* * Enchantment, which normally improves a weapon, has an * addition adverse reaction on Magicbane whose effects are * spe dependent. Give an obscure clue here. */ if (uwep->oartifact == ART_MAGICBANE && uwep->spe >= 0) { pline("Your right %s %sches!", body_part(HAND), (((amount > 1) && (uwep->spe > 1)) ? "flin" : "it")); } /* an elven magic clue, cookie@keebler */ /* elven weapons vibrate warningly when enchanted beyond a limit */ if ((uwep->spe > 5) && (is_elven_weapon(uwep) || uwep->oartifact || !rn2(7))) pline("Your %s unexpectedly.", aobjnam(uwep, "suddenly vibrate")); return 1; }
struct monst * make_familiar(struct obj *otmp, xchar x, xchar y, boolean quietly) { const struct permonst *pm; struct monst *mtmp = 0; int chance, trycnt = 100; do { if (otmp) { /* figurine; otherwise spell */ int mndx = otmp->corpsenm; pm = &mons[mndx]; /* activating a figurine provides one way to exceed the maximum number of the target critter created--unless it has a special limit (erinys, Nazgul) */ if ((mvitals[mndx].mvflags & G_EXTINCT) && mbirth_limit(mndx) != MAXMONNO) { if (!quietly) /* have just been given "You <do something with> the figurine and it transforms." message */ pline("... into a pile of dust."); break; /* mtmp is null */ } } else if (!rn2(3)) { pm = &mons[pet_type(NULL)]; } else { pm = rndmonst(&u.uz, rng_t_create_monster); if (!pm) { if (!quietly) pline ("There seems to be nothing available for a familiar."); break; } } mtmp = makemon(pm, level, x, y, MM_EDOG | MM_IGNOREWATER | (otmp ? 0 : (MM_CREATEMONSTER | MM_CMONSTER_T))); if (otmp && !mtmp) { /* monster was genocided or square occupied */ if (!quietly) pline("The figurine writhes and then shatters into pieces!"); break; } } while (!mtmp && --trycnt > 0); if (!mtmp) return NULL; if (is_pool(level, mtmp->mx, mtmp->my) && minliquid(mtmp)) return NULL; initedog(mtmp); mtmp->msleeping = 0; if (otmp) { /* figurine; resulting monster might not become a pet */ chance = rn2_on_rng(10, rng_figurine_effect); /* 0: tame, 1: peaceful, 2: hostile, 3+: matching BCU; this gives an 80% chance of the desired effect, 10% of each other effect */ if (chance > 2) chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2; if (chance > 0) { mtmp->mtame = 0; /* not tame after all */ if (chance == 2) { /* hostile (cursed figurine) */ if (!quietly) pline("You get a bad feeling about this."); msethostility(mtmp, TRUE, TRUE); } } /* if figurine has been named, give same name to the monster */ if (otmp->onamelth) mtmp = christen_monst(mtmp, ONAME(otmp)); } set_malign(mtmp); /* more alignment changes */ newsym(mtmp->mx, mtmp->my); /* must wield weapon immediately since pets will otherwise drop it */ if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) { mtmp->weapon_check = NEED_HTH_WEAPON; mon_wield_item(mtmp); } return mtmp; }
/* * Allocate a new and possibly larger storage space for an obj. */ struct obj *realloc_obj(struct obj *obj, int oextra_size, void *oextra_src, int oname_size, const char *name) { struct obj *otmp; otmp = newobj(oextra_size + oname_size); *otmp = *obj; /* the cobj pointer is copied to otmp */ if (oextra_size) { if (oextra_src) memcpy(otmp->oextra, oextra_src, oextra_size); } else { otmp->oattached = OATTACHED_NOTHING; } otmp->oxlth = oextra_size; otmp->onamelth = oname_size; if (oname_size) { if (name) strcpy(ONAME(otmp), name); } /* !obj->olev means the obj is currently being restored and no pointer * from or to it is valid. Re-equipping, timer linking, etc. will happen * elsewhere in that case. */ if (obj->olev) { if (obj->owornmask) { boolean save_twoweap = u.twoweap; /* unwearing the old instance will clear dual-wield mode if this object is either of the two weapons */ setworn(NULL, obj->owornmask); setworn(otmp, otmp->owornmask); u.twoweap = save_twoweap; } /* replace obj with otmp */ replace_object(obj, otmp); /* fix ocontainer pointers */ if (Has_contents(obj)) { struct obj *inside; for (inside = obj->cobj; inside; inside = inside->nobj) inside->ocontainer = otmp; } /* move timers and light sources from obj to otmp */ otmp->timed = 0; /* not timed, yet */ if (obj->timed) obj_move_timers(obj, otmp); otmp->lamplit = 0; /* ditto */ if (obj->lamplit) obj_move_light_source(obj, otmp); /* objects possibly being manipulated by multi-turn occupations which have been interrupted but might be subsequently resumed */ if (obj->oclass == FOOD_CLASS) food_substitution(obj, otmp); /* eat food or open tin */ else if (obj->oclass == SPBOOK_CLASS) book_substitution(obj, otmp); /* read spellbook */ } else { /* make sure dealloc_obj doesn't explode */ obj->where = OBJ_FREE; obj->timed = FALSE; obj->lamplit = FALSE; } /* obfree(obj, otmp); now unnecessary: no pointers on bill */ dealloc_obj(obj); /* let us hope nobody else saved a pointer */ return otmp; }