/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* _/ _/_/_/ _/ _/ _/ ACK! MUD is modified *
* _/_/ _/ _/ _/ _/ Merc2.0/2.1/2.2 code *
* _/ _/ _/ _/_/ _/ (c)Stephen Zepp 1998 *
* _/_/_/_/ _/ _/ _/ Version #: 4.3.1 *
* _/ _/ _/_/_/ _/ _/ _/ *
* *
* http://ackmud.nuc.net/ *
* zenithar@ackmud.nuc.net *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
/***************************************************************************
* _/_/_/_/ _/ _/ _/_/_/_/ _/_/_/_/ AckFUSS is modified ACK!MUD 4.3.1 *
* _/ _/ _/ _/ _/ copyright Matt Goff (Kline) 2008 *
* _/_/ _/ _/ _/_/_/_/ _/_/_/_/ *
* _/ _/ _/ _/ _/ Support for this code is provided *
* _/ _/_/_/_/ _/_/_/_/ _/_/_/_/ at www.ackmud.net -- check it out!*
***************************************************************************/
#include <algorithm>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <stdarg.h>
#include "globals.h"
#include "hash.h"
#include <unistd.h> /* for execl */
#include <math.h> /* For fread_float */
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#ifndef DEC_ACT_INFO_H
#include "h/act_info.h"
#endif
#ifndef DEC_ACT_MOB_H
#include "h/act_mob.h"
#endif
#ifndef DEC_ACT_OBJ_H
#include "h/act_obj.h"
#endif
#ifndef DEC_ACT_WIZ_H
#include "h/act_wiz.h"
#endif
#ifndef DEC_COMM_H
#include "h/comm.h"
#endif
#ifndef DEC_DB_H
#include "h/db.h"
#endif
#ifndef DEC_HANDLER_H
#include "h/handler.h"
#endif
#ifndef DEC_MONEY_H
#include "h/money.h"
#endif
#ifndef DEC_SPENDQP_H
#include "h/spendqp.h"
#endif
#ifndef DEC_SSM_H
#include "h/ssm.h"
#endif
#if !defined(macintosh)
extern int _filbuf args( ( FILE * ) );
#endif
/*
* Globals.
*/
char bug_buf[2 * MAX_INPUT_LENGTH];
char log_buf[2 * MAX_INPUT_LENGTH];
char testerbuf[MSL];
KILL_DATA kill_table[MAX_LEVEL];
TIME_INFO_DATA time_info;
WEATHER_DATA weather_info;
SYS_DATA_TYPE sysdata;
CHAN_HISTORY chan_history;
bool booting_up;
bool area_resetting_global;
bool mem_log;
short gsn_martial_arts;
short gsn_stake;
short gsn_dualwield;
short gsn_stun;
short gsn_feed;
short gsn_knee;
short gsn_shadow;
short gsn_appraise;
short gsn_climb;
short gsn_find_doors;
short gsn_bash;
short gsn_smash;
short gsn_notrip;
short gsn_nodisarm;
short gsn_trip;
short gsn_dirt;
short gsn_shield_block;
short gsn_berserk;
short gsn_circle;
short gsn_backstab;
short gsn_dodge;
short gsn_hide;
short gsn_hunt;
short gsn_peek;
short gsn_pick_lock;
short gsn_sneak;
short gsn_warcry;
short gsn_steal;
short gsn_punch;
short gsn_headbutt;
short gsn_disarm;
short gsn_enhanced_damage;
short gsn_kick;
short gsn_parry;
short gsn_rescue;
short gsn_enhanced_reflexes;
short gsn_sleight_of_hand;
short gsn_crushing_blow;
short gsn_combat_prowess;
short gsn_quickstrike;
short gsn_blindness;
short gsn_charm_person;
short gsn_curse;
short gsn_invis;
short gsn_mass_invis;
short gsn_poison;
short gsn_sleep;
short gsn_disguise;
short gsn_instruct;
short gsn_adrenaline;
short gsn_frenzy;
short gsn_emotion_control;
short gsn_target;
short gsn_charge;
short gsn_unit_tactics;
short gsn_imprint;
short gsn_scent;
short gsn_mount;
short gsn_scout;
short gsn_decapitate;
short gsn_potency;
short gsn_thaumatergy;
extern bool auto_quest;
extern COUNCIL_DATA super_councils[MAX_SUPER];
/*
* Locals.
*/
MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
OBJ_INDEX_DATA *obj_index_hash[MAX_KEY_HASH];
ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH];
char *string_hash[MAX_KEY_HASH];
AREA_DATA *area_used[MAX_AREAS];
AREA_DATA *area_load;
ROOM_INDEX_DATA *room_load;
MOB_INDEX_DATA *mob_load;
OBJ_INDEX_DATA *obj_load;
int fp_open;
int fp_close;
int nAllocPerm;
int sAllocPerm;
/*
* Semi-locals.
*/
bool fBootDb;
FILE *fpArea;
char strArea[MAX_INPUT_LENGTH];
int area_revision = -1;
#define SHOW_AREA \
if (!previous_bug) \
{ \
bug (" In %s.",(int) pArea->filename); \
previous_bug=1; \
}
/*
* Big mama top level function.
*/
void boot_db( void )
{
int a;
/*
* Init some data space stuff.
*/
init_string_space( );
fBootDb = TRUE;
send_to_descrips( "Initialising Ack! Mud. Please Wait....\r\n" );
/*
* Init random number generator.
*/
{
init_mm( );
}
load_sysdata(); /* Must be first, can possibly alter things to follow! --Kline */
/*
* Set time and weather.
*/
{
long lhour, lday, lmonth;
lhour = ( current_time - 650336715 ) / ( PULSE_TICK / PULSE_PER_SECOND );
time_info.hour = lhour % 24;
lday = lhour / 24;
time_info.day = lday % 35;
lmonth = lday / 35;
time_info.month = lmonth % 17;
time_info.year = lmonth / 17;
time_info.moon = 0;
weather_info.moon_loc = MOON_DOWN;
weather_info.moon_phase = number_range( MOON_NEW, MOON_FULL );
if( time_info.hour < 5 )
weather_info.sunlight = SUN_DARK;
else if( time_info.hour < 6 )
weather_info.sunlight = SUN_RISE;
else if( time_info.hour < 19 )
weather_info.sunlight = SUN_LIGHT;
else if( time_info.hour < 20 )
weather_info.sunlight = SUN_SET;
else
weather_info.sunlight = SUN_DARK;
weather_info.change = 0;
weather_info.mmhg = 960;
if( time_info.month >= 7 && time_info.month <= 12 )
weather_info.mmhg += number_range( 1, 50 );
else
weather_info.mmhg += number_range( 1, 80 );
if( weather_info.mmhg <= 980 )
weather_info.sky = SKY_LIGHTNING;
else if( weather_info.mmhg <= 1000 )
weather_info.sky = SKY_RAINING;
else if( weather_info.mmhg <= 1020 )
weather_info.sky = SKY_CLOUDY;
else
weather_info.sky = SKY_CLOUDLESS;
}
/*
* Initialize Supernatural Councils
*/
{
short index;
char buf[MAX_STRING_LENGTH];
log_f( "Initializing supernatural councils..." );
for( index = SUPER_NONE; index < MAX_SUPER; index++ )
{
super_councils[index].first_member = NULL;
super_councils[index].last_member = NULL;
super_councils[index].quorum = FALSE;
super_councils[index].council_time = 0;
switch ( index )
{
case SUPER_NONE:
snprintf( buf, MSL, "%s", "ORDINARIES" );
break;
case SUPER_VAMP:
snprintf( buf, MSL, "%s", "@@rJUSTICARS@@N" );
break;
default:
snprintf( buf, MSL, "%s", "NONE" );
break;
}
super_councils[index].council_name = str_dup( buf );
}
log_f("Done.");
}
/*
* Assign gsn's for skills which have them.
*/
{
int sn;
for( sn = 0; sn < MAX_SKILL; sn++ )
{
if( skill_table[sn].pgsn != 0 )
*skill_table[sn].pgsn = sn;
}
}
/*
* Clear list of used areas
*/
for( a = 0; a < MAX_AREAS; a++ )
{
area_used[a] = NULL;
}
/*
* Read in clan data table
*/
{
extern POL_DATA politics_data;
FILE *clanfp;
char clan_file_name[MAX_STRING_LENGTH];
short x, y;
char buf[MAX_STRING_LENGTH];
snprintf( clan_file_name, MSL, "%s", CLAN_FILE );
snprintf( buf, MSL, "Loading %s", clan_file_name );
log_f("%s",buf);
if( ( clanfp = file_open( clan_file_name, "r" ) ) == NULL )
{
log_f( "failed open of clan_table.dat in load_clan_table" );
}
else
{
fpArea = clanfp;
snprintf( strArea, MSL, "%s", clan_file_name );
for( x = 1; x < MAX_CLAN; x++ )
{
for( y = 1; y < MAX_CLAN; y++ )
{
politics_data.diplomacy[x][y] = fread_number( clanfp );
}
}
for( x = 1; x < MAX_CLAN; x++ )
{
politics_data.treasury[x] = fread_number( clanfp );
}
for( x = 1; x < MAX_CLAN; x++ )
{
for( y = 1; y < MAX_CLAN; y++ )
{
politics_data.end_current_state[x][y] = fread_number( clanfp );
}
}
file_close( clanfp );
}
fpArea = NULL;
log_f("Done.");
}
/*
* Start loading up data files!
*/
load_areas();
load_social_table();
/* load_gold(); */
load_notes();
load_marks();
load_bans();
load_rulers();
load_brands();
load_corpses();
load_disabled();
/*
* Fix up exits.
* MAG Mod: Check resets. (Allows loading objects of later areas.)
* Declare db booting over.
* Reset all areas once.
* Load up the notes file.
*/
{
log_f( "Fixing exits..." );
fix_exits( );
log_f( "Done." );
fBootDb = FALSE;
log_f( "Checking resets..." );
check_resets( );
log_f( "Done.");
log_f( "Updating areas..." );
area_update( );
log_f("Done.");
booting_up = FALSE;
}
boot_done();
auto_quest = TRUE;
return;
}
#if defined(KEY)
#undef KEY
#endif
#define KEY( literal, field, value ) if ( !str_cmp( word, literal ) ) { field = value; fMatch = true; break;}
#define SKEY( literal, field, value ) if ( !str_cmp( word, literal ) ) { if (field!=NULL) free_string(field);field = value; fMatch = true; break;}
/*
* Read in all the area files.
*/
void load_areas( void )
{
FILE *fpList;
log_f( "Loading area files..." );
if( ( fpList = file_open( AREA_LIST, "r" ) ) == NULL )
{
perror( AREA_LIST );
log_f( "Unable to open area.lst, aborting bootup." );
kill( getpid( ), SIGQUIT );
}
for( ;; )
{
strcpy( strArea, fread_word( fpList ) );
if( strArea[0] == '$' )
break;
if( strArea[0] == '-' )
{
fpArea = stdin;
}
else
{
if( ( fpArea = file_open( strArea, "r" ) ) == NULL )
{
log_string( strArea );
kill( getpid( ), SIGQUIT );
}
}
for( ;; )
{
char *word;
if( fread_letter( fpArea ) != '#' )
{
bug( "Boot_db: # not found.", 0 );
kill( getpid( ), SIGQUIT );
}
word = fread_word( fpArea );
if( word[0] == '$' )
break;
if( !str_cmp( word, "AREA" ) )
load_area( fpArea );
else if( !str_cmp( word, "DOOR" ) )
load_door( fpArea );
else if( !str_cmp( word, "MOBILE" ) )
load_mobile( fpArea );
else if( !str_cmp( word, "OAFFECT" ) )
load_oaffect( fpArea );
else if( !str_cmp( word, "OBJECT" ) )
load_object( fpArea );
else if( !str_cmp( word, "OEXTRA" ) )
load_oextra( fpArea );
else if( !str_cmp( word, "RESETS" ) )
load_resets( fpArea );
else if( !str_cmp( word, "REXTRA" ) )
load_rextra( fpArea );
else if( !str_cmp( word, "ROOM" ) )
load_room( fpArea );
else if( !str_cmp( word, "SHOP" ) )
load_shop( fpArea );
else
{
bug( "Boot_db: bad section name.", 0 );
exit( 1 );
}
}
if( fpArea != stdin )
file_close( fpArea );
fpArea = NULL;
}
file_close( fpList );
log_f("Done.");
return;
}
/*
* Snarf an 'area' header line.
*/
void load_area( FILE * fp )
{
AREA_DATA *pArea;
const char *word;
bool fMatch = false;
int a;
pArea = new AREA_DATA;
pArea->filename = str_dup( strArea );
area_revision = -1;
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch ( UPPER( word[0] ) )
{
case '*':
fMatch = TRUE;
fread_to_eol( fp );
break;
case 'C':
SKEY("CanRead", pArea->can_read, fread_string( fp ) );
SKEY("CanWrite", pArea->can_write, fread_string( fp ) );
break;
case 'F':
if( !str_cmp( word, "Flags" ) )
{
const char *tmp = fread_word(fp);
while( str_cmp(tmp,"EOL") )
{
pArea->flags.set(atoi(tmp));
tmp = fread_word(fp);
}
fMatch = TRUE;
break;
}
break;
case 'K':
SKEY("Keyword", pArea->keyword, fread_string( fp ) );
break;
case 'L':
SKEY("LevLabel", pArea->level_label, fread_string( fp ) );
if( !str_cmp(word,"LevRange") )
{
pArea->min_level = fread_number(fp);
pArea->max_level = fread_number(fp);
fMatch = true;
break;
}
break;
case 'N':
SKEY("Name", pArea->name, fread_string( fp ) );
KEY("Number", pArea->area_num, fread_number( fp ) );
break;
case 'O':
SKEY("Owner", pArea->owner, fread_string( fp ) );
break;
case 'R':
KEY("ResetMsg", pArea->reset_msg, fread_string( fp ) );
KEY("ResetRate", pArea->reset_rate, fread_number( fp ) );
KEY("Revision", area_revision, fread_number( fp ) );
break;
case 'V':
if( !str_cmp(word,"VnumRange") )
{
pArea->min_vnum = fread_number(fp);
pArea->max_vnum = fread_number(fp);
fMatch = true;
break;
}
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in area :%s, no match for ( %s ).", pArea->name, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
if( pArea->area_num == 0 )
{
/*
* Find a unique area number
*/
for( a = 0; a < MAX_AREAS; a++ )
if( area_used[a] == NULL )
break;
pArea->area_num = a;
}
area_used[pArea->area_num] = pArea;
area_load = pArea;
return;
}
void load_door( FILE *fp )
{
EXIT_DATA *pExit;
short dir = 0;
const char *word;
bool fMatch = false;
if( room_load == NULL )
{
bug( "Load_door: no #ROOM seen yet.", 0 );
hang( "Loading doors in db.c" );
}
pExit = new EXIT_DATA;
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch( UPPER(word[0]) )
{
case '*':
fMatch = true;
fread_to_eol(fp);
break;
case 'D':
SKEY("Desc", pExit->description, fread_string(fp));
if( !str_cmp(word,"Dir") )
{
dir = fread_number(fp);
if( dir < 0 || dir > MAX_DIR )
{
bug( "Load_door: dir %d has bad door number.", dir );
hang( "Loading doors in db.c" );
}
fMatch = true;
break;
}
break;
case 'F':
if( !str_cmp(word,"Flags") )
{
const char *tmp;
tmp = fread_word(fp);
while( str_cmp(tmp,"EOL") )
{
pExit->exit_info.set(atoi(tmp));
tmp = fread_word(fp);
}
fMatch = true;
break;
}
break;
case 'K':
KEY("Key", pExit->key, fread_number(fp));
SKEY("Keyword", pExit->keyword, fread_string(fp));
break;
case 'V':
KEY("Vnum", pExit->vnum, fread_number(fp));
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in door :%s (%s), no match for ( %s ).", area_load->name, room_load->name, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
room_load->exit[dir] = pExit;
return;
}
void load_corpses( void )
{
FILE *corpsefp;
char corpse_file_name[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
snprintf( corpse_file_name, MSL, "%s", CORPSE_FILE );
snprintf( buf, MSL, "Loading %s", CORPSE_FILE);
log_f( "%s", buf );
if( ( corpsefp = file_open( corpse_file_name, "r" ) ) == NULL )
{
log_f( "Load corpse Table: file_open" );
perror( "failed open of corpse_table.dat in load_corpse_table" );
}
else
{
fpArea = corpsefp;
snprintf( strArea, MSL, "%s", corpse_file_name );
for( ;; )
{
char letter;
char *word;
letter = fread_letter( corpsefp );
if( letter == '*' )
{
fread_to_eol( corpsefp );
continue;
}
if( letter != '#' )
{
log_f( "Load_char_obj: # not found." );
break;
}
word = fread_word( corpsefp );
if( !str_cmp( word, "OBJECT" ) )
fread_corpse( corpsefp );
else if( !str_cmp( word, "END" ) )
break;
else
{
log_f( "Load_char_obj: bad section." );
break;
}
}
}
file_close( corpsefp );
fpArea = NULL;
log_f("Done.");
}
/*
* Load marked rooms
*
*/
void load_marks( void )
{
FILE *fp;
snprintf(log_buf,(2 * MIL),"Loading %s",MARKS_FILE);
log_f("%s",log_buf);
if( (fp = file_open(MARKS_FILE,"r")) == NULL )
{
file_close(fp);
log_f("No marks file to read.");
return;
}
for( ;; )
{
MARK_DATA *mark;
std::list<MARK_DATA *>::iterator li;
char letter;
do
{
letter = getc(fp);
if( feof(fp) )
{
file_close(fp);
log_f("Done.");
return;
}
}
while( isspace(letter) );
ungetc(letter,fp);
mark = new MARK_DATA;
if( str_cmp(fread_word(fp),"Room") )
break;
mark->room_vnum = fread_number(fp);
if( get_room_index(mark->room_vnum) == NULL )
{
bug("NULL room %d loading marks!",mark->room_vnum);
delete mark;
file_close(fp);
log_f("Done.");
return;
}
if( str_cmp(fread_word(fp),"Author") )
break;
mark->author = fread_string(fp);
if( str_cmp(fread_word(fp),"Duration") )
break;
mark->duration = fread_number(fp);
if( str_cmp(fread_word(fp),"Message") )
break;
mark->message = fread_string(fp);
if( str_cmp(fread_word(fp),"Type") )
break;
mark->type = fread_number(fp);
get_room_index(mark->room_vnum)->mark_list.push_back(mark);
}
bug("Load_marks: bad key word.",0);
hang("Loading marks in db.c");
return;
}
void load_bans( void )
{
FILE *bansfp;
char bans_file_name[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
snprintf( bans_file_name, MSL, "%s", BANS_FILE );
snprintf( buf, MSL, "Loading %s",BANS_FILE);
log_f( "%s", buf );
if( ( bansfp = file_open( bans_file_name, "r" ) ) == NULL )
{
log_f( "Load bans Table: file_open" );
perror( "failed open of bans_table.dat in load_bans_table" );
}
else
{
fpArea = bansfp;
snprintf( strArea, MSL, "%s", bans_file_name );
for( ;; )
{
char *word;
BAN_DATA *pban;
word = fread_string( bansfp );
if( !str_cmp( word, "#BAN" ) )
{
short get_bool = FALSE;
pban = new BAN_DATA;
get_bool = fread_number( bansfp );
if( get_bool == 1 )
pban->newbie = TRUE;
else
pban->newbie = FALSE;
pban->name = fread_string( bansfp );
pban->banned_by = fread_string( bansfp );
free_string( word );
}
else if( !str_cmp( word, "#END" ) )
{
free_string( word );
break;
}
else
{
free_string( word );
log_f( "Load_bans: bad section." );
break;
}
}
file_close( bansfp );
fpArea = NULL;
log_f("Done.");
}
}
/*
* Snarf a mob section.
*/
void load_mobile( FILE * fp )
{
MOB_INDEX_DATA *pMobIndex;
BUILD_DATA_LIST *pList;
char buf[MSL];
const char *word;
const char *tmp;
bool fMatch = false;
int vnum = 0, iHash = 0;
if( area_load == NULL )
{
bug( "Load_mobile: no #AREA seen yet.", 0 );
hang( "Loading Mobiles in db.c" );
}
pMobIndex = new MOB_INDEX_DATA;
pMobIndex->area = area_load;
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch( UPPER( word[0] ) )
{
case '*':
fMatch = true;
fread_to_eol( fp );
break;
case 'A':
KEY("AcMod",pMobIndex->ac_mod,fread_number(fp));
if( !str_cmp(word,"Act") )
{
tmp = fread_word(fp);
while( str_cmp(tmp,"EOL") )
{
pMobIndex->act.set(atoi(tmp));
tmp = fread_word(fp);
}
fMatch = true;
break;
}
KEY("Affected",pMobIndex->affected_by,fread_number(fp));
KEY("Alignment",pMobIndex->alignment,fread_number(fp));
break;
case 'C':
KEY("Cast",pMobIndex->cast,fread_number(fp));
KEY("Clan",pMobIndex->clan,fread_number(fp));
KEY("Class",pMobIndex->p_class,fread_number(fp));
break;
case 'D':
KEY("Def",pMobIndex->def,fread_number(fp));
SKEY("Desc",pMobIndex->description,fread_string(fp));
KEY("DrMod",pMobIndex->dr_mod,fread_number(fp));
break;
case 'H':
KEY("HrMod",pMobIndex->hr_mod,fread_number(fp));
break;
case 'L':
KEY("Level",pMobIndex->level,fread_number(fp));
SKEY("LongDesc",pMobIndex->long_descr,fread_string(fp));
break;
case 'P':
SKEY("PlrName",pMobIndex->player_name,fread_string(fp));
KEY("Position",pMobIndex->position,fread_number(fp));
break;
case 'R':
KEY("Race",pMobIndex->race,fread_number(fp));
KEY("RaceMods", pMobIndex->race_mods,fread_number(fp));
KEY("Resist",pMobIndex->resist,fread_number(fp));
break;
case 'S':
KEY("Sex",pMobIndex->sex,fread_number(fp));
SKEY("ShortDesc",pMobIndex->short_descr,fread_string(fp));
KEY("Skills",pMobIndex->skills,fread_number(fp));
KEY("SMagic",pMobIndex->strong_magic,fread_number(fp));
if( !str_cmp(word,"SpecFun") )
{
tmp = fread_word(fp);
if( str_cmp(tmp,"(null)") )
{
pMobIndex->spec_fun = spec_lookup(tmp);
if( pMobIndex->spec_fun == NULL )
{
snprintf(buf,MSL,"Load_mobile: spec_fun invalid for mob %d in %s.",pMobIndex->vnum,area_load->filename);
log_string(buf);
}
}
fMatch = true;
break;
}
KEY("Suscept",pMobIndex->suscept,fread_number(fp));
break;
case 'V':
if( !str_cmp(word,"Vnum") )
{
vnum = fread_number(fp);
if( vnum < area_load->min_vnum || vnum > area_load->max_vnum )
{
snprintf(buf,MSL,"Load_mobile: vnum %d out of bounds for %s.",vnum,area_load->filename);
log_string(buf);
}
fBootDb = FALSE;
if( get_mob_index( vnum ) != NULL )
{
bug( "Load_mobile: vnum %d duplicated.", vnum );
hang( "Loading Mobiles in db.c" );
}
fBootDb = TRUE;
pMobIndex->vnum = vnum;
fMatch = true;
break;
}
break;
case 'W':
KEY("WMagic",pMobIndex->weak_magic,fread_number(fp));
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in mob :%s (%s), no match for ( %s ).", area_load->name, pMobIndex->short_descr, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
iHash = vnum % MAX_KEY_HASH;
SING_TOPLINK( pMobIndex, mob_index_hash[iHash], next );
pList = new BUILD_DATA_LIST;
pList->data = pMobIndex;
LINK( pList, area_load->first_area_mobile, area_load->last_area_mobile, next, prev );
mob_load = pMobIndex;
kill_table[URANGE( 0, pMobIndex->level, MAX_LEVEL - 1 )].number++;
return;
}
void load_oaffect( FILE * fp )
{
AFFECT_DATA *pAf;
const char *word;
bool fMatch = false;
if( obj_load == NULL )
{
bug( "Load_oaffect: no #OBJECT seen yet.", 0 );
hang( "Loading Oaffects in db.c" );
}
pAf = new AFFECT_DATA;
affect_list.push_back(pAf); //Done manually due to how the "affects list" could be shared in the ctor --Kline
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch( UPPER(word[0]) )
{
case '*':
fMatch = true;
fread_to_eol(fp);
break;
case 'L':
KEY("Location", pAf->location, fread_number(fp));
break;
case 'M':
KEY("Modifier", pAf->modifier, fread_number(fp));
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in oaffect :%s (%s), no match for ( %s ).", area_load->name, obj_load->name, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
LINK( pAf, obj_load->first_apply, obj_load->last_apply, next, prev );
return;
}
/*
* Snarf an obj section.
*/
void load_object( FILE * fp )
{
OBJ_INDEX_DATA *pObjIndex;
BUILD_DATA_LIST *pList;
const char *word;
const char *tmp;
bool fMatch = false;
int vnum = 0, iHash = 0;
char buf[MSL];
if( area_load == NULL )
{
bug( "Load_object: no #AREA seen yet.", 0 );
hang( "Loading Objects in db.c" );
}
pObjIndex = new OBJ_INDEX_DATA;
pObjIndex->area = area_load;
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch( UPPER( word[0] ) )
{
case '*':
fMatch = true;
fread_to_eol( fp );
break;
case 'D':
KEY("Durability",pObjIndex->max_durability,fread_number(fp));
break;
case 'E':
if( !str_cmp(word,"ExtraFlags") )
{
tmp = fread_word(fp);
while( str_cmp(tmp,"EOL") )
{
pObjIndex->extra_flags.set(atoi(tmp));
tmp = fread_word(fp);
}
fMatch = true;
break;
}
break;
case 'I':
KEY("ItemApply",pObjIndex->item_apply,fread_number(fp));
break;
case 'L':
KEY("Level",pObjIndex->level,fread_number(fp));
SKEY("LongDesc",pObjIndex->long_descr,fread_string(fp));
break;
case 'N':
SKEY("Name",pObjIndex->name,fread_string(fp));
break;
case 'O':
if( !str_cmp(word,"ObjFun") )
{
tmp = fread_word(fp);
if( str_cmp(tmp,"(null)") )
{
pObjIndex->obj_fun = obj_fun_lookup(tmp);
if( pObjIndex->obj_fun == NULL )
{
snprintf(buf,MSL,"Load_object: obj_fun invalid for item %d in %s.",pObjIndex->vnum,area_load->filename);
log_string(buf);
}
}
fMatch = true;
break;
}
break;
case 'T':
KEY("Type",pObjIndex->item_type,fread_number(fp));
break;
case 'S':
SKEY("ShortDesc",pObjIndex->short_descr,fread_string(fp));
KEY("Speed",pObjIndex->speed,fread_float(fp));
break;
case 'V':
if( !str_cmp(word,"Values") )
{
for( short i = 0; i < MAX_OBJ_VALUE; i++ )
pObjIndex->value[i] = fread_number(fp);
fMatch = true;
break;
}
if( !str_cmp(word,"Vnum") )
{
vnum = fread_number(fp);
if( vnum < area_load->min_vnum || vnum > area_load->max_vnum )
{
snprintf(buf,MSL,"Load_object: vnum %d out of bounds for %s.",vnum,area_load->filename);
log_string(buf);
}
fBootDb = FALSE;
if( get_obj_index( vnum ) != NULL )
{
bug( "Load_object: vnum %d duplicated.", vnum );
hang( "Loading Objects in db.c" );
}
fBootDb = TRUE;
pObjIndex->vnum = vnum;
fMatch = true;
break;
}
break;
case 'W':
if( !str_cmp(word,"WearFlags") )
{
tmp = fread_word(fp);
while( str_cmp(tmp,"EOL") )
{
pObjIndex->wear_flags.set(atoi(tmp));
tmp = fread_word(fp);
}
fMatch = true;
break;
}
KEY("Weight",pObjIndex->weight,fread_number(fp));
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in obj :%s (%s), no match for ( %s ).", area_load->name, pObjIndex->short_descr, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
iHash = vnum % MAX_KEY_HASH;
SING_TOPLINK( pObjIndex, obj_index_hash[iHash], next );
pList = new BUILD_DATA_LIST;
pList->data = pObjIndex;
LINK( pList, area_load->first_area_object, area_load->last_area_object, next, prev );
obj_load = pObjIndex;
return;
}
void load_oextra( FILE * fp )
{
EXTRA_DESCR_DATA *pEd;
const char *word;
bool fMatch = false;
if( obj_load == NULL )
{
bug( "Load_oextra: no #OBJECT seen yet.", 0 );
hang( "Loading Oextras in db.c" );
}
pEd = new EXTRA_DESCR_DATA;
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch( UPPER(word[0]) )
{
case '*':
fMatch = true;
fread_to_eol(fp);
break;
case 'D':
SKEY("Desc", pEd->description, fread_string(fp));
break;
case 'K':
SKEY("Keyword", pEd->keyword, fread_string(fp));
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in oextra :%s (%s), no match for ( %s ).", area_load->name, obj_load->name, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
LINK( pEd, obj_load->first_exdesc, obj_load->last_exdesc, next, prev );
return;
}
/*
* Snarf a reset section.
*/
/* Spec: it isn't obvious how this works, so I'll add a comment here.
*
* load_resets only allows resets that are placed in current rooms - this is
* the reset_ok code here. It does _not_ check the validity of room and object
* vnums. It handles linking the resets into the appropriate room-reset-list
* for OLC.
*
* check_resets is called after all areas are loaded. It checks that all
* resets point to valid mobs and object and spits errors as necessary. It
* does _not_ touch the room lists any more!
*/
void load_resets( FILE * fp )
{
RESET_DATA *pReset = NULL;
BUILD_DATA_LIST *pList = NULL;
ROOM_INDEX_DATA *last_mob_room;
ROOM_INDEX_DATA *last_obj_room;
last_mob_room = NULL;
last_obj_room = NULL;
if( area_load == NULL )
{
bug( "Load_resets: no #AREA seen yet.", 0 );
hang( "Loading Resets in db.c" );
}
for( ;; )
{
ROOM_INDEX_DATA *pRoomIndex;
/*
* EXIT_DATA *pexit; unused?
*/
char letter;
/*
* Temp values to hold reset, while we see if valid
*/
char Tcommand;
int Targ1;
int Targ2;
int Targ3;
bool reset_ok;
reset_ok = FALSE;
if( ( letter = fread_letter( fp ) ) == 'S' )
break;
if( letter == '*' )
{
fread_to_eol( fp );
continue;
}
Tcommand = letter;
/*
* MAG Mod
*/
Targ1 = fread_number( fp );
Targ2 = fread_number( fp );
Targ3 = ( letter == 'G' || letter == 'R' ) ? 0 : fread_number( fp );
pRoomIndex = NULL; /* Set it to check for room numbers */
/*
* Validate parameters.
* We're calling the index functions for the side effect.
*/
switch ( letter )
{
default:
bug( "Load_resets: bad command '%c'.", letter );
reset_ok = FALSE;
break;
case 'A':
reset_ok = FALSE;
break; /* obsolete reset, discard */
case 'M':
if( ( pRoomIndex = get_room_index( Targ3 ) ) != NULL )
{
reset_ok = TRUE;
last_mob_room = pRoomIndex;
}
break;
case 'O':
if( ( pRoomIndex = get_room_index( Targ3 ) ) != NULL )
{
reset_ok = TRUE;
last_obj_room = pRoomIndex;
}
break;
case 'P':
if ( last_obj_room )
{
pRoomIndex = last_obj_room;
reset_ok = TRUE;
}
break;
case 'G':
case 'E':
if( last_mob_room )
{
pRoomIndex = last_mob_room;
reset_ok = TRUE;
}
break;
case 'D':
if( ( pRoomIndex = get_room_index( Targ1 ) ) != NULL )
{
reset_ok = TRUE;
}
break;
case 'R':
if( ( pRoomIndex = get_room_index( Targ1 ) ) != NULL )
{
reset_ok = TRUE;
}
break;
}
if( reset_ok ) /* i.e. only add if reset is valid. */
{
pReset = new RESET_DATA;
pReset->command = Tcommand;
pReset->arg1 = Targ1;
pReset->arg2 = Targ2;
pReset->arg3 = Targ3;
pReset->notes = fsave_to_eol( fp );
LINK( pReset, area_load->first_reset, area_load->last_reset, next, prev );
pList = new BUILD_DATA_LIST;
pList->data = pReset;
LINK( pList, pRoomIndex->first_room_reset, pRoomIndex->last_room_reset, next, prev );
}
}
return;
}
void load_rextra( FILE * fp )
{
EXTRA_DESCR_DATA *pEd;
const char *word;
bool fMatch = false;
if( room_load == NULL )
{
bug( "Load_rextra: no #ROOM seen yet.", 0 );
hang( "Loading Rextras in db.c" );
}
pEd = new EXTRA_DESCR_DATA;
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch( UPPER(word[0]) )
{
case '*':
fMatch = true;
fread_to_eol(fp);
break;
case 'D':
SKEY("Desc", pEd->description, fread_string(fp));
break;
case 'K':
SKEY("Keyword", pEd->keyword, fread_string(fp));
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in rextra :%s (%s), no match for ( %s ).", area_load->name, room_load->name, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
LINK( pEd, room_load->first_exdesc, room_load->last_exdesc, next, prev );
return;
}
/*
* Snarf a room section.
*/
void load_room( FILE * fp )
{
ROOM_INDEX_DATA *pRoomIndex;;
BUILD_DATA_LIST *pList;
char buf[MSL];
const char *tmp;
const char *word;
bool fMatch = false;
int vnum = 0, iHash;
if( area_load == NULL )
{
bug( "Load_room: no #AREA seen yet.", 0 );
hang( "Loading Rooms in db.c" );
}
pRoomIndex = new ROOM_INDEX_DATA;
pRoomIndex->area = area_load;
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch( UPPER( word[0] ) )
{
case '*':
fMatch = true;
fread_to_eol( fp );
break;
case 'D':
SKEY("Desc", pRoomIndex->description, fread_string( fp ) );
break;
case 'F':
if( !str_cmp(word,"Flags") )
{
tmp = fread_word(fp);
while( str_cmp(tmp,"EOL") )
{
pRoomIndex->room_flags.set(atoi(tmp));
tmp = fread_word(fp);
}
fMatch = true;
break;
}
break;
case 'N':
SKEY("Name", pRoomIndex->name, fread_string( fp ) );
break;
case 'S':
KEY("Sect", pRoomIndex->sector_type, fread_number( fp ) );
break;
case 'V':
if( !str_cmp(word,"Vnum") )
{
vnum = fread_number(fp);
if( vnum < area_load->min_vnum || vnum > area_load->max_vnum )
{
snprintf(buf,MSL,"Load_room: vnum %d out of bounds for %s.",vnum,area_load->filename);
log_string(buf);
}
fBootDb = FALSE;
if( get_room_index( vnum ) != NULL )
{
bug( "Load_room: vnum %d duplicated.", vnum );
hang( "Loading Rooms in db.c" );
}
fBootDb = TRUE;
pRoomIndex->vnum = vnum;
fMatch = true;
break;
}
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in room :%s (%s), no match for ( %s ).", area_load->name, pRoomIndex->name, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
if( pRoomIndex->sector_type == SECT_NULL )
pRoomIndex->sector_type = SECT_INSIDE;
iHash = vnum % MAX_KEY_HASH;
SING_TOPLINK( pRoomIndex, room_index_hash[iHash], next );
pList = new BUILD_DATA_LIST;
pList->data = pRoomIndex;
LINK( pList, area_load->first_area_room, area_load->last_area_room, next, prev );
room_load = pRoomIndex;
return;
}
/*
* Snarf a shop section.
*/
void load_shop( FILE * fp )
{
SHOP_DATA *pShop;
BUILD_DATA_LIST *pList;
MOB_INDEX_DATA *pMobIndex;
int iTrade, keeper;
const char *word;
char buf[MSL];
bool fMatch = false;
if( area_load == NULL )
{
bug( "Load_shop: no #AREA seen yet.", 0 );
hang( "Loading Shops in db.c" );
}
pShop = new SHOP_DATA;
for( ;; )
{
word = fread_word( fp );
fMatch = false;
if( !str_cmp(word,"End") )
break;
switch( UPPER( word[0] ) )
{
case '*':
fMatch = true;
fread_to_eol( fp );
break;
case 'B':
if( !str_cmp(word,"BuyType") )
{
for( iTrade = 0; iTrade < MAX_TRADE; iTrade++ )
pShop->buy_type[iTrade] = fread_number( fp );
fMatch = true;
break;
}
break;
case 'H':
KEY("HourClose",pShop->close_hour,fread_number(fp));
KEY("HourOpen",pShop->open_hour,fread_number(fp));
break;
case 'K':
if( !str_cmp(word,"Keeper") )
{
keeper = fread_number(fp);
if( keeper < area_load->min_vnum || keeper > area_load->max_vnum )
{
snprintf(buf,MSL,"Load_shop: keeper %d out of bounds for %s.",keeper,area_load->filename);
log_string(buf);
}
if( get_mob_index(keeper) == NULL )
{
snprintf(buf,MSL,"Load_shop: keeper %d not found in %s.",keeper,area_load->filename);
log_string(buf);
}
pShop->keeper = keeper;
fMatch = true;
break;
}
break;
case 'P':
KEY("ProfBuy",pShop->profit_buy,fread_number(fp));
KEY("ProfSell",pShop->profit_sell,fread_number(fp));
break;
}
}
if( !fMatch )
{
snprintf( log_buf, (2 * MIL), "Loading in shop :%s (%s), no match for ( %s ).", area_load->name, get_mob_index(pShop->keeper)->short_descr, word );
monitor_chan( log_buf, MONITOR_BAD );
fread_to_eol( fp );
}
pMobIndex = get_mob_index( pShop->keeper );
pMobIndex->pShop = pShop;
pList = new BUILD_DATA_LIST;
pList->data = pShop;
LINK( pList, area_load->first_area_shop, area_load->last_area_shop, next, prev );
return;
}
/*
* Snarf notes file.
*/
void load_notes( void )
{
FILE *fp;
snprintf(log_buf,(2 * MIL),"Loading %s",NOTE_FILE);
log_f("%s",log_buf);
if( ( fp = file_open( NOTE_FILE, "r" ) ) == NULL )
{
log_f( "No note file to read." );
return;
}
for( ;; )
{
NOTE_DATA *pnote;
char letter;
do
{
letter = getc( fp );
if( feof( fp ) )
{
file_close( fp );
log_f("Done.");
return;
}
}
while( isspace( letter ) );
ungetc( letter, fp );
pnote = new NOTE_DATA;
if( str_cmp( fread_word( fp ), "sender" ) )
break;
pnote->sender = fread_string( fp );
if( str_cmp( fread_word( fp ), "date" ) )
break;
pnote->date = fread_string( fp );
if( str_cmp( fread_word( fp ), "stamp" ) )
break;
pnote->date_stamp = fread_number( fp );
if( str_cmp( fread_word( fp ), "to" ) )
break;
pnote->to_list = fread_string( fp );
if( str_cmp( fread_word( fp ), "subject" ) )
break;
pnote->subject = fread_string( fp );
if( str_cmp( fread_word( fp ), "text" ) )
break;
pnote->text = fread_string( fp );
}
strcpy( strArea, NOTE_FILE );
fpArea = fp;
bug( "Load_notes: bad key word.", 0 );
hang( "Loading Notes in db.c" );
return;
}
/*
* Translate all room exits from virtual to real.
* Has to be done after all rooms are read in.
* Check for bad reverse exits.
*/
void fix_exits( void )
{
char buf[MAX_STRING_LENGTH];
ROOM_INDEX_DATA *pRoomIndex;
EXIT_DATA *pexit;
int iHash;
int door;
for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
{
for( pRoomIndex = room_index_hash[iHash]; pRoomIndex != NULL; pRoomIndex = pRoomIndex->next )
{
bool fexit;
fexit = FALSE;
for( door = 0; door < MAX_DIR; door++ )
{
if( ( pexit = pRoomIndex->exit[door] ) != NULL )
{
if( ( pexit->vnum <= 0 ) || ( get_room_index( pexit->vnum ) == NULL ) )
{
snprintf( buf, MSL, "Bad exit vnum %d in room %d", pexit->vnum, pRoomIndex->vnum );
bug( buf, 0 );
delete pexit;
pRoomIndex->exit[door] = NULL;
/* pexit->to_room = NULL; */
}
else
{
fexit = TRUE;
pexit->to_room = get_room_index( pexit->vnum );
}
}
}
if( !fexit )
pRoomIndex->room_flags.set(RFLAG_NO_MOB);
}
}
return;
}
/* Load up gold into areas */
void load_gold( void )
{
FILE *fpGold;
int area_num;
int gold;
AREA_DATA *pArea;
fpGold = file_open( "area.gld", "r" );
if( fpGold == NULL )
{
bug( "Could not open area.gld for reading.", 0 );
return;
}
for( ;; )
{
area_num = fread_number( fpGold );
if( area_num == -1 )
break;
gold = fread_number( fpGold );
if( ( pArea = area_used[area_num] ) != NULL )
pArea->gold = gold;
}
file_close( fpGold );
}
void load_disabled( void )
{
FILE *fp;
DISABLED_DATA *p;
const char *word;
short i;
snprintf( log_buf, (2 * MIL), "Loading %s", DISABLED_FILE);
log_f( "%s", log_buf );
if( (fp = file_open(DISABLED_FILE,"r")) == NULL )
{
log_f("Done.");
file_close(fp);
return;
}
for( ;; )
{
word = feof(fp) ? "End" : fread_word(fp);
if( !str_cmp(word,"End") )
{
file_close(fp);
log_f("Done.");
return;
}
for( i = 0; cmd_table[i].name[0] != '\0'; i++ )
if( !str_cmp(cmd_table[i].name,word) )
break;
if( cmd_table[i].name[0] == '\0' ) // Old command now removed?
{
snprintf(log_buf,(2 * MIL),"Skipping unknown command (%s) in disabled commands.",word);
log_f("%",log_buf);
fread_number(fp); // Level
fread_word(fp); // Disabled by
}
else
{
p = new DISABLED_DATA;
p->command = &cmd_table[i];
p->level = fread_number(fp);
p->disabled_by = str_dup(fread_word(fp));
}
}
log_f("Done.");
file_close(fp);
return;
}
void save_disabled( void )
{
FILE *fp;
DISABLED_DATA *p;
std::list<DISABLED_DATA *>::iterator li;
if( disabled_list.empty() )
{
unlink(DISABLED_FILE);
return;
}
if( (fp = file_open(DISABLED_FILE,"w")) == NULL )
{
bug("Couldn't open " DISABLED_FILE " for writing.",0);
file_close(fp);
return;
}
for( li = disabled_list.begin(); li != disabled_list.end(); li++ )
{
p = *li;
fprintf(fp,"%s %d %s\n",p->command->name,p->level,p->disabled_by);
}
fprintf(fp,"End\n\n");
file_close(fp);
return;
}
/* Spec: see the comments on load_resets about what check_resets does */
#define VALID_RESET 0
#define INVAL_ROOM 1
#define INVAL_OBJ 2
#define INVAL_MOB 3
#define INVAL_GEN 4
void check_resets( void )
{
AREA_DATA *pArea;
RESET_DATA *pReset;
RESET_DATA *nextReset;
ROOM_INDEX_DATA *last_mob_room;
std::list<AREA_DATA *>::iterator li;
int previous_bug = 0;
for( li = area_list.begin(); li != area_list.end(); li++ )
{
pArea = *li;
last_mob_room = NULL;
for( pReset = pArea->first_reset; pReset; pReset = nextReset )
{
ROOM_INDEX_DATA *pRoomIndex = NULL;
EXIT_DATA *pexit;
int ValReset = VALID_RESET;
nextReset = pReset->next;
switch ( pReset->command )
{
default:
SHOW_AREA;
bug( "Load_resets: bad command '%c'.", pReset->command );
ValReset = INVAL_GEN;
break;
case 'A': /* obsolete.. */
if( !get_room_index( pReset->arg1 ) )
ValReset = INVAL_ROOM;
break;
case 'M':
if( !get_mob_index( pReset->arg1 ) )
ValReset = INVAL_MOB;
if( !( last_mob_room = get_room_index( pReset->arg3 ) ) )
ValReset = INVAL_ROOM;
break;
case 'O':
if( !get_obj_index( pReset->arg1 ) )
ValReset = INVAL_OBJ;
if( !get_room_index( pReset->arg3 ) )
ValReset = INVAL_ROOM;
break;
case 'P': /* obsolete.. */
if( !get_obj_index( pReset->arg1 ) || !get_obj_index( pReset->arg3 ) )
ValReset = INVAL_OBJ;
break;
case 'G':
case 'E':
if( !get_obj_index( pReset->arg1 ) )
ValReset = INVAL_OBJ;
if( !last_mob_room )
ValReset = INVAL_ROOM;
break;
case 'D':
if( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
{
ValReset = INVAL_ROOM;
break;
}
if( pReset->arg2 < 0 || pReset->arg2 > 5 ||
!( pexit = pRoomIndex->exit[pReset->arg2] ) || !pexit->exit_info.test(EX_ISDOOR) )
{
SHOW_AREA;
bug( "Check_resets: 'D': exit %d not door.", pReset->arg2 );
ValReset = INVAL_GEN;
}
if( pReset->arg3 < 0 || pReset->arg3 > 2 )
{
SHOW_AREA;
bug( "Check_resets: 'D': bad 'locks': %d.", pReset->arg3 );
ValReset = INVAL_GEN;
}
break;
case 'R':
if( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
{
ValReset = INVAL_ROOM;
break;
}
if( pReset->arg2 < 0 || pReset->arg2 > 5 )
{
SHOW_AREA;
bug( "Check_resets: 'R': bad exit %d.", pReset->arg2 );
ValReset = INVAL_GEN;
}
break;
}
if( ValReset != VALID_RESET )
{
char buf[128];
switch ( ValReset )
{
case INVAL_ROOM:
snprintf( buf, MSL, "Invalid room for reset: " );
break;
case INVAL_OBJ:
snprintf( buf, MSL, "Invalid obj for reset: " );
break;
case INVAL_MOB:
snprintf( buf, MSL, "Invalid mob for reset: " );
break;
case INVAL_GEN:
default:
snprintf( buf, MSL, "Invalid arg for reset: " );
break;
}
SHOW_AREA;
snprintf( buf + strlen( buf ), MSL, "%c %d %d %d.", pReset->command,
pReset->arg1, pReset->arg2, pReset->arg3 );
bug( buf, 0 );
{
int room = 0;
ROOM_INDEX_DATA *reset_room;
RESET_DATA *criminal;
BUILD_DATA_LIST *guilty_reset;
room = pReset->arg1;
reset_room = get_room_index( room );
for( guilty_reset = reset_room->first_room_reset; guilty_reset; guilty_reset = guilty_reset->next )
{
criminal = (RESET_DATA *)guilty_reset->data;
if( criminal == pReset )
{
bug( "Found the reset", 0 );
break;
}
}
if( guilty_reset == NULL )
{
snprintf( bug_buf, (2 * MIL), "Uhoh, couldn't find that damn reset!" );
monitor_chan( bug_buf, MONITOR_AREA_BUGS );
bug( "Couldn't find the reset.", 0 );
}
else
{
UNLINK( guilty_reset, reset_room->first_room_reset, reset_room->last_room_reset, next, prev );
guilty_reset->data = NULL;
build_dat_list.remove(guilty_reset);
delete guilty_reset;
}
}
UNLINK( pReset, pArea->first_reset, pArea->last_reset, next, prev );
delete pReset;
}
}
}
return;
}
/*
* Repopulate areas periodically.
*/
void area_update( void )
{
AREA_DATA *pArea;
std::list<AREA_DATA *>::iterator li;
for( li = area_list.begin(); li != area_list.end(); li++ )
{
CHAR_DATA *pch;
std::list<CHAR_DATA *>::iterator pi;
pArea = *li;
pArea->age++;
/*
* Check for PC's.
*/
if( !pArea->player_list.empty() && ( pArea->age >= ( pArea->reset_rate - 1 ) ) )
{
for( pi = pArea->player_list.begin(); pi != pArea->player_list.end(); pi++ )
{
pch = *pi;
if( !IS_NPC( pch ) && IS_AWAKE( pch ) && pch->in_room != NULL && str_cmp(pArea->reset_msg,"off") )
{
char reset_buf[MSL];
snprintf( reset_buf, MSL, "%s\r\n", pArea->reset_msg );
send_to_char( reset_buf, pch );
}
}
}
/*
* Check age and reset.
* Note: Mud School resets every 3 minutes (not 15).
*/
if( ( pArea->player_list.empty() && ( pArea->age >= 5 ) ) || ( pArea->age >= pArea->reset_rate ) )
{
reset_area( pArea );
pArea->age = UMIN( pArea->reset_rate - 1, number_range( 0, 3 ) );
}
}
return;
}
/*
* Reset one area.
*/
void reset_area( AREA_DATA * pArea )
{
RESET_DATA *pReset;
CHAR_DATA *mob;
char buf[MAX_STRING_LENGTH];
bool last;
bool just_loaded = FALSE;
int level;
int previous_bug = 0;
snprintf( buf, MSL, "Area Reset called for %s.", pArea->name );
monitor_chan( buf, MONITOR_AREA_UPDATE );
area_resetting_global = TRUE;
mob = NULL;
last = TRUE;
level = 0;
for( pReset = pArea->first_reset; pReset != NULL; pReset = pReset->next )
{
ROOM_INDEX_DATA *pRoomIndex;
MOB_INDEX_DATA *pMobIndex;
OBJ_INDEX_DATA *pObjIndex;
OBJ_INDEX_DATA *pObjToIndex;
EXIT_DATA *pexit;
OBJ_DATA *obj;
OBJ_DATA *obj_to;
switch ( pReset->command )
{
default:
bug( "Reset_area: bad command %c.", pReset->command );
break;
case 'A':
break;
case 'M':
just_loaded = FALSE;
if( ( pMobIndex = get_mob_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'M': bad vnum %d.", pReset->arg1 );
continue;
}
if( ( pRoomIndex = get_room_index( pReset->arg3 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'R': bad vnum %d.", pReset->arg3 );
continue;
}
level = pMobIndex->level;
if( pReset->count >= pReset->arg2 )
{
last = FALSE;
break;
}
mob = create_mobile( pMobIndex );
mob->npcdata->reset = pReset;
pReset->count++;
just_loaded = TRUE;
/*
* Check for pet shop.
*/
{
ROOM_INDEX_DATA *pRoomIndexPrev;
pRoomIndexPrev = get_room_index( pRoomIndex->vnum - 1 );
if( pRoomIndexPrev != NULL && pRoomIndexPrev->room_flags.test(RFLAG_PET_SHOP) )
mob->act.set(ACT_PET);
}
if( room_is_dark( pRoomIndex ) )
SET_BIT( mob->affected_by, AFF_INFRARED );
if( mob->in_room != NULL )
char_to_room( mob, mob->in_room );
else
char_to_room( mob, pRoomIndex );
level = URANGE( 0, mob->level - 2, LEVEL_HERO );
last = TRUE;
break;
case 'O':
if( ( pObjIndex = get_obj_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'O': bad vnum %d.", pReset->arg1 );
continue;
}
if( ( pRoomIndex = get_room_index( pReset->arg3 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'R': bad vnum %d.", pReset->arg3 );
continue;
}
if( ( count_obj_room( pObjIndex, pRoomIndex->first_content ) >= pReset->arg2 )
|| ( ( count_obj_room( pObjIndex, pRoomIndex->first_content ) > 0 )
&& ( ( pObjIndex->item_type == ITEM_BOARD )
|| ( pObjIndex->item_type == ITEM_FOUNTAIN )
|| ( pObjIndex->item_type == ITEM_FURNITURE )
|| ( pObjIndex->item_type == ITEM_PORTAL )
|| ( pObjIndex->item_type == ITEM_PIECE ) || ( IS_OBJ_STAT(pObjIndex,ITEM_EXTRA_RARE) ) ) ) )
{
last = FALSE;
break;
}
level = pObjIndex->level;
obj = create_object( pObjIndex, level > 1 ? number_fuzzy( level ) : level );
obj->reset = pReset;
pReset->count++;
obj_to_room( obj, pRoomIndex );
if( ( IS_OBJ_STAT(obj,ITEM_EXTRA_RARE) ) && !( ( number_percent( ) < 2 ) && ( number_percent( ) < 8 ) ) )
{
extract_obj( obj );
}
else if( ( pRoomIndex->room_flags.test(RFLAG_NO_REPOP) ) && ( pRoomIndex->first_person != NULL ) )
{
extract_obj( obj );
}
last = TRUE;
break;
case 'P':
if( ( pObjIndex = get_obj_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'P': bad vnum %d.", pReset->arg1 );
continue;
}
if( ( pObjToIndex = get_obj_index( pReset->arg3 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'P': bad vnum %d.", pReset->arg3 );
continue;
}
if( ( obj_to = get_obj_type( pObjToIndex ) ) == NULL
|| count_obj_list( pObjIndex, obj_to->first_in_carry_list ) >= pReset->arg2 )
{
last = FALSE;
break;
}
level = pObjIndex->level;
obj = create_object( pObjIndex, obj_to->level > 1 ? number_fuzzy( obj_to->level ) : obj_to->level );
obj->reset = pReset;
pReset->count++;
obj_to_obj( obj, obj_to );
last = TRUE;
break;
case 'G':
case 'E':
if( ( pObjIndex = get_obj_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'E' or 'G': bad vnum %d.", pReset->arg1 );
continue;
}
if( !just_loaded )
break;
if( mob == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'E' or 'G': null mob for vnum %d.", pReset->arg1 );
last = FALSE;
break;
}
if( mob->npcdata->pIndexData->pShop != NULL )
{
int olevel;
switch ( pObjIndex->item_type )
{
default:
olevel = 0;
break;
case ITEM_PILL:
olevel = number_range( 0, 10 );
break;
case ITEM_POTION:
olevel = number_range( 0, 10 );
break;
case ITEM_SCROLL:
olevel = number_range( 5, 15 );
break;
case ITEM_WAND:
olevel = number_range( 10, 20 );
break;
case ITEM_STAFF:
olevel = number_range( 15, 25 );
break;
case ITEM_ARMOR:
olevel = number_range( 5, 15 );
break;
case ITEM_WEAPON:
olevel = number_range( 5, 15 );
break;
}
obj = create_object( pObjIndex, olevel > 1 ? number_fuzzy( olevel ) : olevel );
obj->reset = pReset;
pReset->count++;
obj->extra_flags.set(ITEM_EXTRA_INVENTORY);
}
else
{
bool has_obj = FALSE;
OBJ_DATA *carried;
for( carried = mob->first_carry; carried; carried = carried->next_in_carry_list )
{
if( carried->pIndexData == pObjIndex )
{
has_obj = TRUE;
break;
}
}
if( has_obj )
break;
level = pObjIndex->level;
obj = create_object( pObjIndex, level > 1 ? number_fuzzy( level ) : level );
obj->reset = pReset;
pReset->count++;
}
obj_to_char( obj, mob );
if( pReset->command == 'E' )
{
char objname[MSL];
one_argument( obj->name, objname );
do_wear( mob, objname );
}
last = TRUE;
break;
case 'D':
if( ( pRoomIndex = get_room_index( pReset->arg1 ) ) == NULL )
{
bug( "Reset_area: 'D': bad vnum %d.", pReset->arg1 );
continue;
}
if( ( pexit = pRoomIndex->exit[pReset->arg2] ) == NULL )
break;
switch ( pReset->arg3 )
{
case 0:
pexit->exit_info.reset(EX_CLOSED);
pexit->exit_info.reset(EX_LOCKED);
break;
case 1:
pexit->exit_info.set(EX_CLOSED);
pexit->exit_info.reset(EX_LOCKED);
break;
case 2:
pexit->exit_info.set(EX_CLOSED);
pexit->exit_info.set(EX_LOCKED);
break;
}
last = TRUE;
break;
case 'R':
if( ( pRoomIndex = get_room_index( pReset->arg1 ) ) == NULL )
{
SHOW_AREA;
bug( "Reset_area: 'R': bad vnum %d.", pReset->arg1 );
continue;
}
{
int d0;
int d1;
for( d0 = 0; d0 < pReset->arg2 - 1; d0++ )
{
d1 = number_range( d0, pReset->arg2 - 1 );
pexit = pRoomIndex->exit[d0];
pRoomIndex->exit[d0] = pRoomIndex->exit[d1];
pRoomIndex->exit[d1] = pexit;
}
}
break;
}
}
area_resetting_global = FALSE;
return;
}
/*
* Create an instance of a mobile.
*/
CHAR_DATA *create_mobile( MOB_INDEX_DATA * pMobIndex )
{
CHAR_DATA *mob;
char buf[255];
float hold = 0;
if( pMobIndex == NULL )
{
bug( "Create_mobile: NULL pMobIndex.", 0 );
hang( "Create Mobile in db.c" );
}
if( pMobIndex->act.test(ACT_INTELLIGENT) )
{
/*
* Only load one with the same name
*/
#if !defined(machintosh) && !defined(MSDOS)
snprintf( buf, MSL, "%s n%i", pMobIndex->player_name, 1 );
#else
snprintf( buf, MSL, "n%i %s", 1, pMobIndex->player_name );
#endif
}
mob = new CHAR_DATA;
mob->npcdata = new NPC_DATA;
mob->npcdata->pIndexData = pMobIndex;
if( pMobIndex->act.test(ACT_INTELLIGENT) )
mob->name = str_dup( buf );
else
mob->name = str_dup( pMobIndex->player_name );
mob->npcdata->short_descr = str_dup( pMobIndex->short_descr );
mob->long_descr = str_dup( pMobIndex->long_descr );
mob->description = str_dup( pMobIndex->description );
mob->npcdata->spec_fun = pMobIndex->spec_fun;
mob->prompt = str_dup( "<%h %m %v> " );
mob->level = pMobIndex->level;
mob->npc = true; /* New check for NPC's */
mob->act = pMobIndex->act;
mob->affected_by = pMobIndex->affected_by;
mob->alignment = pMobIndex->alignment;
mob->sex = pMobIndex->sex;
mob->ac_mod = pMobIndex->ac_mod;
mob->hr_mod = pMobIndex->hr_mod;
mob->dr_mod = pMobIndex->dr_mod;
mob->armor = interpolate( mob->level / 2, 100, -100 );
hold = mob->armor;
hold *= sysdata.mob_ac;
mob->armor = (int)hold;
mob->hitroll += (get_psuedo_level(mob) / 4);
hold = mob->hitroll;
hold *= sysdata.mob_hr;
mob->hitroll = (int)hold;
mob->damroll += (get_psuedo_level(mob) / 4);
hold = mob->damroll;
hold *= sysdata.mob_dr;
mob->damroll = (int)hold;
mob->max_hit = mob->level * 15 + number_range( mob->level * mob->level / 2, mob->level * mob->level / 1 );
hold = mob->max_hit;
hold *= sysdata.mob_hp;
mob->max_hit = (int)hold;
mob->hit = mob->max_hit;
mob->exp = exp_for_mobile( mob->level, mob );
/*
* mana for mobs...
*/
mob->max_mana = mob->level * 25;
hold = mob->max_mana;
hold *= sysdata.mob_mp;
mob->max_mana = (int)hold;
mob->mana = mob->max_mana;
/*
* move for mobs...
*/
mob->max_move = mob->level * 25;
hold = mob->max_move;
hold *= sysdata.mob_mv;
mob->max_move = (int)hold;
mob->move = mob->max_move;
mob->npcdata->skills = pMobIndex->skills;
mob->cast = pMobIndex->cast;
mob->def = pMobIndex->def;
mob->p_class = pMobIndex->p_class;
mob->clan = pMobIndex->clan;
mob->npcdata->strong_magic = pMobIndex->strong_magic;
mob->npcdata->weak_magic = pMobIndex->weak_magic;
mob->npcdata->resist = pMobIndex->resist;
mob->npcdata->suscept = pMobIndex->suscept;
mob->race_mods = pMobIndex->race_mods;
mob->race = pMobIndex->race;
mob->position = POS_STANDING;
mob->extract_timer = -1;
mob->saving_throw = (get_psuedo_level(mob) / 10);
hold = mob->saving_throw;
hold *= sysdata.mob_svs;
mob->saving_throw = (int)hold;
// Create group data for mob
if( AI_MOB( mob ) )
{
NPC_GROUP_DATA *ngroup;
ngroup = new NPC_GROUP_DATA;
ngroup->next = NULL;
ngroup->prev = NULL;
ngroup->state = GRP_STATE_IDLE;
ngroup->first_follower = NULL;
ngroup->last_follower = NULL;
ngroup->leader = mob;
ngroup->seek_room = NULL;
ngroup->enemies = str_dup( "none" );
ngroup->last_fighting = str_dup( "none" );
ngroup->wants = str_dup( "none" );
ngroup->needs = str_dup( "none" );
mob->npcdata->ngroup = ngroup;
LINK( ngroup, first_npc_group, last_npc_group, next, prev );
}
return mob;
}
/*
* Create an instance of an object.
*/
OBJ_DATA *create_object( OBJ_INDEX_DATA * pObjIndex, int level )
{
OBJ_DATA *obj;
AFFECT_DATA *af;
AFFECT_DATA *new_af;
int new_cost;
int looper;
if( level < 0 )
level = 1;
if( pObjIndex == NULL )
{
bug( "Create_object: NULL pObjIndex.", 0 );
hang( "Creating Objext in db.c" );
}
obj = new OBJ_DATA;
obj->pIndexData = pObjIndex;
obj->in_room = NULL;
if( pObjIndex->level < 3 )
{
if( pObjIndex->level == 2 )
{
obj->level = 1;
}
else
{
obj->level = level;
}
}
else
{
obj->level = pObjIndex->level;
}
obj->wear_loc = -1;
obj->name = str_dup( pObjIndex->name );
obj->short_descr = str_dup( pObjIndex->short_descr );
obj->long_descr = str_dup( pObjIndex->long_descr );
obj->item_type = pObjIndex->item_type;
obj->extra_flags = pObjIndex->extra_flags;
obj->wear_flags = pObjIndex->wear_flags;
obj->item_apply = pObjIndex->item_apply;
obj->obj_fun = pObjIndex->obj_fun;
obj->weight = pObjIndex->weight;
if( (obj->speed = pObjIndex->speed) < 0.01 || (obj->speed = pObjIndex->speed) > 4.00 )
obj->speed = number_speed();
if( (obj->max_durability = pObjIndex->max_durability) < 1 )
obj->max_durability = number_range(2,100);
obj->durability = obj->max_durability;
/*
* We want to copy pObjIndex->affected to obj->index
*/
for( af = pObjIndex->first_apply; af != NULL; af = af->next )
{
/*
* Create new_af, or use a free_affect
*/
new_af = new AFFECT_DATA;
new_af->location = af->location;
new_af->modifier = af->modifier;
LINK( new_af, obj->first_apply, obj->last_apply, next, prev );
}
for( looper = 0; looper < 10; looper++ )
{
obj->value[looper] = pObjIndex->value[looper];
}
new_cost = get_item_value( obj );
if( IS_OBJ_STAT(obj,ITEM_EXTRA_REMORT) )
new_cost *= 2;
if( IS_OBJ_STAT(obj,ITEM_EXTRA_ADEPT) )
new_cost *= 3;
if( IS_OBJ_STAT(obj,ITEM_EXTRA_RARE) )
new_cost *= 10;
obj->cost = new_cost;
if( obj->item_type == ITEM_FOOD )
obj->cost /= 200;
obj->cost = UMAX( 10, obj->cost );
/*
* Mess with object properties.
*/
switch ( obj->item_type )
{
default:
bugf( "create_object: vnum %d bad type %d.", pObjIndex->vnum, obj->item_type );
break;
case ITEM_CHARM:
case ITEM_ANVIL:
case ITEM_COOKING_FIRE:
case ITEM_ALCHEMY_LAB:
case ITEM_FORGE:
case ITEM_LOOM:
case ITEM_SPELL_MATRIX:
case ITEM_ENCHANTMENT:
case ITEM_LIGHT:
case ITEM_BEACON:
case ITEM_TREASURE:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_CLUTCH:
break;
case ITEM_CONTAINER:
obj->wear_flags.set(ITEM_TAKE);
case ITEM_DRINK_CON:
case ITEM_BOARD:
case ITEM_KEY:
case ITEM_FOOD:
case ITEM_BOAT:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_FOUNTAIN:
case ITEM_PORTAL:
case ITEM_PIECE:
case ITEM_SOUL:
case ITEM_TRIGGER:
case ITEM_STAKE:
case ITEM_QUEST:
case ITEM_WRAPPED_PRESENT:
break;
case ITEM_SCROLL:
obj->value[0] = number_fuzzy( obj->value[0] );
break;
case ITEM_WAND:
case ITEM_STAFF:
obj->value[0] = number_fuzzy( obj->value[0] );
obj->value[1] = number_fuzzy( obj->value[1] );
obj->value[2] = obj->value[1];
break;
case ITEM_WEAPON:
obj->value[1] = number_fuzzy( obj->value[1] );
obj->value[2] = number_fuzzy( obj->value[2] );
break;
case ITEM_ARMOR:
obj->value[0] = number_fuzzy( level / 12 + 4 );
break;
case ITEM_POTION:
case ITEM_PILL:
obj->value[0] = number_fuzzy( number_fuzzy( obj->value[0] ) );
break;
case ITEM_MONEY:
obj->value[0] = obj->cost;
break;
}
if( pObjIndex->value[7] > 0 )
obj->timer = pObjIndex->value[7];
return obj;
}
/*
* Get an extra description from a list.
*/
char *get_extra_descr( const char *name, EXTRA_DESCR_DATA * ed )
{
for( ; ed != NULL; ed = ed->next )
{
if( is_name( name, ed->keyword ) )
return ed->description;
}
return NULL;
}
/*
* Translates mob virtual number to its mob index struct.
* Hash table lookup.
*/
MOB_INDEX_DATA *get_mob_index( int vnum )
{
MOB_INDEX_DATA *pMobIndex;
for( pMobIndex = mob_index_hash[vnum % MAX_KEY_HASH]; pMobIndex != NULL; pMobIndex = pMobIndex->next )
{
if( pMobIndex->vnum == vnum )
return pMobIndex;
}
if( fBootDb )
{
bug( "Get_mob_index: bad vnum %d.", vnum );
hang( "Get mob index in db.c" );
}
return NULL;
}
/*
* Translates mob virtual number to its obj index struct.
* Hash table lookup.
*/
OBJ_INDEX_DATA *get_obj_index( int vnum )
{
OBJ_INDEX_DATA *pObjIndex;
for( pObjIndex = obj_index_hash[vnum % MAX_KEY_HASH]; pObjIndex != NULL; pObjIndex = pObjIndex->next )
{
if( pObjIndex->vnum == vnum )
return pObjIndex;
}
if( fBootDb )
{
bug( "Get_obj_index: bad vnum %d.", vnum );
hang( "Get Object Index in db.c" );
}
return NULL;
}
/*
* Translates mob virtual number to its room index struct.
* Hash table lookup.
*/
ROOM_INDEX_DATA *get_room_index( int vnum )
{
ROOM_INDEX_DATA *pRoomIndex;
for( pRoomIndex = room_index_hash[vnum % MAX_KEY_HASH]; pRoomIndex != NULL; pRoomIndex = pRoomIndex->next )
{
if( pRoomIndex->vnum == vnum )
return pRoomIndex;
}
if( fBootDb )
{
bug( "Get_room_index: bad vnum %d.", vnum );
/* exit( 1 ); */
}
return NULL;
}
/*
* Read a letter from a file.
*/
char fread_letter( FILE * fp )
{
char c;
do
{
c = getc( fp );
}
while( isspace( c ) );
return c;
}
/*
* Read a float number from a file. Turn the result into a float value.
* Taken from AFKMud by Samson
*/
float fread_float( FILE *fp )
{
float number;
bool sign, decimal;
char c;
int place = 0;
do
{
if( feof(fp) )
{
bug("fread_float: EOF encountered on read.",0);
if( fBootDb )
{
bug( "Corrupt file somewhere.",0);
exit(1);
}
return 0;
}
c = getc( fp );
}
while( isspace(c) );
number = 0;
sign = FALSE;
decimal = FALSE;
if( c == '+' )
c = getc( fp );
else if( c == '-' )
{
sign = TRUE;
c = getc( fp );
}
if( !isdigit(c) )
{
bug( "Fread_float: bad format. (%c)", c );
if( fBootDb )
exit( 1 );
return 0;
}
while( 1 )
{
if( c == '.' || isdigit(c) )
{
if( c == '.' )
{
decimal = TRUE;
c = getc( fp );
}
if( feof(fp) )
{
bug("fread_float: EOF encountered on read.",0);
if( fBootDb )
exit( 1 );
return number;
}
if( !decimal )
number = number * 10 + c - '0';
else
{
place++;
number += pow( 10, ( -1 * place ) ) * ( c - '0' );
}
c = getc( fp );
}
else break;
}
if( sign )
number = 0 - number;
if( c == '|' )
number += fread_float( fp );
else if( c != ' ' )
ungetc( c, fp );
return number;
}
/*
* Read a number from a file.
*/
int fread_number( FILE * fp )
{
int number;
bool sign;
char c;
do
{
c = getc( fp );
}
while( isspace( c ) );
number = 0;
sign = FALSE;
if( c == '+' )
{
c = getc( fp );
}
else if( c == '-' )
{
sign = TRUE;
c = getc( fp );
}
if( !isdigit( c ) )
{
char error_buf[MSL];
snprintf( error_buf, MSL, "%c", c );
bug_string( "Fread_number: looking for a digit, found a %s.", error_buf );
hang( "Error in fread_number" );
}
while( isdigit( c ) )
{
number = number * 10 + c - '0';
c = getc( fp );
}
if( sign )
number = 0 - number;
if( c == '|' )
number += fread_number( fp );
else if( c != ' ' )
ungetc( c, fp );
return number;
}
/*
* Read to end of line (for comments).
*/
/* Spec: fixed to handle EOF more gracefully */
void fread_to_eol( FILE * fp )
{
char c;
do
{
c = getc( fp );
}
while( c != '\n' && c != '\r' && c != EOF );
while( c == '\n' || c == '\r' )
{
c = getc( fp );
}
if( c == EOF )
{
bugf( "fread_to_eol: EOF" );
return;
}
ungetc( c, fp );
return;
}
/* Same as above, but returns the rest of the line */
/* Spec: fixed to handle EOF more gracefully */
char *fsave_to_eol( FILE * fp )
{
char string[MAX_INPUT_LENGTH + 1];
int a;
char c;
a = 0;
do
{
string[a++] = getc( fp );
}
while( a < MAX_INPUT_LENGTH && string[a - 1] != '\n' && string[a - 1] != '\r' && string[a - 1] != EOF );
if( string[a - 1] == EOF )
{
bugf( "fsave_to_eol: EOF" );
string[a - 1] = 0;
return str_dup( string );
}
if( a == MAX_INPUT_LENGTH )
fread_to_eol( fp );
else
{
c = string[a - 1];
while( c == '\n' || c == '\r' )
c = getc( fp );
if( c == EOF )
bugf( "fsave_to_eol: EOF" );
else
ungetc( c, fp );
}
string[a] = '\0';
return str_dup( string );
}
/*
* Read one word (into static buffer).
*/
char *fread_word( FILE * fp )
{
static char word[MAX_INPUT_LENGTH];
char *pword;
char cEnd;
do
{
if( feof( fp ) )
{
bug( "fread_word: EOF encountered on read.\r\n", 0 );
if( fBootDb )
kill( getpid( ), SIGQUIT );
strcpy( word, "" );
return word;
}
cEnd = getc( fp );
}
while( isspace( cEnd ) );
if( cEnd == '\'' || cEnd == '"' )
{
pword = word;
}
else
{
word[0] = cEnd;
pword = word + 1;
cEnd = ' ';
}
for( ; pword < word + MAX_INPUT_LENGTH; pword++ )
{
if( feof( fp ) )
{
bug( "fread_word: EOF encountered on read.\r\n", 0 );
if( fBootDb )
kill( getpid( ), SIGQUIT );
*pword = '\0';
return word;
}
*pword = getc( fp );
if( cEnd == ' ' ? isspace( *pword ) : *pword == cEnd )
{
if( cEnd == ' ' )
ungetc( *pword, fp );
*pword = '\0';
return word;
}
}
bug( "Fread_word: word too long", 0 );
kill( getpid( ), SIGQUIT );
return NULL;
}
void *_getmem( int size, const char *caller, int log )
{
void *mem;
if( !( mem = malloc( size ) ) )
{
fprintf( stderr, "Out of memory.\n" );
raise( SIGSEGV );
}
memset( mem, 0, size );
if( log && mem_log )
log_f( "getmem(%d)=%p from %s", size, mem, caller );
return mem;
}
void do_areas( CHAR_DATA * ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
char msg[MAX_STRING_LENGTH];
char arg1[MSL];
short foo;
AREA_DATA *pArea;
std::list<AREA_DATA *>::iterator li;
bool fall = FALSE;
argument = one_argument( argument, arg1 );
if( !str_cmp( arg1, "all" ) )
fall = TRUE;
snprintf( buf, MSL, "@@W" mudnamecolor " AREA LISTING\r\n" );
strncat( buf, "+-------+------------+------------------------------------------------+\r\n", MSL );
strncat( buf, "| @@yLevel@@W | | |\r\n", MSL );
strncat( buf, "| @@yrange@@W | @@yAuthor@@W | @@yName of Area@@W |\r\n", MSL );
strncat( buf, "+-------+------------+------------------------------------------------+\r\n", MSL );
foo = 0;
for( li = area_list.begin(); li != area_list.end(); li++ )
{
pArea = *li;
if( pArea->flags.test(AFLAG_NOSHOW) || pArea->flags.test(AFLAG_BUILDING) )
continue; /* for non-finished areas - don't show */
if( ( !fall )
&& ( ( pArea->min_level > ( get_psuedo_level( ch ) ) ) || ( pArea->max_level < ( get_psuedo_level( ch ) ) ) ) )
continue;
foo++;
snprintf( msg, MSL, " %s %12s %s\r\n", pArea->level_label, capitalize( pArea->owner ), pArea->name );
strncat( buf, msg, MSL );
}
snprintf( msg, MSL, "@@R%d Areas listed.\r\n@@N Type areas all to list the entire " mudnamecolor " realm.\r\n@@N", foo );
strncat( buf, msg, MSL );
send_to_char( buf, ch );
return;
}
void perm_update( )
{
/*
* output perm usage to log file
*/
FILE *po;
char *strtime;
po = file_open( "perm.out", "a" );
strtime = ctime( ¤t_time );
strtime[strlen( strtime ) - 1] = '\0';
fprintf( po, "%s :: Perms %5d blocks of %7d bytes.\r\n", strtime, nAllocPerm, sAllocPerm );
file_close( po );
return;
}
void do_memory( CHAR_DATA * ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
if( !str_cmp( argument, "defrag" ) )
{
send_to_char( "Defragmenting SSM heap.", ch );
log_f( "SSM: %s called defrag_heap.", ch->name );
defrag_heap( );
return;
}
if( !str_cmp( argument, "log" ) )
{
if( get_trust( ch ) < MAX_LEVEL )
{
send_to_char( "Not at your level.\r\n", ch );
return;
}
if( mem_log )
{
mem_log = FALSE;
send_to_char( "Memory logging is now OFF.\r\n", ch );
log_f( "%s turned off memory logging", ch->name );
return;
}
else
{
mem_log = TRUE;
send_to_char( "Memory logging is now ON.. remember to turn it off!\r\n", ch );
log_f( "%s turned on memory logging", ch->name );
return;
}
}
snprintf( buf, MSL, "Affects %5d\r\n", affect_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Areas %5d\r\n", area_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "ExDes %5d\r\n", exdesc_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Exits %5d\r\n", exit_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Helps %5d\r\n", count_helps() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Mobs %5d\r\n", mob_index_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Objs %5d\r\n", obj_index_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Resets %5d\r\n", reset_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Rooms %5d\r\n", room_index_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Shops %5d\r\n", shop_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Shared String Info:\r\n" );
send_to_char( buf, ch );
snprintf( buf, MSL, "Strings %5ld strings of %7ld bytes (max %ld).\r\n", nAllocString, sAllocString, MAX_STRING );
send_to_char( buf, ch );
snprintf( buf, MSL, "Overflow Strings %5ld strings of %7ld bytes.\r\n", nOverFlowString, sOverFlowString );
send_to_char( buf, ch );
if( Full )
{
send_to_char( "Shared String Heap is full, increase MAX_STRING.\r\n", ch );
snprintf( buf, MSL, "Overflow high-water-mark is %ld bytes.\r\n", hwOverFlow );
send_to_char( buf, ch );
}
snprintf( buf, MSL, "Perms %5d blocks of %7d bytes.\r\n", nAllocPerm, sAllocPerm );
send_to_char( buf, ch );
snprintf( buf, MSL, "Freelist Info: Gets: %5d Puts: %5d\r\n",free_get,free_put);
send_to_char( buf, ch );
snprintf( buf, MSL, "File Streams: Opens: %5d Closes: %5d\r\n",fp_open,fp_close);
send_to_char( buf, ch );
return;
}
void do_status( CHAR_DATA * ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
send_to_char( " Status Report for Ack! Mud:\r\n", ch );
send_to_char( " ---------------------------\r\n\r\n", ch );
do_time( ch, "" );
send_to_char( "\r\n", ch );
send_to_char( "The following counts are for *distinct* mobs/objs/rooms, not a count\r\n", ch );
send_to_char( "of how many are actually in the game at this time.\r\n", ch );
snprintf( buf, MSL, "Areas %5d\r\n", area_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Helps %5d\r\n", count_helps() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Mobs %5d\r\n", mob_index_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Objs %5d\r\n", obj_index_list.size() );
send_to_char( buf, ch );
snprintf( buf, MSL, "Rooms %5d\r\n", room_index_list.size() );
send_to_char( buf, ch );
return;
}
/*
* Generate a random float for weapon speed.
*/
float number_speed(void)
{
float s1, s2, s3, value = 0.00;
s1 = number_range(1,4);
s2 = ((number_range(0,4) + 0.00) / 10);
s3 = ((number_range(0,4) + 0.00) / 100);
value = s1+s2+s3;
if (value > 4.00)
value = 4.00;
return value;
}
/*
* Stick a little fuzz on a number.
*/
int number_fuzzy( int number )
{
switch ( number_bits( 2 ) )
{
case 0:
number -= 1;
break;
case 3:
number += 1;
break;
}
return UMAX( 1, number );
}
/*
* Generate a random number.
*/
int number_range( int from, int to )
{
int power;
int number;
if( ( to = to - from + 1 ) <= 1 )
return from;
for( power = 2; power < to; power <<= 1 )
;
while( ( number = number_mm( ) & ( power - 1 ) ) >= to )
;
return from + number;
}
/*
* Generate a percentile roll.
*/
int number_percent( void )
{
int percent;
while( ( percent = number_mm( ) & ( 128 - 1 ) ) > 99 )
;
return 1 + percent;
}
/*
* Generate a random door.
*/
int number_door( void )
{
int door;
while( ( door = number_mm( ) & ( 8 - 1 ) ) > 5 )
;
return door;
}
int number_bits( int width )
{
return number_mm( ) & ( ( 1 << width ) - 1 );
}
/*
* I've gotten too many bad reports on OS-supplied random number generators.
* This is the Mitchell-Moore algorithm from Knuth Volume II.
* Best to leave the constants alone unless you've read Knuth.
* -- Furey
*/
static int rgiState[2 + 55];
void init_mm( )
{
int *piState;
int iState;
piState = &rgiState[2];
piState[-2] = 55 - 55;
piState[-1] = 55 - 24;
piState[0] = ( ( int )current_time ) & ( ( 1 << 30 ) - 1 );
piState[1] = 1;
for( iState = 2; iState < 55; iState++ )
{
piState[iState] = ( piState[iState - 1] + piState[iState - 2] ) & ( ( 1 << 30 ) - 1 );
}
return;
}
int number_mm( void )
{
int *piState;
int iState1;
int iState2;
int iRand;
piState = &rgiState[2];
iState1 = piState[-2];
iState2 = piState[-1];
iRand = ( piState[iState1] + piState[iState2] ) & ( ( 1 << 30 ) - 1 );
piState[iState1] = iRand;
if( ++iState1 == 55 )
iState1 = 0;
if( ++iState2 == 55 )
iState2 = 0;
piState[-2] = iState1;
piState[-1] = iState2;
return iRand >> 6;
}
/*
* Roll some dice.
*/
int dice( int number, int size )
{
int idice;
int sum;
switch ( size )
{
case 0:
return 0;
case 1:
return number;
}
for( idice = 0, sum = 0; idice < number; idice++ )
sum += number_range( 1, size );
return sum;
}
/*
* Simple linear interpolation.
*/
int interpolate( int level, int value_00, int value_32 )
{
return value_00 + level * ( value_32 - value_00 ) / 32;
}
/*
* Append a string to a file.
*/
void append_file( CHAR_DATA * ch, char *file, char *str )
{
FILE *fp;
char buf[MSL];
if( IS_NPC( ch ) || str[0] == '\0' )
return;
if( ( fp = file_open( file, "a" ) ) == NULL )
{
file_close(fp);
perror( file );
send_to_char( "Could not open the file!\r\n", ch );
}
else
{
snprintf( buf, MSL, "[%5d] %s: %s\n", ch->in_room ? ch->in_room->vnum : 0, ch->name, str );
fprintf(fp,"%s",buf);
buf[strlen(buf)-1] = '\0'; /* Strip newline */
if( !str_cmp(file,TYPO_FILE) )
monitor_chan(buf,MONITOR_TYPO);
else if( !str_cmp(file,IDEA_FILE) )
monitor_chan(buf,MONITOR_IDEA);
else if( !str_cmp(file,BUG_FILE) )
monitor_chan(buf,MONITOR_BUG);
file_close( fp );
}
return;
}
/*
* Nice little functions that limit the amount of typing you have to do with
* each and every log File entry and bug report.---Flar
*/
void bugf( char *fmt, ... )
{
char buf[MSL];
va_list args;
va_start( args, fmt );
vsnprintf( buf, sizeof( buf ), fmt, args );
va_end( args );
bug( buf, 0 );
}
void log_f( char *fmt, ... )
{
char buf[2 * MSL];
va_list args;
va_start( args, fmt );
vsnprintf( buf, sizeof( buf ), fmt, args );
va_end( args );
log_string( buf );
}
/*
* Reports a bug.
*/
void bug( const char *str, int param )
{
char buf[MAX_STRING_LENGTH];
FILE *fp;
if( fpArea != NULL )
{
int iLine;
int iChar;
if( fpArea == stdin )
{
iLine = 0;
}
else
{
iChar = ftell( fpArea );
fseek( fpArea, 0, 0 );
for( iLine = 0; ftell( fpArea ) < iChar; iLine++ )
{
while( getc( fpArea ) != '\n' )
;
}
fseek( fpArea, iChar, 0 );
}
snprintf( buf, MSL, "[*****] FILE: %s LINE: %d", strArea, iLine );
log_string( buf );
if( ( fp = file_open( SHUTDOWN_FILE, "a" ) ) != NULL )
{
fprintf( fp, "[*****] %s\n", buf );
file_close( fp );
}
}
if( param > 0 )
snprintf( buf, MSL, "[*****] BUG: %s %d", str, param );
else
snprintf( buf, MSL, "[*****] BUG: %s", str );
log_string( buf );
if( ( fp = file_open( BUG_FILE, "a" ) ) != NULL )
{
fprintf( fp, "%s\n", buf );
file_close( fp );
}
return;
}
void bug_string( const char *str, const char *str2 )
{
char buf[MAX_STRING_LENGTH];
FILE *fp;
if( fpArea != NULL )
{
int iLine;
int iChar;
if( fpArea == stdin )
{
iLine = 0;
}
else
{
iChar = ftell( fpArea );
fseek( fpArea, 0, 0 );
for( iLine = 0; ftell( fpArea ) < iChar; iLine++ )
{
while( getc( fpArea ) != '\n' )
;
}
fseek( fpArea, iChar, 0 );
}
snprintf( buf, MSL, "[*****] FILE: %s LINE: %d", strArea, iLine );
log_string( buf );
if( ( fp = file_open( SHUTDOWN_FILE, "a" ) ) != NULL )
{
fprintf( fp, "[*****] %s\n", buf );
file_close( fp );
}
}
snprintf( buf, MSL, "[*****] BUG: %s %s", str, str2 );
log_string( buf );
if( ( fp = file_open( BUG_FILE, "a" ) ) != NULL )
{
fprintf( fp, "%s\n", buf );
file_close( fp );
}
return;
}
/*
* Writes a string to the log.
*/
void log_string( const char *str )
{
char *strtime;
strtime = ctime( ¤t_time );
strtime[strlen( strtime ) - 1] = '\0';
fprintf( stderr, "%s :: %s\n", strtime, str );
monitor_chan(str,MONITOR_LOG);
return;
}
/*
* This function is here to aid in debugging.
* If the last expression in a function is another function call,
* gcc likes to generate a JMP instead of a CALL.
* This is called "tail chaining."
* It hoses the debugger call stack for that call.
* So I make this the last call in certain critical functions,
* where I really need the call stack to be right for debugging!
*
* If you don't understand this, then LEAVE IT ALONE.
* Don't remove any calls to tail_chain anywhere.
*
* -- Furey
*/
void tail_chain( void )
{
return;
}
void message_update( void )
{
RESET_DATA *pReset;
AREA_DATA *pArea;
ROOM_INDEX_DATA *pRoom;
CHAR_DATA *ch;
std::list<AREA_DATA *>::iterator li;
for( li = area_list.begin(); li != area_list.end(); li++ )
{
pArea = *li;
for( pReset = pArea->first_reset; pReset != NULL; pReset = pReset->next )
{
if( pReset->command != 'A' )
continue;
if( ( pRoom = get_room_index( pReset->arg1 ) ) == NULL )
{
bug( "message_update, no room %d found.", pReset->arg1 );
continue;
}
for( ch = pRoom->first_person; ch != NULL; ch = ch->next_in_room )
if( ch->level >= pReset->arg2 && ch->level <= pReset->arg3 )
send_to_char( pReset->notes, ch );
}
}
return;
}
bool char_exists( char *argument )
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
bool found = FALSE;
snprintf( buf, MSL, "%s%s%s%s", PLAYER_DIR, initial( argument ), "/", capitalize( argument ) );
if( ( fp = file_open( buf, "r" ) ) != NULL )
found = TRUE;
file_close( fp );
return found;
}
int bv_log( int n )
{
int result = 0;
while( n > 0 )
{
n >>= 1;
result++;
}
return result;
}
void check_chistory( CHAR_DATA *ch, int channel )
{
short x,y = 0;
bool found = FALSE;
char buf[MAX_STRING_LENGTH];
x = (bv_log(channel)-1);
for( y = 0; y < MAX_HISTORY; y++ )
if( chan_history.message[x][y][0] != '\0' )
{
if( IS_IMMORTAL(ch) )
{
found = TRUE;
snprintf(buf,MSL,"[%s",ctime(&chan_history.time[x][y]));
buf[(strlen(buf)-1)] = '\0'; /* I realize how ugly this chunk looks but it was */
strncat(buf,"] ",MSL); /* necessary to get around ctime adding a newline --Kline */
strncat(buf,chan_history.message[x][y],MSL);
send_to_char(buf,ch);
}
else if( ch->logon <= chan_history.time[x][y] )
{
switch( channel )
{
default: found = TRUE; send_to_char(chan_history.message[x][y],ch); break;
case CHANNEL_DIPLOMAT:
if( ch->act.test(ACT_CDIPLOMAT) )
{
found = TRUE;
send_to_char(chan_history.message[x][y],ch);
}
break;
case CHANNEL_REMORTTALK:
if( is_remort(ch) )
{
found = TRUE;
send_to_char(chan_history.message[x][y],ch);
}
break;
case CHANNEL_YELL:
if( !str_cmp(ch->in_room->area->name,chan_history.aname[x][y]) )
{
found = TRUE;
send_to_char(chan_history.message[x][y],ch);
}
break;
case CHANNEL_CLAN:
if( ch->clan == chan_history.cbit[x][y] )
{
send_to_char(buf,ch);
found = TRUE;
send_to_char(chan_history.message[x][y],ch);
}
break;
case CHANNEL_RACE:
if( ch->race == chan_history.cbit[x][y] )
{
found = TRUE;
send_to_char(chan_history.message[x][y],ch);
}
break;
case CHANNEL_FAMILY:
if( IS_VAMP(ch) && ch->pcdata->super->bloodline == chan_history.cbit[x][y] )
{
found = TRUE;
send_to_char(chan_history.message[x][y],ch);
}
break;
case CHANNEL_HOWL:
if( IS_WOLF(ch) && ch->pcdata->super->bloodline == chan_history.cbit[x][y] )
{
found = TRUE;
send_to_char(chan_history.message[x][y],ch);
}
break;
}
}
}
if( !found )
send_to_char("No history available for that channel yet.\r\n",ch);
return;
}
void update_chistory( CHAR_DATA *ch, char *argument, int channel )
{
short x,y = 0;
x = (bv_log(channel)-1);
for( y = 0; y < MAX_HISTORY; y++ )
{
if( chan_history.message[x][y] == '\0' )
{
snprintf(chan_history.message[x][y],MSL,"%s: %s@@N\r\n",NAME(ch),argument);
chan_history.time[x][y] = current_time;
snprintf(chan_history.aname[x][y],128,"none");
chan_history.cbit[x][y] = -1;
switch( channel )
{
default: break;
case CHANNEL_YELL: snprintf(chan_history.aname[x][y],128,"%s",ch->in_room->area->name); break;
case CHANNEL_CLAN: chan_history.cbit[x][y] = ch->clan; break;
case CHANNEL_RACE: chan_history.cbit[x][y] = ch->race; break;
case CHANNEL_FAMILY: if( !IS_NPC(ch) ) chan_history.cbit[x][y] = ch->pcdata->super->bloodline; break;
case CHANNEL_HOWL: if( !IS_NPC(ch) ) chan_history.cbit[x][y] = ch->pcdata->super->bloodline; break;
}
break;
}
if( y == (MAX_HISTORY -1) )
{
int i = 0;
for( i = 1; i < MAX_HISTORY; i++ )
{
snprintf(chan_history.message[x][(i-1)],MSL,"%s",chan_history.message[x][i]);
chan_history.time[x][(i-1)] = chan_history.time[x][i];
snprintf(chan_history.aname[x][(i-1)],128,"%s",chan_history.aname[x][i]);
chan_history.cbit[x][(i-1)] = chan_history.cbit[x][i];
}
chan_history.message[x][y][0] = '\0';
chan_history.time[x][y] = 0;
chan_history.aname[x][y][0] = '\0';
chan_history.cbit[x][y] = 0;
snprintf(chan_history.message[x][y],MSL,"%s: %s@@N\r\n",NAME(ch),argument);
chan_history.time[x][y] = current_time;
snprintf(chan_history.aname[x][y],128,"none");
chan_history.cbit[x][y] = -1;
switch( channel )
{
default: break;
case CHANNEL_YELL: snprintf(chan_history.aname[x][y],128,"%s",ch->in_room->area->name); break;
case CHANNEL_CLAN: chan_history.cbit[x][y] = ch->clan; break;
case CHANNEL_RACE: chan_history.cbit[x][y] = ch->race; break;
case CHANNEL_FAMILY: if( !IS_NPC(ch) ) chan_history.cbit[x][y] = ch->pcdata->super->bloodline; break;
case CHANNEL_HOWL: if( !IS_NPC(ch) ) chan_history.cbit[x][y] = ch->pcdata->super->bloodline; break;
}
}
}
return;
}
int count_helps( void )
{
char buf[MSL];
char tmp[MSL];
snprintf(tmp,MSL,"expr `ls -1 -R %s | wc -l` - 26",HELP_DIR);
snprintf(buf,MSL,"%s",_popen(tmp));
return atoi(buf);
}
int count_skills( void )
{
int cnt = 0;
while( skill_table[cnt].name != NULL )
cnt++;
return cnt;
}
char *search_helps( const char *string )
{
static char ret[MSL];
char tmp[MSL] = {'\0'};
char *t_buf;
char *t_out;
char *pipe;
t_buf = (char *)calloc(1,sizeof(char));
t_out = (char *)calloc(1,sizeof(char));
pipe = (char *)calloc(1,sizeof(char));
snprintf(tmp,MSL,"%s",_popen(string));
pipe = tmp;
for( t_out = strtok_r(pipe,"\n",&t_buf); t_out != NULL; t_out = strtok_r(NULL,"\n",&t_buf) )
{
t_out += 9; /* Strip off ../helps/ at the start, edit if you change your HELP_DIR */
snprintf(tmp,MSL,"%s",t_out);
tmp[strlen(tmp)-4] = '\0'; /* Strip off .ext at the end, edit if you change HELP_MORT or HELP_IMM */
snprintf(ret,MSL,"%s ",tmp);
}
t_buf = NULL;
free(t_buf);
t_out = NULL;
free(t_out);
pipe = NULL;
free(pipe);
return ret;
}
char *_popen( const char *string )
{
static char ret[MSL];
char tmp[MSL];
FILE *fp;
ret[0] = '\0';
tmp[0] = '\0';
if( fpReserve != NULL )
{
fclose(fpReserve);
fpReserve = NULL;
}
if( (fp = popen(string,"r")) == NULL )
snprintf(ret,MSL,"%s","");
else
{
while( fgets(tmp,MSL,fp) )
{
if( ret[0] == '\0' )
snprintf(ret,MSL,"%s",tmp);
else
strncat(ret,tmp,MSL);
}
}
fp_open++;
fp_close++;
fclose(fp);
if( fpReserve == NULL )
{
fpReserve = fopen(NULL_FILE,"r");
}
return ret;
}
FILE *file_open( const char *file, const char *opt )
{
FILE *fp;
if( fpReserve != NULL )
{
fclose(fpReserve);
fpReserve = NULL;
}
fp = fopen(file,opt);
return fp;
}
void file_close( FILE *file )
{
if( file != NULL )
{
fflush(file);
fclose(file);
}
if( fpReserve == NULL )
{
fpReserve = fopen(NULL_FILE,"r");
}
return;
}
void clear_lists( void )
{
DESCRIPTOR_DATA *d, *d_next;
extern hash_table *hash_changed_vnums;
for( d = first_desc; d != NULL; d = d_next )
{
d_next = d->next;
delete d;
}
for_each( affect_list.begin(), affect_list.end(), DeleteObject() );
for_each( area_list.begin(), area_list.end(), DeleteObject() );
for_each( ban_list.begin(), ban_list.end(), DeleteObject() );
for_each( board_list.begin(), board_list.end(), DeleteObject() );
for_each( build_dat_list.begin(), build_dat_list.end(), DeleteObject() );
for_each( char_list.begin(), char_list.end(), DeleteObject() );
for_each( disabled_list.begin(), disabled_list.end(), DeleteObject() );
for_each( exdesc_list.begin(), exdesc_list.end(), DeleteObject() );
for_each( exit_list.begin(), exit_list.end(), DeleteObject() );
for_each( file_list.begin(), file_list.end(), DeleteObject() );
for_each( mob_index_list.begin(), mob_index_list.end(), DeleteObject() );
for_each( note_list.begin(), note_list.end(), DeleteObject() );
for_each( obj_list.begin(), obj_list.end(), DeleteObject() );
for_each( obj_index_list.begin(), obj_index_list.end(), DeleteObject() );
for_each( reset_list.begin(), reset_list.end(), DeleteObject() );
for_each( room_index_list.begin(), room_index_list.end(), DeleteObject() );
for_each( shop_list.begin(), shop_list.end(), DeleteObject() );
comlog(NULL,true,0,NULL);
fclose(fpReserve);
delete_hash_table(hash_changed_vnums);
free(string_space);
free(social_table);
#ifdef IMC
free_imcdata(true);
#endif
}