// 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; }