// $Id: room.cc,v 1.27.2.20 2000/05/03 02:25:13 justin Exp $ // $Revision: 1.27.2.20 $ $Author: justin $ $Date: 2000/05/03 02:25:13 $ // //ScryMUD Server Code //Copyright (C) 1998 Ben Greear // //This program is free software; you can redistribute it and/or //modify it under the terms of the GNU General Public License //as published by the Free Software Foundation; either version 2 //of the License, or (at your option) any later version. // //This program is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with this program; if not, write to the Free Software //Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // To contact the Author, Ben Greear: greear@cyberhighway.net, (preferred) // greearb@agcs.com // //**********************************************************************// ///************************ room ********************************/// #include "door.h" #include "room.h" #include "misc.h" #include "misc2.h" #include "battle.h" #include <PtrArray.h> #include "const.h" #include "zone.h" #include "load_wld.h" #include "Filters.h" int KeywordPair::_cnt = 0; void KeywordPair::show(int idx, critter& pc) { String buf(100); Sprintf(buf, "Keyword [%i] ", idx); Cell<String*> cll(names); String* ptr; while ((ptr = cll.next())) { buf.Append(*ptr); buf.Append(" "); }//while buf.Append("\n\n"); pc.show(buf); pc.show("\n"); pc.show(desc); pc.show("\n"); if (pc.isUsingClient()) { Sprintf(buf, "<KEYWORD %i ", idx); names.head(cll); while ((ptr = cll.next())) { buf.Append(*ptr); buf.Append(" "); }//while buf.Append(">\n"); pc.show(buf); pc.show("<KEYWORD_DESC>"); pc.show(desc); pc.show("</KEYWORD_DESC>"); }//if }//show int KeywordPair::isNamed(const String* name) { Cell<String*> cll(names); String* ptr; while ((ptr = cll.next())) { if (strncasecmp(*name, *ptr, name->Strlen()) == 0) { return TRUE; }//if }//while return FALSE; }//isNamed void KeywordPair::clear() { clear_ptr_list(names); desc.Clear(); } KeywordPair::~KeywordPair() { _cnt--; clear(); } KeywordPair::KeywordPair(const KeywordPair& src) { _cnt++; *this = src; } KeywordPair& KeywordPair::operator=(const KeywordPair& rhs) { if (&rhs != this) { clear(); Cell<String*> cll(rhs.names); String* ptr; while ((ptr = cll.next())) { names.append(new String(*ptr)); } desc = rhs.desc; }//if return *this; }//operator= void KeywordPair::write(ofstream& dafile) { Cell<String*> cll(names); String* ptr; while ((ptr = cll.next())) { dafile << *ptr << " "; }//while dafile << "~" << endl; dafile << desc << "\n~\n"; }//write void KeywordPair::read(ifstream& dafile) { String buf(80); char buf2[100]; while (TRUE) { dafile >> buf; if (strcmp(buf, "~") == 0) { dafile.getline(buf2, 79); break; } else { names.append(new String(buf)); } }//while desc.Termed_Read(dafile); }//read KeywordPair* room::haveKeyword(int i_th, const String* name) { int foo = 0; return haveKeyword(i_th, name, foo); } KeywordPair* room::haveKeyword(int i_th, const String* name, int& count_sofar) { int cnt = 0; Cell<KeywordPair*> cll(keywords); KeywordPair* ptr; while ((ptr = cll.next())) { if (ptr->isNamed(name)) { cnt++; count_sofar++; if (cnt == i_th) { return ptr; } }//if }//while return NULL; }//haveKeyword int room::_cnt = 0; room::room() { _cnt++; for (int i = 0; i<ROOM_CUR_STATS; i++) { cur_stats[i] = 0; } setVisBit(1024); //hack, forgot 'normal' vis bit earlier pause = 0; obj_ptr_log << "RM_CON " << getIdNum() << " " << this << "\n"; } // sub_room constructor room::room(int rm_num) { _cnt++; for (int i = 0; i<ROOM_CUR_STATS; i++) { cur_stats[i] = 0; } cur_stats[2] = rm_num; setVisBit(1024); //hack, forgot 'normal' vis bit earlier pause = 0; obj_ptr_log << "RM_CON_I " << getIdNum() << " " << this << "\n"; } // sub_room constructor int room::makeReadyForAreaSpell() { Cell<critter*> cll(critters); critter* ptr; while ((ptr = cll.next())) { ptr->CRIT_FLAGS.turn_off(20); } return 0; } critter* room::findNextSpellCritter() { Cell<critter*> cll(critters); critter* ptr; while ((ptr = cll.next())) { if (!ptr->CRIT_FLAGS.get(20)) { //if spell_tested ptr->CRIT_FLAGS.turn_on(20); return ptr; }//if not affected yet }//while return NULL; }//findNextSpellCritter critter* room::findNextProcMob() { Cell<critter*> cll(critters); critter* ptr; while ((ptr = cll.next())) { if (!(ptr->pc)) { if (ptr->mob) { if (!ptr->master) { if (ptr->MOB_FLAGS.get(3)) { ptr->MOB_FLAGS.turn_off(3); return ptr; }//if haven't done procs yet }//if }//if a mob }//needed if obj has BOTH mob and pc data fields }//while return NULL; }//findNextProcMob void room::recursivelyLoad() { //mobs and objects Cell<critter*> ccll(critters); critter* cptr; while ((cptr = ccll.next())) { recursive_init_loads(*cptr); cptr->incrementCurInGame(); //recursive_... no longer does it. }//while Cell<object*> ocll(inv); object* optr; while ((optr = ocll.next())) { recursive_init_loads(*optr, 0); }//while }//recursivelyLoad() room::room(room& source) { _cnt++; *this = source; //overloaded = operator obj_ptr_log << "RM_CC " << getIdNum() << " " << this << "\n"; } // sub_room copy constructor room::~room() { _cnt--; obj_ptr_log << "RM_DES " << getIdNum() << " " << this << "\n"; if (!do_shutdown) { affected_rooms.loseData(this); pulsed_proc_rooms.loseData(this); embattled_rooms.loseData(this); }//if Clear(); }//sub_room deconstructor room& room::operator=(room& source) { if (this == &source) return *this; Cell<stat_spell_cell*> cell; stat_spell_cell *tmp_stat, *tmp_stat2; int i; String* string; Cell<String*> cll(source.names); Cell<object*> obj_cll; object* obj_ptr; Cell<critter*> crit_cll; critter* crit_ptr; //mudlog.log(DBG, "In rm operator= overload.\n"); Clear(); //clear this thing out!! while ((string = cll.next())) { Put(new String(*(string)), names); }//while short_desc = source.short_desc; long_desc = source.long_desc; room_flags = source.room_flags; Cell<KeywordPair*> kcll(source.keywords); KeywordPair* kptr; while ((kptr = kcll.next())) { keywords.append(new KeywordPair(*kptr)); } for (i = 0; i<ROOM_CUR_STATS; i++) { cur_stats[i] = source.cur_stats[i]; } clear_ptr_list(affected_by); source.affected_by.head(cell); while ((tmp_stat = cell.next())) { tmp_stat2 = new stat_spell_cell; *tmp_stat2 = *tmp_stat; //shallow copy should work affected_by.append(tmp_stat2); }//while source.inv.head(obj_cll); while ((obj_ptr = obj_cll.next())) { if (!obj_ptr->IN_LIST) { //no multiple ptrs to SOBJ's inv.append(obj_ptr); }//if }//while Cell<door*> dcell(source.doors); door* dptr; while ((dptr = dcell.next())) { doors.append(new door(*dptr)); }//while source.critters.head(crit_cll); while ((crit_ptr = crit_cll.next())) { if (crit_ptr->isMob()) { //only copy MOB's gainCritter(crit_ptr); //will increment cur_in_game }//if }//while Cell<RoomScript*> script_cll(room_proc_scripts); RoomScript* script_ptr; while ((script_ptr = script_cll.next())) { room_proc_scripts.append(new RoomScript(*script_ptr)); } // Don't copy pending scripts. return *this; }//room::operator= overload void room::Clear() { int i; if (mudlog.ofLevel(TRC)) { mudlog << "room::Clear..." << endl; } clear_ptr_list(names); short_desc.Clear(); long_desc.Clear(); room_flags.Clear(); clear_ptr_list(keywords); for (i = 0; i<ROOM_CUR_STATS; i++) { cur_stats[i] = 0; } clear_ptr_list(affected_by); clear_obj_list(inv); // Assume here that the mob is only on the affected_mobs list. // Otherwise, have to do a better cleanup to get em out of the game // cleanly. critter* tmp; while (!critters.isEmpty()) { tmp = critters.peekFront(); removeCritter(tmp); //decrement cur_in_game if (tmp->isSmob()) { affected_mobs.loseData(tmp); delete tmp; } }//while clear_ptr_list(doors); //doors.clear(); if (mudlog.ofLevel(TRC)) { mudlog << "room::Clear... DONE." << endl; } clear_ptr_list(pending_scripts); clear_ptr_list(room_proc_scripts); cur_script = NULL; // points into the pending_scripts pause = 0; }// Clear #ifdef USEMYSQL void room::dbRead(int room_num, short read_all) { int quantity, obj_num, sobj_num, mob_num; MYSQL_RES* result; MYSQL_ROW row; String query="select * from Rooms where ROOM_NUM="; query += room_num; Clear(); if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if row=mysql_fetch_row(result); short_desc = row[ROOMTBL_SHORT_DESC]; long_desc = row[ROOMTBL_LONG_DESC]; cur_stats[0] = atoi(row[ROOMTBL_VIS_BIT]); cur_stats[1] = atoi(row[ROOMTBL_MOVEMENT_COST]); cur_stats[2] = atoi(row[ROOMTBL_ROOM_NUM]); cur_stats[3] = atoi(row[ROOMTBL_FALL_TO]); room_flags.set(ROOMFLAG_NO_RESTRICTIONS, atoi(row[ROOMTBL_NO_RESTRICTIONS])); room_flags.set(ROOMFLAG_NO_IMM, atoi(row[ROOMTBL_NO_IMM])); room_flags.set(ROOMFLAG_NO_GOD, atoi(row[ROOMTBL_NO_GOD])); room_flags.set(ROOMFLAG_IS_PERM_DARK, atoi(row[ROOMTBL_IS_PERM_DARK])); room_flags.set(ROOMFLAG_WEATHER, atoi(row[ROOMTBL_WEATHER])); room_flags.set(ROOMFLAG_NO_SHOUT, atoi(row[ROOMTBL_NO_SHOUT])); room_flags.set(ROOMFLAG_NO_MAGICAL_EXIT, atoi(row[ROOMTBL_NO_MAGICAL_EXIT])); room_flags.set(ROOMFLAG_IS_HAVEN, atoi(row[ROOMTBL_IS_HAVEN])); room_flags.set(ROOMFLAG_NO_PK, atoi(row[ROOMTBL_NO_PK])); room_flags.set(ROOMFLAG_NO_MAGIC, atoi(row[ROOMTBL_NO_MAGIC])); room_flags.set(ROOMFLAG_NO_MOB, atoi(row[ROOMTBL_NO_MOB])); room_flags.set(ROOMFLAG_NO_POTIONS, atoi(row[ROOMTBL_NO_POTIONS])); room_flags.set(ROOMFLAG_NO_STAFFS, atoi(row[ROOMTBL_NO_STAFFS])); room_flags.set(ROOMFLAG_NO_MORTALS, atoi(row[ROOMTBL_NO_MORTALS])); room_flags.set(ROOMFLAG_NORMALLY_DARK, atoi(row[ROOMTBL_NORMALLY_DARK])); room_flags.set(ROOMFLAG_SHALLOW_WATER, atoi(row[ROOMTBL_SHALLOW_WATER])); room_flags.set(ROOMFLAG_DEEP_WATER, atoi(row[ROOMTBL_DEEP_WATER])); room_flags.set(ROOMFLAG_SWAMP, atoi(row[ROOMTBL_SWAMP])); room_flags.set(ROOMFLAG_NEED_FLY, atoi(row[ROOMTBL_NEED_FLY])); room_flags.set(ROOMFLAG_NEED_BOAT, atoi(row[ROOMTBL_NEED_BOAT])); room_flags.set(ROOMFLAG_NEED_CLIMB, atoi(row[ROOMTBL_NEED_CLIMB])); room_flags.set(ROOMFLAG_NO_MAGICAL_ENTRY, atoi(row[ROOMTBL_NO_MAGICAL_ENTRY])); room_flags.set(ROOMFLAG_NO_VEHICLES, atoi(row[ROOMTBL_NO_VEHICLES])); room_flags.set(ROOMFLAG_CRAMPED, atoi(row[ROOMTBL_CRAMPED])); room_flags.set(ROOMFLAG_NO_RANGED_ATTACK, atoi(row[ROOMTBL_NO_RANGED_ATTACK])); room_flags.set(ROOMFLAG_NEED_DIVE, atoi(row[ROOMTBL_NEED_DIVE])); room_flags.set(ROOMFLAG_USED_IN_TRACK, atoi(row[ROOMTBL_USED_IN_TRACK])); room_flags.set(ROOMFLAG_CAN_CAMP, atoi(row[ROOMTBL_CAN_CAMP])); room_flags.set(ROOMFLAG_HAS_KEYWORDS, atoi(row[ROOMTBL_HAS_KEYWORDS])); room_flags.set(ROOMFLAG_NO_WANDERING_MOBS, atoi(row[ROOMTBL_NO_WANDERING_MOBS])); room_flags.set(ROOMFLAG_NO_FOREIGN_WANDERING_MOBS, atoi(row[ROOMTBL_NO_FOREIGN_WANDERING_MOBS])); room_flags.set(ROOMFLAG_HAS_PROC_SCRIPT, atoi(row[ROOMTBL_HAS_PROC_SCRIPT])); mysql_free_result(result); } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if return; } // else // names query="select NAME from RoomNames where ROOM_NUM="; query+=room_num; if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if while ((row=mysql_fetch_row(result))) { Put(new String(row[0]), names); } // while mysql_free_result(result); } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if return; } // else // inventory query="select OBJ_NUM, SOBJ_NUM, QUANTITY from RoomInv where ROOM_NUM="; query+=room_num; if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if while ((row=mysql_fetch_row(result))) { obj_num = atoi(row[0]); sobj_num = atoi(row[1]); quantity = atoi(row[2]); for (;quantity > 0; quantity--) { if (check_l_range(obj_num, 0, NUMBER_OF_ITEMS, mob_list[0], FALSE)) { if (obj_list[obj_num].isInUse()) { if (read_all || ((obj_list[obj_num].OBJ_PRCNT_LOAD * config.currentLoadModifier)/100) > d(1,100)) { if (obj_list[obj_num].isPlayerOwned()) { object* po_sack = load_player_box(obj_num); if (po_sack) { po_sack->IN_LIST = &(inv); po_sack->setCurRoomNum(getIdNum(), 0); affected_objects.gainData(po_sack); gainInv(po_sack); } // if } // if else { gainInv(&(obj_list[obj_num])); } // else } // if } // if else { if (mudlog.ofLevel(ERROR)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "ERROR: Trying to load non-existant object" << obj_num << " in room " << room_num << ".\n"; } // if } // else } // if } // for } // while mysql_free_result(result); } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if return; } // else // doors query="select EXIT_NUM, DOOR_NUM, DESTINATION, DISTANCE from RoomExits "; query+="where ROOM_NUM="; query+=room_num; if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if Cell<door*> cll; door* dr_ptr; door* walker; short did_insert = FALSE; while ((row=mysql_fetch_row(result))) { dr_ptr = new door; dr_ptr->destination = atoi(row[2]); dr_ptr->distance = atoi(row[3]); dr_ptr->dr_data = &(door_list[atoi(row[1])]); dr_ptr->in_room = room_num; MYSQL_RES* tmp_res; MYSQL_ROW tmp_row; String tmp_qry="select SPELL_NUM, DURATION from RoomExitSplls "; tmp_qry+="where ROOM_NUM="; tmp_qry+=room_num; tmp_qry+=" and EXIT_NUM="; tmp_qry+=atoi(row[0]); if (mysql_real_query(database, tmp_qry, strlen(tmp_qry))==0) { if ((tmp_res=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In door::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if while ((tmp_row=mysql_fetch_row(result))) { Put(new stat_spell_cell(atoi(row[0]), atoi(row[1])), dr_ptr->affected_by); } // while } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In door::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if } // else mysql_free_result(tmp_res); doors.head(cll); String* dr_name = name_of_door(*dr_ptr, ~0); String* walk_name; while ((walker = cll.next())) { walk_name = name_of_door(*walker, ~0); if (*walk_name > *dr_name) { doors.insertBefore(cll, dr_ptr); did_insert=TRUE; break; } // if } // while if (!did_insert) doors.append(dr_ptr); } // while mysql_free_result(result); } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if return; } // else // critters query="select MOB_NUM, QUANTITY from RoomMobs where ROOM_NUM="; query+=room_num; if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if while ((row=mysql_fetch_row(result))) { mob_num = atoi(row[0]); if (mob_list[mob_num].isInUse()) { if (mob_list[mob_num].isPlayerShopKeeper()) { critter* shop_owner = load_player_shop_owner(mob_num); if (shop_owner) { shop_owner->setCurRoomNum(room_num); gainCritter(shop_owner); } // if } // if else { gainCritter(&(mob_list[mob_num])); } // else } // if else { if (mudlog.ofLevel(ERROR)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error: Trying to load non-existant mob" << mob_num << " in room " << room_num << ".\n"; } // if } // else } // while mysql_free_result(result); } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if return; } // else if (room_flags.get(ROOMFLAG_HAS_PROC_SCRIPT)) { RoomScript* rs_ptr; query="select * from RoomScripts where ROOM_NUM="; query+=room_num; if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if while ((row=mysql_fetch_row(result))) { String* tmp_disc = new String(row[RMSCRTBL_DISCRIMINATOR]); tmp_disc->Strip(); tmp_disc->Prepend(" "); tmp_disc->Append(" "); rs_ptr = new RoomScript(*(new String(row[RMSCRTBL_TRIGGER_CMD])), atoi(row[RMSCRTBL_TARGET]), atoi(row[RMSCRTBL_ACTOR]), *tmp_disc, atoi(row[RMSCRTBL_PRECEDENCE])); String sbuf(1024); sbuf = row[RMSCRTBL_SCRIPT_COMMANDS]; String* tmp_str; while ((tmp_str = sbuf.getUntil(';'))) { rs_ptr->appendCmd(*tmp_str); delete tmp_str; } // while rs_ptr->compile(); } // while mysql_free_result(result); } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if return; } // else } // spells query="select SPELL_NUM, DURATION from RoomSpells where ROOM_NUM="; query+=room_num; if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if stat_spell_cell* ss_ptr; while ((row=mysql_fetch_row(result))) { ss_ptr = new stat_spell_cell; ss_ptr->stat_spell = atoi(row[0]); ss_ptr->bonus_duration = atoi(row[1]); Put(ss_ptr, affected_by); } // while mysql_free_result(result); } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if return; } // else // keywords if (room_flags.get(ROOMFLAG_HAS_KEYWORDS)) { query="select KEYWORD_INDEX, DESCRIPTION from RoomKeywords where ROOM_NUM="; query+=room_num; if (mysql_real_query(database, query, strlen(query))==0) { if ((result=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if while ((row=mysql_fetch_row(result))) { KeywordPair* kwd_ptr; MYSQL_RES* tmp_res; MYSQL_ROW tmp_row; String tmp_qry="select KEYWORD from RoomKeynames where ROOM_NUM="; tmp_qry+=room_num; tmp_qry+=" and KEYWORD_INDEX="; tmp_qry+=row[0]; if (mysql_real_query(database, tmp_qry, strlen(tmp_qry))==0) { if ((tmp_res=mysql_store_result(database))==NULL) { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error retrieving query results: " << mysql_error(database) << endl; } // if return; } // if kwd_ptr = new KeywordPair(); while ((tmp_row=mysql_fetch_row(tmp_res))) { kwd_ptr->names.append(new String(tmp_row[0])); } // while mysql_free_result(tmp_res); kwd_ptr->desc = *(new String(row[1])); } // if } // while mysql_free_result(result); } // if else { if (mudlog.ofLevel(WRN)) { mudlog << "In room::dbRead(int, short):\n"; mudlog << "Error executing query: " << mysql_error(database) << endl; } // if return; } // else } // if setVisBit(getVisBit() | 1024); if (getVisBit() & 1) { room_flags.turn_on(14); } // if } // dbRead #endif void room::fileRead(ifstream& ofile, short read_all) { int i, test = TRUE; stat_spell_cell* ss_ptr; char tmp[81]; String tmp_str(80); String* string; door* dr_ptr; if (mudlog.ofLevel(DB)) { mudlog << "Reading room, read_all: " << read_all << endl; } Clear(); //stop up any memory leaks etc. if (!ofile) { if (mudlog.ofLevel(ERROR)) { mudlog << "ERROR: da_file FALSE in sub_room read." << endl; } return; } while (test) { if (!ofile) { if (mudlog.ofLevel(ERROR)) { mudlog << "ERROR: da_file FALSE in room read." << endl; } return; } ofile >> tmp_str; if (strcmp(tmp_str, "~") == 0) { test = FALSE; }//if else { string = new String(tmp_str); Put(string, names); }//else }//while ofile.getline(tmp, 80); short_desc.Termed_Read(ofile); //mudlog.log(DBG, short_desc); long_desc.Termed_Read(ofile); room_flags.Read(ofile); room_flags.turn_on(23); //turn on in_use flag for CERTAIN if (room_flags.get(21)) { //if zlocked read_all = TRUE; room_flags.turn_on(22); //it will be totally loaded }//if setComplete(); //if we can read it, it's complete! KeywordPair* kwd_ptr; if (room_flags.get(32)) { //if has keywords while (TRUE) { ofile >> i; ofile.getline(tmp, 80); if (i != -1) { kwd_ptr = new KeywordPair(); kwd_ptr->read(ofile); keywords.append(kwd_ptr); } else { //read line, then read desc break; } }//while }//if if (mudlog.ofLevel(DB)) { mudlog << "Reading room, about to do cur_stats. " << endl; } for (i = 0; i<ROOM_CUR_STATS; i++) { ofile >> cur_stats[i]; } ofile.getline(tmp, 80); /* Affected By */ ofile >> i; while (i != -1) { if (!ofile) { if (mudlog.ofLevel(ERROR)) { mudlog << "ERROR: da_file FALSE in room read." << endl; } return; } ss_ptr = new stat_spell_cell; ss_ptr->stat_spell = i; ofile >> ss_ptr->bonus_duration; Put(ss_ptr, affected_by); ofile >> i; }//while ofile.getline(tmp, 80); if (!affected_by.isEmpty()) { // Also place it on the list of rooms to be checked for loss of spell... affected_rooms.gainData(this); }//if if (mudlog.ofLevel(DB)) { mudlog << "Reading room, about to do inventory." << endl; } /* Inventory */ ofile >> i; while (i != -1) { if (!ofile) { if (mudlog.ofLevel(ERROR)) { mudlog << "ERROR: da_file FALSE in room read, inv." << endl; } return; } if (check_l_range(i, 0, NUMBER_OF_ITEMS, mob_list[0], FALSE)) { if (obj_list[i].isInUse()) { if (read_all || ((obj_list[i].OBJ_PRCNT_LOAD*config.currentLoadModifier)/100) > d(1,100)) { if (obj_list[i].isPlayerOwned()) { object* po_sack = load_player_box(i); if (po_sack) { // Denote it as 'modified', (SOBJ) po_sack->IN_LIST = &(inv); po_sack->setCurRoomNum(getIdNum(), 0); affected_objects.gainData(po_sack); gainInv(po_sack); } else { //put a virgin copy in the room gainInv(&(obj_list[i])); } } else { gainInv(&(obj_list[i])); //add it to inventory } // obj_list[i].OBJ_CUR_IN_GAME++; //increment cur_in_game }//if }//if else { Sprintf(tmp_str, "ERROR: trying to load non_existant inv: %i in room: %i.\n", i, cur_stats[2]); mudlog.log(ERROR, tmp_str); }//else }//if ofile >> i; }//while ofile.getline(tmp, 80); /* Doors */ Cell<door*> cll; door* walker; short did_insert = FALSE; ofile >> i; //check for terminal value while (i != -1) { if (!ofile) { if (mudlog.ofLevel(ERROR)) { mudlog << "ERROR: da_file FALSE in sub_room read." << endl; } return; } dr_ptr = new door; dr_ptr->Read(ofile); dr_ptr->in_room = cur_stats[2]; //RM_NUM doors.head(cll); String* dr_name = name_of_door(*dr_ptr, ~0); if (!dr_name) { mudlog.log(ERROR, "ERROR: dr_name is NULL."); }//if String* walk_name; while ((walker = cll.next())) { walk_name = name_of_door(*walker, ~0); if (*walk_name > *dr_name) { doors.insertBefore(cll, dr_ptr); did_insert = TRUE; break; }//if }//while if (!did_insert) doors.append(dr_ptr); ofile >> i; //check for next terminal value }//while ofile.getline(tmp, 80); //clear rest of line if (mudlog.ofLevel(DB)) { mudlog << "Reading room About to read critters.." << endl; } /* Critters, stored mobl# */ ofile >> i; while (i != -1) { if (!ofile) { if (mudlog.ofLevel(ERROR)) { mudlog << "ERROR: da_file FALSE in sub_room read." << endl; } return; } if (mob_list[i].isInUse()) { if (mob_list[i].isPlayerShopKeeper()) { critter* shop_owner = load_player_shop_owner(i); if (shop_owner) { // it will be a SMOB, but it needs it's room set here. shop_owner->setCurRoomNum(getIdNum()); gainCritter(shop_owner); }//if }//if else { //regular case gainCritter(&(mob_list[i])); //this will increment cur_in_game } }//if else { Sprintf(tmp_str, "ERROR: trying to load non_existant mob: %i, in room: %i\n", i, cur_stats[2]); mudlog.log(ERROR, tmp_str); }//else ofile >> i; }//while ofile.getline(tmp, 80); //get comments after mobs... /* read procs, if we have them. */ if (room_flags.get(35)) { //mudlog.log("Mob has proc scripts..."); int sent_; RoomScript* ptr; ofile >> sent_; ofile.getline(tmp, 80); if (mudlog.ofLevel(DB)) { mudlog << "Tmp, after script#: " << sent_ << " -:" << tmp << ":-\n"; } while (sent_ != -1) { if (mudlog.ofLevel(DB)) mudlog << "\nReading script# " << sent_ << endl; if (!ofile) { if (mudlog.ofLevel(ERROR)) { mudlog << "ERROR: mob_data reading script da_file FALSE." << endl; } return; } ptr = new RoomScript(); ptr->read(ofile); Put(ptr, room_proc_scripts); ofile >> sent_; ofile.getline(tmp, 80); if (mudlog.ofLevel(DB)) mudlog << "Got rest of line -:" << tmp << ":-" << endl; } }//if it had proc scripts ofile.getline(tmp, 80); //get comments at end of room.. // Post processing... int vb = getVisBit(); setVisBit(vb | 1024); //hack, forgot a flag :P if (vb & 1) { room_flags.turn_on(14); //make normally_dark } if (mudlog.ofLevel(DB)) { mudlog << "Done reading room, number: " << getRoomNum() << endl; } }//Read stat_spell_cell* room::isAffectedBy(int spell_num) { Cell<stat_spell_cell*> cll(affected_by); stat_spell_cell* ptr; while ((ptr = cll.next())) { if (ptr->stat_spell == spell_num) return ptr; }//while return NULL; }//is_affected_by void room::checkLight(int do_msg) { int vb = getVisBit(); //mudlog << "In room::checkLight(), id_num: " << getIdNum() << endl; if (isPermDark()) { //mudlog << "Permdark, trying to make the room dark.\n"; setVisBit(vb | 1); //perm dark it is }//if else if (isNormallyDark()) { //normally dark //mudlog << "Normally dark, trying to make the room dark.\n"; setVisBit(vb | 1); if (isAffectedBy(ILLUMINATE_SKILL_NUM)) { //mudlog << "Room was ILLUMINATED, making it light." << endl; setVisBit(vb & ~1); }//if else { Cell<critter*> cll(critters); critter* crit_ptr; while ((crit_ptr = cll.next())) { if (crit_ptr->CRIT_FLAGS.get(1)) { //if using_light source //if (mudlog.ofLevel(DBG)) { // mudlog << "Room was ILLUMINATED, making it light." << endl; //} setVisBit(vb & ~1); break; }//if }//while }//else }//if normally_dark else { setVisBit(vb & ~1); }//else if (do_msg) { if (vb != getVisBit()) { if (vb & 1) { //it was changed to dark showAllCept("The room becomes dark.\n"); }//if else { showAllCept("The room becomes light.\n"); }//else }//if }//if do_messages }//checkLight void room::Write(ofstream& ofile) { int i, j; Cell<stat_spell_cell*> ss_cell(affected_by); stat_spell_cell* ss_ptr; Cell<String*> n_cell(names); String* n_ptr; Cell<door*> d_cell(doors); door* d_ptr; Cell<object*> ob_cell(inv); object* ob_ptr; Cell<critter*> c_cell(critters); critter* c_ptr; short was_totally_read = FALSE; normalize(); //make sure everything jives! if (room_flags.get(22)) { //totaly read flag was_totally_read = TRUE; room_flags.turn_off(22); // this flag is purely temp, don't write }//if while ((n_ptr = n_cell.next())) { ofile << *n_ptr << " "; }//while ofile << "~" << "\tnames\n"; parse_for_max_80(short_desc); ofile << short_desc << endl << "~" << endl; parse_for_max_80(long_desc); ofile << long_desc << endl << "~" << endl; room_flags.Write(ofile); //mudlog << "Keywords size: " << keywords.size() << endl; if (room_flags.get(32)) { //if has keywords Cell<KeywordPair*> kcll(keywords); KeywordPair* kptr; while ((kptr = kcll.next())) { ofile << "1 Start of KeywordPair\n"; kptr->write(ofile); } ofile << "-1 No more KeywordPairs\n"; }//if //mudlog << "DOne writing out keywordds.." << endl; for (i = 0; i<ROOM_CUR_STATS; i++) { ofile << cur_stats[i] << " "; if ((i + 1) % 20 == 0) ofile << endl; }//for ofile << "\tcur_stats\n"; /* Affected By */ while ((ss_ptr = ss_cell.next())) { ofile << ss_ptr->stat_spell << " " << ss_ptr->bonus_duration << " "; if ((i + 1) % 20 == 0) ofile << endl; }//while ofile << -1 << "\taffected_by\n"; /* Inventory */ j = 0; inv.head(ob_cell); while ((ob_ptr = ob_cell.next())) { ofile << ob_ptr->OBJ_NUM << " "; if ((++j % 20) == 0) ofile << endl; }//while ofile << -1 << "\tinv\n"; /* Doors, stored door#, dest */ j = 0; while ((d_ptr = d_cell.next())) { if (d_ptr->dr_data->door_data_flags.get(10)) { ofile << 1 << " "; //test for next, will read untill -1 d_ptr->Write(ofile); if (++j > 8) { ofile << endl; j = 0; }//if }//if else { if (mudlog.ofLevel(WRN)) { mudlog << "WARNING: door not in use for room: " << getIdNum() << " door: " << d_ptr->getIdNum() << endl; } } }//while ofile << -1 << "\tEnd of Doors\n"; /* Critters, stored mob# */ int cnt = 0; while ((c_ptr = c_cell.next())) { if (++cnt > 20) { ofile << "\n"; cnt = 0; } if (c_ptr->mob && !c_ptr->pc) ofile << c_ptr->MOB_NUM << " "; }//while ofile << -1 << "\tmobs\n"; if (room_flags.get(35)) { Cell<RoomScript*> cll; room_proc_scripts.head(cll); RoomScript* ptr; int i = 1; while ((ptr = cll.next())) { ofile << i++ << " Start of a room proc script\n"; ptr->write(ofile); } ofile << "-1 End of room proc scripts" << endl; } ofile << "End of Room\n"; if (was_totally_read) { room_flags.turn_on(22); //make it as it was }//if }//Write....sub_room void room::checkForProc(String& cmd, String& arg1, critter& actor, int targ) { Cell<critter*> cll(critters); critter* ptr; mudlog.log("room::checkForProc."); while ((ptr = cll.next())) { //if (!ptr->pc) { //SMOB (not a PC) // if (ptr->mob->mob_data_flags.get(17)) { //ok then, it has data // if (mudlog.ofLevel(DBG)) { // mudlog << "room::checkForProc, found a mob: " // << ptr->getName() << endl; // } // Make sure that the actor is still in the room. if (!critters.haveData(&actor)) { return; } // Have to check all, because mob also checks objects that // the mob owns. if (ptr->isMob()) { //if it's a MOB //mudlog.log("Doing mob_to_smob.."); ptr = mob_to_smob(*ptr, getRoomNum()); } ptr->checkForProc(cmd, arg1, actor, targ, *this); // }//if //}//if }//while Cell<object*> ocll(inv); object* optr; while ((optr = ocll.next())) { // Make sure that the actor is still in the room. if (!critters.haveData(&actor)) { return; } if (optr->hasScript()) { if (mudlog.ofLevel(DBG)) { mudlog << "room::checkForProc, found an object: " << optr->getName() << endl; } if (!optr->isModified()) { //mudlog.log("Doing obj_to_sobj.."); object* tmp = optr; optr = obj_to_sobj(*optr, &inv, getIdNum()); if (!inv.substituteData(tmp, optr, 1)) { mudlog.log(ERROR, "ERROR: checkForProc: substituteData failed after obj_to_sobj.\n"); }//if } optr->checkForProc(cmd, arg1, actor, targ, *this); }//if }//while // Now, check for room procs!! Cell<RoomScript*> rcll; RoomScript* rptr; room_proc_scripts.head(rcll); int idx = 0; while ((rptr = rcll.next())) { if (mudlog.ofLevel(DBG)) { mudlog << "room::checkForProc, found room script: " << rptr->toStringBrief(0, getIdNum(), ENTITY_ROOM, idx) << endl; } // Make sure that the actor is still in the room. if (!critters.haveData(&actor)) { return; } if (rptr->matches(cmd, arg1, actor, targ)) { mudlog.log("Script matches..\n"); if (pending_scripts.size() >= 10) { //only queue 10 scripts return; //do nothing, don't want to get too much backlog. } else { // add it to the pending scripts. mudlog.log("Generating script.\n"); rptr->generateScript(cmd, arg1, actor, targ, *this, NULL); mudlog.log("Inserting new script.\n"); insertNewScript(new RoomScript(*rptr)); if (cur_script) { mudlog.log("Had a cur_script.\n"); if (cur_script->getPrecedence() < pending_scripts.peekFront()->getPrecedence()) { mudlog.log("Junking cur_script because of precedence.\n"); pending_scripts.loseData(cur_script); //take it out of queue delete cur_script; //junk it! cur_script = pending_scripts.peekFront(); cur_script->resetStackPtr(); //get ready to start }//if // else, it just goes into the queue }//if we currently have a script. else { //there was none, so grab the first one. mudlog.log("Was no cur_script, taking top of pending stack.\n"); cur_script = pending_scripts.peekFront(); proc_action_rooms.gainData(this); cur_script->resetStackPtr(); //get ready to start } return; }//else }//if matches idx++; }//while }//checkForProc /** Attempt to trigger a room script directly. So far, we support only * pull and push, but more can easily be added. */ int room::attemptExecuteUnknownScript(String& cmd, int i_th, String& arg1, critter& actor) { int targ; targ = i_th = -1; //use i_th to quiet the compiler. // Now, check for room procs!! Cell<RoomScript*> rcll; RoomScript* rptr; room_proc_scripts.head(rcll); int idx = 0; while ((rptr = rcll.next())) { if (mudlog.ofLevel(DBG)) { mudlog << "room::attemptExecuteUnknownScript, found room script: " << rptr->toStringBrief(0, getIdNum(), ENTITY_ROOM, idx) << endl; } if (rptr->matches(cmd, arg1, actor, targ)) { mudlog.log("Script matches..\n"); if (pending_scripts.size() >= 10) { //only queue 10 scripts actor.show("Please try again in a bit.\n"); return 0; //do nothing, don't want to get too much backlog. } else { // add it to the pending scripts. mudlog.log("Generating script.\n"); rptr->generateScript(cmd, arg1, actor, targ, *this, NULL); mudlog.log("Inserting new script.\n"); insertNewScript(new RoomScript(*rptr)); if (cur_script) { mudlog.log("Had a cur_script.\n"); if (cur_script->getPrecedence() < pending_scripts.peekFront()->getPrecedence()) { mudlog.log("Junking cur_script because of precedence.\n"); pending_scripts.loseData(cur_script); //take it out of queue delete cur_script; //junk it! cur_script = pending_scripts.peekFront(); cur_script->resetStackPtr(); //get ready to start }//if // else, it just goes into the queue }//if we currently have a script. else { //there was none, so grab the first one. mudlog.log("Was no cur_script, taking top of pending stack.\n"); cur_script = pending_scripts.peekFront(); proc_action_rooms.gainData(this); cur_script->resetStackPtr(); //get ready to start } return 0; }//else }//if matches idx++; }//while return -1; //didn't find anything that matched }//attemptExecuteUnknownScript int room::getZoneNum() { return ZoneCollection::instance().getZoneFor(*this).getIdNum(); } void room::stat(critter& pc) { String buf2(100); if (names.peekFront()) { show(*(names.peekFront()), pc); }//if Sprintf(buf2, " Belongs to zone: %i.\n", getZoneNum()); show(buf2, pc); show(short_desc, pc); show("\n", pc); show(long_desc, pc); pc.show("\n"); Cell<KeywordPair*> cll(keywords); KeywordPair* ptr; int cnt = 0; while ((ptr = cll.next())) { ptr->show(cnt, pc); cnt++; } out_field(room_flags, pc, ROOM_FLAGS_NAMES); show("\n", pc); Sprintf(buf2, "v_bit: %i mv$: %i r_num: %i pause: %i fall_to: %i\n", getVisBit(), getMovCost(), getRoomNum(), getPause(), getFallTo()); show(buf2, pc); Sprintf(buf2, "Number of critters: %i Number of Scripts Pending: %i\n\n", critters.size(), pending_scripts.size()); show(buf2, pc); if (room_proc_scripts.size() > 0) { listScripts(pc); } }//stat /* called after OLC to enforce as much state as possible. */ void room::normalize() { setVisBit(getVisBit() | 1024); if (keywords.size() > 0) { room_flags.turn_on(32); } else { room_flags.turn_off(32); } }//normalize_room const String* room::getRandomExitDir(critter& pc) { int sz = doors.size(); int idx = d(1, sz); Cell<door*> cll(doors); door* ptr; int cnt = 0; while ((ptr = cll.next())) { cnt++; if (cnt == idx) { if (ptr->getDestRoom()) { if (!(ptr->getDestRoom()->isNoWanderForeignMob() && (pc.getNativeZoneNum() != ptr->getDestRoom()->getZoneNum()))) { if (!(ptr->getDestRoom()->isNoWanderMob() && pc.isNpc()) && mob_can_enter(pc, *(ptr->getDestRoom()), FALSE)) { return ptr->getDirection(); }//if }//if }//if }//if else if (cnt > idx) { break; }//else }//while if (mudlog.ofLevel(DBG)) { mudlog << "Didn't find the one we wanted..getting first one." << endl; } // Didn't find the one we wanted...get the first one. doors.head(cll); while ((ptr = cll.next())) { if (ptr->getDestRoom()) { if (!(ptr->getDestRoom()->isNoWanderForeignMob() && (pc.getNativeZoneNum() != ptr->getDestRoom()->getZoneNum()))) { if (!(ptr->getDestRoom()->isNoWanderMob() && !pc.isPc()) && mob_can_enter(pc, *(ptr->getDestRoom()), FALSE)) { return ptr->getDirection(); }//if }//if }//if }//while return &UNKNOWN; }//getRandomExitDir int room::isInUse() const { return (room_flags.get(23) || critters.size()); } int room::getCritCount(critter& pc) { return crit_count(critters, pc); } int room::getObjCount(object& obj) { int retval = 0; Cell<object*> cll(inv); object* ptr; while ((ptr = cll.next())) if (ptr->getIdNum() == obj.getIdNum()) retval++; return retval; } int room::getObjCount(int onum) { int retval = 0; Cell<object*> cll(inv); object* ptr; while ((ptr = cll.next())) if (ptr->getIdNum() == onum) retval++; return retval; } /* this returns the critter if exists. rm_num is the number of * the room we found it in. Returns NULL if not found. * searches entire world. */ critter* room::haveCritNamedInWorld(const int i_th, const String* name, const int see_bit, int& rm_num) { Cell<String*> char_cell; Cell<critter*> cell; critter* crit_ptr; int count = 0, len; String *string; mudlog.log(DBG, "In have_crit_named, for whole room_list"); if ((len = name->Strlen()) == 0) return NULL; if (i_th <= 0) return NULL; //mudlog.log(DBG, "Looking in room number: "); for (int i = 0; i<NUMBER_OF_ROOMS; i++) { // if (mudlog.ofLevel(DBG)) { // mudlog << i << " "; // if (((i + 1) % 100) == 0) // mudlog << flush; // } if (room_list.elementAtNoCreate(i)) { room_list[i].critters.head(cell); while ((crit_ptr = cell.next())) { if (detect(see_bit, crit_ptr->VIS_BIT)) { crit_ptr->names.head(char_cell); while ((string = char_cell.next())) { if (strncasecmp(*string, *name, len) == 0){ count++; if (count == i_th) { rm_num = i; return crit_ptr; }//if }//if }//while }//if }//while }//for }//if rm_num = 0; return NULL; }//have_crit_named for whole room_list, returns room# /** Find a critter in a given zone. Returns the critter, or * NULL if not found. in_room holds the room number we found it * in. */ critter* room::haveCritNamedInZone(zone& zn, const int i_th, const String* name, const int see_bit, int& in_room) { Cell<String*> char_cell; Cell<critter*> cell; critter* crit_ptr; int count = 0, len; String *string; in_room = 0; //log("In have_crit_named, for whole zone"); if (!name) { mudlog.log(ERROR, "ERROR: NULL name sent to have_crit_named.\n"); return NULL; }//if if ((len = name->Strlen()) == 0) return NULL; if (i_th <= 0) return NULL; int end = zn.getEndRoomNum(); for (int i = zn.getBeginRoomNum(); i <= end; i++) { room_list[i].critters.head(cell); while ((crit_ptr = cell.next())) { if (detect(see_bit, crit_ptr->VIS_BIT)) { crit_ptr->names.head(char_cell); while ((string = char_cell.next())) { if (strncasecmp(*string, *name, len) == 0){ count++; if (count == i_th) { in_room = i; return crit_ptr; }//if }//if }//while }//if }//while }//for in_room = 0; return NULL; }//have_crit_named for whole zone void room::doPoofOut(critter& pc) { String buf(100); Cell<critter*> cll(critters); critter* ptr; while ((ptr = cll.next())) { if ((&pc != ptr) && ptr->canDetect(pc) && !ptr->isSleeping()) { if (ptr->isImmort() && (ptr->IMM_LEVEL >= pc.IMM_LEVEL)) { Sprintf(buf, "[OUT: %S] %S\n", pc.getName(), &(pc.getPoofout())); } else { Sprintf(buf, "%S\n", &(pc.getPoofout())); } ptr->show(buf); } }//while }//doPoofOut int room::doRclear(int new_rm_num) { critter* crit_ptr; while (!critters.isEmpty()) { crit_ptr = critters.peekFront(); if ((crit_ptr->isPc()) || crit_ptr->isSmob()) { //mudlog << "Was a SMOB or PC." << endl; int is_dead; crit_ptr->doGoToRoom(new_rm_num, NULL, NULL, is_dead, getIdNum(), 1); if (!is_dead) { show("The void has swallowed your previous location!!\n", *crit_ptr); } } else { //just remove the pointer... removeCritter(crit_ptr); }//else }//while Clear(); //clear out the room pc WAS in!! return 0; }//doRclear int room::doScan(critter& pc) { String buf(100); Cell<door*> dcll(doors); Cell<critter*> cll; critter* ptr; int a, b; int pl = get_percent_lrnd(SCAN_SKILL_NUM, pc); door* dptr; while ((dptr = dcll.next())) { if (detect(pc.SEE_BIT, dptr->getVisBit() | getVisBit())) { if (dptr->isOpen()) { dptr->getDestRoom()->critters.head(cll); while ((ptr = cll.next())) { if (detect(pc.SEE_BIT, ptr->VIS_BIT | dptr->getDestRoom()->getVisBit())) { a = max((pc.LEVEL - pc.POS), 10) + pl; b = max((ptr->LEVEL - ptr->POS), 10) + 100; if (ptr->isHiding()) { b *= max(1, max(get_percent_lrnd(HIDE_SKILL_NUM, *ptr), get_percent_lrnd(BLEND_SKILL_NUM, *ptr)) / 10); } if (d(1, a) > d(1, b)) { Sprintf(buf, " %S%P25 %S.\n", dptr->getDirection(), ptr->getName()); pc.show(buf); }//if }//if }//while }//if }//if }//while return 0; }//doScan void room::doPoofIn(critter& pc) { String buf(100); Cell<critter*> cll(critters); critter* ptr; while ((ptr = cll.next())) { if ((&pc != ptr) && !ptr->isSleeping() && ptr->canDetect(pc)) { if (ptr->isImmort() && (ptr->IMM_LEVEL >= pc.IMM_LEVEL)) { Sprintf(buf, "[IN: %S] %S\n", pc.getName(), &(pc.getPoofin())); } else { Sprintf(buf, "%S\n", &(pc.getPoofin())); } ptr->show(buf); } }//while }//doPoofIn void room::resetProcMobs() { Cell<critter*> cll(critters); critter* ptr; while ((ptr = cll.next())) { //mudlog << "Found a critter: " << ptr << endl << flush; if (ptr->mob) { //mudlog << "Was a mob..." << endl; ptr->MOB_FLAGS.turn_on(3); //should do spec procs }//if }//while }//resetProcMobs void room::purgeCritter(int mob_num, critter& pc) { int done = FALSE; while (!done) { Cell<critter*> cll(critters); critter* ptr; done = TRUE; while ((ptr = cll.next())) { if (ptr->isNpc() && (ptr->getIdNum() == mob_num)) { agg_kills_vict(&pc, *ptr); done = FALSE; break; }//if }//while }//for }//purgeCritter int room::sub_a_4_b(critter* crit_ptr, int i_th, const String& name, int see_bit) { return crit_sub_a_4_b(crit_ptr, critters, i_th, &name, see_bit, *this); } int room::sub_a_4_b(critter* a, critter* b, int i_th) { // Don't want to add it if we can't substitute it, but the list<> // method does indeed append if it's not already there. if (critters.haveData(b)) { return critters.substituteData(b, a, i_th); } return FALSE; } void room::gainCritter(critter* crit) { if (crit->isNpc()) { crit->incrementCurInGame(); } critters.prepend(crit); // This nips a bunch of bugs in the bud. No more will we have // MOB's running around in the game. If it's in the game, it will // be a SMOB, which for reasons lost in antiquity, means it is a // unique Instance and may be modified independently of the database. if (crit->isMob()) { crit = mob_to_smob(*crit, *this); }//if crit->setCurRoomNum(getRoomNum()); } void room::loseObjectFromGame(object& which_un) { Cell<object*> ocll(inv); object* optr; Cell<critter*> ccll; critter* cptr; int targ_num = which_un.getIdNum(); optr = ocll.next(); while (optr) { if (optr->IN_LIST && (optr->getIdNum() == targ_num)) { //if SOBJ delete optr; optr = inv.lose(ocll); } else if (optr->getIdNum() == targ_num) { optr = inv.lose(ocll); } else optr = ocll.next(); }//while critters.head(ccll); while ((cptr = ccll.next())) { cptr->loseObjectFromGame(&which_un); }//while }//loseObjectFromGame critter* room::removeCritter(critter* crit) { critter* retval; retval = critters.loseData(crit); if (retval) { if (crit->isNpc()) { crit->decrementCurInGame(); } }//if else { // We use room 0 for newbies logging in and such...will get boundary // case errors here in some instances... if (getIdNum() != 0) { if (mudlog.ofLevel(WRN)) { mudlog << "WARNING: could not remove the critter in" << " room::removeCrit(), crit_name: " << *(crit->getName()) << " num: " << crit->getIdNum() << " room: " << getIdNum() << endl; core_dump("removeCritter"); }//if }//if }//else return retval; }//removeCritter void room::getPetsFor(critter& owner, List<critter*>& rslts) { critter* ptr; Cell<critter*> cll(critters); while ((ptr = cll.next())) { if (owner.PETS.haveData(ptr)) { rslts.append(ptr); }//if }//while }//getPetsFor void room::showCritters(critter& pc) { out_crit(critters, pc); } //show inv to pc (use out_inv method) void room::outInv(critter& pc) { out_inv(inv, pc, ROOM_INV); } void room::gainInv(object* obj) { if (obj->obj_flags.get(55)) { //if it's coins if (obj->cur_stats[1] == 0) { if (obj->IN_LIST) { mudlog << "ERROR: Possible memory leak, gainInv: obj is SOBJ" << " but has zero coins, obj#" << obj->getIdNum() << " room# " << getIdNum() << endl; } return; //don't add it, it had zero coins }//if }//if // If this ever changes from prepend, must change the disolve-pet // code in misc.cc (it disolves the corpse) inv.prepend(obj); if (obj->IN_LIST) { obj->IN_LIST = &inv; obj->setCurRoomNum(getIdNum(), 0); } }//gainInv void room::purgeObj(object* obj, critter* pc, int do_msg) { loseInv(obj); if (!obj->isBulletinBoard()) { recursive_init_unload(*obj, 0); } else { obj->decrementCurInGame(); } if (do_msg && pc) { pc->show("Ok, object purged from room.\n"); } if (obj->IN_LIST) { delete obj; }//if }//purgeObj object* room::loseInv(object* obj) { obj->setCurRoomNum(0, 0); return inv.loseData(obj); } int room::canSeeSky() { return (room_flags.get(4) || room_flags.get(15) || room_flags.get(16) || room_flags.get(17)); } critter* room::haveCritNamed(int i_th, const String* name, int see_bit) { return ::have_crit_named(critters, i_th, name, see_bit, *this); } critter* room::haveCritNamed(int i_th, const String* name, critter& pc) { int foo = 0; return haveCritNamed(i_th, name, pc, foo); } critter* room::haveCritNamed(int i_th, const String* name, critter& pc, int& count_sofar) { if ((strcasecmp(*name, "me") == 0) || (strcasecmp(*name, "self") == 0)) { return &pc; } return ::have_crit_named(critters, i_th, name, pc.SEE_BIT, count_sofar, *this); } critter* room::haveCritter(critter* ptr) { if (critters.haveData(ptr)) { return ptr; } return NULL; } object* room::haveObject(object* ptr) { if (inv.haveData(ptr)) { return ptr; } return NULL; } object* room::haveObjNamed(int i_th, const String* name, int see_bit) { int foo = 0; return ::have_obj_named(inv, i_th, name, see_bit, *this, foo); } object* room::haveAccessibleObjNamed(int i_th, const String* name, critter& pc, int& count_sofar, int& posn) { object* ptr; ptr = have_obj_named(inv, i_th, name, pc.getSeeBit(), *this, count_sofar); if (!ptr) { ptr = have_obj_named(pc.inv, i_th - count_sofar, name, pc.getSeeBit(), *this, count_sofar); } if (!ptr) { ptr = pc.findObjInEq(i_th - count_sofar, *name, pc.getSeeBit(), *this, posn, count_sofar); } return ptr; }//haveAccesibleObjNamed int room::doClose(int i_th, const String* name) { door* dr_ptr; object* ob_ptr; String buf(100); if ((dr_ptr = door::findDoor(this->DOORS, i_th, name, ~0, *this))) { if (dr_ptr->isOpen()) { if (dr_ptr->canClose()) { dr_ptr->close(); return 0; } } } else { ob_ptr = this->haveObjNamed(i_th, name, ~0); if (ob_ptr && ob_ptr->bag && !ob_ptr->isModified()) { ob_ptr = obj_to_sobj(*ob_ptr, this->getInv(), TRUE, i_th, name, ~0, *this); } if (ob_ptr && ob_ptr->bag && !ob_ptr->isClosed()) { ob_ptr->bag->close(); return 0; } } return -1; } int room::doMload(int i_th) { critter* crit_ptr; if ((i_th >= 1) && (i_th < NUMBER_OF_MOBS)) { crit_ptr = &(mob_list[i_th]); if (!crit_ptr->CRIT_FLAGS.get(18)) { return -1; }//if }//if /* do it then */ if (crit_ptr->isPlayerShopKeeper()) { critter* shop_keeper = load_player_shop_owner(crit_ptr->getIdNum()); if (shop_keeper) { gainCritter(shop_keeper); }//if }//if else { gainCritter(&(mob_list[crit_ptr->getIdNum()])); } recursive_init_loads(*crit_ptr); return 0; }//mload int room::doOload(int i_th) { object* obj_ptr; // mudlog.log(TRC, "In oclone.\n"); if ((i_th >= 1) && (i_th < NUMBER_OF_ITEMS)) { obj_ptr = &(obj_list[i_th]); if (!obj_ptr->OBJ_FLAGS.get(10)) { return -1; }//if }//if else { return -1; }//else if (!obj_ptr->isBulletinBoard()) { recursive_init_loads(*obj_ptr, 0); } else { obj_ptr->incrementCurInGame(); } gainInv(obj_ptr); return 0; }//oload critter* room::findFirstBanker() { Cell<critter*> cell(critters); critter* crit_ptr; while ((crit_ptr = cell.next())) { if (crit_ptr->isBanker()) { return crit_ptr; }//if }//while return NULL; }//findFirstBanker critter* room::findFirstShopKeeper() { Cell<critter*> cell(critters); critter* crit_ptr; while ((crit_ptr = cell.next())) { if (crit_ptr->isShopKeeper()) { return crit_ptr; }//if }//while return NULL; }//findFirstShopOwner critter* room::findFirstTeacher() { Cell<critter*> cell(critters); critter* crit_ptr; while ((crit_ptr = cell.next())) { if (crit_ptr->isTeacher()) { return crit_ptr; }//if }//while return NULL; }//findFirstTeacher void room::showAllCept(const char* msg, critter* pc) const { Cell<critter*> cell(critters); critter* crit_ptr; while ((crit_ptr = cell.next())) { if (crit_ptr != pc) if (crit_ptr->POS < POS_SLEEP) show(msg, *crit_ptr); }//while Cell<object*> cll(inv); object* obj; while ((obj = cll.next())) { if (obj->obj_proc && (crit_ptr = obj->obj_proc->w_eye_owner)) { if (crit_ptr != pc) { if (crit_ptr->POS < POS_SLEEP) { show("#####", *crit_ptr); show(msg, *crit_ptr); }//if }//if }//if }//while }// show_all_cept void room::finishedRoomProc() { if (cur_script) { pending_scripts.loseData(cur_script); delete cur_script; } // This could easily end up being NULL, that's OK! cur_script = pending_scripts.peekFront(); }//finishedRoomProc void room::addProcScript(const String& txt, RoomScript* script_data) { //similar to reading it in... //first, see if we are over-writing one... if (mudlog.ofLevel(DBG)) { mudlog << "In room::addProcScript, txt: \n" << txt << "\nscript data: " << script_data->toStringBrief(0, 0, ENTITY_ROOM, 0) << endl; } room_flags.turn_on(35); Cell<RoomScript*> cll; RoomScript* ptr; room_proc_scripts.head(cll); while ((ptr = cll.next())) { if (ptr->matches(*script_data)) { //got a match. mudlog.log("room::addProcScript, they match."); *ptr = *script_data; ptr->setScript(txt); delete script_data; return; }//if }//while mudlog.log(DBG, "About to setScript."); script_data->setScript(txt); mudlog.log(DBG, "done with setScript."); if (!script_data) { mudlog.log(ERROR, "script_data is NULL, room::addProcScript."); return; } room_proc_scripts.append(script_data); }//addProcScript void room::listScripts(critter& pc) { String buf(500); buf.Append("These scripts are defined for this room, the actual scripts may be seen by using the stat_room_script [rm_num] [script_index] command.\n\n"); pc.show(buf); String tmp(100); int found_one = FALSE; Cell<RoomScript*> cll(room_proc_scripts); RoomScript* ptr; int idx = 0; while ((ptr = cll.next())) { found_one = TRUE; tmp = ptr->toStringBrief(FALSE, 0, ENTITY_ROOM, idx); Sprintf(buf, "[%i] %S\n", idx, &(tmp)); pc.show(buf); idx++; } if (!found_one) { buf.Append("No scripts defined for this room.\n"); show(buf, pc); } }//listScripts void room::removeScript(String& trigger, int i_th, critter& pc) { int sofar = 1; String buf(500); Cell<RoomScript*> cll(room_proc_scripts); RoomScript* ptr; ptr = cll.next(); while (ptr) { if (strcasecmp(*(ptr->getTrigger()), trigger) == 0) { if (sofar == i_th) { delete ptr; ptr = room_proc_scripts.lose(cll); show("Deleted it...\n", pc); return; }//if else { ptr = cll.next(); } sofar++; }//if else { ptr = cll.next(); } }//while show("Didn't find that script..\n", pc); }//removeScript int room::insertNewScript(RoomScript* script) { RoomScript* ptr; Cell<RoomScript*> cll(pending_scripts); // Don't append scripts that have a zero precedence, if there // are other scripts in the queue. if ((script->getPrecedence() == 0) && (!pending_scripts.isEmpty())) { delete script; return 0; } while ((ptr = cll.next())) { if (ptr->getPrecedence() < script->getPrecedence()) { // Then insert it pending_scripts.insertBefore(cll, script); return 0; }//if }//while // If here, then we need to place it at the end. pending_scripts.append(script); return 0; } void room::doScriptJump(int abs_offset) { if (cur_script) cur_script->doScriptJump(abs_offset); } int room::doEmote(critter& pc, CSelectorColl& includes, CSelectorColl& denies, CSentryE cs_entry, ...) { va_list argp; va_start(argp, cs_entry); int retval = 0; retval = vDoEmote(pc, includes, denies, cs_entry, argp); va_end(argp); return retval; } int room::vDoEmote(critter& pc, CSelectorColl& includes, CSelectorColl& denies, CSentryE cs_entry, va_list argp) { Cell<critter*> cll(critters); critter* ptr; String buf(100); String buf2(100); while ((ptr = cll.next())) { if (!(denies.matches(ptr, &pc))) { if (mudlog.ofLevel(DBG)) { mudlog << "room::doEmote, not denied." << endl; } if (includes.matches(ptr, &pc)) { if (mudlog.ofLevel(DBG)) { mudlog << "room::doEmote, includes matched." << endl; mudlog << "cstr of " << (int)(cs_entry) << "-:" << cstr(cs_entry, *ptr) << ":-" << endl; } vSprintf(buf, cstr(cs_entry, *ptr), argp); if (mudlog.ofLevel(DBG)) { mudlog << endl << "buf -:" << buf << ":-" << endl << endl; } Sprintf(buf2, "%S %S", pc.getName(ptr->SEE_BIT), &buf); buf2.Cap(); ptr->show(buf2); }//if }//if }//while return 0; }//vDoEmote