// 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 "structs.h"
#include "awake.h"
#include "comm.h"
#include "db.h"
#include "utils.h"
#include "dblist.h"
#include "handler.h"
// extern vars
extern struct room_data *world;
// extern funcs
extern void print_object_location(int, struct obj_data *, struct char_data *, int);
extern int isname(char *str, char *namelist);
int objList::PrintList(struct char_data *ch, const char *arg)
{
register nodeStruct<struct obj_data *> *temp = head, *next;
register int num = 0;
bool ground = FALSE;
ground = !strcmp( arg, "ground" );
while (temp) {
next = temp->next;
if (!temp->data->name) {
if (temp->data->item_number) {
sprintf(buf, "Object #%d has no name.", temp->data->item_number);
log(buf);
} else {
log("Object with no name and no number...deleting from list:");
sprintf(buf, "#:%d, R:%d, T:%d, W:%d, E:%d, Wt:%d, C:%d\n"
"M:%d, B:%d, Sd:%s, D:%s, Ld:%s\r\n"
"0:%d, 1:%d, 2:%d, 3:%d, 4:%d, 5:%d, 6:%d, 7:%d, 8:%d, 9:%d\r\n",
temp->data->item_number, temp->data->in_room,
GET_OBJ_TYPE(temp->data), GET_OBJ_WEAR(temp->data),
GET_OBJ_EXTRA(temp->data), GET_OBJ_WEIGHT(temp->data),
GET_OBJ_COST(temp->data), GET_OBJ_MATERIAL(temp->data),
GET_OBJ_BARRIER(temp->data), temp->data->short_description,
temp->data->description, temp->data->long_description,
GET_OBJ_VAL(temp->data, 0), GET_OBJ_VAL(temp->data, 1),
GET_OBJ_VAL(temp->data, 2), GET_OBJ_VAL(temp->data, 3),
GET_OBJ_VAL(temp->data, 4), GET_OBJ_VAL(temp->data, 5),
GET_OBJ_VAL(temp->data, 6), GET_OBJ_VAL(temp->data, 7),
GET_OBJ_VAL(temp->data, 8), GET_OBJ_VAL(temp->data, 9));
log(buf);
if (temp->data->worn_by)
act("$p suddenly disappears.", FALSE, temp->data->worn_by,
temp->data, 0, TO_CHAR);
else if (temp->data->carried_by)
act("$p suddenly disappears.", FALSE, temp->data->carried_by,
temp->data, 0, TO_CHAR);
else if (temp->data->in_room > 0) {
sprintf(buf, "%s suddenly disappears.\r\n", temp->data->short_description);
send_to_room(buf, temp->data->in_room);
}
extract_obj(temp->data);
}
} else if (CAN_SEE_OBJ(ch, temp->data)
&& (isname((char *)arg, temp->data->name)
|| (ground
&& temp->data->carried_by == NULL
&& temp->data->in_obj == NULL
&& temp->data->worn_by == NULL
&& temp->data->in_room > 0
&& (temp->data->in_room < 320||temp->data->in_room>=421))))
print_object_location(++num, temp->data, ch, TRUE);
temp = next;
}
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 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 struct nodeStruct<struct obj_data *> *temp = head;
register int i = 0;
while (temp && (i <= num)) {
if (isname(name, temp->data->name) && 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 struct 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;
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;
/* 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) == 1
&& temp->data->contains != NULL )
continue;
// only corpses and immloaded items usually have timers
if (IS_OBJ_STAT(temp->data, ITEM_CORPSE) || IS_OBJ_STAT(temp->data, ITEM_IMMLOAD)) {
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 */
if (!(IS_OBJ_STAT(temp->data, ITEM_CORPSE) &&
!GET_OBJ_VAL(temp->data, 4) && GET_OBJ_TYPE(temp2) != ITEM_MONEY)) {
obj_from_obj(temp2);
if (temp->data->in_obj)
obj_to_obj(temp2, temp->data->in_obj);
else if (temp->data->carried_by)
obj_to_room(temp2, temp->data->carried_by->in_room);
else if (temp->data->worn_by)
obj_to_room(temp2, temp->data->worn_by->in_room);
else if (temp->data->in_room != NOWHERE)
obj_to_room(temp2, temp->data->in_room);
else assert(FALSE);
} else extract_obj(temp2);
}
next = temp->next; // just to make sure...
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::RemoveObjs()
{
nodeStruct<struct obj_data *> *temp = head, *last;
while (temp) {
last = temp->next;
if (from_ip_zone(GET_OBJ_VNUM(temp->data)) ||
IS_OBJ_STAT(temp->data, ITEM_VOLATILE)) {
if (temp->data->carried_by
&& !IS_NPC(temp->data->carried_by)
&& GET_LEVEL(temp->data->carried_by) < LVL_LEGEND) {
act("$p decays into nothing.", FALSE, temp->data->carried_by,
temp->data, 0, TO_CHAR);
extract_obj(temp->data);
} else if (temp->data->worn_by && !IS_NPC(temp->data->worn_by) &&
GET_LEVEL(temp->data->worn_by) < LVL_LEGEND) {
act("$p decays into nothing.", FALSE, temp->data->carried_by,
temp->data, 0, TO_CHAR);
extract_obj(temp->data);
}
}
temp = last;
}
}
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);
}
}