// 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 "structs.h"
#include "awake.h"
#include "comm.h"
#include "db.h"
#include "utils.h"
#include "dblist.h"
#include "handler.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);
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(temp->data) == ITEM_PROGRAM && GET_OBJ_VAL(temp->data, 0) == SOFT_EVALUATE) {
if (!GET_OBJ_VAL(temp->data, 5)) {
GET_OBJ_VAL(temp->data, 5) = time(0);
GET_OBJ_VAL(temp->data, 6) = GET_OBJ_VAL(temp->data, 5);
} else if (GET_OBJ_VAL(temp->data, 5) < time(0) - SECS_PER_REAL_DAY / 2 && !(temp->data->carried_by && IS_NPC(temp->data->carried_by))) {
GET_OBJ_VAL(temp->data, 1) -= number(0, 3);
GET_OBJ_VAL(temp->data, 5) = time(0);
if (GET_OBJ_VAL(temp->data, 1) < 0)
GET_OBJ_VAL(temp->data, 1) = 0;
}
continue;
}
if (GET_OBJ_TYPE(temp->data) == ITEM_WORKSHOP && GET_OBJ_VAL(temp->data, 2)) {
struct char_data *ch;
for (ch = world[temp->data->in_room].people; ch; ch = ch->next_in_room)
if (PLR_FLAGGED(ch, PLR_PACKING)) {
GET_OBJ_VAL(temp->data, 2)--;
if (!GET_OBJ_VAL(temp->data, 2)) {
if (GET_OBJ_VAL(temp->data, 1)) {
send_to_char(ch, "You finish packing up %s.\r\n", temp->data->text.name);
act("$n finishes packing up $o", FALSE, ch, 0, temp->data, TO_ROOM);
GET_OBJ_VAL(temp->data, 1)--;
} else {
send_to_char(ch, "You finish setting up %s.\r\n", temp->data->text.name);
act("$n finishes setting up $o", FALSE, ch, 0, temp->data, TO_ROOM);
GET_OBJ_VAL(temp->data, 1)++;
}
PLR_FLAGS(ch).RemoveBit(PLR_PACKING);
}
break;
}
if (ch)
continue;
GET_OBJ_VAL(temp->data, 2) = 0;
}
/* anti-twink measure...no decay until there's no eq in it */
if ( IS_OBJ_STAT(temp->data, ITEM_CORPSE) && GET_OBJ_VAL(temp->data, 4)
&& temp->data->contains != NULL )
continue;
if (IS_OBJ_STAT(temp->data, ITEM_CORPSE)) {
if (GET_OBJ_TIMER(temp->data) > 1) {
GET_OBJ_TIMER(temp->data)--;
} else {
if (temp->data->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 crumbles into dust.", TRUE, world[temp->data->in_room].people,
temp->data, 0, TO_ROOM);
act("$p crumbles into dust.", 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);
}
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(buf2, "%s%30s", buf2, buf);
if (++i == 3) {
send_to_char(ch, buf2);
send_to_char(ch, "\r\n");
buf2[0] = '\0';
i = 0;
}
}
}
bool helpList::FindTopic(char *help, char *arg)
{
nodeStruct<struct help_index_data *> *temp;
FILE *fl;
for (temp = head; temp; temp = temp->next) {
if (isname(arg, temp->data->keyword)) {
fl = fopen(temp->data->filename, "r");
if (fl) {
get_line(fl, help);
sprintf(buf, "^W%s^n\r\n", temp->data->keyword);
while (get_line(fl, buf2)) {
strcat(buf, buf2);
strcat(buf, "\r\n");
}
strcpy(help, buf);
fclose(fl);
return TRUE;
}
}
}
return FALSE;
}