// $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