AwakeMUD-0.8.18B/
AwakeMUD-0.8.18B/doc/
AwakeMUD-0.8.18B/lib/
AwakeMUD-0.8.18B/lib/etc/
AwakeMUD-0.8.18B/lib/etc/pfiles/
AwakeMUD-0.8.18B/lib/misc/
AwakeMUD-0.8.18B/lib/text/
AwakeMUD-0.8.18B/lib/text/help/
AwakeMUD-0.8.18B/lib/text/wizhelp/
AwakeMUD-0.8.18B/lib/veh/
AwakeMUD-0.8.18B/lib/world/
AwakeMUD-0.8.18B/lib/world/mob/
AwakeMUD-0.8.18B/lib/world/mtx/
AwakeMUD-0.8.18B/lib/world/qst/
AwakeMUD-0.8.18B/lib/world/shp/
AwakeMUD-0.8.18B/lib/world/veh/
//  file: dblist.cc
//  authors: Chris Dickey, Andrew Hynek
//  purpose: contains the ObjList functions
//  Copyright (c) 1996 by Chris Dickey,
//  some parts Copyright (c) 1998 by Andrew Hynek

#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/time.h>

#include "structs.h"
#include "awake.h"
#include "comm.h"
#include "db.h"
#include "utils.h"
#include "dblist.h"
#include "handler.h"
#include "file.h"

// extern vars
extern class helpList Help;
extern class helpList WizHelp;
//extern struct room_data *world;

// extern funcs
extern void print_object_location(int, struct obj_data *, struct char_data *, int);
#define OBJ temp->data

int objList::PrintList(struct char_data *ch, const char *arg)
{
  register nodeStruct<struct obj_data *> *temp = head;
  register int num = 0;

  for (;temp; temp = temp->next)
    if (temp->data && CAN_SEE_OBJ(ch, temp->data)
        && isname((char *)arg, temp->data->text.keywords))
      print_object_location(++num, temp->data, ch, TRUE);

  return num;
}

void objList::Traverse(void (*func)(struct obj_data *))
{
  for (nodeStruct<struct obj_data *> *temp = head; temp; temp = temp->
       next)
    func(temp->data);
}

// this function searches through the list and returns a count of objects
// with the specified virtual number.
int objList::CountObj(int num)
{
  int counter = 0;
  register nodeStruct<struct obj_data *> *temp;
  for (temp = head; temp; temp = temp->next)
    if (num == GET_OBJ_RNUM(temp->data))
      counter++;

  return counter;
}

// this function searches through the list and returns a pointer to the
// object whose object rnum matches num
struct obj_data *objList::FindObj(int num)
{
  register nodeStruct<struct obj_data *> *temp;
  for (temp = head; temp; temp = temp->next)
    if (num == GET_OBJ_RNUM(temp->data))
      return temp->data;

  return NULL;
}

// this function searches through the list and returns a pointer to the
// object whose name matches 'name' and who is the 'num'th object in the
// list
struct obj_data *objList::FindObj(struct char_data *ch, char *name, int num)
{
  register nodeStruct<struct obj_data *> *temp = head;
  register int i = 0;

  while (temp && (i <= num))
  {
    if (isname(name, temp->data->text.keywords) &&
        CAN_SEE_OBJ(ch, temp->data) &&
        (++i == num))
      return temp->data;
    temp = temp->next;
  }

  return NULL;
}

// this function updates pointers to this particular prototype--necessary
// for OLC so objects on the mud get updated with the correct values
void objList::UpdateObjs(const struct obj_data *proto, int rnum)
{
  static nodeStruct<struct obj_data *> *temp;
  static struct obj_data old;

  for (temp = head; temp; temp = temp->next)
  {
    if (temp->data->item_number == rnum) {
      old = *temp->data;
      *temp->data = *proto;
      temp->data->in_room = old.in_room;
      temp->data->item_number = rnum;
      temp->data->carried_by = old.carried_by;
      temp->data->worn_by = old.worn_by;
      temp->data->worn_on = old.worn_on;
      temp->data->in_obj = old.in_obj;
      temp->data->contains = old.contains;
      temp->data->next_content = old.next_content;
      temp->data->obj_flags.condition = old.obj_flags.condition;
      temp->data->restring = old.restring;
      temp->data->photo = old.photo;
      if (temp->data->carried_by)
        affect_total(temp->data->carried_by);
      else if (temp->data->worn_by)
        affect_total(temp->data->worn_by);
    }
  }
}

// this function runs through the list and checks the timers of each
// object, extracting them if their timers hit 0
void objList::UpdateCounters(void)
{
  static nodeStruct<struct obj_data *> *temp, *next;

  for (temp = head; temp; temp = next) {
    next = temp->next;
    if (GET_OBJ_TYPE(OBJ) == ITEM_PROGRAM && GET_OBJ_VAL(temp->data, 0) == SOFT_EVALUATE) {
      if (!GET_OBJ_VAL(OBJ, 5)) {
        GET_OBJ_VAL(OBJ, 5) = time(0);
        GET_OBJ_VAL(OBJ, 6) = GET_OBJ_VAL(OBJ, 5);
      } else if (GET_OBJ_VAL(OBJ, 5) < time(0) - SECS_PER_REAL_DAY / 2 && !(OBJ->carried_by && IS_NPC(OBJ->carried_by))) {
        GET_OBJ_VAL(OBJ, 1) -= number(0, 3);
        GET_OBJ_VAL(OBJ, 5) = time(0);
        if (GET_OBJ_VAL(OBJ, 1) < 0)
          GET_OBJ_VAL(OBJ, 1) = 0;
      }
      continue;
    }
    if (GET_OBJ_ATTEMPT(OBJ) >  0)
      GET_OBJ_ATTEMPT(OBJ)--;

    if (GET_OBJ_TYPE(OBJ) == ITEM_WORKSHOP && GET_OBJ_VAL(OBJ, 3)) {
      struct char_data *ch;
      for (ch = OBJ->in_veh ? OBJ->in_veh->people : world[OBJ->in_room].people; ch; ch = OBJ->in_veh ? ch->next_in_veh : ch->next_in_room)
        if (AFF_FLAGGED(ch, AFF_PACKING)) {
          if (!--GET_OBJ_VAL(OBJ, 3)) {
            if (GET_OBJ_VAL(OBJ, 2)) {
              send_to_char(ch, "You finish packing up %s.\r\n", GET_OBJ_NAME(OBJ));
              act("$n finishes packing up $P", FALSE, ch, 0, OBJ, TO_ROOM);
              GET_OBJ_VAL(OBJ, 2)--;
            } else {
              send_to_char(ch, "You finish setting up %s.\r\n", GET_OBJ_NAME(OBJ));
              act("$n finishes setting up $P", FALSE, ch, 0, OBJ, TO_ROOM);
              GET_OBJ_VAL(OBJ, 2)++;
            }
            AFF_FLAGS(ch).RemoveBit(AFF_PACKING);
          }
          break;
        }
      if (ch)
        continue;
      GET_OBJ_VAL(OBJ, 3) = 0;
    }
    if (GET_OBJ_TYPE(OBJ) == ITEM_DECK_ACCESSORY && GET_OBJ_VAL(OBJ, 0) == TYPE_COOKER && OBJ->contains && GET_OBJ_VAL(OBJ, 9) > 0) {
      if (--GET_OBJ_VAL(OBJ, 9) < 1) {
        struct obj_data *chip = OBJ->contains;
        act("$p beeps loudly, signalling completion.", FALSE, 0, OBJ, 0, TO_ROOM);
        if (GET_OBJ_TIMER(chip) == -1) {
          if (chip->restring)
            delete [] chip->restring;
          chip->restring = str_dup("a ruined optical chip");
        } else
          GET_OBJ_TIMER(chip) = 1;
      }
    }

    if (((GET_OBJ_TYPE(OBJ) == ITEM_GUN_CLIP && !GET_OBJ_VAL(OBJ, 9)) || (GET_OBJ_TYPE(OBJ) == ITEM_MONEY && !GET_OBJ_VAL(OBJ, 0))) 
        && ++GET_OBJ_TIMER(OBJ) == 3 && OBJ->in_room) {
      act("$p is lost on the ground.", TRUE, world[temp->data->in_room].people,
              temp->data, 0, TO_CHAR);
      next = temp->next;
      extract_obj(temp->data);
      continue;
    }
    /* anti-twink measure...no decay until there's no eq in it */
    if ( IS_OBJ_STAT(OBJ, ITEM_CORPSE) && GET_OBJ_VAL(OBJ, 4)
         && OBJ->contains != NULL )
      continue;

    if (IS_OBJ_STAT(OBJ, ITEM_CORPSE)) {
      if (GET_OBJ_TIMER(OBJ) > 1) {
        GET_OBJ_TIMER(OBJ)--;
      } else {
        if (OBJ->carried_by)
          act("$p decays in your hands.", FALSE, temp->data->carried_by,
              temp->data, 0, TO_CHAR);
        else if (temp->data->worn_by)
          act("$p decays in your hands.", FALSE, temp->data->worn_by,
              temp->data, 0, TO_CHAR);
        else if ((temp->data->in_room != NOWHERE) &&
                 (world[temp->data->in_room].people)) {
          act("$p is taken away by the coroner.", TRUE, world[temp->data->in_room].people,
              temp->data, 0, TO_ROOM);
          act("$p is taken away by the coroner.", TRUE, world[temp->data->in_room].people,
              temp->data, 0, TO_CHAR);
        }
        // here we make sure to remove all items from the object
        struct obj_data *next_thing, *temp2;
        for (temp2 = temp->data->contains; temp2; temp2 = next_thing) {
          next_thing = temp2->next_content;     /*Next in inventory */
          extract_obj(temp2);
        }
        next = temp->next;
        extract_obj(temp->data);
      }
    }
  }
}

// this function updates the objects in the list whose real numbers are
// greater than num--necessary for olc--but maybe obsolete once the new
// structures come into effect
void objList::UpdateNums(int num)
{
  register nodeStruct<struct obj_data *> *temp;
  // just loop through the list and update
  for (temp = head; temp; temp = temp->next)
    if (GET_OBJ_RNUM(temp->data) >= num)
      GET_OBJ_RNUM(temp->data)++;
}

/* this function goes through each object, and if it has a spec, calls it */
void objList::CallSpec()
{
  nodeStruct<struct obj_data *> *temp;

  for (temp = head; temp; temp = temp->next)
    if (GET_OBJ_SPEC(temp->data) != NULL)
      GET_OBJ_SPEC(temp->data) (NULL, temp->data, 0, "");
}

void objList::RemoveObjNum(int num)
{
  nodeStruct<struct obj_data *> *temp, *next;

  for (temp = head; temp; temp = next) {
    next = temp->next;

    if (GET_OBJ_RNUM(temp->data) == num) {
      if (temp->data->carried_by)
        act("$p disintegrates.", FALSE, temp->data->carried_by,
            temp->data, 0, TO_CHAR);
      else if (temp->data->worn_by)
        act("$p disintegrates.", FALSE, temp->data->carried_by,
            temp->data, 0, TO_CHAR);
      else if (temp->data->in_room != NOWHERE && world[temp->data->in_room].people) {
        act("$p disintegrates.", TRUE, world[temp->data->in_room].people,
            temp->data, 0, TO_ROOM);
        act("$p disintegrates.", TRUE, world[temp->data->in_room].people,
            temp->data, 0, TO_CHAR);
      }
      extract_obj(temp->data);
    }
  }
}

void objList::RemoveQuestObjs(int id)
{
  nodeStruct<struct obj_data *> *temp, *next;

  for (temp = head; temp; temp = next) {
    next = temp->next;

    if (temp->data->obj_flags.quest_id == id)
      extract_obj(temp->data);
  }
}

void helpList::CreateIndex(bool wiz)
{
  DIR *directory;
  FILE *fl;
  struct dirent *dirEntry;

  if (wiz)
    directory = opendir(WIZHELP_FILE);
  else
    directory = opendir(HELP_PAGE_FILE);
  if (!directory) {
    log("Help directory not found. Continuing anyway.");
    return;
  }
  while ((dirEntry = readdir(directory))) {
    if (dirEntry->d_name[0] != '.') {
      struct help_index_data *help;
      sprintf(buf, "%s/%s", wiz ? WIZHELP_FILE : HELP_PAGE_FILE, dirEntry->d_name);
      help = new help_index_data;
      fl = fopen(buf, "r");
      get_line(fl, buf2);
      help->keyword = str_dup(buf2);
      fclose(fl);
      help->filename = str_dup(buf);
      if (wiz)
        WizHelp.ADD(help);
      else
        Help.ADD(help);
    }
  }
  closedir(directory);
  nodeStruct<struct help_index_data *> *temp, *temp2, *temp3, *last = NULL, *last1 = NULL, *next;
  for (temp2 = head; temp2 && next->next; temp2 = next) {
    next = temp2->next;
    if (str_cmp(temp2->data->keyword[0] == '"' ? temp2->data->keyword+1 : temp2->data->keyword,
                next->data->keyword[0] == '"' ? next->data->keyword+1 : next->data->keyword) > 0) {
      last = NULL;
      for (temp3 = head; temp3; temp3 = temp3->next) {
        if (str_cmp(temp2->data->keyword[0] == '"' ? temp2->data->keyword+1 : temp2->data->keyword,
                    temp3->data->keyword[0] == '"' ? temp3->data->keyword+1 : temp3->data->keyword) < 0) {
          if (last1 && temp2->data != head->data)
            last1->next = temp2->next;
          else
            head = temp2->next;
          REMOVE_FROM_LIST(head, temp2, next);
          if (last)
            last->next = temp2;
          temp2->next = temp3;
          next = head;
          break;
        }
        last = temp3;
      }
    }
    last1 = temp2;
  }
}
void helpList::RebootIndex(bool wiz)
{
  nodeStruct<struct help_index_data *> *temp, *next;
  for (temp = head; temp; temp = next) {
    next = temp->next;
    if (wiz)
      WizHelp.RemoveItem(temp);
    else
      Help.RemoveItem(temp);
  }
  if (wiz)
    WizHelp.CreateIndex(TRUE);
  else
    Help.CreateIndex(FALSE);
}

void helpList::ListIndex(struct char_data *ch, char *letter)
{
  nodeStruct<struct help_index_data *> *temp;
  FILE *fl;
  int i = 0;
  sprintf(buf2, "The following help topics are available:\r\n");
  for (temp = head; temp; temp = temp->next)
  {
    fl = fopen(temp->data->filename, "r");
    get_line(fl, buf);
    fclose(fl);
    sprintf(ENDOF(buf2), "%-30s", buf);
    if (++i == 3) {
      strcat(buf2, "\r\n");
      i = 0;
    }
  }
  page_string(ch->desc, buf2, 1);
}

bool helpList::FindTopic(char *help, char *arg)
{
  nodeStruct<struct help_index_data *> *temp;
  for (temp = head; temp; temp = temp->next) {
    if (*temp->data->keyword == '\"' ? !strn_cmp(temp->data->keyword+1, arg, strlen(arg)) : isname(arg, temp->data->keyword)) {
      File fl(temp->data->filename, "r");
      if (fl.IsOpen()) {
        char tempc[256];
        fl.GetLine(tempc, 256, FALSE);
        sprintf(buf, "^W%s^n\r\n", temp->data->keyword);
        while (fl.GetLine(tempc, 256, TRUE))
          sprintf(ENDOF(buf), "%s\r\n", tempc);
        strcpy(help, buf);
        fl.Close();
        return TRUE;
      }
    }
  }
  return FALSE;
}