                                 OBJECT TIMERS

Standard Diku does not support items crumbling as I had said, but it
does in fact support AFF_ bits set on items. At any rate, I've pulled
out my code that does support timers on items, and included
instructions for installing it. I can't be positive that the lines
that I tell you to look for are correct, since my copies of Circle
have been mangled pretty bad, and I don't have the patience to get a
new copy at 1200 baud. The new code below was pulled from my copy of
Circle 2.01, and should work fine with 2.2, and probably 3.0.

Step 1: Go into db.c and look for the following lines in
load_objects():

         for (; (j < MAX_OBJ_AFFECT); j++) {
            obj_proto[i].affected[j].location = APPLY_NONE;
            obj_proto[i].affected[j].modifier = 0;
         }

After these, add:

         if (*chk == 'F') {
            fscanf(obj_f, " %d %d \n", &tmp, &tmp2);
            obj_proto[i].obj_flags.bitvector = tmp;
            obj_proto[i].obj_flags.timer = tmp2;
            fscanf(obj_f, " %s \n", chk);
         }

At this point, you can add flag lines to your object files by going to
the very end of the object (after the Affected values if you have
them) and adding a single line of the form:

   F <bitvector> <timer>

The bitvector corresponds to the AFF_ values in structs.h, and
whenever this item is worn, these AFF_ bits will be set. At this
point, the timer does not work yet. To get it to work:

Step 2: Go into handler.c and look for void update_object(). Change it
to look somewhat like the following code:

void crumble_obj(struct char_data *ch, struct obj_data *obj)
{
   struct obj_data *loop;
   int index;

   if (obj->in_room != NOWHERE) {               /* In a room */
      if (world[obj->in_room].people) {
         act("A quivering horde of maggots consumes $p.",
           TRUE, world[obj->in_room].people, obj, 0, TO_ROOM);
         act("A quivering horde of maggots consumes $p.",
           TRUE, world[obj->in_room].people, obj, 0, TO_CHAR);
         for(loop = obj->contains; loop; loop = obj->contains) {
            obj_from_obj(loop);
            obj_to_room(loop, obj->in_room);
         }
      }
   } else if (!obj->in_obj) {                   /* Worn or inventory */
      act("$p decays in your hands.", FALSE, ch, obj, 0, TO_CHAR);
      for(loop = obj->contains; loop; loop = obj->contains) {
         obj_from_obj(loop);
         obj_to_char(loop, ch);
      }
      if (!obj->carried_by)
         for(index = 0; index < MAX_WEAR; index++)
            if (ch->equipment[index] == obj)
               obj = unequip_char(ch, index);
   } else                                       /* In an object */
      for(loop = obj->contains; loop; loop = obj->contains) {
         obj_from_obj(loop);
         obj_to_obj(loop, obj->in_obj);
      }
   extract_obj(obj);
}

void update_object(struct char_data *ch, struct obj_data *obj, int use)
{

   if (obj->next_content)
      update_object(ch, obj->next_content, use);
   if (obj->contains)
      update_object(ch, obj->contains, use);
   if (obj->obj_flags.timer > 0)
      if ((obj->obj_flags.timer -= use) < 1)
         crumble_obj(ch, obj);
}

Step 3: Go down to update_char_objects() (in the same file) and modify
the calls to update_object() so that they look like

   update_object(ch, ch->equipment[i], 2)

and

   update_object(ch, ch->carrying, 1)

Step 4: Go into limits.c and look for void point_update(). There's a
set of code that looks like:

      if (!IS_NPC(i)) {
         update_char_objects(i);
         if (GET_LEVEL(i) < LEVEL_GOD)
            check_idling(i);
      }

Change the ifs to match the ones below:

      if (!IS_NPC(i) || IS_AFFECTED(i, AFF_CHARM)) {
         update_char_objects(i);
         if (!IS_NPC(i) && (GET_LEVEL(i) < LEVEL_GOD))
            check_idling(i);
      }

Step 5: Further down in point update there's a loop that starts with
for(j = object_list; j; j = next_thing) {. Delete everything between
this for() statement and its closing bracket, and insert this as the
loop contents:

      next_thing = j->next; /* Next in object list */

      if (j->in_room == NOWHERE)
         continue;

      if ((GET_ITEM_TYPE(j) != ITEM_CONTAINER) || (!j->obj_flags.value[3]))
         continue;

      if (j->obj_flags.timer > 0)
         if (!(--j->obj_flags.timer))
            crumble_obj(0, j);

And there you go. If the timer is set > 0 in the object file, the
objects will deteriorate by 1 if in a PC's inventory (or in a PCs
bag), and by 2 if equipped. Since I have experience with running a MUD
with this code, I think I ought to give a warning: Objects with any of
the AFF_ bits can be extremely powerful and should be quite rare. Of
course, you could set a timer on the object and hope it crumbles as
they walk in on the dracolich...
