/***************************************************************************
* Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming *
* License by Wizards of the Coast. All comments referring to D20, OGL, *
* and SRD refer to the System Reference Document for the Open Gaming *
* system. Any inclusion of these derivatives must include credit to the *
* Mud20 system, the full and complete Open Gaming LIcense, and credit to *
* the respective authors. See ../doc/srd.txt for more information. *
* *
* Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. *
* *
* MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey *
* *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. *
***************************************************************************/
/***************************************************************************
* db.c: Server load, loop and event functions *
***************************************************************************/
#include <sys/time.h>
#include <stdarg.h>
#include "mud.h"
/*
Locals.
*/
AREA_DATA *area_load;
int tot_memory_warning = 0;
CHAR_DATA *supermob;
OBJ_DATA *supermob_obj;
ROOM_INDEX_DATA *supermob_room;
void create_menu_tree();
/*
Cpu management
*/
lg_int timers[TIMER_MAXTIMER][5];
const char timer_strings[TIMER_MAXTIMER][40] =
{
"Area Save Time:",
"Update Shops:",
"Update Character:",
"Update Areas:",
"Update Weather:",
"Update Objects:",
"Char Save Time:",
"Update Violence:",
"Update Obj Progs:",
"Update Mob Progs:",
"Update Mobiles:",
"Update Aggressive:",
"Update Purger:",
"Update Tactical:",
"Scan Descriptor:",
"Process Input:",
"Process Output:",
"Update Time:",
};
/*
Memory management
*/
#define MAX_PERM_BLOCK 1000000
#define MAX_MEM_LIST 48
const int rgSizeList [MAX_MEM_LIST] =
{
8, 16, 24, 32,
40, 48, 56, 64,
80, 96, 112, 128,
144, 160, 176, 192,
224, 256, 288, 320,
352, 384, 416, 448,
512, 576, 640, 704,
768, 832, 896, 960,
1088, 1216, 1344, 1472,
1728, 1984, 2240, 2496,
3072, 4096, 6144, 8192,
16384, 32768, 65536, 72016
};
void * alloc_perm ( bool iList );
typedef struct perm_block_list PERM_BLOCK_LIST;
struct perm_block_list
{
int iMemPerm;
};
PERM_BLOCK_LIST *perm_block_index[ 255 ]; /* Maximum perm blocks of 256 */
typedef struct free_mem_list FREE_MEM_LIST;
struct free_mem_list
{
FREE_MEM_LIST * next;
};
FREE_MEM_LIST *rgFreeList [MAX_MEM_LIST];
int rgFreeCount[MAX_MEM_LIST]; /* count of freed memory */
int rgUsedCount[MAX_MEM_LIST]; /* count of used memory */
/*
Semi-locals.
*/
FILE * fpArea;
char strArea[MAX_INPUT_LENGTH];
/*
Local booting procedures.
*/
void load_auth_list args( ( void ) ); /* New Auth Code */
void save_auth_list args( ( void ) );
void save_style args( (int num) );
void save_styles args( ( void ) );
void load_style args( (int num) );
void load_styles args( ( void ) );
void save_races args( ( void ) );
void load_races args( ( void ) );
void save_domain args( (int num) );
void save_domains args( ( void ) );
void load_domain args( (int num) );
void load_domains args( ( void ) );
void save_god args( (int num) );
void save_gods args( ( void ) );
void load_god args( (int num) );
void load_gods args( ( void ) );
void fread_components args( ( void ) );
void fread_bloodlines args( ( void ) );
void save_class args( (int num) );
void save_classes args( ( void ) );
void load_classes args( ( void ) );
void load_area args( ( FILE *fp, int segment ) );
void load_helps args( ( FILE *fp ) );
void load_mobiles args( ( FILE *fp ) );
void load_objects args( ( FILE *fp ) );
void load_resets args( ( FILE *fp ) );
void load_rooms args( ( FILE *fp ) );
void load_shops args( ( FILE *fp ) );
void load_inns args( ( FILE *fp ) );
void load_stables args( ( FILE *fp ) );
void load_specials args( ( FILE *fp ) );
void load_ranges args( ( FILE *fp ) );
void load_version args( ( FILE *fp ) );
void load_olc_ranges args( ( FILE *fp ) );
void load_resetmsg args( ( FILE *fp ) );
void load_justice args( ( FILE *fp ) );
void load_authors args( ( FILE *fp ) );
void load_flags args( ( FILE *fp ) );
void load_temperature args( ( FILE *fp ) );
void load_weather args( ( FILE *fp ) );
void load_repairs args( ( FILE *fp ) );
void load_fk_mobiles args( ( FILE *fp ) );
void load_fk_objects args( ( FILE *fp ) );
void load_fk_rooms args( ( FILE *fp ) );
void load_fk_weather args( ( FILE *fp ) );
void load_fk_weather args( ( FILE *fp ) );
OBJ_PROG * load_object_program args( ( FILE *fp ) );
void obj_prog_if_dest args( ( OBJ_INDEX_DATA * ) );
void expand_mob_prog args( ( MOB_INDEX_DATA * , OBJ_INDEX_DATA *, ROOM_INDEX_DATA *, MPROG_DATA * ) );
char expand_line_mprog args( ( MOB_INDEX_DATA * , OBJ_INDEX_DATA *, ROOM_INDEX_DATA *, MPROG_DATA *, char *, bool, char ) );
RESET_DATA * get_reset_from_obj args( ( RESET_DATA *lReset ) );
RESET_DATA * get_reset_from_mob args( ( RESET_DATA *lReset ) );
RESET_DATA * get_reset_from_trap args( ( RESET_DATA *lReset ) );
/*
MOBprogram locals
*/
void mprog_read_programs args ( ( FILE* fp, MOB_INDEX_DATA *pMobIndex ) );
void init_supermob( void )
{
supermob = create_mobile( get_mob_index( 3 ) );
char_to_room( supermob, 3, FALSE );
}
/*
* convert a bitvector to a string - Kregor
*/
char *bits_to_str(lg_int number, char *vector)
{
char *buf;
lg_int cnt;
push_call("bits_to_str(%p,%p)",number,vector);
for (cnt = 0 ; *bitvector_table[cnt].name != '\0' ; cnt++)
{
if (!str_prefix(vector, bitvector_table[cnt].name))
{
if (number == bitvector_table[cnt].value)
{
pop_call();
return (bitvector_table[cnt].name);
}
}
}
sprintf(buf, "%lld", number );
pop_call();
return buf;
}
/*
* convert a string to a bitvector
* if no value found, return 0 - Kregor
*/
lg_int str_to_bits(char *vector)
{
lg_int cnt;
push_call("str_to_bits(%p)",vector);
for (cnt = 0 ; *bitvector_table[cnt].name != '\0' ; cnt++)
{
if (!strcasecmp(vector, bitvector_table[cnt].name))
{
pop_call();
return (bitvector_table[cnt].value);
}
}
pop_call();
return 0;
}
/*
* Return a string of bitvectors - Kregor
*/
char *broken_bits( lg_int number, char *vector, bool linear )
{
lg_int bit, cnt;
bool found;
static char broken_string[MAX_INPUT_LENGTH];
push_call("broken_bits(%p,%p,%p)",number,vector,linear);
if (IS_SET(mud->flags, MUD_STRAIGHTNUMBERS))
{
sprintf(broken_string, "%lld" , number);
pop_call();
return broken_string;
}
found = FALSE;
bit = 0;
broken_string[0] = '\0';
if (!linear)
{
while (bit <= number && number >= 0)
{
if (IS_SET(number, bit))
{
for (cnt = mud->bitvector_ref[*vector - 'A'] ; *bitvector_table[cnt].name != '\0' ; cnt++)
{
if (bit == bitvector_table[cnt].value)
{
if (!str_prefix(vector, bitvector_table[cnt].name))
{
if (found)
{
strcat( broken_string, "|" );
}
strcat(broken_string, bitvector_table[cnt].name);
found = TRUE;
break;
}
}
}
if (*bitvector_table[cnt].name == '\0')
{
if (found)
{
strcat(broken_string, "|" );
}
log_printf("broken_bits: %s not found %lld", vector, bit);
cat_sprintf(broken_string, "%lld", bit);
found = TRUE;
}
}
if (bit != 0)
{
bit *= 2;
}
else
{
bit++;
}
}
}
else
{
for (cnt = mud->bitvector_ref[*vector - 'A'] ; *bitvector_table[cnt].name != '\0' ; cnt++)
{
if (number == bitvector_table[cnt].value)
{
if (vector[0] == bitvector_table[cnt].name[0] && !str_prefix(vector, bitvector_table[cnt].name))
{
strcat(broken_string, bitvector_table[cnt].name);
found = TRUE;
break;
}
}
}
}
if (!found)
{
sprintf(broken_string, "%lld", number);
}
pop_call();
return( broken_string);
}
/*
* for use in load_mobiles in db.c to
* advance simple mobiles by hit dice - Kregor
*
* Compares hard set level to hit dice in race file,
* advances mobile based on difference.
*/
void advance_mobile( MOB_INDEX_DATA *mob )
{
int lvl, cnt;
push_call("resize_mobile(%p)", mob);
// do not run on custom non-raced mobiles
if (mob->race == RACE_NONE)
{
pop_call();
return;
}
// if classed, levels are class levels
if (mob->class != CLASS_MONSTER)
{
pop_call();
return;
}
// humanoids and fey advance by class levels
switch (race_table[mob->race].type)
{
default:
break;
case RTYPE_HUMANOID:
case RTYPE_MONSTROUS:
case RTYPE_FEY:
pop_call();
return;
}
if (race_table[mob->race].hit_dice >= mob->level)
{
pop_call();
return;
}
/* can't get any bigger than this... */
if (race_table[mob->race].size >= SIZE_COLOSSAL)
{
pop_call();
return;
}
lvl = race_table[mob->race].hit_dice;
// dragons get special advancement rules
if (race_table[mob->race].type == RTYPE_DRAGON)
{
int sizeplus;
lvl = UMAX(0, mob->level - lvl);
switch(lvl / 2)
{
default:
sizeplus = 5;
mob->perm_dex = UMAX(1, mob->perm_dex - 8);
break;
case 0:
sizeplus = 0;
break;
case 1:
sizeplus = 1;
mob->perm_dex = UMAX(1, mob->perm_dex - 2);
break;
case 2:
case 3:
sizeplus = 2;
mob->perm_dex = UMAX(1, mob->perm_dex - 4);
break;
case 4:
case 5:
case 6:
sizeplus = 3;
mob->perm_dex = UMAX(1, mob->perm_dex - 6);
break;
case 7:
case 8:
case 9:
case 10:
sizeplus = 4;
mob->perm_dex = UMAX(1, mob->perm_dex - 8);
break;
}
if (sizeplus)
{
mob->size = UMIN(mob->size + sizeplus, SIZE_COLOSSAL);
mob->nat_armor += lvl * 3 / 2;
mob->perm_str += lvl + 2;
if (lvl >= 4)
mob->perm_str += 2;
mob->perm_con += sizeplus * 2;
mob->perm_int += lvl / 2 + 1;
mob->perm_wis += lvl / 2 + 1;
mob->perm_cha += lvl / 2 + 1;
}
}
else if (mob->level >= ROUNDUP(lvl * 3 / 2))
{
// size up & add stat mods for size
for (cnt = mob->size ; cnt <= SIZE_COLOSSAL ; cnt++)
{
if (mob->level < ROUNDUP(lvl * 3 / 2)) // mob level is less than 50% more, no resize
break;
if (mob->size == SIZE_COLOSSAL)
break;
lvl *= 3;
lvl = ROUNDUP(lvl/2);
if (mob->size > SIZE_FINE)
mob->perm_str += mob->size;
if (mob->size < SIZE_GARGANTUAN)
mob->perm_dex = UMAX(3, mob->perm_dex - 2);
if (mob->size > SIZE_TINY)
{
mob->perm_con += mob->size / 2;
mob->nat_armor += mob->size - 3;
}
mob->size++;
}
}
// add points to racial skills for advancement
for (cnt = 0 ; is_string(skill_table[cnt].name) ; cnt++)
{
if (skill_table[cnt].skilltype != FSKILL_SKILL)
continue;
if (skill_table[cnt].race_skill[mob->race])
mob->learned[cnt] += UMAX(0, mob->level - race_table[mob->race].hit_dice);
}
pop_call();
return;
}
/*
Big mama top level function.
*/
void boot_db( bool fCopyOver )
{
lg_int boot_start, boot_end;
int index, cnt;
push_call("boot_db(%p)",fCopyOver);
boot_start = get_game_usec();
SET_BIT(mud->flags, MUD_EMUD_BOOTING);
SET_BIT(mud->flags, MUD_EMUD_BOOTDB);
srand48(mud->current_time);
log_string("Loading Bitvector Table...");
for (index = 0 ; index < 26 ; index++)
{
for (cnt = 0 ; *bitvector_table[cnt].name != '\0' ; cnt++)
{
if (bitvector_table[cnt].name[0] == 'A' + index)
{
/*
log_printf("bitvector_ref[%c] = %d", 'A' + index, cnt);
*/
mud->bitvector_ref[index] = cnt;
break;
}
}
}
load_sites();
load_nsites();
load_usage();
load_players();
load_timeinfo();
load_bounties();
load_victors();
load_hiscores();
load_classes();
load_domains();
load_styles();
load_races();
load_gods();
fread_components();
fread_bloodlines();
/*
Assign table indexes - Scandum
*/
for (index = 0 ; index < 26 ; index++)
{
for (cnt = 0 ; *cmd_table[cnt].name != '\0' ; cnt++)
{
if (*cmd_table[cnt].name == 'a' + index)
{
/*
log_printf("command_ref[%c] = %d", 'a' + index, cnt);
*/
mud->command_ref[index] = cnt;
break;
}
}
}
for (index = 0 ; index < 26 ; index++)
{
for (cnt = 0 ; *social_table[cnt].name != '\0' ; cnt++)
{
if (*social_table[cnt].name == 'a' + index)
{
/*
log_printf("social_ref[%c] = %d", 'a' + index, cnt);
*/
mud->social_ref[index] = cnt;
break;
}
}
}
/* removed dependency on MAX_SKILL changing,
* MAX_REAL_SKILL advances until a skill with no
* name is reached in skill table - Kregor
*/
for (cnt = MAX_REAL_SKILL = 0 ; *skill_table[cnt].name != '\0' ; cnt++)
{
if (skill_table[cnt].pgsn != NULL)
{
/*
log_printf("skill_table[%03d].name = %s", cnt, skill_table[cnt].name);
*/
*skill_table[cnt].pgsn = cnt;
}
MAX_REAL_SKILL++;
}
/*
Read in all the area files.
*/
{
FILE *fpList;
log_printf("Loading Areas");
if ((fpList = my_fopen(AREA_LIST, "r", FALSE)) == NULL)
{
perror( AREA_LIST );
abort();
}
while (TRUE)
{
strcpy(strArea, fread_word(fpList));
log_string(strArea);
if (strArea[0] == '$')
{
break;
}
if ((fpArea = my_fopen(strArea, "r", FALSE)) == NULL)
{
perror( strArea );
abort( );
}
fread_area(fpArea, 0);
my_fclose(fpArea);
fpArea = NULL;
}
if (fpList)
{
my_fclose( fpList );
}
}
if (mud->time_info->hour < 5)
{
mud->sunlight = SUN_DARK;
}
else if (mud->time_info->hour < 6)
{
mud->sunlight = SUN_RISE;
}
else if ( mud->time_info->hour < 11 )
{
mud->sunlight = SUN_LIGHT;
}
else if ( mud->time_info->hour < 15 )
{
mud->sunlight = SUN_NOON;
}
else if ( mud->time_info->hour < 19 )
{
mud->sunlight = SUN_LIGHT;
}
else if ( mud->time_info->hour < 20 )
{
mud->sunlight = SUN_SET;
}
else
{
mud->sunlight = SUN_DARK;
}
SET_BIT(mud->flags, MUD_EMUD_BOOTDB);
log_string("Loading the SuperMob");
init_supermob();
log_string("Updating Areas");
area_update();
REMOVE_BIT(mud->flags, MUD_EMUD_BOOTDB);
log_string("Loading Notes");
load_notes();
log_string("Creating Menu Tree");
create_menu_tree();
log_string("Loading Saved Storerooms");
load_lockers();
log_string( "Loading Clans" );
load_clans();
log_string( "Loading Auth Name list" );
load_auth_list( );
save_auth_list( );
REMOVE_BIT(mud->flags, MUD_EMUD_BOOTING);
{
/*
Clear out timers
*/
int cnt;
for (cnt = 0 ; cnt < TIMER_MAXTIMER ; cnt++)
{
timers[cnt][0] = 0;
timers[cnt][1] = 0;
timers[cnt][2] = 0;
timers[cnt][3] = 0;
timers[cnt][4] = 0;
}
}
if (fCopyOver)
{
copyover_recover();
}
boot_end = get_game_usec();
log_printf("Database booted in %lld usec!", boot_end - boot_start);
pop_call();
return;
}
void fread_area(FILE *fp, int segment)
{
char *word;
push_call("fread_area(%p,%p)",fp, segment);
while (TRUE)
{
if (fread_letter(fp) != '#')
{
bug( "Boot_db: # not found.", 0 );
abort( );
}
word = fread_word(fp);
switch (word[0])
{
case '$':
pop_call();
return;
case 'A':
if (!strcmp(word, "AREA"))
{
load_area(fp, segment);
break;
}
if (!strcmp(word, "AUTHORS") || !strcmp(word, "AUTHOR") )
{
load_authors(fp);
break;
}
case 'F':
if (!strcmp(word, "FLAGS"))
{
load_flags(fp);
break;
}
case 'E':
if (!strcmp(word, "ECONOMY")) // For loading FKMud areas with stupid economy - Kregor
{
break;
}
case 'H':
if (!strcmp(word, "HELPS"))
{
load_helps(fp);
break;
}
case 'I':
if (!strcmp(word, "INNS"))
{
load_inns(fp);
break;
}
case 'J':
if (!strcmp(word, "JUSTICE"))
{
load_justice(fp);
break;
}
case 'M':
if (!strcmp(word, "MOBILES"))
{
if (area_load->version == 99)
load_fk_mobiles(fp);
else
load_mobiles(fp);
break;
}
case 'O':
if (!strcmp(word, "OLC_RANGES"))
{
load_olc_ranges(fp);
break;
}
if (!strcmp(word, "OBJECTS"))
{
if (area_load->version == 99)
load_fk_objects(fp);
else
load_objects (fp);
break;
}
case 'Q':
if (!strcmp(word, "QUESTS")) // here til I can reverse engineer it - Kregor
{
break;
}
case 'R':
if (!strcmp(word, "RANGES"))
{
load_ranges(fp);
break;
}
if (!strcmp(word, "REPAIRS")) // Because FKMud uses the silly Smaug way - Kregor
{
load_resetmsg(fp);
break;
}
if (!strcmp(word, "RESETMSG"))
{
load_resetmsg(fp);
break;
}
if (!strcmp(word, "RESETS"))
{
load_resets(fp);
break;
}
if (!strcmp(word, "ROOMS"))
{
if (area_load->version == 99)
load_fk_rooms(fp);
else
load_rooms(fp);
break;
}
case 'S':
if (!strcmp(word, "SHOPS"))
{
load_shops(fp);
break;
}
if (!strcmp(word, "SPECIALS"))
{
load_specials(fp);
break;
}
if (!strcmp(word, "STABLES"))
{
load_stables(fp);
break;
}
case 'T':
if (!strcmp(word, "TEMPERATURE"))
{
load_temperature(fp);
break;
}
case 'V':
if (!strcmp(word, "VERSION"))
{
load_version(fp);
break;
}
case 'W':
if (!strcmp(word, "WEATHER"))
{
if (area_load->version == 99)
load_fk_weather(fp);
else
load_weather(fp);
break;
}
default:
bug("boot_db: bad section name: %s", word);
abort( );
}
}
}
/*
Snarf an 'area' header line.
*/
void load_area ( FILE *fp, int segment )
{
AREA_DATA *pArea, *temp_area;
int cnt;
push_call("load_area(%p,%p)",fp,segment);
ALLOCMEM(pArea, AREA_DATA, 1);
pArea->name = fread_string( fp );
pArea->age = 99;
pArea->version = 0;
pArea->low_r_vnum = MAX_VNUM-1;
pArea->low_o_vnum = MAX_VNUM-1;
pArea->low_m_vnum = MAX_VNUM-1;
pArea->olc_range_lo = MAX_VNUM-1;
pArea->resetmsg = STRDUPE(str_empty);
pArea->hi_soft_range = MAX_LEVEL;
pArea->hi_hard_range = MAX_LEVEL;
pArea->authors = STRDUPE(str_empty);
for (cnt = 0 ; cnt < CRIME_MAX ; cnt++)
{
pArea->punishment[cnt] = 0;
}
pArea->courtroom = 0;
pArea->dungeon = 0;
pArea->judge = 0;
pArea->guard = 0;
ALLOCMEM(pArea->weather_info, WEATHER_DATA, 1);
pArea->weather_info->temp_winter = -10;
pArea->weather_info->temp_summer = 20;
pArea->weather_info->temp_daily = 10;
pArea->weather_info->wind_scale = 4;
pArea->weather_info->wet_scale = 4;
{
for (temp_area = mud->f_area ; temp_area ; temp_area = temp_area->next)
{
if (strcmp(pArea->name, temp_area->name) < 0)
{
INSERT_LEFT(pArea, temp_area, mud->f_area, next, prev);
break;
}
}
if (!temp_area)
{
LINK(pArea, mud->f_area, mud->l_area, next, prev);
}
mud->top_area++;
}
pArea->filename = STRALLOC(strArea);
area_load = pArea;
pop_call();
return;
}
void load_temperature( FILE * fp )
{
push_call("load_temperature(%p)",fp);
fread_number(fp);
fread_number(fp);
fread_number(fp);
fread_number(fp);
pop_call();
return;
}
void load_weather( FILE * fp )
{
push_call("load_weather(%p)",fp);
area_load->weather_info->temp_winter = fread_number(fp);
area_load->weather_info->temp_summer = fread_number(fp);
area_load->weather_info->temp_daily = fread_number(fp);
area_load->weather_info->wet_scale = fread_number(fp);
area_load->weather_info->wind_scale = fread_number(fp);
pop_call();
return;
}
void load_flags( FILE *fp )
{
if (area_load->version < 2 || area_load->version == 99)
{
fread_number(fp);
fread_number(fp);
}
else
{
area_load->flags = fread_number(fp);
}
}
void load_authors( FILE *fp )
{
push_call("load_authors(%p)",fp);
STRFREE(area_load->authors);
area_load->authors = fread_string(fp);
pop_call();
return;
}
void load_ranges( FILE *fp )
{
push_call("load_ranges(%p)",fp);
area_load->low_soft_range = fread_number( fp );
area_load->hi_soft_range = fread_number( fp );
area_load->low_hard_range = fread_number( fp );
area_load->hi_hard_range = fread_number( fp );
if (area_load->low_soft_range > area_load->hi_soft_range)
{
log_printf("Low soft range is greater than high soft range.");
}
if (area_load->low_hard_range > area_load->hi_hard_range)
{
log_printf("Low hard range is greater than high hard range.");
}
pop_call();
return;
}
void load_version( FILE *fp )
{
push_call("load_version(%p)",fp);
area_load->version = fread_number(fp);
pop_call();
return;
}
void load_olc_ranges( FILE *fp )
{
push_call("load_olc_ranges(%p)",fp);
area_load->olc_range_lo = fread_number( fp );
area_load->olc_range_hi = fread_number( fp );
pop_call();
return;
}
void load_resetmsg( FILE *fp )
{
push_call("load_resetmsg(%p)",fp);
STRFREE( area_load->resetmsg );
area_load->resetmsg = fread_string( fp );
pop_call();
return;
}
void load_justice( FILE *fp )
{
char *word;
push_call("load_justice(%p)",fp);
while (TRUE)
{
word = fread_word(fp);
switch (word[0])
{
case '$':
pop_call();
return;
case 'C':
if (!strcmp(word, "Courtroom"))
{
area_load->courtroom = fread_number(fp);
break;
}
if (!strcmp(word, "Crime"))
{
area_load->punishment[fread_number(fp)] = fread_number(fp);
break;
}
case 'D':
if (!strcmp(word, "Dungeon"))
{
area_load->dungeon = fread_number(fp);
break;
}
case 'G':
if (!strcmp(word, "Guard"))
{
area_load->guard = fread_number(fp);
break;
}
case 'J':
if (!strcmp(word, "Judge"))
{
area_load->judge = fread_number(fp);
break;
}
case 'S':
if (!strcmp(word, "Storeroom"))
{
area_load->storeroom = fread_number(fp);
break;
}
default:
bug("load_justice: bad section name: %s", word);
abort( );
}
}
pop_call();
return;
}
/*
Snarf a help section.
*/
void load_helps( FILE *fp )
{
HELP_DATA *pHelp;
push_call("load_helps(%p)",fp);
while (TRUE)
{
ALLOCMEM(pHelp, HELP_DATA, 1);
pHelp->level = fread_number( fp );
pHelp->keyword = fread_string( fp );
if (pHelp->keyword[0] == '$')
{
FREEMEM(pHelp);
break;
}
if (IS_SET(area_load->flags, AFLAG_NEWHELPS))
{
pHelp->title = fread_string( fp );
}
pHelp->text = fread_string( fp );
pHelp->area = area_load;
LINK( pHelp, area_load->first_help, area_load->last_help, next, prev );
mud->top_help++;
}
pop_call();
return;
}
/*
Add a character to the list of all characters
*/
void add_char( CHAR_DATA *ch )
{
push_call("add_char(%p)",ch);
if (!IS_NPC(ch))
{
LINK(ch, mud->f_char, mud->l_char, next, prev);
}
else
{
LINK(ch, mud->f_char, mud->l_char, next, prev);
LINK(ch, ch->pIndexData->first_instance, ch->pIndexData->last_instance, next_instance, prev_instance);
}
pop_call();
return;
}
/*
Snarf a mob section.
*/
void load_mobiles( FILE *fp )
{
MOB_INDEX_DATA *pMobIndex;
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *paf;
char buf[256], *pt;
int vnum, sn, value;
char letter;
push_call("load_mobiles(%p)",fp);
while (TRUE)
{
letter = fread_letter( fp );
if (letter != '#')
{
bug( "Load_mobiles: # not found.", 0 );
abort( );
}
vnum = fread_number( fp );
if (vnum == 0)
{
break;
}
if (vnum < 1 || vnum >= MAX_VNUM)
{
bug("load_mobiles: vnum %u out of range.", vnum);
abort( );
}
if (get_mob_index(vnum) != NULL)
{
bug("load_mobiles: vnum %u duplicated.", vnum);
abort( );
}
ALLOCMEM(pMobIndex, MOB_INDEX_DATA, 1);
pMobIndex->vnum = vnum;
mob_index[vnum] = pMobIndex;
pMobIndex->area = area_load;
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
if (area_load->low_m_vnum > vnum)
{
area_load->low_m_vnum = vnum;
}
if (vnum > area_load->hi_m_vnum)
{
area_load->hi_m_vnum = vnum;
}
}
pt = fread_string( fp ); /* Add M### system to names */
sprintf( buf, "m%u", vnum );
if (strstr(pt, buf) == NULL)
{
sprintf( buf, "%s m%u", pt, vnum );
}
else
{
strcpy( buf, pt );
}
STRFREE (pt);
pMobIndex->player_name = STRALLOC(buf);
/* pMobIndex->player_name = fread_string( fp ); */
pMobIndex->short_descr = fread_string( fp );
pMobIndex->long_descr = fread_string( fp );
pMobIndex->description = fread_string( fp );
pMobIndex->unique = FALSE;
/* The read section for the new mob format starts HERE - Kregor 3/13/07 */
if (area_load->version >= 4)
{
letter = fread_letter( fp );
if (letter == 'U')
pMobIndex->unique = TRUE;
else if (letter == 'S')
pMobIndex->unique = FALSE;
else
{
bug( "Load_mobiles: vnum %u not U or S.", vnum );
abort( );
}
pMobIndex->level = fread_number( fp );
pMobIndex->class = fread_number( fp );
pMobIndex->race = fread_number( fp );
pMobIndex->sex = fread_number( fp );
pMobIndex->position = fread_number( fp );
pMobIndex->god = fread_number( fp );
pMobIndex->act = fread_number( fp );
// Adjust old area levels to Mud20 standard - Kregor
if (!IS_SET(pMobIndex->act, ACT_MOBINVIS))
pMobIndex->level = URANGE(1, pMobIndex->level, 30);
if (!pMobIndex->unique)
{
if (pMobIndex->race <= RACE_NONE)
{
bug( "Load_mobiles: no race set on S mobile.", vnum );
pMobIndex->race = RACE_HUMAN;
}
if (pMobIndex->class != CLASS_MONSTER && pMobIndex->class < MAX_CLASS)
pMobIndex->hitsizedice = class_table[pMobIndex->class].hp_max;
else if (pMobIndex->race > RACE_NONE)
pMobIndex->hitsizedice = race_type_table[race_table[pMobIndex->race].type].hit_die;
else
{
bug( "Load_mobiles: neither class nor race hit die.", vnum );
pMobIndex->hitsizedice = 8;
}
pMobIndex->alignment = race_table[pMobIndex->race].alignment;
pMobIndex->ethos = race_table[pMobIndex->race].ethos;
pMobIndex->gold = 0; // need to add means to determine standard random gold
/*
* assign stats based on class pri and sec stats
* These routines effectively gives standard NPCs
* an elite array of abilities - Kregor
*/
if (pMobIndex->class > CLASS_MONSTER)
{
int class = pMobIndex->class;
if (class_table[class].attr_prime == APPLY_STR)
pMobIndex->perm_str = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[0];
else if (class_table[class].attr_second == APPLY_STR)
pMobIndex->perm_str = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[0];
else
pMobIndex->perm_str = best_three_of_four() + race_table[pMobIndex->race].race_mod[0];
if (class_table[class].attr_prime == APPLY_DEX)
pMobIndex->perm_dex = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[1];
else if (class_table[class].attr_second == APPLY_DEX)
pMobIndex->perm_dex = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[1];
else
pMobIndex->perm_dex = best_three_of_four() + race_table[pMobIndex->race].race_mod[1];
if (class_table[class].attr_prime == APPLY_CON)
pMobIndex->perm_con = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[2];
else if (class_table[class].attr_second == APPLY_CON)
pMobIndex->perm_con = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[2];
else
pMobIndex->perm_con = best_three_of_four() + race_table[pMobIndex->race].race_mod[2];
if (class_table[class].attr_prime == APPLY_INT)
pMobIndex->perm_int = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[3];
else if (class_table[class].attr_second == APPLY_INT)
pMobIndex->perm_int = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[3];
else
pMobIndex->perm_int = best_three_of_four() + race_table[pMobIndex->race].race_mod[3];
if (class_table[class].attr_prime == APPLY_WIS)
pMobIndex->perm_wis = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[4];
else if (class_table[class].attr_second == APPLY_WIS)
pMobIndex->perm_wis = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[4];
else
pMobIndex->perm_wis = best_three_of_four() + race_table[pMobIndex->race].race_mod[4];
if (class_table[class].attr_prime == APPLY_CHA)
pMobIndex->perm_cha = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[5];
else if (class_table[class].attr_second == APPLY_CHA)
pMobIndex->perm_cha = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[5];
else
pMobIndex->perm_cha = best_three_of_four() + race_table[pMobIndex->race].race_mod[5];
}
else
{
pMobIndex->perm_str = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[0];
pMobIndex->perm_int = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[1];
pMobIndex->perm_wis = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[2];
pMobIndex->perm_dex = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[3];
pMobIndex->perm_con = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[4];
pMobIndex->perm_cha = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[5];
}
// zero out nonabilities by race
if (race_table[pMobIndex->race].nonability[STAT_STR])
pMobIndex->perm_str = 0;
if (race_table[pMobIndex->race].nonability[STAT_DEX])
pMobIndex->perm_dex = 0;
if (race_table[pMobIndex->race].nonability[STAT_CON])
pMobIndex->perm_con = 0;
if (race_table[pMobIndex->race].nonability[STAT_INT])
pMobIndex->perm_int = 0;
if (race_table[pMobIndex->race].nonability[STAT_WIS])
pMobIndex->perm_wis = 0;
if (race_table[pMobIndex->race].nonability[STAT_CHA])
pMobIndex->perm_cha = 0;
pMobIndex->nat_armor = race_table[pMobIndex->race].nat_armor;
pMobIndex->wear_locs = race_table[pMobIndex->race].wear_locs;
pMobIndex->size = race_table[pMobIndex->race].size;
pMobIndex->understands = race_table[pMobIndex->race].understands;
pMobIndex->speaks = race_table[pMobIndex->race].speaks;
}
else
{
pMobIndex->affected_by = fread_number( fp );
pMobIndex->nat_armor = fread_number( fp );
pMobIndex->armor_type = fread_number( fp );
/* 'd' */ fread_letter( fp );
if (pMobIndex->class > CLASS_MONSTER && pMobIndex->class < MAX_CLASS)
{
fread_number( fp );
pMobIndex->hitsizedice = class_table[pMobIndex->class].hp_max;
}
else if (pMobIndex->race > RACE_NONE)
{
fread_number( fp );
pMobIndex->hitsizedice = race_type_table[race_table[pMobIndex->race].type].hit_die;
}
else
{
pMobIndex->hitsizedice = fread_number( fp );
}
/* '+' */ fread_letter( fp );
pMobIndex->hitplus = fread_number( fp );
// damage stats no longer used in Mud20, but keeping in file
fread_number( fp );
/* 'd' */ fread_letter( fp );
fread_number( fp );
/* '+' */ fread_letter( fp );
fread_number( fp );
pMobIndex->alignment = fread_number( fp );
pMobIndex->ethos = fread_number( fp );
pMobIndex->gold = fread_number( fp );
pMobIndex->perm_str = fread_number( fp );
pMobIndex->perm_int = fread_number( fp );
pMobIndex->perm_wis = fread_number( fp );
pMobIndex->perm_dex = fread_number( fp );
pMobIndex->perm_con = fread_number( fp );
pMobIndex->perm_cha = fread_number( fp );
if (!pMobIndex->race)
{
pMobIndex->body_type = fread_number( fp );
pMobIndex->wear_locs = fread_number( fp );
pMobIndex->size = fread_number( fp );
pMobIndex->race_type = fread_number( fp );
pMobIndex->rspecs = fread_number( fp );
}
else
{
/* Unused */ fread_number( fp );
pMobIndex->wear_locs = race_table[pMobIndex->race].wear_locs;
/* Unused */ fread_number( fp );
pMobIndex->size = fread_number( fp );
/* Unused */ fread_number( fp );
/* Unused */ fread_number( fp );
}
pMobIndex->understands = fread_number( fp );
pMobIndex->speaks = fread_number( fp );
/* Unused */ fread_number( fp );
/* Unused */ fread_number( fp );
/* Unused */ fread_number( fp );
}
}
else
{
pMobIndex->act = fread_number( fp );
pMobIndex->affected_by = fread_number( fp );
pMobIndex->alignment = fread_number( fp );
letter = fread_letter( fp );
if (letter != 'S')
{
bug( "Load_mobiles: vnum %u non-S.", vnum );
abort( );
}
pMobIndex->level = fread_number( fp );
pMobIndex->level = URANGE(1, pMobIndex->level, 40);
/* unused */ fread_number( fp );
pMobIndex->wear_locs = fread_number( fp );
pMobIndex->hitnodice = fread_number( fp );
fread_letter( fp ); /* 'd' */
pMobIndex->hitsizedice = fread_number( fp );
fread_letter( fp ); /* '+' */
pMobIndex->hitplus = fread_number( fp );
fread_number( fp );
fread_letter( fp ); /* 'd' */
fread_number( fp );
fread_letter( fp ); /* '+' */
fread_number( fp );
pMobIndex->gold = fread_number( fp );
pMobIndex->race = fread_number( fp );
pMobIndex->position = fread_number( fp );
fread_number( fp ); /* Unused */
pMobIndex->sex = fread_number( fp );
pMobIndex->perm_str = 10;
pMobIndex->perm_dex = 10;
pMobIndex->perm_int = 10;
pMobIndex->perm_wis = 10;
pMobIndex->perm_cha = 10;
pMobIndex->perm_con = 10;
if (pMobIndex->race > RACE_NONE)
{
if (race_table[pMobIndex->race].nonability[STAT_STR])
pMobIndex->perm_str = 0;
else
pMobIndex->perm_str += race_table[pMobIndex->race].race_mod[0];
if (race_table[pMobIndex->race].nonability[STAT_DEX])
pMobIndex->perm_dex = 0;
else
pMobIndex->perm_dex += race_table[pMobIndex->race].race_mod[1];
if (race_table[pMobIndex->race].nonability[STAT_CON])
pMobIndex->perm_con = 0;
else
pMobIndex->perm_con += race_table[pMobIndex->race].race_mod[2];
if (race_table[pMobIndex->race].nonability[STAT_INT])
pMobIndex->perm_int = 0;
else
pMobIndex->perm_int += race_table[pMobIndex->race].race_mod[3];
if (race_table[pMobIndex->race].nonability[STAT_WIS])
pMobIndex->perm_wis = 0;
else
pMobIndex->perm_wis += race_table[pMobIndex->race].race_mod[4];
if (race_table[pMobIndex->race].nonability[STAT_CHA])
pMobIndex->perm_cha = 0;
else
pMobIndex->perm_cha += race_table[pMobIndex->race].race_mod[5];
}
}
if (pMobIndex->size == 0)
pMobIndex->size = race_table[pMobIndex->race].size;
pMobIndex->mclass[pMobIndex->class] = pMobIndex->level;
if (IS_SET(pMobIndex->affected_by, AFF_ETHEREAL))
{
SET_BIT(pMobIndex->act, ACT_MOBINVIS);
REMOVE_BIT(pMobIndex->affected_by, AFF_ETHEREAL);
}
while (letter)
{
switch (letter = fread_letter(fp))
{
case 'A':
ALLOCMEM(paf, AFFECT_DATA, 1);
paf->type = 0;
paf->duration = -1;
paf->location = fread_number( fp );
paf->modifier = fread_number( fp );
paf->bitvector = fread_number( fp );
paf->bittype = paf->bitvector ? AFFECT_TO_CHAR : AFFECT_TO_NONE;
paf->level = pMobIndex->level;
paf->caster = STRALLOC("None");
LINK(paf, pMobIndex->first_affect, pMobIndex->last_affect, next, prev);
mud->top_affect++;
break;
case 'C':
pMobIndex->mclass[fread_number( fp )] = fread_number( fp );
break;
case 'E':
ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
LINK(ed, pMobIndex->first_extradesc, pMobIndex->last_extradesc, next, prev);
mud->top_ed++;
break;
case 'M':
pMobIndex->reset_msg = fread_string( fp );
break;
case 'O':
pMobIndex->load_eq[fread_number( fp )] = fread_number( fp );
break;
case 'X':
pMobIndex->attacks[fread_number( fp )] = fread_number( fp );
break;
case '%':
value = fread_number( fp );
value = URANGE(0, value, 99);
sn = skill_lookup( fread_string( fp ) );
if (sn < 0)
{
bug("load_mobiles: %d - unknown skill.", vnum);
break;
}
pMobIndex->learned[sn] = value;
break;
case '>':
ungetc(letter, fp);
mprog_read_programs(fp, pMobIndex);
letter = FALSE;
break;
default:
ungetc(letter, fp);
letter = FALSE;
break;
}
}
// Add sorcerer "multiclass" to dragon race
if (race_table[pMobIndex->race].parent_race == RACE_DRAGON && pMobIndex->mclass[CLASS_SORCERER] == 0)
pMobIndex->mclass[CLASS_SORCERER] = dragon_caster_level(pMobIndex->level);
if (!pMobIndex->unique && pMobIndex->race && pMobIndex->level > race_table[pMobIndex->race].hit_dice)
advance_mobile(pMobIndex);
mud->top_mob_index++;
}
pop_call();
return;
}
/*
Snarf an obj section.
*/
void load_objects( FILE *fp )
{
OBJ_PROG *prg;
OBJ_INDEX_DATA *pObjIndex;
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *paf;
char buf[256], *pt;
int vnum, val, sn;
char letter;
push_call("load_object(%p)",fp);
while (TRUE)
{
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_objects: # not found.", 0 );
abort( );
}
vnum = fread_number( fp );
if ( vnum == 0 )
{
break;
}
if (vnum < 1 || vnum >= MAX_VNUM)
{
bug("load_objects: vnum %u out of range.", vnum);
abort( );
}
if (get_obj_index(vnum) != NULL)
{
bug("load_objects: vnum %u duplicated.", vnum);
abort();
}
ALLOCMEM(pObjIndex, OBJ_INDEX_DATA, 1);
pObjIndex->vnum = vnum;
if (area_load->low_o_vnum > vnum)
{
area_load->low_o_vnum = vnum;
}
if (vnum > area_load->hi_o_vnum)
{
area_load->hi_o_vnum = vnum;
}
obj_index[ vnum ] = pObjIndex;
pObjIndex->area = area_load;
pt = fread_string( fp ); /* Add I### system to names */
sprintf( buf, "i%u", vnum );
if (strstr(pt, buf) == NULL)
{
sprintf( buf, "%s i%u", pt, vnum );
}
else
{
strcpy( buf, pt );
}
STRFREE (pt );
pObjIndex->name = STRALLOC(buf);
pObjIndex->short_descr = fread_string( fp );
pObjIndex->long_descr = fread_string( fp );
pObjIndex->description = fread_string( fp );
pObjIndex->item_type = fread_number( fp );
pObjIndex->extra_flags = fread_number( fp );
pObjIndex->wear_flags = fread_number( fp );
if (area_load->version >= 4)
{
/* unused */ fread_number( fp );
pObjIndex->material = fread_number( fp );
pObjIndex->hit_points = fread_number( fp );
pObjIndex->size = fread_number( fp );
}
pObjIndex->value[0] = fread_number( fp );
pObjIndex->value[1] = fread_number( fp );
pObjIndex->value[2] = fread_number( fp );
pObjIndex->value[3] = fread_number( fp );
if (area_load->version > 2)
{
pObjIndex->value[4] = fread_number( fp );
pObjIndex->value[5] = fread_number( fp );
pObjIndex->value[6] = fread_number( fp );
pObjIndex->value[7] = fread_number( fp );
}
pObjIndex->weight = fread_number(fp);
pObjIndex->cost = abs(fread_number( fp ));
pObjIndex->level = fread_number( fp );
pObjIndex->attack_string = STRDUPE(str_empty);
pObjIndex->id_name = STRDUPE(str_empty);
pObjIndex->id_descr = STRDUPE(str_empty);
/* added to fix new wear size value for armor */
if (pObjIndex->item_type == ITEM_ARMOR && pObjIndex->value[3] <= 0)
pObjIndex->value[3] = SIZE_MEDIUM;
while (letter)
{
switch (letter = fread_letter(fp))
{
case 'A':
ALLOCMEM(paf, AFFECT_DATA, 1);
paf->type = 0;
paf->duration = -1;
paf->location = fread_number( fp );
paf->modifier = fread_number( fp );
if (area_load->version != 2)
paf->bitvector = fread_number( fp );
paf->bittype = paf->bitvector ? AFFECT_TO_CHAR : AFFECT_TO_NONE;
paf->level = pObjIndex->level;
paf->caster = STRALLOC("None");
LINK(paf, pObjIndex->first_affect, pObjIndex->last_affect, next, prev);
SET_BIT(pObjIndex->extra_flags, ITEM_MAGIC);
mud->top_affect++;
break;
case 'C':
STRFREE(pObjIndex->attack_string);
pObjIndex->attack_string = fread_string( fp );
pObjIndex->class_flags = fread_number( fp );
break;
case 'E':
ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
LINK(ed, pObjIndex->first_extradesc, pObjIndex->last_extradesc, next, prev);
mud->top_ed++;
break;
case 'I':
STRFREE(pObjIndex->id_name);
pObjIndex->id_name = fread_string( fp );
STRFREE(pObjIndex->id_descr);
pObjIndex->id_descr = fread_string( fp );
break;
// this remnant of MRMud left to simply allow loading of old areas
case 'P':
prg = load_object_program(fp);
break;
case '>':
ungetc(letter, fp);
oprog_read_programs(fp, pObjIndex);
letter = FALSE;
break;
// added to deprecate skill bitvectors for scrolls etc. - Kregor
case 'V':
val = fread_number( fp );
if ((sn = skill_lookup(fread_word( fp ))) == -1)
{
bug("load_objects: %u bad skill for value %d.", vnum, val);
}
pObjIndex->value[val] = sn;
break;
default:
ungetc(letter, fp);
letter = FALSE;
break;
}
}
if (obj_index_cost(pObjIndex) != -1)
pObjIndex->cost = obj_index_cost(pObjIndex);
fix_materials(pObjIndex);
fix_sizes(pObjIndex);
if (load_obj_weight(pObjIndex) != -1)
pObjIndex->weight = load_obj_weight(pObjIndex);
load_obj_hit(pObjIndex);
mud->top_obj_index++;
}
pop_call();
return;
}
/*
Snarf a reset section.
*/
void load_resets( FILE *fp )
{
RESET_DATA *pReset;
char letter;
push_call("load_resets(%p)",fp);
if (area_load == NULL)
{
bug( "Load_resets: no #AREA seen yet.", 0 );
abort( );
}
while (TRUE)
{
if ((letter = fread_letter(fp)) == 'S')
{
break;
}
ALLOCMEM(pReset, RESET_DATA, 1);
pReset->command = letter;
if (area_load->version <= 2 || area_load->version == 99) // Get rid of MERC extraneous number - Kregor
fread_number( fp );
pReset->arg1 = fread_number( fp );
pReset->arg2 = fread_number( fp );
if ((area_load->version < 4 || area_load->version == 99) && letter != 'D') // pre Mud20 1.0 used as a repop limit, not percentage - Kregor
pReset->arg2 = 100;
if ((area_load->version <= 2 || area_load->version == 99) && letter == 'G') // Other bases leave this number out - Kregor
pReset->arg3 = 0;
else
pReset->arg3 = fread_number( fp );
fread_to_eol( fp );
LINK(pReset, area_load->first_reset, area_load->last_reset, next, prev);
mud->top_reset++;
/*
Add container references while at it - Scandum
*/
switch ( letter )
{
case 'P':
pReset->container = get_reset_from_obj(pReset);
break;
case 'T':
pReset->container = get_reset_from_trap(pReset);
break;
case 'G':
case 'E':
pReset->container = get_reset_from_mob(pReset);
break;
}
}
pop_call();
return;
}
/*
Snarf a room section.
And counting occurances of things.
*/
void load_rooms( FILE *fp )
{
ROOM_INDEX_DATA *pRoomIndex;
EXIT_DATA *pExit;
EXTRA_DESCR_DATA *ed;
int vnum;
bool door;
char letter;
push_call("load_rooms(%p)",fp);
if (area_load == NULL)
{
bug( "Load_resets: no #AREA seen yet.", 0 );
abort( );
}
while (TRUE)
{
letter = fread_letter( fp );
if (letter != '#')
{
bug( "Load_rooms: # not found.", 0 );
abort( );
}
vnum = fread_number(fp);
if (vnum == 0)
{
break;
}
if (vnum < 0 || vnum >= MAX_VNUM)
{
bug("load_rooms: vnum %u out of range.", vnum);
abort( );
}
if (room_index[vnum] != NULL && vnum < MAX_VNUM)
{
bug("load_rooms: vnum %u duplicated.", vnum);
abort( );
}
ALLOCMEM(pRoomIndex, ROOM_INDEX_DATA, 1);
if (vnum < area_load->low_r_vnum)
{
area_load->low_r_vnum = vnum;
}
if (vnum > area_load->hi_r_vnum)
{
area_load->hi_r_vnum = vnum;
}
pRoomIndex->area = area_load;
pRoomIndex->vnum = vnum;
room_index[vnum] = pRoomIndex;
pRoomIndex->name = fread_string( fp );
pRoomIndex->description = fread_string( fp );
pRoomIndex->listen_desc = STRDUPE( str_empty );
pRoomIndex->night_desc = STRDUPE( str_empty );
pRoomIndex->creator_pvnum = fread_number( fp );
pRoomIndex->room_flags = fread_number( fp );
pRoomIndex->sector_type = fread_number( fp );
if (area_load->version >= 4)
{
/* not used */ fread_number( fp );
/* not used */ fread_number( fp );
/* not used */ fread_number( fp );
}
for (door = 0 ; door < MAX_LAST_LEFT ; door++)
{
pRoomIndex->last_left[door] = STRDUPE(str_empty);
}
while (letter)
{
switch (letter = fread_letter(fp))
{
case 'S':
letter = FALSE;
break;
case 'D':
door = fread_number( fp );
if (door > 5)
{
bug("fread_rooms: vnum %u has bad door number.", vnum);
abort( );
}
ALLOCMEM(pExit, EXIT_DATA, 1);
pExit->description = fread_string( fp );
pExit->keyword = fread_string( fp );
pExit->exit_info = fread_number( fp );
pExit->key = fread_number( fp );
pExit->vnum = fread_number( fp );
if (area_load->version >= 4)
{
pExit->exit_size = fread_number( fp );
pExit->climb_dc = fread_number( fp );
pExit->fall_dist = fread_number( fp );
}
pExit->to_room = pExit->vnum;
pRoomIndex->exit[door] = pExit;
mud->top_exit++;
break;
case 'E':
ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
LINK(ed, pRoomIndex->first_extradesc, pRoomIndex->last_extradesc, next, prev);
mud->top_ed++;
break;
case 'L': /* listen desc - Kregor */
pRoomIndex->listen_desc = fread_string( fp );
break;
case 'N': /* night desc - Kregor */
pRoomIndex->night_desc = fread_string( fp );
break;
case '>':
ungetc(letter, fp);
rprog_read_programs(fp, pRoomIndex);
// letter = FALSE;
break;
default:
bug("Load_rooms: vnum %u uses bad flag '%c'.", vnum, letter);
abort();
}
}
mud->top_room++;
}
pop_call();
return;
}
/*
Snarf a shop section.
*/
void load_shops( FILE *fp )
{
SHOP_DATA *pShop;
MOB_INDEX_DATA *pMobIndex;
bool iTrade;
push_call("load_shops(%p)",fp);
while (TRUE)
{
ALLOCMEM( pShop, SHOP_DATA, 1);
pShop->keeper = fread_number( fp );
if (pShop->keeper == 0)
{
FREEMEM(pShop);
break;
}
if (get_mob_index(pShop->keeper) == NULL)
{
bug("load_shop: Mobile %d does not exist", pShop->keeper);
abort();
}
for (iTrade = 0 ; iTrade < MAX_TRADE ; iTrade++)
{
pShop->buy_type[iTrade] = fread_number( fp );
}
pShop->shop_flags = fread_number( fp );
if (area_load->version < 4 || area_load->version == 99)
pShop->shop_flags = 0;
pShop->profit_buy = fread_number( fp );
pShop->profit_buy = UMAX(pShop->profit_buy, 100);
pShop->profit_sell = fread_number( fp );
pShop->profit_sell = UMIN(pShop->profit_sell, 50);
pShop->open_hour = fread_number( fp );
pShop->close_hour = fread_number( fp );
fread_to_eol( fp );
pMobIndex = get_mob_index( pShop->keeper );
pMobIndex->pShop = pShop;
LINK(pShop, mud->f_shop, mud->l_shop, next, prev);
mud->top_shop++;
}
pop_call();
return;
}
/*
Snarf a inn section.
*/
void load_inns( FILE *fp )
{
INN_DATA *pInn;
MOB_INDEX_DATA *pMobIndex;
int iRoom;
push_call("load_inns(%p)",fp);
while (TRUE)
{
ALLOCMEM( pInn, INN_DATA, 1);
pInn->keeper = fread_number( fp );
if (pInn->keeper == 0)
{
FREEMEM(pInn);
break;
}
if (get_mob_index(pInn->keeper) == NULL)
{
bug("load_inn: Mobile %d does not exist", pInn->keeper);
abort();
}
for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++)
{
pInn->room[iRoom] = fread_number( fp );
if (pInn->room[iRoom] > 0 && room_index[pInn->room[iRoom]] == NULL)
{
bug("load_inn: Room %d does not exist", pInn->room);
abort();
}
}
for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++)
{
pInn->rent[iRoom] = fread_number( fp );
}
fread_number( fp );
pInn->open_hour = fread_number( fp );
pInn->close_hour = fread_number( fp );
pInn->shop_flags = fread_number( fp );
fread_to_eol( fp );
pMobIndex = get_mob_index( pInn->keeper );
pMobIndex->pInn = pInn;
LINK(pInn, mud->f_inn, mud->l_inn, next, prev);
mud->top_inn++;
}
pop_call();
return;
}
/*
Snarf a stable section.
*/
void load_stables( FILE *fp )
{
STABLE_DATA *pStable;
MOB_INDEX_DATA *pMobIndex;
push_call("load_stables(%p)",fp);
while (TRUE)
{
ALLOCMEM( pStable, STABLE_DATA, 1);
pStable->keeper = fread_number( fp );
if (pStable->keeper == 0)
{
FREEMEM(pStable);
break;
}
if (get_mob_index(pStable->keeper) == NULL)
{
bug("load_stable: Mobile %d does not exist", pStable->keeper);
abort();
}
pStable->room = fread_number( fp );
if (room_index[pStable->room] == NULL)
{
bug("load_stable: Room %d does not exist", pStable->room);
abort();
}
pStable->shop_flags = fread_number( fp );
pStable->rent = fread_number( fp );
pStable->open_hour = fread_number( fp );
pStable->close_hour = fread_number( fp );
fread_to_eol( fp );
pMobIndex = get_mob_index( pStable->keeper );
pMobIndex->pStable = pStable;
LINK(pStable, mud->f_stable, mud->l_stable, next, prev);
mud->top_stable++;
}
pop_call();
return;
}
/*
Snarf spec proc declarations.
*/
void load_specials( FILE *fp )
{
int vnum;
MOB_INDEX_DATA *pMobIndex;
char letter;
push_call("load_special(%p)",fp);
while (TRUE)
{
switch (letter = fread_letter(fp))
{
default:
bug("load_specials: letter '%c' not MSO.", letter);
abort( );
case 'S':
pop_call();
return;
case 'M':
vnum = fread_number ( fp );
pMobIndex = get_mob_index ( vnum );
pMobIndex->spec_fun = spec_lookup ( fread_word ( fp ) );
if (pMobIndex->spec_fun == NULL)
{
log_printf("load_specials: 'M': vnum %u.", pMobIndex->vnum );
}
break;
}
fread_to_eol( fp );
}
pop_call();
return;
}
/*
Conversion for FKMud/Smaug repair shops.
*/
void load_repairs( FILE *fp )
{
int vnum, skill;
MOB_INDEX_DATA *pMobIndex;
push_call("load_shops(%p)",fp);
while (TRUE)
{
if ((vnum = fread_number( fp )) == 0)
{
break;
}
if ((pMobIndex = get_mob_index(vnum)) == NULL)
{
bug("load_shop: Mobile %d does not exist", vnum);
abort();
}
// grabs each item type repair and converts to Mud20 skill
switch (fread_number( fp ))
{
case ITEM_ARMOR:
skill = gsn_craft_armor;
break;
case ITEM_WEAPON:
skill = gsn_craft_weapons;
break;
case ITEM_TREASURE:
skill = gsn_craft_jewelry;
break;
case ITEM_CONTAINER:
skill = gsn_craft_leather;
break;
default:
skill = -1;
break;
}
if (skill != -1)
{
pMobIndex->learned[skill] = pMobIndex->level + 3;
}
switch (fread_number( fp ))
{
case ITEM_ARMOR:
skill = gsn_craft_armor;
break;
case ITEM_WEAPON:
skill = gsn_craft_weapons;
break;
case ITEM_TREASURE:
skill = gsn_craft_jewelry;
break;
case ITEM_CONTAINER:
skill = gsn_craft_leather;
break;
default:
skill = -1;
break;
}
if (skill != -1)
{
pMobIndex->learned[skill] = pMobIndex->level + 3;
}
// just get rid of substance type because it's assumed in Mud20 skill
fread_number( fp );
// and the rest don't matter
fread_to_eol( fp );
}
pop_call();
return;
}
/*
* Written to covert areas from my
* previous server FKMud - Kregor
*/
void load_fk_mobiles( FILE *fp )
{
MOB_INDEX_DATA *pMobIndex;
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *paf;
char buf[256], *pt;
int vnum, sn, value;
char letter;
push_call("load_mobiles(%p)",fp);
while (TRUE)
{
letter = fread_letter( fp );
if (letter != '#')
{
bug( "Load_mobiles: # not found.", 0 );
abort( );
}
vnum = fread_number( fp );
if (vnum == 0)
{
break;
}
if (vnum < 1 || vnum >= MAX_VNUM)
{
bug("load_mobiles: vnum %u out of range.", vnum);
abort( );
}
if (get_mob_index(vnum) != NULL)
{
bug("load_mobiles: vnum %u duplicated.", vnum);
abort( );
}
ALLOCMEM(pMobIndex, MOB_INDEX_DATA, 1);
pMobIndex->vnum = vnum;
mob_index[vnum] = pMobIndex;
pMobIndex->area = area_load;
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
if (area_load->low_m_vnum > vnum)
{
area_load->low_m_vnum = vnum;
}
if (vnum > area_load->hi_m_vnum)
{
area_load->hi_m_vnum = vnum;
}
}
pt = fread_string( fp ); /* Add M### system to names */
sprintf( buf, "m%u", vnum );
if (strstr(pt, buf) == NULL)
{
sprintf( buf, "%s m%u", pt, vnum );
}
else
{
strcpy( buf, pt );
}
STRFREE (pt);
pMobIndex->player_name = STRALLOC(buf);
pMobIndex->short_descr = fread_string( fp );
pMobIndex->long_descr = fread_string( fp );
pMobIndex->description = fread_string( fp );
pMobIndex->unique = FALSE;
letter = fread_letter( fp );
if (letter == 'U')
pMobIndex->unique = TRUE;
else if (letter == 'S')
pMobIndex->unique = FALSE;
else
{
bug( "Load_mobiles: vnum %u not U or S.", vnum );
abort( );
}
pMobIndex->level = fread_number( fp );
pMobIndex->class = fread_number( fp );
pMobIndex->race = fread_number( fp );
pMobIndex->sex = fread_number( fp );
pMobIndex->position = fread_number( fp );
pMobIndex->god = fread_number( fp );
pMobIndex->act = fread_number( fp );
// Convert 50 level scale to 20 - Kregor
if (!IS_SET(pMobIndex->act, ACT_MOBINVIS))
pMobIndex->level = UMAX(1, pMobIndex->level / 2);
if (!pMobIndex->unique)
{
if (pMobIndex->race <= RACE_NONE)
{
bug( "Load_mobiles: no race set on S mobile.", vnum );
pMobIndex->race = RACE_HUMAN;
}
if (pMobIndex->class != CLASS_MONSTER && pMobIndex->class < MAX_CLASS)
pMobIndex->hitsizedice = class_table[pMobIndex->class].hp_max;
else if (pMobIndex->race > RACE_NONE)
pMobIndex->hitsizedice = race_type_table[race_table[pMobIndex->race].type].hit_die;
else
{
bug( "Load_mobiles: neither class nor race hit die.", vnum );
pMobIndex->hitsizedice = 8;
}
pMobIndex->alignment = race_table[pMobIndex->race].alignment;
pMobIndex->ethos = race_table[pMobIndex->race].ethos;
pMobIndex->gold = 0; // need to add means to determine standard random gold
/*
* assign stats based on class pri and sec stats
* These routines effectively gives standard NPCs
* an elite array of abilities - Kregor
*/
if (pMobIndex->class > CLASS_MONSTER)
{
int class = pMobIndex->class;
if (class_table[class].attr_prime == APPLY_STR)
pMobIndex->perm_str = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[0];
else if (class_table[class].attr_second == APPLY_STR)
pMobIndex->perm_str = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[0];
else
pMobIndex->perm_str = best_three_of_four() + race_table[pMobIndex->race].race_mod[0];
if (class_table[class].attr_prime == APPLY_DEX)
pMobIndex->perm_dex = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[1];
else if (class_table[class].attr_second == APPLY_DEX)
pMobIndex->perm_dex = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[1];
else
pMobIndex->perm_dex = best_three_of_four() + race_table[pMobIndex->race].race_mod[1];
if (class_table[class].attr_prime == APPLY_CON)
pMobIndex->perm_con = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[2];
else if (class_table[class].attr_second == APPLY_CON)
pMobIndex->perm_con = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[2];
else
pMobIndex->perm_con = best_three_of_four() + race_table[pMobIndex->race].race_mod[2];
if (class_table[class].attr_prime == APPLY_INT)
pMobIndex->perm_int = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[3];
else if (class_table[class].attr_second == APPLY_INT)
pMobIndex->perm_int = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[3];
else
pMobIndex->perm_int = best_three_of_four() + race_table[pMobIndex->race].race_mod[3];
if (class_table[class].attr_prime == APPLY_WIS)
pMobIndex->perm_wis = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[4];
else if (class_table[class].attr_second == APPLY_WIS)
pMobIndex->perm_wis = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[4];
else
pMobIndex->perm_wis = best_three_of_four() + race_table[pMobIndex->race].race_mod[4];
if (class_table[class].attr_prime == APPLY_CHA)
pMobIndex->perm_cha = 12 + dice(1,6) + race_table[pMobIndex->race].race_mod[5];
else if (class_table[class].attr_second == APPLY_CHA)
pMobIndex->perm_cha = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[5];
else
pMobIndex->perm_cha = best_three_of_four() + race_table[pMobIndex->race].race_mod[5];
}
else
{
pMobIndex->perm_str = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[0];
pMobIndex->perm_int = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[1];
pMobIndex->perm_wis = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[2];
pMobIndex->perm_dex = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[3];
pMobIndex->perm_con = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[4];
pMobIndex->perm_cha = 8 + dice(1,6) + race_table[pMobIndex->race].race_mod[5];
}
// zero out nonabilities by race
if (race_table[pMobIndex->race].nonability[STAT_STR])
pMobIndex->perm_str = 0;
if (race_table[pMobIndex->race].nonability[STAT_DEX])
pMobIndex->perm_dex = 0;
if (race_table[pMobIndex->race].nonability[STAT_CON])
pMobIndex->perm_con = 0;
if (race_table[pMobIndex->race].nonability[STAT_INT])
pMobIndex->perm_int = 0;
if (race_table[pMobIndex->race].nonability[STAT_WIS])
pMobIndex->perm_wis = 0;
if (race_table[pMobIndex->race].nonability[STAT_CHA])
pMobIndex->perm_cha = 0;
pMobIndex->nat_armor = race_table[pMobIndex->race].nat_armor;
pMobIndex->wear_locs = race_table[pMobIndex->race].wear_locs;
pMobIndex->size = race_table[pMobIndex->race].size;
pMobIndex->understands = race_table[pMobIndex->race].understands;
pMobIndex->speaks = race_table[pMobIndex->race].speaks;
}
else
{
pMobIndex->affected_by = fread_number( fp );
pMobIndex->armor_type = fread_number( fp );
/*unused*/ fread_number( fp );
/* 'd' */ fread_letter( fp );
if (pMobIndex->class > CLASS_MONSTER && pMobIndex->class < MAX_CLASS)
{
fread_number( fp );
pMobIndex->hitsizedice = class_table[pMobIndex->class].hp_max;
}
else if (pMobIndex->race > RACE_NONE)
{
fread_number( fp );
pMobIndex->hitsizedice = race_type_table[race_table[pMobIndex->race].type].hit_die;
}
else
{
pMobIndex->hitsizedice = fread_number( fp );
}
/* '+' */ fread_letter( fp );
pMobIndex->hitplus = fread_number( fp );
pMobIndex->alignment = fread_number( fp );
pMobIndex->perm_str = fread_number( fp );
pMobIndex->perm_int = fread_number( fp );
pMobIndex->perm_wis = fread_number( fp );
pMobIndex->perm_dex = fread_number( fp );
pMobIndex->perm_con = fread_number( fp );
pMobIndex->perm_cha = fread_number( fp );
fread_number( fp ); // read and discard LUCK stat
fread_number( fp ); // unused field
fread_number( fp ); // unused field
fread_number( fp ); // unused field
fread_number( fp ); // unused field
fread_number( fp ); // unused field
pMobIndex->speaks = fread_number( fp );
pMobIndex->understands = fread_number( fp );
/* Unused */ fread_number( fp );
/* Unused */ fread_number( fp );
/* Unused */ fread_number( fp );
}
if (pMobIndex->size == 0)
pMobIndex->size = race_table[pMobIndex->race].size;
pMobIndex->mclass[pMobIndex->class] = pMobIndex->level;
while (letter)
{
switch (letter = fread_letter(fp))
{
case 'A':
ALLOCMEM(paf, AFFECT_DATA, 1);
paf->type = 0;
paf->duration = -1;
paf->location = fread_number( fp );
paf->modifier = fread_number( fp );
paf->bittype = AFFECT_TO_NONE;
paf->level = pMobIndex->level;
paf->caster = STRALLOC("None");
LINK(paf, pMobIndex->first_affect, pMobIndex->last_affect, next, prev);
mud->top_affect++;
break;
case 'E':
ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
LINK(ed, pMobIndex->first_extradesc, pMobIndex->last_extradesc, next, prev);
mud->top_ed++;
break;
case '%':
value = fread_number( fp );
value = URANGE(0, value, 99);
fread_number( fp ); // unused
sn = skill_lookup( fread_string( fp ) );
if (sn < 0)
{
break;
}
if (skill_table[sn].skilltype != FSKILL_FEAT
&& skill_table[sn].skilltype != FSKILL_SKILL
&& skill_table[sn].skilltype != FSKILL_SPELL
&& skill_table[sn].skilltype != FSKILL_CRAFT
&& skill_table[sn].skilltype != FSKILL_KNOWLEDGE)
{
break;
}
pMobIndex->learned[sn] = value;
break;
case '>':
ungetc(letter, fp);
mprog_read_programs(fp, pMobIndex);
letter = FALSE;
break;
default:
ungetc(letter, fp);
letter = FALSE;
break;
}
}
// Add sorcerer "multiclass" to dragon race
if (race_table[pMobIndex->race].parent_race == RACE_DRAGON && pMobIndex->mclass[CLASS_SORCERER] == 0)
pMobIndex->mclass[CLASS_SORCERER] = dragon_caster_level(pMobIndex->level);
if (!pMobIndex->unique && pMobIndex->race && pMobIndex->level > race_table[pMobIndex->race].hit_dice)
advance_mobile(pMobIndex);
mud->top_mob_index++;
}
pop_call();
return;
}
void load_fk_objects( FILE *fp )
{
OBJ_INDEX_DATA *pObjIndex;
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *paf;
char buf[256], *pt;
int vnum;
char letter;
push_call("load_object(%p)",fp);
while (TRUE)
{
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_objects: # not found.", 0 );
abort( );
}
vnum = fread_number( fp );
if ( vnum == 0 )
{
break;
}
if (vnum < 1 || vnum >= MAX_VNUM)
{
bug("load_objects: vnum %u out of range.", vnum);
abort( );
}
if (get_obj_index(vnum) != NULL)
{
bug("load_objects: vnum %u duplicated.", vnum);
abort();
}
ALLOCMEM(pObjIndex, OBJ_INDEX_DATA, 1);
pObjIndex->vnum = vnum;
if (area_load->low_o_vnum > vnum)
{
area_load->low_o_vnum = vnum;
}
if (vnum > area_load->hi_o_vnum)
{
area_load->hi_o_vnum = vnum;
}
obj_index[ vnum ] = pObjIndex;
pObjIndex->area = area_load;
pt = fread_string( fp ); /* Add i### system to names */
sprintf( buf, "i%u", vnum );
if (strstr(pt, buf) == NULL)
{
sprintf( buf, "%s i%u", pt, vnum );
}
else
{
strcpy( buf, pt );
}
STRFREE (pt);
pObjIndex->name = STRALLOC(buf);
pObjIndex->short_descr = fread_string( fp );
pObjIndex->long_descr = fread_string( fp );
pObjIndex->description = fread_string( fp );
pObjIndex->item_type = fread_number( fp );
pObjIndex->extra_flags = fread_number( fp );
pObjIndex->wear_flags = fread_number( fp );
/* unused */ fread_number( fp ); // was quality in FKMud
pObjIndex->material = fread_number( fp );
pObjIndex->hit_points = fread_number( fp );
pObjIndex->size = fread_number( fp );
pObjIndex->value[0] = fread_number( fp );
pObjIndex->value[1] = fread_number( fp );
pObjIndex->value[2] = fread_number( fp );
pObjIndex->value[3] = fread_number( fp );
pObjIndex->value[4] = fread_number( fp );
pObjIndex->value[5] = fread_number( fp );
pObjIndex->attack_string = STRDUPE(str_empty);
pObjIndex->id_name = STRDUPE(str_empty);
pObjIndex->id_descr = STRDUPE(str_empty);
/* added to fix new wear size value for armor */
if (pObjIndex->item_type == ITEM_ARMOR && pObjIndex->value[3] <= 0)
pObjIndex->value[3] = SIZE_MEDIUM;
while (letter)
{
switch (letter = fread_letter(fp))
{
case 'A':
ALLOCMEM(paf, AFFECT_DATA, 1);
paf->type = 0;
paf->duration = -1;
paf->location = fread_number( fp );
paf->modifier = fread_number( fp );
paf->bittype = AFFECT_TO_NONE;
paf->level = obj_level_estimate(pObjIndex);
paf->caster = STRALLOC("None");
LINK(paf, pObjIndex->first_affect, pObjIndex->last_affect, next, prev);
SET_BIT(pObjIndex->extra_flags, ITEM_MAGIC);
mud->top_affect++;
break;
case 'E':
ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
LINK(ed, pObjIndex->first_extradesc, pObjIndex->last_extradesc, next, prev);
mud->top_ed++;
break;
case 'I':
STRFREE(pObjIndex->id_name);
pObjIndex->id_name = fread_line( fp );
STRFREE(pObjIndex->id_descr);
pObjIndex->id_descr = fread_string( fp );
break;
// this remnant of MRMud left to simply allow loading of old areas
case '>':
ungetc(letter, fp);
oprog_read_programs(fp, pObjIndex);
letter = FALSE;
break;
default:
ungetc(letter, fp);
letter = FALSE;
break;
}
}
if (obj_index_cost(pObjIndex) != -1)
pObjIndex->cost = obj_index_cost(pObjIndex);
fix_materials(pObjIndex);
fix_sizes(pObjIndex);
if (load_obj_weight(pObjIndex) != -1)
pObjIndex->weight = load_obj_weight(pObjIndex);
load_obj_hit(pObjIndex);
mud->top_obj_index++;
}
pop_call();
return;
}
/*
* Read in FKMud/Smaug weather stat,
* convert into Mud20 stats - Kregor
*/
void load_fk_weather( FILE * fp )
{
push_call("load_weather(%p)",fp);
area_load->weather_info->temp_summer = fread_number(fp) * 12;
area_load->weather_info->temp_winter = area_load->weather_info->temp_summer / 2;
area_load->weather_info->temp_daily = (area_load->weather_info->temp_summer - area_load->weather_info->temp_summer) / 2;
area_load->weather_info->wet_scale = fread_number(fp);
pop_call();
return;
}
void load_fk_rooms( FILE *fp )
{
ROOM_INDEX_DATA *pRoomIndex;
EXIT_DATA *pExit;
EXTRA_DESCR_DATA *ed;
int vnum;
bool door;
char letter;
push_call("load_rooms(%p)",fp);
if (area_load == NULL)
{
bug( "Load_resets: no #AREA seen yet.", 0 );
abort( );
}
while (TRUE)
{
letter = fread_letter( fp );
if (letter != '#')
{
bug( "Load_rooms: # not found.", 0 );
abort( );
}
vnum = fread_number(fp);
if (vnum == 0)
{
break;
}
if (vnum < 0 || vnum >= MAX_VNUM)
{
bug("load_rooms: vnum %u out of range.", vnum);
abort( );
}
if (room_index[vnum] != NULL && vnum < MAX_VNUM)
{
bug("load_rooms: vnum %u duplicated.", vnum);
abort( );
}
ALLOCMEM(pRoomIndex, ROOM_INDEX_DATA, 1);
if (vnum < area_load->low_r_vnum)
{
area_load->low_r_vnum = vnum;
}
if (vnum > area_load->hi_r_vnum)
{
area_load->hi_r_vnum = vnum;
}
pRoomIndex->area = area_load;
pRoomIndex->vnum = vnum;
room_index[vnum] = pRoomIndex;
pRoomIndex->name = fread_string( fp );
pRoomIndex->description = fread_string( fp );
pRoomIndex->listen_desc = STRDUPE( str_empty );
pRoomIndex->night_desc = STRDUPE( str_empty );
/* not used */ fread_number( fp );
pRoomIndex->room_flags = fread_number( fp );
pRoomIndex->sector_type = fread_number( fp );
/* not used */ fread_number( fp );
/* not used */ fread_number( fp );
/* not used */ fread_number( fp );
for (door = 0 ; door < MAX_LAST_LEFT ; door++)
{
pRoomIndex->last_left[door] = STRDUPE(str_empty);
}
while (letter)
{
switch (letter = fread_letter(fp))
{
case 'S':
letter = FALSE;
break;
case 'D':
door = fread_number( fp );
if (door > 5)
{
bug("fread_rooms: vnum %u has bad door number.", vnum);
abort( );
}
ALLOCMEM(pExit, EXIT_DATA, 1);
pExit->description = fread_string( fp );
pExit->keyword = fread_string( fp );
pExit->exit_info = fread_number( fp );
pExit->key = fread_number( fp );
pExit->vnum = fread_number( fp );
/* not used */ fread_number( fp );
pExit->to_room = pExit->vnum;
pRoomIndex->exit[door] = pExit;
mud->top_exit++;
break;
case 'E':
ALLOCMEM(ed, EXTRA_DESCR_DATA, 1);
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
LINK(ed, pRoomIndex->first_extradesc, pRoomIndex->last_extradesc, next, prev);
mud->top_ed++;
break;
case '>':
ungetc(letter, fp);
rprog_read_programs(fp, pRoomIndex);
// letter = FALSE;
break;
default:
bug("Load_rooms: vnum %u uses bad flag '%c'.", vnum, letter);
abort();
}
}
mud->top_room++;
}
pop_call();
return;
}
/*
This procedure is responsible for reading any in_file MOBprograms.
*/
void mprog_read_programs( FILE *fp, MOB_INDEX_DATA *pMobIndex)
{
MPROG_DATA *mprg;
bool done = FALSE;
push_call("mprog_read_programs(%p,%p)",fp,pMobIndex);
if (fread_letter(fp) != '>')
{
bug("load_mobiles: vnum %d MOBPROG char", pMobIndex->vnum);
abort( );
}
ALLOCMEM(mprg, MPROG_DATA, 1);
while (!done)
{
mprg->type = mprog_name_to_type(fread_word(fp));
switch ( mprg->type )
{
case ERROR_PROG:
bug("load_mobiles: vnum %u ERROR_PROG type.", pMobIndex->vnum);
abort( );
break;
default:
SET_BIT(pMobIndex->progtypes, mprg->type);
mprg->arglist = fread_string( fp );
fread_to_eol( fp );
mprg->comlist = fread_string( fp );
fread_to_eol( fp );
if (strstr(mprg->comlist, "$r") != NULL)
{
SET_BIT(mprg->flags, MPTRIGGER_RAND_PLR);
}
expand_mob_prog( pMobIndex, NULL, NULL, mprg ); /* Tokenize Mobprog */
LINK(mprg, pMobIndex->first_prog, pMobIndex->last_prog, next, prev);
switch (fread_letter( fp ) )
{
case '>':
ALLOCMEM(mprg, MPROG_DATA, 1);
break;
case '|':
fread_to_eol( fp );
done = TRUE;
break;
default:
bug( "Load_mobiles: vnum %u bad MOBPROG.", pMobIndex->vnum );
abort();
break;
}
break;
}
}
pop_call();
return;
}
/*
This procedure is responsible for reading any in_file OBJprograms.
*/
void oprog_read_programs( FILE *fp, OBJ_INDEX_DATA *pObjIndex)
{
MPROG_DATA *mprg;
bool done = FALSE;
char letter;
push_call("oprog_read_programs(%p,%p)",fp,pObjIndex);
if ((letter = fread_letter(fp)) != '>')
{
bug("load_objects: vnum %d MOBPROG obj, letter is '%c'", pObjIndex->vnum, letter);
abort( );
}
ALLOCMEM(mprg, MPROG_DATA, 1);
while (!done)
{
mprg->type = mprog_name_to_type(fread_word(fp));
switch ( mprg->type )
{
case ERROR_PROG:
bug("load_objects: vnum %u ERROR_PROG type.", pObjIndex->vnum);
abort( );
break;
default:
SET_BIT(pObjIndex->progtypes, mprg->type);
mprg->arglist = fread_string( fp );
fread_to_eol( fp );
mprg->comlist = fread_string( fp );
fread_to_eol( fp );
if (strstr(mprg->comlist, "$r") != NULL)
{
SET_BIT(mprg->flags, MPTRIGGER_RAND_PLR);
}
expand_mob_prog( NULL, pObjIndex, NULL, mprg ); /* Tokenize Mobprog */
LINK(mprg, pObjIndex->first_prog, pObjIndex->last_prog, next, prev);
switch (fread_letter( fp ) )
{
case '>':
ALLOCMEM(mprg, MPROG_DATA, 1);
break;
case '|':
fread_to_eol( fp );
done = TRUE;
break;
default:
bug( "Load_objects: vnum %u bad MOBPROG obj.", pObjIndex->vnum );
abort();
break;
}
break;
}
}
pop_call();
return;
}
/*
This procedure is responsible for reading any in_file ROOMprograms.
*/
void rprog_read_programs( FILE *fp, ROOM_INDEX_DATA *pRoomIndex)
{
MPROG_DATA *mprg;
bool done = FALSE;
push_call("rprog_read_programs(%p,%p)",fp,pRoomIndex);
if (fread_letter(fp) != '>')
{
bug("load_rooms: vnum %d MOBPROG obj", pRoomIndex->vnum);
abort( );
}
ALLOCMEM(mprg, MPROG_DATA, 1);
while (!done)
{
mprg->type = mprog_name_to_type(fread_word(fp));
switch ( mprg->type )
{
case ERROR_PROG:
bug("load_mobiles: vnum %u ERROR_PROG type.", pRoomIndex->vnum);
abort( );
break;
default:
SET_BIT(pRoomIndex->progtypes, mprg->type);
mprg->arglist = fread_string( fp );
fread_to_eol( fp );
mprg->comlist = fread_string( fp );
fread_to_eol( fp );
if (strstr(mprg->comlist, "$r") != NULL)
{
SET_BIT(mprg->flags, MPTRIGGER_RAND_PLR);
}
expand_mob_prog( NULL, NULL, pRoomIndex, mprg ); /* Tokenize Mobprog */
LINK(mprg, pRoomIndex->first_prog, pRoomIndex->last_prog, next, prev);
switch (fread_letter( fp ) )
{
case '>':
ALLOCMEM(mprg, MPROG_DATA, 1);
break;
case '|':
fread_to_eol( fp );
done = TRUE;
break;
default:
bug( "load_rooms: vnum %u bad MOBPROG room.", pRoomIndex->vnum );
abort();
break;
}
break;
}
}
pop_call();
return;
}
void expand_mob_prog( MOB_INDEX_DATA *mind, OBJ_INDEX_DATA *obj, ROOM_INDEX_DATA *room, MPROG_DATA *mprog )
{
char buf[MAX_INPUT_LENGTH];
char *pti, *pto;
char level;
push_call("expand_mob_prog(%p,%p,%p,%p)",mind,obj,room,mprog);
pti = mprog->comlist;
level = 0;
while (*pti != '\0')
{
while (*pti == '\n' || *pti == '\r')
{
pti++;
}
if (*pti != '\0')
{
for (pto = buf ; *pti != '\r' && *pti != '\n' && *pti != '\0' ; pti++, pto++)
{
*pto = *pti;
}
*pto = '\0';
level = expand_line_mprog( mind, obj, room, mprog, buf, FALSE, level );
}
}
/*
fixer_mprog will rebuild the old comlist - Scandum
*/
STRFREE(mprog->comlist);
pop_call();
return;
}
char expand_line_mprog( MOB_INDEX_DATA *mind, OBJ_INDEX_DATA *obj, ROOM_INDEX_DATA *room, MPROG_DATA *mprog, char *line, bool iForce, char level )
{
char *pti, *pto;
char buf[MAX_INPUT_LENGTH];
char string[MAX_INPUT_LENGTH];
int type;
void *func;
int value;
NPC_TOKEN *token;
char achange, bchange;
push_call("expand_line_mprog(%p,%p,%p,%p,%p,%p,%p)",mind,obj,room,mprog,line,iForce,level);
func = NULL;
for (pti = line ; *pti == ' ' ; pti++);
for (pto = buf ; isalnum(*pti) ; pti++, pto++)
{
*pto = *pti;
}
*pto = '\0';
if (*buf == '\0')
{
pop_call();
return(level);
}
type = 0; /* Error type */
value = 0;
achange = 0;
bchange = 0;
switch (buf[0])
{
case 'b':
if (!strcmp(buf, "break"))
{
type = MPTOKEN_BREAK;
}
break;
case 'c':
if (!strcmp(buf, "case"))
{
type = MPTOKEN_CASE;
bchange = -1;
achange = 1;
}
break;
case 'd':
if (!strcmp(buf, "default"))
{
type = MPTOKEN_DEFAULT;
bchange = -1;
achange = 1;
}
break;
case 'e':
if (!strcmp(buf, "else"))
{
type = MPTOKEN_ELSE;
bchange =-1;
achange = 1;
}
else if (!strcmp(buf, "endif"))
{
type = MPTOKEN_ENDIF;
bchange =-1;
}
else if (!strcmp(buf, "endswitch"))
{
type = MPTOKEN_ENDSWITCH;
bchange = -2;
}
break;
case 'i':
if (!strcmp(buf, "if"))
{
type = MPTOKEN_IF;
achange = 1;
}
else if (!strcmp(buf, "ifnot"))
{
type = MPTOKEN_IFNOT;
achange = 1;
}
break;
case 'o':
if (!strcmp(buf, "or"))
{
type = MPTOKEN_OR;
bchange = -1;
achange = 1;
}
else if (!strcmp(buf, "ornot"))
{
type = MPTOKEN_ORNOT;
bchange = -1;
achange = 1;
}
break;
case 's':
if (!strcmp(buf, "switch"))
{
type = MPTOKEN_SWITCH;
achange = 2;
}
break;
}
if (type == 0)
{
if ((value = find_command(buf, MAX_LEVEL - 1)) >= 0)
{
func = (void *) cmd_table[value].do_fun;
type = 2;
}
else if ((value = find_social(buf)) >= 0)
{
func = (void *) social_table[value].name;
type = 1;
}
if (func == NULL)
{
log_printf("expand_line_mprog: unknown command: %s", buf);
value = 0;
type = 0;
}
}
ALLOCMEM(token, NPC_TOKEN, 1);
token->type = type;
token->function = func;
token->value = value;
mud->top_mprog++;
LINK(token, mprog->first_token, mprog->last_token, next, prev);
level += bchange; /* before change */
if (level < 0)
{
level = 0;
}
token->level = level;
level += achange; /* after change */
while (*pti == ' ')
{
pti++;
}
if (type == MPTOKEN_IF || type == MPTOKEN_OR || type == MPTOKEN_SWITCH)
{
pto = string;
while (*pti != '(')
{
if (*pti == '\0')
{
if (mind)
log_build_printf(mind->vnum, "ifchck syntax error");
else if (obj)
log_build_printf(obj->vnum, "ifchck syntax error");
else if (room)
log_build_printf(room->vnum, "ifchck syntax error");
token->type = 0;
break;
}
else if (*pti == ' ')
{
pti++;
}
else
{
*pto++ = *pti++;
}
}
*pto++ = ' ';
while (*pti != ')')
{
if (*pti == '\0')
{
if (mind)
log_build_printf(mind->vnum, "ifchck syntax error");
else if (obj)
log_build_printf(obj->vnum, "ifchck syntax error");
else if (room)
log_build_printf(room->vnum, "ifchck syntax error");
token->type = 0;
break;
}
// else if (*pti == ' ')
// {
// pti++;
// }
else
{
*pto++ = *pti++;
}
}
*pto++ = *pti++;
while (*pti == ' ')
{
pti++;
}
if (*pti == '\0')
{
*pto = '\0';
token->string = STRALLOC(string);
pop_call();
return level;
}
else
{
*pto++ = ' ';
while (*pti != ' ' && !isalnum(*pti))
{
if (*pti == '\0')
{
if (mind)
log_build_printf(mind->vnum, "ifchck operator without value");
else if (obj)
log_build_printf(obj->vnum, "ifchck operator without value");
else if (room)
log_build_printf(room->vnum, "ifchck operator without value");
token->string = STRDUPE(str_empty);
pop_call();
return level;
}
else
{
*pto++ = *pti++;
}
}
while (*pti == ' ')
{
pti++;
}
*pto++ = ' ';
while (*pti != '\0') /* took out *pto++ != ' ' right here */
{
*pto++ = *pti++;
}
*pto = '\0';
token->string = STRALLOC(string);
pop_call();
return level;
}
}
for (pto = string ; *pti != '\0' && *pti != '\r' && *pti != '\n' ; pti++, pto++)
{
*pto = *pti;
}
*pto = '\0';
token->string = STRALLOC(string);
pop_call();
return(level);
}
/*
Repopulate areas periodically.
*/
void repop_area ( AREA_DATA *pArea )
{
PLAYER_GAME *gpl;
push_call("repop_area(%p)",pArea);
pArea->age++;
if (pArea->nplayer > 0 && pArea->age == 39 && (!pArea->resetmsg || strcasecmp(pArea->resetmsg, "off")))
{
int rnd = number_range(1, 4);
for (gpl = mud->f_player ; gpl ; gpl = gpl->next)
{
if (IS_AWAKE(gpl->ch) && gpl->ch->in_room && gpl->ch->in_room->area == pArea)
{
if (pArea->resetmsg && pArea->resetmsg[0] != '\0')
{
ch_printf_color(gpl->ch, "%s\n\r", pArea->resetmsg);
}
else
{
switch (gpl->ch->in_room->sector_type)
{
case SECT_INSIDE:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "You hear the boards creaking.\n\r"); break;
case 2: ch_printf_color(gpl->ch, "You hear growling echoing in the distance.\n\r"); break;
case 3: ch_printf_color(gpl->ch, "You hear wax dripping off a candle.\n\r" ); break;
case 4: ch_printf_color(gpl->ch, "You hear foot steps in the distance.\n\r"); break;
}
break;
case SECT_CITY:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "You hear the shuffle of feet upon the street.\n\r"); break;
case 2: ch_printf_color(gpl->ch, "You hear the idle chatter of passers by.\n\r"); break;
case 3: ch_printf_color(gpl->ch, "You hear shopkeepers announcing their wares.\n\r"); break;
case 4: ch_printf_color(gpl->ch, "Patrons and merchants roam about the streets.\n\r"); break;
}
break;
case SECT_FIELD:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sYou hear small creatures rustling the grass.\n\r", ansi_translate("{128}")); break;
case 2: ch_printf_color(gpl->ch, "%sYou hear large creatures rustling the grass.\n\r", ansi_translate("{128}")); break;
case 3: ch_printf_color(gpl->ch, "%sField mice scurrying about in the brush.\n\r", ansi_translate("{128}")); break;
case 4: ch_printf_color(gpl->ch, "%sThe wind whispers softly through the grasses.\n\r", ansi_translate("{128}")); break;
}
break;
case SECT_FOREST:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sYou hear the trees creaking in the wind.\n\r", ansi_translate("{028}")); break;
case 2: ch_printf_color(gpl->ch, "%sThe sound of forest creatures echoes around the trees.\n\r", ansi_translate("{028}")); break;
case 3: ch_printf_color(gpl->ch, "%sThe wind carries the scent of evergreens through the trees.\n\r", ansi_translate("{028}")); break;
case 4: ch_printf_color(gpl->ch, "%sYou hear the distinct sound of trees grooming one another in the wind.\n\r", ansi_translate("{028}")); break;
}
break;
case SECT_HILLS:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sThe wind causes the grass to sway along the rolling hills.\n\r", ansi_translate("{038}")); break;
case 2: ch_printf_color(gpl->ch, "%sYou hear nothing but a peaceful, easy calm.\n\r", ansi_translate("{038}")); break;
case 3: ch_printf_color(gpl->ch, "%sWildflowers dance with the grass in the wind.\n\r", ansi_translate("{038}")); break;
case 4: ch_printf_color(gpl->ch, "%sThe bleating of a goat carries far across the hillside.\n\r", ansi_translate("{038}")); break;
}
break;
case SECT_MOUNTAIN:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sYou hear a rockslide off in the distance.\n\r", ansi_translate("{038}")); break;
case 2: ch_printf_color(gpl->ch, "%sYou hear echos of large hooved animals wandering across the rocks.\n\r", ansi_translate("{038}")); break;
case 3: ch_printf_color(gpl->ch, "%sThe sound of rams' horns clashing echoes in the distance.\n\r", ansi_translate("{038}")); break;
case 4: ch_printf_color(gpl->ch, "%sThe wind whips briskly along the side of the mountain.\n\r", ansi_translate("{038}")); break;
}
break;
case SECT_LAKE:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sYou hear fish splashing in the water.\n\r", ansi_translate("{168}")); break;
case 2: ch_printf_color(gpl->ch, "%sBubbles gently rise to the surface of the water.\n\r", ansi_translate("{168}")); break;
case 3: ch_printf_color(gpl->ch, "%sThe water ripples gently around you.\n\r", ansi_translate("{168}")); break;
case 4: ch_printf_color(gpl->ch, "%sWater laps lightly against the shoreline.\n\r", ansi_translate("{168}")); break;
}
break;
case SECT_RIVER:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sThe river's waters gurgle softly as they flow.\n\r", ansi_translate("{168}")); break;
case 2: ch_printf_color(gpl->ch, "%sWater splashes as it runs over the rocks.\n\r", ansi_translate("{168}")); break;
case 3: ch_printf_color(gpl->ch, "%sSmall fishes splash about in the water.\n\r", ansi_translate("{168}")); break;
case 4: ch_printf_color(gpl->ch, "%sThe flow of the water continues its way downstream.\n\r", ansi_translate("{168}")); break;
}
break;
case SECT_OCEAN:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sThe waves crest around you loudly.\n\r", ansi_translate("{148}")); break;
case 2: ch_printf_color(gpl->ch, "%sLarge fishes splash in the water around you.\n\r", ansi_translate("{148}")); break;
case 3: ch_printf_color(gpl->ch, "%sYou hear a fog horn echoing through the darkness.\n\r", ansi_translate("{148}")); break;
case 4: ch_printf_color(gpl->ch, "%sYou hear the echoes of sea creatures deep below.\n\r", ansi_translate("{148}")); break;
}
break;
case SECT_AIR:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "The wind blows harshly around you.\n\r"); break;
case 2: ch_printf_color(gpl->ch, "You hear birds of prey screeching nearby.\n\r"); break;
case 3: ch_printf_color(gpl->ch, "The clouds roll and whisp around you.\n\r"); break;
case 4: ch_printf_color(gpl->ch, "The air rushes at you from all directions at once.\n\r"); break;
}
break;
case SECT_DESERT:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sThe desert wind whips the sand fiercely.\n\r", ansi_translate("{138}")); break;
case 2: ch_printf_color(gpl->ch, "%sThe desert heat radiates off of the sands.\n\r", ansi_translate("{138}")); break;
case 3: ch_printf_color(gpl->ch, "%sYou hear a sandstorm growing in the distance.\n\r", ansi_translate("{138}")); break;
case 4: ch_printf_color(gpl->ch, "%sAn oasis appears and fades as a mirage in the distance.\n\r", ansi_translate("{138}")); break;
}
break;
case SECT_LAVA:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sYou hear the bubbling of molten stone.\n\r", ansi_translate("{118}")); break;
case 2: ch_printf_color(gpl->ch, "%sYou hear grinding of rocks.\n\r", ansi_translate("{118}")); break;
case 3: ch_printf_color(gpl->ch, "%sLava steams and sizzles as it bubbles onto cold stone.\n\r", ansi_translate("{118}")); break;
case 4: ch_printf_color(gpl->ch, "%scraters of molten earth groan and bubble around you.\n\r", ansi_translate("{118}")); break;
}
break;
case SECT_ETHEREAL:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "You hear echos of an unknown creature.\n\r"); break;
case 2: ch_printf_color(gpl->ch, "You hear the distant explosions of power.\n\r"); break;
case 3: ch_printf_color(gpl->ch, "You hear an indescribable sound.\n\r"); break;
case 4: ch_printf_color(gpl->ch, "You feel a transparent mist appear and thicken about you momentarily.\n\r"); break;
}
break;
case SECT_ASTRAL:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "You hear silence echoing in your head.\n\r"); break;
case 2: ch_printf_color(gpl->ch, "You hear the pain of a lost soul.\n\r"); break;
case 3: ch_printf_color(gpl->ch, "You hear the beating of your own heart.\n\r"); break;
case 4: ch_printf_color(gpl->ch, "You hear high pitched voices whispering quietly around you.\n\r"); break;
}
break;
case SECT_UNDER_WATER:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sYou hear the gurgling of the water.\n\r", ansi_translate("{048}")); break;
case 2: ch_printf_color(gpl->ch, "%sYou hear the clicking of a large marine animal.\n\r", ansi_translate("{048}")); break;
case 3: ch_printf_color(gpl->ch, "%sSmall fish dart back and forth before your eyes.\n\r", ansi_translate("{048}")); break;
case 4: ch_printf_color(gpl->ch, "%sYou hear the echoing roar of a giant sea creature.\n\r", ansi_translate("{048}")); break;
}
break;
case SECT_UNDER_GROUND:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "You hear a loud crash!\n\r"); break;
case 2: ch_printf_color(gpl->ch, "Some cracks appear in the rock above your head.\n\r"); break;
case 3: ch_printf_color(gpl->ch, "The echo of dripping water echoes against the walls.\n\r"); break;
case 4: ch_printf_color(gpl->ch, "You hear nothing but the sound of your own breathing.\n\r"); break;
}
break;
case SECT_DEEP_EARTH:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sYou hear a distant cry echoing all around you.\n\r", ansi_translate("{108}")); break;
case 2: ch_printf_color(gpl->ch, "%sYou hear the groan of the immense weight above you.\n\r", ansi_translate("{108}")); break;
case 3: ch_printf_color(gpl->ch, "%sYou smell ozone in the air around you.\n\r", ansi_translate("{108}")); break;
case 4: ch_printf_color(gpl->ch, "%sYou hear the rocks around you shifting and settling.\n\r", ansi_translate("{108}")); break;
}
break;
case SECT_ROAD:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sA trading caravan rolls by.\n\r", ansi_translate("{038}")); break;
case 2: ch_printf_color(gpl->ch, "%sYou hear clop of trotting hooves in the distance.\n\r", ansi_translate("{038}")); break;
case 3: ch_printf_color(gpl->ch, "%sYou hear crickets hidden alongside the road.\n\r", ansi_translate("{038}")); break;
case 4: ch_printf_color(gpl->ch, "%sYou feel a gust of wind and dust blown from the road.\n\r", ansi_translate("{038}")); break;
}
break;
case SECT_SWAMP:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sGurgling bubbles belch forth from the calm surface of the water.\n\r", ansi_translate("{028}")); break;
case 2: ch_printf_color(gpl->ch, "%sYou hear frogs croaking in the distance.\n\r", ansi_translate("{028}")); break;
case 3: ch_printf_color(gpl->ch, "%sYou hear mosquitos buzzing around you.\n\r", ansi_translate("{028}")); break;
case 4: ch_printf_color(gpl->ch, "%sThe sounds of marsh life echo all around you.\n\r", ansi_translate("{028}")); break;
}
break;
case SECT_BEACH:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sA cool salty spray blows in the air.\n\r", ansi_translate("{168}")); break;
case 2: ch_printf_color(gpl->ch, "%sThe grating squawk of a seabirds echoes overhead.\n\r", ansi_translate("{168}")); break;
case 3: ch_printf_color(gpl->ch, "%sThe soft roar of waves crashing echoes across the beach.\n\r", ansi_translate("{168}")); break;
case 4: ch_printf_color(gpl->ch, "%sThe clean scent of seaweed fills the air as it washes up on the beach.\n\r", ansi_translate("{168}")); break;
}
break;
case SECT_TUNDRA:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sThe faint sound of arctic creatures can be heard in the distance.\n\r", ansi_translate("{178}")); break;
case 2: ch_printf_color(gpl->ch, "%sThe wind whistles as snows dance and spiral over the tundra.\n\r", ansi_translate("{178}")); break;
case 3: ch_printf_color(gpl->ch, "%sThe icy silence is broken by the sound of a distant snowslide.\n\r", ansi_translate("{178}")); break;
case 4: ch_printf_color(gpl->ch, "%sThe icy chill of the wind stabs at you like daggers.\n\r", ansi_translate("{178}")); break;
}
break;
case SECT_BARREN:
switch (rnd)
{
case 1: ch_printf_color(gpl->ch, "%sA tumbleweed rolls by, driven by an eerily quiet breeze.\n\r", ansi_translate("{038}")); break;
case 2: ch_printf_color(gpl->ch, "%sThe sound of a lone cyote calls in the distance.\n\r", ansi_translate("{038}")); break;
case 3: ch_printf_color(gpl->ch, "%sA flock of buzzards circles in the distance over some unknown quarry.\n\r", ansi_translate("{038}")); break;
case 4: ch_printf_color(gpl->ch, "%sA light arid breeze offers only momentary reprieve from the dry air.\n\r", ansi_translate("{038}")); break;
}
break;
default:
ch_printf_color(gpl->ch, "You hear the patter of little feet.\n\r");
break;
}
}
}
}
}
/*
Check age and reset.
*/
if (pArea->age >= 40)
{
reset_area( pArea );
}
pop_call();
return;
}
void area_update( void )
{
AREA_DATA *pArea;
push_call("area_update(void)");
for (pArea = mud->f_area ; pArea ; pArea = pArea->next)
{
repop_area(pArea);
}
pop_call();
return;
}
/*
Locate last instance of obj reset
*/
RESET_DATA *get_reset_from_obj(RESET_DATA *lReset)
{
RESET_DATA *pReset;
push_call("get_reset_from_obj(%p)",lReset);
for (pReset = lReset ; pReset ; pReset = pReset->prev)
{
if (pReset->arg1 == lReset->arg3)
{
if (pReset->command == 'O' || pReset->command == 'G' || pReset->command == 'E')
{
pop_call();
return pReset;
}
}
}
log_printf("get_reset_from_obj: bad '%c' reset", lReset->command);
pop_call();
return NULL;
}
/*
Locate last instance of mobile reset
*/
RESET_DATA *get_reset_from_mob( RESET_DATA *lReset )
{
RESET_DATA *pReset;
push_call("get_reset_from_mob(%p)",lReset);
for (pReset = lReset->prev ; pReset ; pReset = pReset->prev)
{
if (pReset->command == 'M')
{
pop_call();
return pReset;
}
}
log_printf("get_reset_from_mob: bad '%c' reset", lReset->command);
pop_call();
return NULL;
}
/*
Locate last instance of door reset
*/
RESET_DATA *get_reset_from_trap( RESET_DATA *lReset )
{
RESET_DATA *pReset;
push_call("get_reset_from_trap(%p)",lReset);
for (pReset = lReset->prev ; pReset ; pReset = pReset->prev)
{
if (pReset->arg1 == lReset->arg2)
{
if (pReset->command == 'O' || pReset->command == 'G' || pReset->command == 'E' || pReset->command == 'D')
{
pop_call();
return pReset;
}
}
}
log_printf("get_reset_from_trap: bad '%c' reset", lReset->command);
pop_call();
return NULL;
}
void do_resetarea( CHAR_DATA *ch, char *arg)
{
push_call("do_resetarea(%p,%p)",ch,arg);
if (IS_NPC(ch))
{
log_printf("mob using area reset.");
dump_stack();
pop_call();
return;
}
if (!can_olc_modify(ch, ch->in_room->vnum))
{
ch_printf_color(ch, "This area is not in your allocated range.\n\r");
pop_call();
return;
}
SET_BIT(mud->flags, MUD_EMUD_BOOTDB);
if (IS_SET(mud->flags, MUD_EMUD_REALGAME))
{
log_printf("%s resetted area %s", get_name(ch), ch->in_room->area->name);
}
send_to_char("Resetting area.\n\r", ch);
reset_area(ch->in_room->area);
REMOVE_BIT(mud->flags, MUD_EMUD_BOOTDB);
pop_call();
return;
}
/*
Create an instance of a mobile.
*/
CHAR_DATA *create_mobile( MOB_INDEX_DATA *pMobIndex )
{
CHAR_DATA *mob;
AFFECT_DATA *paf;
NPC_DATA *np;
int cnt;
push_call("create_mobile(%p)",pMobIndex);
if (pMobIndex == NULL)
{
bug("create_mobile: NULL pMobIndex.");
abort( );
}
if (pMobIndex->total_mobiles > 1000)
{
log_build_printf(pMobIndex->vnum, "More than 1000 mobs created: %d.\n\r", pMobIndex->total_mobiles);
}
mud->total_mob++;
ALLOCMEM(mob, CHAR_DATA, 1);
ALLOCMEM(np, NPC_DATA, 1);
mob->level = URANGE(1, pMobIndex->level, 45);
clear_char( mob );
mob->npcdata = np;
mob->pIndexData = pMobIndex;
mob->name = STRDUPE(pMobIndex->player_name);
mob->short_descr = STRDUPE(pMobIndex->short_descr);
mob->long_descr = STRDUPE(pMobIndex->long_descr);
mob->description = STRDUPE(pMobIndex->description);
mob->act = pMobIndex->act;
mob->spec_fun = pMobIndex->spec_fun;
mob->affected_by = pMobIndex->affected_by;
mob->alignment = pMobIndex->alignment;
mob->ethos = pMobIndex->ethos;
mob->sex = pMobIndex->sex;
mob->size = pMobIndex->size;
mob->max_hit = UMAX(pMobIndex->level, dice(pMobIndex->level, pMobIndex->hitsizedice)) + pMobIndex->hitplus;
mob->gold = number_fuzzy(pMobIndex->gold);
mob->perm_str = pMobIndex->perm_str;
mob->perm_dex = pMobIndex->perm_dex;
mob->perm_int = pMobIndex->perm_int;
mob->perm_wis = pMobIndex->perm_wis;
mob->perm_con = pMobIndex->perm_con;
mob->perm_cha = pMobIndex->perm_cha;
mob->npcdata->remember = STRDUPE(str_empty);
mob->npcdata->hate_fear = 0;
mob->npcdata->sac_timer = -1;
mob->npcdata->sac_string = STRDUPE(str_empty);
mob->npcdata->prog_cmd = STRDUPE(str_empty);
mob->race = pMobIndex->race;
mob->class = pMobIndex->class;
height_weight(mob);
if (IS_CLASSED(mob))
{
mob->max_hit = 0;
for (cnt = 1 ; cnt < MAX_CLASS ; cnt++)
{
if (mob->class == cnt && pMobIndex->mclass[cnt] == 0)
mob->mclass[cnt] = mob->level;
if (pMobIndex->mclass[cnt] > 0)
{
mob->mclass[cnt] = pMobIndex->mclass[cnt];
if (cnt == CLASS_MONSTER)
mob->max_hit += dice(pMobIndex->mclass[cnt], race_type_table[race_type(mob)].hit_die);
else
mob->max_hit += dice(pMobIndex->mclass[cnt], class_table[cnt].hp_max);
}
}
}
else if (!mob->race)
{
mob->max_hit = dice(mob->level, race_type_table[race_table[mob->race].type].hit_die);
mob->speak = race_table[mob->race].speaks;
mob->language = race_table[mob->race].understands;
}
else
{
mob->max_hit = dice(mob->level, pMobIndex->hitsizedice);
}
if (pMobIndex->speaks > 0)
mob->speak = pMobIndex->speaks;
SET_BIT(mob->language, pMobIndex->understands);
for (cnt = 0 ; *skill_table[cnt].name != '\0' ; cnt++)
{
if (pMobIndex->learned[cnt] > 0)
{
mob->learned[cnt] = pMobIndex->learned[cnt];
continue;
}
if (skill_table[cnt].flags != FSKILL_SKILL)
continue;
mob->learned[cnt] = learned(mob, cnt);
}
restore_mana(mob);
mob->speed = 1;
mob->position = pMobIndex->position;
mob->hit = get_max_hit(mob);
mob->move = get_max_move(mob);
//transfer MobIndex effects to local effects
for (paf = mob->pIndexData->first_affect ; paf != NULL ; paf = paf->next)
{
affect_to_char(NULL, mob, paf);
}
/*
Insert in list.
*/
add_char( mob );
pMobIndex->total_mobiles++;
/* add objects from load_eq */
OBJ_DATA *obj;
int vnum;
for (cnt = 0 ; cnt < MAX_WEAR ; cnt++)
{
if ((vnum = pMobIndex->load_eq[cnt]) > 0)
{
if ((obj = create_object(obj_index[vnum], 0)) == NULL)
{
log_printf("create_mobile: NULL obj in load_eq %d.", vnum);
continue;
}
obj_to_char(obj, mob);
equip_char(mob, obj, cnt);
}
}
char_reset(mob); //clean up and load applies and resists
pop_call();
return mob;
}
/*
Create an instance of an object.
*/
OBJ_DATA *create_object( OBJ_INDEX_DATA *pObjIndex, bool hashed )
{
OBJ_DATA *obj;
AFFECT_DATA *paf;
push_call("create_object(%p,%p)",pObjIndex,hashed);
if (pObjIndex == NULL)
{
log_string("Create_object: NULL pObjIndex.");
pop_call();
return NULL;
}
ALLOCMEM(obj, OBJ_DATA, 1);
obj->pIndexData = pObjIndex;
obj->level = pObjIndex->level;
obj->wear_loc = WEAR_NONE;
if (!hashed)
{
add_obj_ref_hash(obj);
}
obj->name = STRDUPE(pObjIndex->name);
obj->short_descr = STRDUPE(pObjIndex->short_descr);
obj->long_descr = STRDUPE(pObjIndex->long_descr);
obj->description = STRDUPE(pObjIndex->description);
obj->id_name = STRDUPE(pObjIndex->id_name);
obj->id_descr = STRDUPE(pObjIndex->id_descr);
obj->item_type = pObjIndex->item_type;
obj->extra_flags = pObjIndex->extra_flags;
obj->wear_flags = pObjIndex->wear_flags;
obj->material = pObjIndex->material;
obj->hit_points = pObjIndex->hit_points;
obj->size = pObjIndex->size;
obj->value[0] = pObjIndex->value[0];
obj->value[1] = pObjIndex->value[1];
obj->value[2] = pObjIndex->value[2];
obj->value[3] = pObjIndex->value[3];
obj->value[4] = pObjIndex->value[4];
obj->value[5] = pObjIndex->value[5];
obj->value[6] = pObjIndex->value[6];
obj->value[7] = pObjIndex->value[7];
obj->weight = pObjIndex->weight;
obj->cost = pObjIndex->cost;
obj->level = pObjIndex->level;
obj->identified = FALSE;
//transfer ObjIndex effects to local effects
for (paf = obj->pIndexData->first_affect ; paf != NULL ; paf = paf->next)
{
affect_to_obj(NULL, obj, paf);
}
/*
Mess with object properties.
*/
switch (obj->item_type)
{
default:
log_printf("create_object: vnum %u has bad item_type", pObjIndex->vnum);
break;
case ITEM_FIRE:
case ITEM_LIGHT:
case ITEM_SYMBOL:
case ITEM_SPELLBOOK:
case ITEM_TREASURE:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_SPELLPOUCH:
case ITEM_CONTAINER:
case ITEM_CART:
case ITEM_SHEATH:
case ITEM_QUIVER:
case ITEM_DRINK_CON:
case ITEM_KEY:
case ITEM_CRAFT:
case ITEM_PIECE:
case ITEM_FOOD:
case ITEM_BOAT:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_FOUNTAIN:
case ITEM_PORTAL:
case ITEM_WINDOW:
case ITEM_PAPER:
case ITEM_TRAP:
case ITEM_TOTEM:
case ITEM_BOOK:
break;
case ITEM_TOOLS:
obj->value[1] = number_fuzzy(obj->value[1]);
break;
case ITEM_SCROLL:
case ITEM_POTION:
case ITEM_PILL:
case ITEM_COMPONENT:
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]);
break;
case ITEM_WEAPON:
obj->weight = weapon_table[obj->value[0]].weight;
obj->apply[APPLY_HITROLL] = get_obj_apply(obj, APPLY_HITROLL);
obj->apply[APPLY_DAMROLL] = get_obj_apply(obj, APPLY_DAMROLL);
break;
case ITEM_ARMOR:
obj->weight = armor_table[obj->value[0]].weight;
obj->apply[APPLY_ENHANCE_AC] = get_obj_apply(obj, APPLY_ENHANCE_AC);
break;
case ITEM_MONEY:
obj->cost = obj->value[0] * 100;
obj->cost += obj->value[1] * 10;
obj->cost += obj->value[2];
break;
case ITEM_AMMO:
obj->value[1] = number_fuzzy(obj->value[1]);
obj->apply[APPLY_HITROLL] = get_obj_apply(obj, APPLY_HITROLL);
obj->apply[APPLY_DAMROLL] = get_obj_apply(obj, APPLY_DAMROLL);
break;
}
LINK(obj, mud->f_obj, mud->l_obj, next, prev);
LINK(obj, obj->pIndexData->first_instance, obj->pIndexData->last_instance, next_instance, prev_instance);
mud->total_obj++;
pObjIndex->total_objects++;
pop_call();
return obj;
}
/*
Clear a new character.
*/
void clear_char( CHAR_DATA *ch )
{
push_call("clear_char(%p)",ch);
ch->position = POS_STANDING;
ch->hit = 0;
ch->max_hit = 0;
ch->move = 0;
ch->max_move = 0;
pop_call();
return;
}
/*
Free a character.
*/
void free_char( CHAR_DATA *ch )
{
POISON_DATA *pd;
CRIME_DATA *crime;
int cnt;
push_call("free_char(%p)",ch);
while (ch->first_carrying)
{
extract_obj(ch->first_carrying);
}
while (ch->first_affect)
{
affect_from_char(ch, ch->first_affect);
}
while (ch->first_disease)
{
disease_from_char(ch, ch->first_disease);
}
while ((pd = ch->poison) != NULL)
{
ch->poison = ch->poison->next;
FREEMEM(pd);
}
STRFREE(ch->name);
STRFREE(ch->short_descr);
STRFREE(ch->long_descr);
STRFREE(ch->description);
if (in_combat(ch) || ch->in_battle != NULL)
{
char_from_combat(ch);
}
if (ch->last_attacked)
{
ch->last_attacked = NULL;
}
if (ch->last_attacker)
{
ch->last_attacker = NULL;
}
if (ch->pcdata)
{
STRFREE(ch->pcdata->host );
STRFREE(ch->pcdata->account );
STRFREE(ch->pcdata->mail_address );
STRFREE(ch->pcdata->html_address );
STRFREE(ch->pcdata->block_list );
STRFREE(ch->pcdata->title );
STRFREE(ch->pcdata->auto_command );
STRFREE(ch->pcdata->adjective );
STRFREE(ch->pcdata->authed_by );
STRFREE(ch->pcdata->bamfin );
STRFREE(ch->pcdata->bamfout );
STRFREE(ch->pcdata->pwd );
STRFREE(ch->pcdata->page_buf );
STRFREE(ch->pcdata->edit_buf );
STRFREE(ch->pcdata->prompt_layout );
STRFREE(ch->pcdata->subprompt );
STRFREE(ch->pcdata->clan_name );
STRFREE(ch->pcdata->clan_pledge );
STRFREE(ch->pcdata->last_command );
STRFREE(ch->pcdata->bio );
STRFREE(ch->pcdata->pose );
STRFREE(ch->pcdata->disguise );
STRFREE(ch->pcdata->disguise_descr );
ch->pcdata->tracking = NULL;
while ((crime = ch->pcdata->first_record) != NULL)
{
ch->pcdata->first_record = crime->next;
STRFREE(crime->crime_record);
STRFREE(crime->arrester);
STRFREE(crime->releaser);
FREEMEM(crime);
}
if (ch->pcdata->pnote != NULL)
{
STRFREE(ch->pcdata->pnote->text);
STRFREE(ch->pcdata->pnote->subject);
STRFREE(ch->pcdata->pnote->to_list);
STRFREE(ch->pcdata->pnote->date);
STRFREE(ch->pcdata->pnote->sender);
FREEMEM(ch->pcdata->pnote);
}
if (ch->pcdata->editor)
{
stop_editing(ch);
}
for (cnt = 0 ; cnt < MAX_PK_ATTACKS ; cnt++)
{
STRFREE(ch->pcdata->last_pk_attack_name[cnt]);
}
for (cnt = 0 ; cnt < MAX_ALIAS ; cnt++)
{
STRFREE (ch->pcdata->alias[cnt] );
STRFREE (ch->pcdata->alias_c[cnt] );
}
for (cnt = 0 ; cnt < 26 ; cnt++)
{
STRFREE(ch->pcdata->back_buf[cnt] );
}
for (cnt = 0 ; cnt < MAX_AREA ; cnt++)
{
if (ch->pcdata->quest[cnt] != NULL)
{
FREEMEM(ch->pcdata->quest[cnt]);
}
}
if (ch->pcdata->tactical)
{
FREEMEM(ch->pcdata->tactical);
}
FREEMEM(ch->pcdata);
}
if (ch->npcdata)
{
if (ch->npcdata->mob_quest)
{
FREEMEM(ch->npcdata->mob_quest);
}
STRFREE(ch->npcdata->remember);
STRFREE(ch->npcdata->sac_string);
ch->npcdata->hate_fear = 0;
FREEMEM(ch->npcdata);
}
FREEMEM(ch);
pop_call();
return;
}
/*
Get an extra description from a list.
*/
char *get_extra_descr( const char *name, EXTRA_DESCR_DATA *ed )
{
push_call("get_extra_descr(%p,%p)",name,ed);
for ( ; ed ; ed = ed->next)
{
if (is_name(name, ed->keyword))
{
pop_call();
return ed->description;
}
}
pop_call();
return NULL;
}
/*
Read a letter from a file.
*/
char fread_letter( FILE *fp )
{
char c;
push_call("fread_letter(%p)",fp);
do
{
if (feof(fp))
{
bug("fread_letter: EOF encountered on read.\n\r");
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
exit(1);
}
pop_call();
return '\0';
}
c = getc(fp);
}
while (isspace(c));
pop_call();
return c;
}
/*
Read a number from a file.
*/
lg_int fread_number( FILE *fp )
{
int cnt;
lg_int number;
bool sign;
char c;
char buf[100];
push_call("fread_number(%p)",fp);
buf[0] = '\0';
do
{
if (feof(fp))
{
bug("fread_number: EOF encountered on read.\n\r");
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
exit(1);
}
pop_call();
return 0;
}
c = getc(fp);
}
while (isspace(c));
number = 0;
sign = (c == '-');
if (c == '+' || c == '-')
{
c = getc(fp);
}
for (cnt = 0 ; isdigit(c) || isupper(c) || c == '_' ; cnt++)
{
buf[cnt] = c;
c = getc(fp);
}
buf[cnt] = '\0';
if (isupper(buf[0]))
{
for (cnt = mud->bitvector_ref[*buf - 'A'] ; *bitvector_table[cnt].name != '\0' ; cnt++)
{
if (!strcmp(bitvector_table[cnt].name, buf))
{
number = bitvector_table[cnt].value;
break;
}
}
if (*bitvector_table[cnt].name == '\0')
{
log_printf("fread_number: bad format1 '%s'.", buf);
dump_stack();
}
}
else
{
if (!isdigit(buf[0]))
{
log_printf("fread_number: bad format2 '%c%s'", c, fread_word(fp));
pop_call();
return number;
}
number = atoll(buf);
}
if (sign)
{
number = 0 - number;
}
if (c == '|')
{
number += fread_number( fp );
}
else if (c != ' ')
{
ungetc( c, fp );
}
pop_call();
return number;
}
/*
Read and allocate space for a string from a file.
Strings are created and placed in Dynamic Memory.
*/
char *fread_string( FILE *fp )
{
char buf[MAX_STRING_LENGTH];
char *plast;
char c;
int ln;
push_call("fread_string(%p)",fp);
plast = buf;
buf[0] = '\0';
ln = 0;
/*
Skip blanks.
Read first char.
*/
do
{
if (feof(fp))
{
bug("fread_string: EOF encountered on read.\n\r");
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
exit(1);
}
pop_call();
return STRDUPE(str_empty);
}
c = getc( fp );
}
while (isspace(c));
if ((*plast++ = c) == '~')
{
pop_call();
return STRDUPE(str_empty);
}
for (ln = 0 ; ln < MAX_STRING_LENGTH ; ln++, plast++)
{
switch (*plast = getc(fp))
{
case EOF:
bug( "Fread_string: EOF" );
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
exit( 1 );
}
*plast = '\0';
pop_call();
return STRALLOC(buf);
case '\n':
plast++;
ln++;
*plast = '\r';
break;
case '\r':
plast--;
ln--;
break;
case '~':
*plast = '\0';
pop_call();
return STRALLOC( buf );
}
}
bug("fread_string: string too long" );
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
abort();
}
*plast = '\0';
pop_call();
return STRALLOC(buf);
}
/*
Read to end of line (for comments).
*/
void fread_to_eol( FILE *fp )
{
char c;
push_call("fread_to_eol(%p)",fp);
do
{
if (feof(fp))
{
bug("fread_to_eol: EOF encountered on read.\n\r", 0);
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
abort();
}
pop_call();
return;
}
c = getc( fp );
}
while (c != '\n' && c != '\r');
do
{
c = getc( fp );
}
while (c == '\n' || c == '\r');
ungetc(c, fp);
pop_call();
return;
}
char *fread_line( FILE *fp )
{
static char line[MAX_STRING_LENGTH];
char *pline;
char c;
int ln;
push_call("fread_line(%p)",fp);
pline = line;
line[0] = '\0';
ln = 0;
/*
Skip blanks.
Read first char.
*/
do
{
if (feof(fp))
{
bug("fread_line: EOF encountered on read.\n\r",0);
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
abort();
}
strcpy(line, "");
pop_call();
return line;
}
c = getc( fp );
}
while (isspace(c));
ungetc(c, fp);
do
{
if (feof(fp))
{
bug("fread_line: EOF encountered on read.\n\r",0);
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
abort();
}
*pline = '\0';
pop_call();
return line;
}
c = getc( fp );
*pline++ = c; ln++;
if (ln >= (MAX_STRING_LENGTH - 1))
{
bug( "fread_line: line too long",0 );
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
abort();
}
break;
}
}
while (c != '\n' && c != '\r');
do
{
c = getc( fp );
}
while (c == '\n' || c == '\r');
ungetc( c, fp );
*pline = '\0';
pop_call();
return line;
}
/*
Read one word (into static buffer).
*/
char *fread_word( FILE *fp )
{
static char word[MAX_INPUT_LENGTH];
char *pword;
char cEnd;
int cnt;
push_call("fread_word(%p)",fp);
do
{
if (feof(fp))
{
bug("fread_word: EOF encountered on read.\n\r", 0);
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
abort();
}
word[0] = '\0';
pop_call();
return word;
}
cEnd = getc( fp );
}
while ( isspace(cEnd) );
if (cEnd == '\'' || cEnd == '"')
{
pword = word;
}
else
{
word[0] = cEnd;
pword = word+1;
cEnd = ' ';
}
for (cnt = 0 ; cnt < MAX_INPUT_LENGTH ; cnt++, pword++)
{
if (feof(fp))
{
bug("fread_word: EOF encountered on read.\n\r", 0);
if (IS_SET(mud->flags, MUD_EMUD_BOOTDB))
{
abort();
}
*pword = '\0';
pop_call();
return word;
}
*pword = getc(fp);
if (*pword == cEnd || *pword == EOF || *pword == '\n')
{
if (*pword == EOF || cEnd == ' ')
{
ungetc( *pword, fp );
}
*pword = '\0';
pop_call();
return word;
}
}
word[10] = '\0';
bug("fread_word: word '%s' too long.", word);
abort( );
}
/*
Returns 1000 times normal percentage value
*/
lg_int display_timer( CHAR_DATA *ch, int timer )
{
lg_int tot_usage, ind_usage;
push_call("display_timer(%p,%p)",ch,timer);
tot_usage = mud->total_io_exec + mud->total_io_delay;
if (tot_usage == 0)
{
pop_call();
return(0);
}
if (timers[timer][1] == 0 || timers[timer][4] == 0)
{
pop_call();
return(0);
}
ind_usage = timers[timer][0] / timers[timer][1] * timers[timer][4];
ch_printf_color(ch, "%-30s%8lld %8lld %8.2f %8.2f\n\r",
timer_strings[timer],
timers[timer][0] / timers[timer][1],
timers[timer][3] / timers[timer][4] / 1000,
100.0 * (double) ind_usage / (double) mud->total_io_exec,
100.0 * (double) ind_usage / (double) tot_usage);
pop_call();
return ind_usage;
}
void start_timer( int timer )
{
struct timeval last_time;
lg_int cur_time;
gettimeofday(&last_time, NULL);
cur_time = (lg_int) last_time.tv_usec + 1000000LL * (lg_int) last_time.tv_sec;
if (timers[timer][2] == 0)
{
timers[timer][2] = cur_time ;
return;
}
timers[timer][3] += cur_time - timers[timer][2];
timers[timer][2] = cur_time;
timers[timer][4] ++;
return;
}
void close_timer( int timer )
{
struct timeval last_time;
lg_int cur_time;
gettimeofday(&last_time, NULL);
cur_time = (lg_int) last_time.tv_usec + 1000000LL * (lg_int) last_time.tv_sec;
/*
if (cur_time - timers[timer][2] > 1000000 / PULSE_PER_SECOND)
{
bug("%s heartbeat violation of %lld usec", timer_strings[timer], cur_time - timers[timer][2] - (1000000LL / PULSE_PER_SECOND));
}
*/
timers[timer][0] += (cur_time - timers[timer][2]);
timers[timer][1] ++;
return;
}
/*
randomize number by -10 to 10 percent
*/
int number_fuzzy( int number )
{
return (number - number/10 + number_range(0, number/10*2));
}
/*
randomize each digit in number by -1 to +1
*/
int big_number_fuzzy( int number )
{
char numbuf[MAX_STRING_LENGTH];
sh_int i;
sprintf(numbuf, "%d", number);
for ( i = 0; numbuf[i] != '\0'; i++ )
numbuf[i] = number_fuzzy(numbuf[i]);
number = atoi(numbuf);
return UMAX( 1, number );
}
float what_percent(float current, float max)
{
float percent;
push_call("what_percent(%p,%p)",current,max);
percent = 100 * UMAX(0, current) / UMAX(1, max);
pop_call();
return percent;
}
/*
Generate a random number.
*/
int number_range( int from, int to )
{
int val;
push_call("number_range(%p,%p)",from,to);
if (from > to || from < 0 || to < 0)
{
log_printf("number_range: invalid range (%d,%d)", from, to);
dump_stack();
if (from > to)
{
val = from;
from = to;
to = val;
}
}
pop_call();
return (lrand48() % (to - from + 1)) + from;
}
/*
Roll some dice.
*/
int dice( int number, int size )
{
int idice, sum;
push_call("dice(%p,%p)",number,size);
if (size <= 0)
{
pop_call();
return 0;
}
for (idice = sum = 0 ; idice < number ; idice++)
{
sum += (lrand48() % size) + 1;
}
pop_call();
return sum;
}
/*
Return a value between 1 and 100
*/
int number_percent( void )
{
return ((lrand48() % 100) + 1);
}
/*
Generate a random door.
*/
int number_door( void )
{
return (lrand48() % 6);
}
/*
return a value between 0 and given power of 2
*/
int number_bits( int width )
{
return (lrand48() % (1 << width));
}
/*
Append a string to a file.
*/
void append_file( CHAR_DATA *ch, char *fname, FILE *fp, char *str )
{
push_call("append_file(%p,%p,%p,%p)",ch,fname,fp,str);
if ((ch != NULL && IS_NPC(ch)) || str == NULL || str[0] == '\0')
{
pop_call();
return;
}
if (fpAppend)
{
my_fclose( fpAppend );
}
if (fp == NULL)
{
fp = my_fopen( fname, "a",FALSE);
}
if (fp == NULL)
{
perror( fname );
fpAppend = my_fopen( NULL_FILE, "r",FALSE);
pop_call();
return;
}
if (ch == NULL)
{
fprintf( fp, "%s\n", str );
fflush( fp );
fpAppend = my_fopen( NULL_FILE, "r",FALSE);
pop_call();
return;
}
fprintf( fp, "[%s] %s: %s\n", get_time_string(mud->current_time), ch->name, str );
fflush( fp );
fpAppend = my_fopen( NULL_FILE, "r",FALSE);
pop_call();
return;
}
/*
Reports a bug. -1 param does not put in logs.
*/
void bug( const char *str, ... )
{
char buf[MAX_STRING_LENGTH];
push_call("bug(%p)",str);
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);
}
log_printf("[*****] FILE: %s LINE: %d", strArea, iLine);
}
strcpy(buf, "[+++++] ");
{
va_list param;
va_start(param, str);
vsprintf( buf + strlen(buf), str, param );
va_end(param);
}
log_string( buf );
log_printf("[+++++] %s", mud->last_player_cmd);
pop_call();
return;
}
/*
* Dump a text file to a player, a line at a time
* originally by Thoric
*/
void show_file( CHAR_DATA * ch, char *filename )
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
int c;
int num = 0;
if( ( fp = my_fopen( filename, "r", FALSE ) ) != NULL )
{
while( !feof( fp ) )
{
while( ( buf[num] = fgetc( fp ) ) != EOF
&& buf[num] != '\n' && buf[num] != '\r' && num < ( MAX_STRING_LENGTH - 2 ) )
num++;
c = fgetc( fp );
if( ( c != '\n' && c != '\r' ) || c == buf[num] )
ungetc( c, fp );
buf[num++] = '\n';
buf[num++] = '\r';
buf[num] = '\0';
send_to_char_color( buf, ch );
num = 0;
}
my_fclose( fp );
}
}
/*
Writes a string to the log.
*/
void log_string( char *str )
{
char *strtime;
struct timeval log_time;
CHAR_DATA *fch;
PLAYER_GAME *fpl;
push_call("log_string(%p)",str);
for (fpl = mud->f_player ; fpl ; fpl = fpl->next)
{
fch = fpl->ch;
if (IS_NPC(fch))
{
continue;
}
if (!IS_SET(fch->act, PLR_HEARLOG) || !IS_IMMORTAL(fch))
{
continue;
}
ch_printf_color(fch, "{058}Log: %s\n\r", justify(str, get_page_width(fch)));
}
gettimeofday(&log_time, NULL);
strtime = ctime(&log_time.tv_sec);
strtime[strlen(strtime)-6] = '\0';
fprintf( stderr, "%s- %s\n", strtime, str );
pop_call();
return;
}
void log_build_string(int vnum, char *str )
{
struct timeval log_time;
char *strtime;
CHAR_DATA *fch;
PLAYER_GAME *fpl;
push_call("log_build_string(%p)",str);
for (fpl = mud->f_player ; fpl ; fpl = fpl->next)
{
fch = fpl->ch;
if (!IS_SET(fpl->ch->act, PLR_HEARLOG) || !can_olc_modify(fpl->ch, vnum))
{
continue;
}
ch_printf_color(fch, "{058}Log: [%u] %s\n\r", vnum, str);
}
gettimeofday(&log_time, NULL);
strtime = ctime(&log_time.tv_sec);
strtime[strlen(strtime)-6] = '\0';
fprintf( stderr, "%s- [%u] %s\n", strtime, vnum, str );
pop_call();
return;
}
void log_wiz_string( char *str )
{
CHAR_DATA *fch;
PLAYER_GAME *fpl;
push_call("log_wiz_string(%p)",str);
for (fpl = mud->f_player ; fpl ; fpl = fpl->next)
{
fch = fpl->ch;
if (IS_NPC(fch))
continue;
if (!IS_SET(fpl->ch->act, PLR_WIZTIME))
continue;
ch_printf_color(fch, "{058}DEBUG: %s\n\r", str);
}
pop_call();
return;
}
void log_god_string( char *str )
{
char *strtime;
struct timeval log_time;
CHAR_DATA *fch;
PLAYER_GAME *fpl;
push_call("log_god_string(%p)",str);
for (fpl = mud->f_player ; fpl ; fpl = fpl->next)
{
fch = fpl->ch;
if (IS_NPC(fch))
{
continue;
}
if (!IS_SET(fch->act, PLR_HEARLOG) || !IS_GOD(fch))
{
continue;
}
ch_printf_color(fch, "{058}Log: %s\n\r", justify(str, get_page_width(fch)));
}
gettimeofday(&log_time, NULL);
strtime = ctime(&log_time.tv_sec);
strtime[strlen(strtime)-6] = '\0';
fprintf( stderr, "%s- %s\n", strtime, str );
pop_call();
return;
}
void create_menu_tree()
{
char *pt;
int cnt;
char line[200];
AREA_DATA *pArea, *tArea;
HELP_DATA *pHelp, *tHelp;
HELP_MENU_DATA *menu;
char buf[MAX_STRING_LENGTH];
push_call("create_menu_tree()");
for (pArea = mud->f_area ; pArea ; pArea = pArea->next)
{
for (pHelp = pArea->first_help ; pHelp ; pHelp = pHelp->next)
{
strcpy(buf, pHelp->text);
pt = buf;
pt += strlen(buf) / 4;
while (*pt != '\0')
{
if (*(pt+1) != '{' || *(pt+2) == '\0' || *(pt+3) != '}')
{
pt++;
continue;
}
pt++;
*pt = '\0';
if (pHelp->first_menu == NULL)
{
STRFREE(pHelp->text);
pHelp->text = STRALLOC(buf);
}
*pt = '{';
/*
find menu items here
*/
cnt = 0;
while (*pt != '\r' && *pt != '\n' && *pt != '\0')
{
line[cnt] = *pt;
cnt++;
pt++;
}
line[cnt] = '\0';
for (tHelp = pHelp->area->first_help ; tHelp ; tHelp = tHelp->next)
{
if (line[3] == tHelp->keyword[0] && line[4] == tHelp->keyword[1] && !strcmp(&line[3], tHelp->keyword))
{
ALLOCMEM(menu, HELP_MENU_DATA, 1);
menu->option = tolower(line[1]);
menu->help = tHelp;
LINK(menu, pHelp->first_menu, pHelp->last_menu, next, prev);
goto end_of_loop;
}
}
/*
log_printf("create_menu: inter area help menu: %s", line);
*/
for (tArea = mud->f_area ; tArea ; tArea = tArea->next)
{
for (tHelp = tArea->first_help ; tHelp ; tHelp = tHelp->next)
{
if (line[3] == tHelp->keyword[0] && line[4] == tHelp->keyword[1] && !strcmp(&line[3], tHelp->keyword))
{
ALLOCMEM(menu, HELP_MENU_DATA, 1);
menu->option = tolower(line[1]);
menu->help = tHelp;
LINK(menu, pHelp->first_menu, pHelp->last_menu, next, prev);
goto end_of_loop;
}
}
}
log_printf("create_menu: failed perfect match: %s", line);
for (tArea = mud->f_area ; tArea ; tArea = tArea->next)
{
for (tHelp = tArea->first_help ; tHelp ; tHelp = tHelp->next)
{
if (is_name(&line[3], tHelp->keyword))
{
ALLOCMEM(menu, HELP_MENU_DATA, 1);
menu->option = tolower(line[1]);
menu->help = tHelp;
LINK(menu, pHelp->first_menu, pHelp->last_menu, next, prev);
goto end_of_loop;
}
}
}
end_of_loop:
continue;
}
}
}
pop_call();
return;
}
int find_command( char *cmd_str, int trust )
{
int cmd;
push_call("find_command(%p)",cmd_str);
if (isalpha(*cmd_str))
{
for (cmd = mud->command_ref[tolower(*cmd_str) - 'a'] ; *cmd_table[cmd].name == *cmd_str ; cmd++)
{
if (IS_SET(cmd_table[cmd].flags, CMD_BUILDER|CMD_TESTER) && !str_prefix(cmd_str, cmd_table[cmd].name))
{
pop_call();
return cmd;
}
if (cmd_table[cmd].level <= trust && !str_prefix(cmd_str, cmd_table[cmd].name))
{
pop_call();
return cmd;
}
}
}
else
{
for (cmd = 0 ; !isalpha(*cmd_table[cmd].name) ; cmd++)
{
if (IS_SET(cmd_table[cmd].flags, CMD_BUILDER|CMD_TESTER) && !str_prefix(cmd_str, cmd_table[cmd].name))
{
pop_call();
return cmd;
}
if (cmd_table[cmd].level <= trust && !str_prefix(cmd_str, cmd_table[cmd].name))
{
pop_call();
return cmd;
}
}
}
pop_call();
return -1;
}
int find_social( char *social_str )
{
int cmd;
push_call("find_social(%p)",social_str);
if (isalpha(*social_str))
{
for (cmd = mud->social_ref[tolower(*social_str) - 'a'] ; *social_table[cmd].name == *social_str ; cmd++)
{
if (!str_prefix(social_str, social_table[cmd].name))
{
pop_call();
return cmd;
}
}
}
pop_call();
return -1;
}
OBJ_PROG * load_object_program( FILE *fp)
{
OBJ_PROG *prg;
char buf[MAX_INPUT_LENGTH];
push_call("load_object_program(%p)",fp);
ALLOCMEM(prg, OBJ_PROG, 1);
prg->unknown = STRDUPE(str_empty);
prg->if_symbol = '=';
prg->argument = STRDUPE(str_empty);
prg->index = fread_number( fp ); /* get index number */
prg->trigger = fread_number( fp ); /* get trigger command type */
mud->top_oprog++;
switch (prg->trigger)
{
case TRIG_VOID:
break;
case TRIG_COMMAND:
case TRIG_ROOM_COMMAND:
case TRIG_WEAR_COMMAND:
prg->percentage = fread_number( fp );
if ((prg->cmd = find_command(fread_word(fp), MAX_LEVEL - 1)) == -1)
{
bug("Bad obj_command command name: %s", buf);
abort();
}
break;
case TRIG_UNKNOWN:
case TRIG_ROOM_UNKNOWN:
case TRIG_WEAR_UNKNOWN:
prg->percentage = fread_number( fp );
STRFREE(prg->unknown);
prg->unknown = STRALLOC(fread_word( fp )) ;
break;
case TRIG_TICK:
case TRIG_DAMAGE:
case TRIG_HIT:
case TRIG_WEAR:
case TRIG_REMOVE:
case TRIG_SACRIFICE:
prg->percentage = fread_number( fp );
break;
default:
log_string( "Bad obj_command type");
}
prg->obj_command = fread_number( fp );
switch (prg->obj_command)
{
case OPROG_ECHO:
case OPROG_GOD_COMMAND:
case OPROG_GOD_ARGUMENT:
case OPROG_COMMAND:
case OPROG_ARGUMENT:
STRFREE(prg->argument);
prg->argument = fread_string( fp ) ;
break;
case OPROG_QUEST_SET:
prg->quest_offset = fread_number( fp );
prg->quest_bits = fread_number( fp );
prg->if_value = fread_number( fp );
break;
case OPROG_QUEST_ADD:
prg->quest_offset = fread_number( fp );
prg->quest_bits = fread_number( fp );
prg->if_value = fread_number( fp );
break;
case OPROG_PLAYER_QUEST_IF:
prg->quest_offset = fread_number( fp );
prg->quest_bits = fread_number( fp );
prg->if_symbol = fread_letter( fp );
prg->if_value = fread_number( fp );
prg->if_true = fread_number( fp );
prg->if_false = fread_number( fp );
break;
case OPROG_OBJECT_QUEST_IF:
prg->quest_offset = fread_number( fp );
prg->quest_bits = fread_number( fp );
prg->if_symbol = fread_letter( fp );
prg->if_value = fread_number( fp );
prg->if_true = fread_number( fp );
prg->if_false = fread_number( fp );
break;
case OPROG_IF_HAS_OBJECT:
prg->if_value = fread_number( fp );
prg->if_true = fread_number( fp );
prg->if_false = fread_number( fp );
break;
case OPROG_IF:
prg->if_check = fread_number( fp );
prg->if_symbol = fread_letter( fp );
prg->if_value = fread_number( fp );
prg->if_true = fread_number( fp );
prg->if_false = fread_number( fp );
break;
case OPROG_APPLY:
prg->if_check = fread_number( fp );
prg->if_value = fread_number( fp );
break;
case OPROG_JUNK:
break;
default:
log_string( "Bad obj_command reaction type");
}
pop_call();
return( prg );
}
void obj_prog_if_dest( OBJ_INDEX_DATA *obj )
{
push_call("obj_prog_if_dest(%p)",obj);
pop_call();
return;
}
/*
Load default weight of an object from index data.
*/
int load_obj_weight( OBJ_INDEX_DATA *obj )
{
int weight;
push_call("load_obj_weight(%p)",obj);
switch (obj->item_type)
{
default:
bug("load_obj_weight(%d): unknown item type %d!", obj->vnum, obj->item_type);
pop_call();
return 0;
case ITEM_WAND:
weight = 5;
break;
case ITEM_STAFF:
weight = 40;
break;
case ITEM_FURNITURE:
case ITEM_TOTEM:
weight = obj->size/SIZE_MEDIUM * 500;
break;
case ITEM_TRASH:
weight = obj->size/SIZE_MEDIUM * 50;
break;
case ITEM_LIGHT:
weight = 10;
break;
case ITEM_POTION:
weight = 10;
if (obj->value[0] == 0)
weight /= 3;
break;
case ITEM_SPELLBOOK:
weight = obj->value[0];
break;
case ITEM_BOOK:
weight = 30;
break;
case ITEM_FOOD:
case ITEM_DRINK_CON:
weight = UMAX(1, obj->value[0] * 2);
break;
case ITEM_SCROLL:
case ITEM_COMPONENT:
case ITEM_KEY:
case ITEM_PILL:
case ITEM_PAPER:
case ITEM_FIRE:
weight = 0;
break;
case ITEM_TRAP:
case ITEM_PORTAL:
case ITEM_WINDOW:
case ITEM_CRAFT:
case ITEM_PIECE:
weight = -1;
break;
case ITEM_TOOLS:
weight = tool_table[obj->value[0]].weight;
break;
case ITEM_WEAPON:
weight = weapon_table[obj->value[0]].weight;
break;
case ITEM_AMMO:
weight = 1;
break;
case ITEM_ARMOR:
weight = armor_weight(obj);
break;
case ITEM_QUIVER:
case ITEM_SHEATH:
case ITEM_CART:
case ITEM_CONTAINER:
case ITEM_SPELLPOUCH:
if (IS_SET(obj->value[1], CONT_HOLDING))
weight = ROUNDUP(obj->value[0]/160);
else
weight = obj->size * 10;
break;
case ITEM_SYMBOL:
case ITEM_FOUNTAIN:
case ITEM_TREASURE:
weight = obj->size << obj->size;
break;
case ITEM_MONEY:
weight = obj->value[0];
weight += obj->value[1];
weight += obj->value[2];
break;
case ITEM_BOAT:
weight = 100;
break;
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
weight = 1;
break;
}
pop_call();
return(weight);
}
/*
* Used in load_objects to fix objects that
* load with no material data.
*/
void fix_materials( OBJ_INDEX_DATA *obj )
{
int material;
push_call("fix_materials(%p)", obj);
if ((material = obj->material) <= 0 || material >= MATERIAL_MAX)
{
switch (obj->item_type)
{
case ITEM_WEAPON:
if (IS_SET(weapon_table[obj->value[0]].weap_spec, WSPEC_MISSILE))
material = MATERIAL_SOFTWOOD;
else if (IS_SET(weapon_table[obj->value[0]].weap_spec, WSPEC_WOODEN_HAFTED))
material = MATERIAL_HARDWOOD;
else
material = MATERIAL_STEEL;
break;
case ITEM_ARMOR:
if (obj->value[0] <= ARMOR_TYPE_PADDED)
material = MATERIAL_CLOTH;
else if (obj->value[0] <= ARMOR_TYPE_STUDDED_LEATHER)
material = MATERIAL_LEATHER;
else if (obj->value[0] <= ARMOR_TYPE_HIDE)
material = MATERIAL_HIDE;
else if (obj->value[0] <= ARMOR_TYPE_FULL_PLATE)
material = MATERIAL_STEEL;
else if (obj->value[0] <= ARMOR_TYPE_LIGHT_SHIELD)
material = MATERIAL_HARDWOOD;
else
material = MATERIAL_STEEL;
break;
case ITEM_SCROLL:
case ITEM_PAPER:
case ITEM_BOOK:
case ITEM_MAP:
case ITEM_SPELLBOOK:
material = MATERIAL_PAPER;
break;
case ITEM_WAND:
case ITEM_STAFF:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_BOAT:
case ITEM_TOTEM:
case ITEM_AMMO:
case ITEM_CART:
material = MATERIAL_HARDWOOD;
break;
case ITEM_POTION:
case ITEM_WINDOW:
case ITEM_DRINK_CON:
material = MATERIAL_GLASS;
break;
case ITEM_SPELLPOUCH:
case ITEM_SHEATH:
case ITEM_CONTAINER:
case ITEM_QUIVER:
material = MATERIAL_LEATHER;
break;
case ITEM_KEY:
material = MATERIAL_BRONZE;
break;
case ITEM_TOOLS:
material = MATERIAL_STEEL;
break;
case ITEM_FOUNTAIN:
material = MATERIAL_STONE;
break;
case ITEM_FOOD:
case ITEM_CORPSE_PC:
case ITEM_CORPSE_NPC:
material = MATERIAL_FLESH;
break;
case ITEM_MONEY:
case ITEM_TREASURE:
case ITEM_SYMBOL:
material = MATERIAL_SILVER;
break;
default:
material = -1; // need a control for irrelevant item types
break;
}
if (material != -1)
{
obj->material = material;
bug("fix_materials: obj vnum %d with bad material, fixed.", obj->vnum);
}
}
pop_call();
return;
}
/*
* Used in load_objects to fix objects that
* load with no size data.
*/
void fix_sizes( OBJ_INDEX_DATA *obj )
{
int size;
push_call("fix_sizes(%p)", obj);
if ((size = obj->size) <= 0 || size > SIZE_COLOSSAL)
{
switch (obj->item_type)
{
case ITEM_WEAPON:
size = weapon_table[obj->value[0]].size;
break;
case ITEM_SYMBOL:
case ITEM_KEY:
size = SIZE_FINE;
break;
case ITEM_LIGHT:
case ITEM_POTION:
case ITEM_TREASURE:
case ITEM_SPELLPOUCH:
case ITEM_FOOD:
case ITEM_AMMO:
case ITEM_MAP:
size = SIZE_DIMINUTIVE;
break;
case ITEM_PAPER:
case ITEM_WAND:
case ITEM_SCROLL:
case ITEM_DRINK_CON:
case ITEM_TRASH:
case ITEM_SPELLBOOK:
case ITEM_BOOK:
case ITEM_TOOLS:
case ITEM_PIECE:
size = SIZE_TINY;
break;
case ITEM_FIRE:
case ITEM_TRAP:
case ITEM_CRAFT:
case ITEM_CONTAINER:
case ITEM_SHEATH:
case ITEM_QUIVER:
size = SIZE_SMALL;
break;
case ITEM_ARMOR:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_WINDOW:
case ITEM_FURNITURE:
size = SIZE_MEDIUM;
break;
case ITEM_STAFF:
case ITEM_PORTAL:
case ITEM_TOTEM:
case ITEM_CART:
size = SIZE_LARGE;
break;
case ITEM_BOAT:
case ITEM_FOUNTAIN:
size = SIZE_HUGE;
break;
default:
size = SIZE_FINE;
break;
}
if (size > 0)
{
obj->size = size;
// bug("fix_sizes: obj vnum %d with bad size, fixed.", obj->vnum);
}
}
pop_call();
return;
}
/*
* calculate obj hit points in edit and loading.
*/
void load_obj_hit( OBJ_INDEX_DATA *obj )
{
int hit;
push_call("load_obj_hit(%p)", obj);
switch (obj->item_type)
{
default:
hit = obj->size * material_table[obj->material].hit;
break;
case ITEM_WEAPON:
hit = weapon_table[obj->value[0]].weight / 10;
break;
case ITEM_ARMOR:
hit = armor_table[obj->value[0]].ac_bonus * 5;
break;
case ITEM_SYMBOL:
case ITEM_KEY:
case ITEM_SCROLL:
case ITEM_SPELLPOUCH:
case ITEM_AMMO:
case ITEM_PAPER:
case ITEM_MAP:
case ITEM_POTION:
case ITEM_DRINK_CON:
case ITEM_TOOLS:
case ITEM_PIECE:
case ITEM_TRAP:
case ITEM_SHEATH:
case ITEM_QUIVER:
hit = ROUNDUP(obj->size / 2) * material_table[obj->material].hit;
break;
case ITEM_SPELLBOOK:
case ITEM_BOOK:
case ITEM_BOAT:
case ITEM_FOUNTAIN:
hit = obj->size * obj->size * material_table[obj->material].hit;
break;
}
if (hit > 0)
{
obj->hit_points = hit;
}
pop_call();
return;
}
/*
creation and deletion for OLC - Scandum 22-06-2002
*/
void create_shop( MOB_INDEX_DATA *mob )
{
SHOP_DATA *pShop;
int iTrade;
push_call("create_shop(%p)",mob);
ALLOCMEM(pShop, SHOP_DATA, 1);
pShop->keeper = mob->vnum;
for (iTrade = 0 ; iTrade < MAX_TRADE ; iTrade++)
{
pShop->buy_type[iTrade] = ITEM_NOTHING;
}
pShop->profit_buy = 100;
pShop->profit_sell = 50;
pShop->open_hour = 0;
pShop->close_hour = 23;
mob->pShop = pShop;
LINK(pShop, mud->f_shop, mud->l_shop, next, prev);
mud->top_shop++;
pop_call();
return;
}
void delete_shop( MOB_INDEX_DATA *mob )
{
push_call("delete_shop(%p)",mob);
if (mob->pShop)
{
UNLINK(mob->pShop, mud->f_shop, mud->l_shop, next, prev);
FREEMEM(mob->pShop);
mob->pShop = NULL;
--mud->top_shop;
}
pop_call();
return;
}
void create_stable( MOB_INDEX_DATA *mob )
{
STABLE_DATA *pStable;
push_call("create_stable(%p)",mob);
ALLOCMEM(pStable, STABLE_DATA, 1);
pStable->keeper = mob->vnum;
pStable->room = 0;
pStable->shop_flags = 0;
pStable->rent = 50;
pStable->open_hour = 0;
pStable->close_hour = 23;
mob->pStable = pStable;
LINK(pStable, mud->f_stable, mud->l_stable, next, prev);
mud->top_stable++;
pop_call();
return;
}
void delete_stable( MOB_INDEX_DATA *mob )
{
push_call("delete_stable(%p)",mob);
if (mob->pStable)
{
UNLINK(mob->pStable, mud->f_stable, mud->l_stable, next, prev);
FREEMEM(mob->pStable);
mob->pStable = NULL;
--mud->top_stable;
}
pop_call();
return;
}
void create_inn( MOB_INDEX_DATA *mob )
{
INN_DATA *pInn;
int iRoom;
push_call("create_inn(%p)",mob);
ALLOCMEM(pInn, INN_DATA, 1);
pInn->keeper = mob->vnum;
for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++)
{
pInn->room[iRoom] = -1;
}
for (iRoom = 0 ; iRoom < MAX_INN_ROOMS ; iRoom++)
{
pInn->rent[iRoom] = 50;
}
pInn->shop_flags = 0;
pInn->open_hour = 0;
pInn->close_hour = 23;
mob->pInn = pInn;
LINK(pInn, mud->f_inn, mud->l_inn, next, prev);
mud->top_inn++;
pop_call();
return;
}
void delete_inn( MOB_INDEX_DATA *mob )
{
push_call("delete_inn(%p)",mob);
if (mob->pInn)
{
UNLINK(mob->pInn, mud->f_inn, mud->l_inn, next, prev);
FREEMEM(mob->pInn);
mob->pInn = NULL;
--mud->top_inn;
}
pop_call();
return;
}
void create_exit( ROOM_INDEX_DATA *room, int door)
{
EXIT_DATA *pExit;
push_call("create_exit(%p,%d)",room,door);
if (room->exit[door] != NULL)
{
pop_call();
return;
}
ALLOCMEM(pExit, EXIT_DATA, 1);
pExit->description = STRDUPE(str_empty);
pExit->keyword = STRDUPE(str_empty);
pExit->pvnum = -1;
pExit->vnum = -1;
pExit->key = -1;
room->exit[door] = pExit;
mud->top_exit++;
pop_call();
return;
}
void delete_exit( ROOM_INDEX_DATA *room, int door)
{
EXIT_DATA *pExit;
push_call("delete_exit(%p,%d)",room,door);
if ((pExit = room->exit[door]) == NULL)
{
pop_call();
return;
}
STRFREE(pExit->keyword);
STRFREE(pExit->description);
FREEMEM(pExit);
mud->top_exit--;
room->exit[door] = NULL;
pop_call();
return;
}
void create_room( int vnum )
{
ROOM_INDEX_DATA *room;
push_call("create_room(%d)",vnum);
ALLOCMEM(room, ROOM_INDEX_DATA, 1);
room_index[vnum] = room;
mud->top_room++;
pop_call();
return;
}
bool delete_room( ROOM_INDEX_DATA *room )
{
bool door;
int vnum;
ROOM_INDEX_DATA *prev;
OBJ_DATA *o;
CHAR_DATA *ch;
EXTRA_DESCR_DATA *ed;
RESET_DATA *pReset;
push_call("delete_room(%p)",room);
switch (room->vnum)
{
case ROOM_VNUM_LIMBO:
case ROOM_VNUM_JUNK:
case ROOM_VNUM_TEMPLE:
case ROOM_VNUM_SCHOOL:
case ROOM_VNUM_ARENA:
case ROOM_VNUM_CLANHALLS:
log_printf("Refusing to delete hardcore vnum: %d", room->vnum);
dump_stack();
pop_call();
return FALSE;
}
del_room_timer(room->vnum, -1);
while ((ch = room->first_person) != NULL)
{
if (!IS_NPC(ch))
{
char_from_room(ch);
char_to_room(ch, ROOM_VNUM_TEMPLE, TRUE);
}
else
{
log_printf("junking mob %s", ch->name);
junk_mob(ch);
}
}
while ((o = room->first_content) != NULL)
{
junk_obj(o);
}
while ((ed = room->first_extradesc) != NULL)
{
room->first_extradesc = ed->next;
STRFREE(ed->keyword);
STRFREE(ed->description);
FREEMEM(ed );
--mud->top_ed;
}
if (!IS_SET(room->room_flags, ROOM_HASH))
{
for (pReset = room->area->first_reset ; pReset ; )
{
if (is_room_reset(pReset, room))
{
delete_reset(room->area, pReset);
pReset = room->area->first_reset;
}
else
{
pReset = pReset->next;
}
}
for (vnum = 0 ; vnum < MAX_VNUM ; vnum++)
{
if ((prev = room_index[vnum]) == NULL)
{
continue;
}
for (door = 0 ; door <= 5 ; door++)
{
if (prev->exit[door] == NULL)
{
continue;
}
if (prev->exit[door]->vnum != room->vnum)
{
continue;
}
log_printf("[%u] Deleting connection to room [%u]", prev->vnum, prev->exit[door]->vnum);
delete_exit(prev, door);
}
}
if (room->vnum == room->area->low_r_vnum)
{
vnum = room->area->low_r_vnum + 1;
for (room->area->low_r_vnum = MAX_VNUM-1 ; vnum <= room->area->hi_r_vnum ; vnum++)
{
if ((prev = get_room_index(vnum)) == NULL)
{
continue;
}
if (prev->area != room->area)
{
continue;
}
room->area->low_r_vnum = prev->vnum;
break;
}
}
if (room->vnum == room->area->hi_r_vnum)
{
vnum = room->area->hi_r_vnum - 1;
for (room->area->hi_r_vnum = 0 ; vnum >= room->area->low_r_vnum ; vnum--)
{
if ((prev = get_room_index(vnum)) == NULL)
{
continue;
}
if (prev->area != room->area)
{
continue;
}
room->area->hi_r_vnum = prev->vnum;
break;
}
}
}
for (door = 0 ; door <= 5 ; door++)
{
if (room->exit[door] == NULL)
{
continue;
}
/*
log_printf("[%u] Deleting connection to room [%u]", room->vnum, room->exit[door]->vnum);
*/
delete_exit(room, door);
}
for (door = 0 ; door < MAX_LAST_LEFT ; door++)
{
STRFREE(room->last_left[door]);
}
STRFREE (room->name);
STRFREE (room->description);
if (room->vnum >= ROOM_VNUM_WILDERNESS)
{
room_index[room->vnum] = room_index[ROOM_VNUM_WILDERNESS + room->sector_type];
}
else
{
room_index[room->vnum] = NULL;
}
FREEMEM(room );
--mud->top_room;
pop_call();
return TRUE;
}
bool delete_obj( OBJ_INDEX_DATA *obj )
{
EXTRA_DESCR_DATA *ed;
AFFECT_DATA *af;
RESET_DATA *pReset;
push_call("delete_obj(%p)",obj);
if (obj->vnum < 100)
{
log_printf("Refusing to delete hardcore vnum: %d", obj->vnum);
dump_stack();
pop_call();
return FALSE;
}
while (obj->first_instance)
{
extract_obj(obj->first_instance);
}
for (pReset = obj->area->first_reset ; pReset ; )
{
if (is_obj_reset(pReset, obj))
{
delete_reset(obj->area, pReset);
pReset = obj->area->first_reset;
}
else
{
pReset = pReset->next;
}
}
/* Remove references to object index */
while ((ed = obj->first_extradesc) != NULL)
{
obj->first_extradesc = ed->next;
STRFREE (ed->keyword);
STRFREE (ed->description);
FREEMEM(ed);
--mud->top_ed;
}
while ((af = obj->first_affect) != NULL)
{
obj->first_affect = af->next;
FREEMEM(af);
--mud->top_affect;
}
if (obj->vnum == obj->area->low_o_vnum && obj->vnum == obj->area->hi_o_vnum)
{
obj->area->low_o_vnum = MAX_VNUM - 1;
obj->area->hi_o_vnum = 0;
}
else if (obj->vnum == obj->area->low_o_vnum)
{
for (obj->area->low_o_vnum++ ; obj->area->low_o_vnum <= obj->area->hi_o_vnum ; obj->area->low_o_vnum++)
{
if (obj_index[obj->area->low_o_vnum] != NULL)
{
break;
}
}
}
else if (obj->vnum == obj->area->hi_o_vnum)
{
for (obj->area->hi_o_vnum-- ; obj->area->hi_o_vnum >= obj->area->low_o_vnum ; obj->area->hi_o_vnum--)
{
if (obj_index[obj->area->hi_o_vnum] != NULL)
{
break;
}
}
}
STRFREE (obj->name);
STRFREE (obj->short_descr);
STRFREE (obj->long_descr);
STRFREE (obj->description);
STRFREE (obj->attack_string);
obj_index[obj->vnum] = NULL;
FREEMEM(obj);
--mud->top_obj_index;
pop_call();
return TRUE;
}
/*
Scandum 28-04-2002
*/
bool delete_mob( MOB_INDEX_DATA *mob )
{
int vnum;
MOB_INDEX_DATA *prev;
RESET_DATA *pReset;
push_call("delete_mob(%p)",mob);
if (mob->vnum >= 9900 && mob->vnum < 10000)
{
log_printf("Refusing to delete hardcore vnum: %d", mob->vnum);
dump_stack();
pop_call();
return FALSE;
}
while (mob_index[mob->vnum]->first_instance)
{
extract_char(mob_index[mob->vnum]->first_instance);
}
for (pReset = mob->area->first_reset ; pReset ; )
{
if (is_mob_reset(pReset, mob))
{
delete_reset(mob->area, pReset);
pReset = mob->area->first_reset;
}
else
{
pReset = pReset->next;
}
}
if (mob->pShop)
{
delete_shop(mob);
}
if (mob->pStable)
{
delete_shop(mob);
}
if (mob->pInn)
{
delete_inn(mob);
}
if (mob->vnum == mob->area->low_m_vnum)
{
vnum = mob->area->low_m_vnum+1;
for (mob->area->low_m_vnum = MAX_VNUM-1 ; vnum <= mob->area->hi_m_vnum ; vnum++)
{
if ((prev = get_mob_index(vnum)) == NULL)
{
continue;
}
if (prev->area != mob->area)
{
continue;
}
mob->area->low_m_vnum = prev->vnum;
break;
}
}
if (mob->vnum == mob->area->hi_m_vnum)
{
vnum = mob->area->hi_m_vnum-1;
for (mob->area->hi_m_vnum = 0 ; vnum > mob->area->low_m_vnum ; vnum--)
{
if ((prev = get_mob_index(vnum)) == NULL)
{
continue;
}
if (prev->area != mob->area)
{
continue;
}
mob->area->hi_m_vnum = prev->vnum;
break;
}
}
STRFREE (mob->player_name);
STRFREE (mob->short_descr);
STRFREE (mob->long_descr);
STRFREE (mob->description);
STRFREE (mob->reset_msg);
mob_index[mob->vnum] = NULL;
FREEMEM(mob);
--mud->top_mob_index;
pop_call();
return TRUE;
}
bool delete_help( HELP_DATA *help )
{
HELP_MENU_DATA *menu;
push_call("delete_help(%p)",help);
while ((menu = help->first_menu) != NULL)
{
help->first_menu = menu->next;
FREEMEM(menu);
}
STRFREE (help->keyword);
STRFREE (help->title);
STRFREE (help->text);
UNLINK(help, help->area->first_help, help->area->last_help, next, prev);
FREEMEM(help);
--mud->top_help;
pop_call();
return TRUE;
}
int get_alloc_size( unsigned char *str )
{
push_call("get_alloc_size(%p)",str);
if (str == NULL)
{
log_printf("get_alloc_size: null pointer");
pop_call();
return -1;
}
if (*(str-1) != *(str-2) + *(str-3) + *(str-4))
{
log_printf("get_alloc_size: failed check sum");
pop_call();
return -1;
}
switch (*(str-3))
{
case 'F':
case 'D':
case 'S':
pop_call();
return rgSizeList[*(str-2)];
}
log_printf("get_alloc_size: bad block type");
pop_call();
return -1;
}
unsigned char *set_block_header( bool iBlock, bool typ, bool iList, bool *pMem )
{
push_call("set_block_header(%p,%p,%p,%p)",iBlock,typ,iList,pMem);
*pMem = iBlock; /* Index for perm_block_index */
pMem++;
*pMem = typ; /* D dynamic, P perm, F Free */
pMem++;
*pMem = iList; /* Index for rgSizeList */
pMem++;
*pMem = iList + typ + iBlock; /* Checksum */
pMem++;
pop_call();
return( pMem );
}
void set_block_type( bool typ, bool *pMem )
{
push_call("set_block_type(%p,%p)",typ,pMem);
*(pMem-3) = typ;
*(pMem-1) = *(pMem-2) + *(pMem-3) + *(pMem-4);
pop_call();
return;
}
/*
Allocate some ordinary memory,
with the expectation of freeing it someday.
*/
void *alloc_mem( int sMem )
{
PERM_BLOCK_LIST *pBlock;
bool iList, *pMem;
push_call("alloc_mem(%d)",sMem);
for (iList = 0 ; iList < MAX_MEM_LIST ; iList++)
{
if (sMem <= rgSizeList[iList])
{
break;
}
}
if (iList == MAX_MEM_LIST)
{
log_printf("alloc_mem: size %d too large.", sMem);
dump_stack();
abort();
}
if (rgFreeList[iList] == NULL)
{
pMem = (bool *) alloc_perm(iList);
rgUsedCount[iList]++;
}
else
{
pMem = (bool *) rgFreeList[iList];
rgFreeList[iList] = rgFreeList[iList]->next;
rgFreeCount[iList]--;
pBlock = perm_block_index[*(pMem-4)];
if (get_alloc_size(pMem) != rgSizeList[iList])
{
log_string("alloc_mem: allocating a free with wrong size");
dump_stack();
pMem = (bool *) alloc_perm(iList);
rgUsedCount[iList]++;
tot_memory_warning++;
}
else if (pBlock == NULL || (bool *) pBlock > pMem || (bool *) pBlock + MAX_PERM_BLOCK < pMem)
{
log_printf("free_mem: bad header: block index out of range");
dump_stack();
pMem = (bool *) alloc_perm(iList);
rgUsedCount[iList]++;
tot_memory_warning++;
}
else
{
rgUsedCount[iList]++;
}
}
memset(pMem, 0, sMem);
set_block_type('D', pMem);
pop_call();
return ((void *) pMem);
}
/*
Free some memory.
Recycle it back onto the free list for blocks of that size.
The pAdd is the pointer to the pointer of the memory.
*/
void free_mem( bool *pMem )
{
FREE_MEM_LIST *fm;
PERM_BLOCK_LIST *pBlock;
bool iBlock, iList;
push_call("free_mem(%p)",pMem);
if (pMem == NULL)
{
log_printf("free_mem: null pointer");
dump_stack();
pop_call();
return;
}
iList = *(pMem-2);
iBlock = *(pMem-4);
if (get_alloc_size(pMem) < 0)
{
dump_stack();
tot_memory_warning++;
pop_call();
return;
}
pBlock = perm_block_index[iBlock];
if (pBlock == NULL || (bool *) pBlock > pMem || (bool *) pBlock + MAX_PERM_BLOCK < pMem)
{
log_printf("free_mem: bad header: block index out of range");
dump_stack();
tot_memory_warning++;
pop_call();
return;
}
fm = (FREE_MEM_LIST *) pMem;
fm->next = rgFreeList[iList];
rgFreeList[iList] = fm;
rgFreeCount[iList]++;
rgUsedCount[iList]--;
set_block_type( 'F', pMem );
pop_call();
return;
}
/*
Allocate some permanent memory.
Permanent memory is never freed,
pointers into it may be copied safely.
*/
void *alloc_perm( bool iList )
{
int sMem;
PERM_BLOCK_LIST *pBlock;
bool block_index, *pMem;
push_call("alloc_perm(%p)", iList);
sMem = rgSizeList[iList];
sMem += 4; /* Add 4 bytes for header */
for (block_index = 0 ; block_index < 255 && perm_block_index[block_index] ; block_index++)
{
if (perm_block_index[block_index]->iMemPerm + sMem < MAX_PERM_BLOCK)
{
break;
}
}
if (block_index == 255)
{
log_string( "alloc_perm: no free blocks left" );
abort();
}
pBlock = perm_block_index[block_index];
if (pBlock == NULL)
{
if ((pBlock = calloc(1, MAX_PERM_BLOCK)) == NULL)
{
perror("alloc_perm");
abort();
}
pBlock->iMemPerm = sizeof( *pBlock );
perm_block_index[block_index] = pBlock;
}
pMem = (bool *) pBlock + pBlock->iMemPerm;
pBlock->iMemPerm += sMem;
set_block_header(block_index, 'P', iList, pMem);
pop_call();
return (void *) (pMem+4);
}
void do_memory( CHAR_DATA *ch, char *argument )
{
char buf[MAX_STRING_LENGTH];
int cnt, Ftotal, Utotal, Ptotal;
push_call("do_memory(%p,%p)",ch,argument);
buf[0] = '\0';
cat_sprintf(buf, "{078}Players: {178}%6d ", mud->total_plr);
cat_sprintf(buf, "{078}Descs: {178}%6d ", mud->total_desc);
cat_sprintf(buf, "{078}Areas: {178}%6d ", mud->top_area);
cat_sprintf(buf, "{078}Helps: {178}%6d\n\r", mud->top_help);
cat_sprintf(buf, "{078}Rooms: {178}%6d ", mud->top_room);
cat_sprintf(buf, "{078}MobsIn: {178}%6d ", mud->top_mob_index);
cat_sprintf(buf, "{078}ObjsIn: {178}%6d ", mud->top_obj_index);
cat_sprintf(buf, "{078}Resets: {178}%6d\n\r", mud->top_reset);
cat_sprintf(buf, "{078}Exits: {178}%6d ", mud->top_exit);
cat_sprintf(buf, "{078}Mobs: {178}%6d ", mud->total_mob);
cat_sprintf(buf, "{078}Objs: {178}%6d ", mud->total_obj);
cat_sprintf(buf, "{078}Affects: {178}%6d\n\r", mud->top_affect);
cat_sprintf(buf, "{078}Shops: {178}%6d ", mud->top_shop);
cat_sprintf(buf, "{078}Stables: {178}%6d ", mud->top_stable);
cat_sprintf(buf, "{078}Inns: {178}%6d ", mud->top_inn);
cat_sprintf(buf, "{078}Skills: {178}%6d\n\r", MAX_REAL_SKILL);
cat_sprintf(buf, "{078}Mprog: {178}%6d ", mud->top_mprog);
cat_sprintf(buf, "{078}Oprog: {178}%6d ", mud->top_oprog);
cat_sprintf(buf, "{078}Extra: {178}%6d\n\r", mud->top_ed);
Utotal = Ftotal = 0;
for (cnt = 0 ; cnt < MAX_MEM_LIST ; cnt++)
{
Utotal += (4 + rgSizeList[cnt]) * rgUsedCount[cnt];
Ftotal += (4 + rgSizeList[cnt]) * rgFreeCount[cnt];
}
for (Ptotal = 0 ; Ptotal < 255 ; Ptotal++)
{
if (perm_block_index[Ptotal] == NULL)
{
Ptotal *= MAX_PERM_BLOCK;
break;
}
}
cat_sprintf(buf, "\n\r");
cat_sprintf(buf, "{078}Perm Mem: {178}%8d ", Ptotal);
cat_sprintf(buf, "{078}Used Mem: {178}%8d ", Utotal);
cat_sprintf(buf, "{078}Free Mem: {178}%8d ", Ftotal);
cat_sprintf(buf, "\n\r\n\r");
for (cnt = 0 ; cnt < MAX_MEM_LIST ; cnt++)
{
cat_sprintf(buf, "{178}%6d {118}%6d {128}%5d ",
rgSizeList[cnt],
rgUsedCount[cnt],
rgFreeCount[cnt]);
if (cnt % 4 == 3)
{
strcat(buf, "\n\r");
}
}
if (str_suffix("\n\r", buf))
{
strcat(buf, "\n\r");
}
if (tot_memory_warning)
{
cat_sprintf(buf, "\n\r{018}Total Memory Warnings: {178}%8d\n\r", tot_memory_warning);
}
send_to_char_color(buf, ch);
pop_call();
return;
}
/*
Create new stuff (OLC) - Scandum 10-07-2002
*/
ROOM_INDEX_DATA *make_room( int vnum )
{
ROOM_INDEX_DATA *pRoomIndex;
bool door;
push_call("make_room(%p)",vnum);
if (get_area_from_vnum(vnum) == NULL)
{
log_printf("make_room: failed to add area data.");
pop_call();
return NULL;
}
ALLOCMEM( pRoomIndex, ROOM_INDEX_DATA, 1 );
pRoomIndex->vnum = vnum;
pRoomIndex->area = get_area_from_vnum(vnum);
if (vnum < pRoomIndex->area->low_r_vnum)
{
pRoomIndex->area->low_r_vnum = vnum;
}
if (vnum > pRoomIndex->area->hi_r_vnum)
{
pRoomIndex->area->hi_r_vnum = vnum;
}
pRoomIndex->name = STRALLOC("Floating in a void");
pRoomIndex->description = STRDUPE(str_empty);
pRoomIndex->listen_desc = STRDUPE(str_empty);
pRoomIndex->night_desc = STRDUPE(str_empty);
for (door = 0 ; door < MAX_LAST_LEFT ; door++)
{
pRoomIndex->last_left[door] = STRDUPE(str_empty);
}
room_index[vnum] = pRoomIndex;
mud->top_room++;
pop_call();
return pRoomIndex;
}
OBJ_INDEX_DATA *make_object(int vnum)
{
OBJ_INDEX_DATA *pObjIndex;
push_call("make_object(%p)",vnum);
if (get_area_from_vnum(vnum) == NULL)
{
log_printf("Make_object: Failed to add area data to object.");
pop_call();
return NULL;
}
ALLOCMEM( pObjIndex, OBJ_INDEX_DATA, 1 );
pObjIndex->vnum = vnum;
pObjIndex->area = get_area_from_vnum(vnum);
if (vnum < pObjIndex->area->low_o_vnum)
{
pObjIndex->area->low_o_vnum = vnum;
}
if (vnum > pObjIndex->area->hi_o_vnum)
{
pObjIndex->area->hi_o_vnum = vnum;
}
obj_index[vnum] = pObjIndex;
pObjIndex->name = STRDUPE(str_empty);
pObjIndex->short_descr = STRDUPE(str_empty);
pObjIndex->long_descr = STRDUPE(str_empty);
pObjIndex->description = STRDUPE(str_empty);
pObjIndex->attack_string = STRDUPE(str_empty);
pObjIndex->id_name = STRDUPE(str_empty);
pObjIndex->id_descr = STRDUPE(str_empty);
pObjIndex->item_type = ITEM_TRASH;
pObjIndex->extra_flags = 0;
pObjIndex->wear_flags = 0;
pObjIndex->value[0] = 0;
pObjIndex->value[1] = 0;
pObjIndex->value[2] = 0;
pObjIndex->value[3] = 0;
pObjIndex->value[4] = 0;
pObjIndex->value[5] = 0;
pObjIndex->value[6] = 0;
pObjIndex->value[7] = 0;
pObjIndex->weight = 1;
pObjIndex->cost = 10;
pObjIndex->level = 1;
pObjIndex->level = 1;
pObjIndex->progtypes = 0;
mud->top_obj_index++;
pop_call();
return pObjIndex;
}
HELP_DATA * make_helpfile( char *argument, AREA_DATA *area )
{
HELP_DATA *help;
push_call("make_helpfile(%p,%p)",argument,area);
ALLOCMEM(help, HELP_DATA, 1);
help->level = 0;
help->keyword = STRALLOC(argument);
help->text = STRDUPE(str_empty);
help->area = area;
LINK (help, area->first_help, area->last_help, next, prev );
mud->top_help++;
pop_call();
return help;
}
AREA_DATA * get_area_from_vnum (int vnum)
{
AREA_DATA * pArea;
push_call("get_area_from_vnum(%p)",vnum);
for (pArea = mud->f_area ; pArea ; pArea = pArea->next)
{
if (pArea->olc_range_lo <= vnum && pArea->olc_range_hi >= vnum)
{
break;
}
if (pArea->low_r_vnum <= vnum && pArea->hi_r_vnum >= vnum)
{
break;
}
if (pArea->low_m_vnum <= vnum && pArea->hi_m_vnum >= vnum)
{
break;
}
if (pArea->low_o_vnum <= vnum && pArea->hi_o_vnum >= vnum)
{
break;
}
}
pop_call();
return pArea;
}
/*
Create a new INDEX mobile (OLC)
*/
MOB_INDEX_DATA *make_mobile( int vnum )
{
MOB_INDEX_DATA *pMobIndex;
push_call("make_mobile(%p)",vnum);
if (get_area_from_vnum(vnum) == NULL)
{
log_printf("make_mobile: couldn't find area.\n\r");
pop_call();
return NULL;
}
ALLOCMEM( pMobIndex, MOB_INDEX_DATA, 1 );
pMobIndex->vnum = vnum;
pMobIndex->player_name = STRALLOC("newly created mobile");
pMobIndex->short_descr = STRALLOC("a newly created mobile");
pMobIndex->long_descr = STRALLOC("a newly created mobile stands here");
pMobIndex->description = STRALLOC("");
pMobIndex->act = ACT_SENTINEL;
pMobIndex->level = 1;
pMobIndex->hitplus = 0;
pMobIndex->position = POS_STANDING;
pMobIndex->area = get_area_from_vnum (vnum);
if (vnum < pMobIndex->area->low_m_vnum)
{
pMobIndex->area->low_m_vnum = vnum;
}
if (vnum > pMobIndex->area->hi_m_vnum)
{
pMobIndex->area->hi_m_vnum = vnum;
}
mob_index[vnum] = pMobIndex;
mud->top_mob_index++;
pop_call();
return pMobIndex;
}
EXIT_DATA *make_exit( ROOM_INDEX_DATA *pRoomIndex, ROOM_INDEX_DATA *to_room, bool door )
{
EXIT_DATA *pExit;
push_call("make_exit(%p,%p,%p)",pRoomIndex,to_room,door);
ALLOCMEM(pExit, EXIT_DATA, 1);
pExit->exit_info = 0;
pExit->pvnum = 0;
pExit->key = -1;
pExit->exit_size = 0;
pExit->climb_dc = 0;
pExit->fall_dist = 0;
if (to_room)
{
pExit->to_room = to_room->vnum;
pExit->vnum = to_room->vnum;
}
room_index[pRoomIndex->vnum]->exit[door] = pExit;
mud->top_exit++;
pop_call();
return pExit;
}
/*
This routine makes sure that files are not cross linked or chopped
Chaos - 4/26/99
*/
bool is_valid_save( char *file_name , char *text_crc)
{
char buf[MAX_INPUT_LENGTH];
sh_int cnt, cf;
FILE *fp;
push_call("is_valid_save(%p,%p)",file_name,text_crc);
if ((fp = my_fopen(file_name, "r", FALSE)) == NULL)
{
pop_call();
return( FALSE );
}
fseek(fp, 0, SEEK_END);
if (ftell(fp) < 10)
{
my_fclose(fp);
log_printf("Oops, file system full! %s failed.", file_name);
pop_call();
return( FALSE );
}
cf = ' ';
cnt = 0;
while (cf != '#' && cnt > -25)
{
cnt--;
fseek(fp, cnt, SEEK_END);
cf = fgetc( fp );
}
if (cnt < -25)
{
my_fclose(fp);
log_printf("Didn't find an #%s on %s", text_crc, file_name);
pop_call();
return( FALSE );
}
cf = fgetc(fp);
for (cnt = 0 ; cf != '\n' && cf != EOF ; cnt++)
{
buf[cnt] = cf;
cf = fgetc(fp);
}
buf[cnt] = '\0';
if (!strcmp(buf, text_crc))
{
my_fclose( fp );
pop_call();
return( TRUE );
}
my_fclose( fp );
log_printf("Cross linked file %s on %s", buf, file_name);
pop_call();
return( FALSE );
}
/* Save this class */
/*
* Thanks for Erwin's MERC tips on dynamically
* loading class tables - Kregor
*/
void fwrite_class (int num)
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
int sn;
sprintf (buf, "%s/%s.txt", CLASSES_DIR, bits_to_str(num, "CLASS_"));
close_reserve();
if ((fp = my_fopen(buf, "w", FALSE)) == NULL)
{
log_printf("Could not open file %s in order to save class.", buf);
}
fprintf( fp, "Name %s~\n", !is_string(class_table[num].who_name_long) ? strlower(bits_to_str(num, "CLASS_")) : class_table[num].who_name_long);
fprintf( fp, "WhoName %s~\n", !is_string(class_table[num].who_name) ? "???" : class_table[num].who_name);
fprintf( fp, "HitDice %d\n", class_table[num].hp_max );
fprintf( fp, "FORTSave %d\n", class_table[num].fort_save );
fprintf( fp, "REFLSave %d\n", class_table[num].refl_save );
fprintf( fp, "WILLSave %d\n", class_table[num].will_save );
fprintf( fp, "EntryLvl %d\n", class_table[num].pc_class );
fprintf( fp, "Mana %d\n", class_table[num].mana_table );
fprintf( fp, "BAB %d\n", class_table[num].base_attack );
fprintf( fp, "AttrPrime %d\n", class_table[num].attr_prime );
fprintf( fp, "AttrSecond %d\n", class_table[num].attr_second );
fprintf( fp, "PriMod %d\n", class_table[num].prime_mod );
fprintf( fp, "SecMod %d\n", class_table[num].sec_mod );
fprintf( fp, "SkillPts %d\n", class_table[num].skill_pts );
fprintf( fp, "MaxLevel %d\n", class_table[num].max_level );
fprintf( fp, "FirstFeat %d\n", class_table[num].first_bonus );
fprintf( fp, "FeatLevel %d\n", class_table[num].bonus_lvl );
for (sn = 0; *skill_table[sn].name != '\0' ; sn++)
{
if (skill_table[sn].name == NULL)
continue;
if (skill_table[sn].skill_level[num] < LEVEL_IMMORTAL)
fprintf (fp, "Skill %d '%s'\n", skill_table[sn].skill_level[num], skill_table[sn].name);
if (skill_table[sn].skilltype == FSKILL_FEAT && skill_table[sn].bonus_feat[num] < LEVEL_IMMORTAL)
fprintf (fp, "BonusFeat %d '%s'\n", skill_table[sn].bonus_feat[num], skill_table[sn].name);
}
fprintf( fp, "%s", "EndClass\n\n" );
my_fclose (fp);
open_reserve();
}
void save_classes()
{
int i;
for (i = 0; i < MAX_CLASS; i++)
{
fwrite_class(i);
}
}
/* Load a class */
void fread_class (int num)
{
char buf[MAX_STRING_LENGTH];
char *word;
bool fMatch;
FILE *fp;
sprintf (buf, "%s/%s.txt", CLASSES_DIR, bits_to_str(num, "CLASS_"));
close_reserve();
if ((fp = my_fopen(buf, "r", FALSE)) == NULL)
{
fwrite_class(num);
fread_class(num);
return;
}
for ( ; ; )
{
word = feof(fp) ? "EndClass" : fread_word(fp);
fMatch = FALSE;
switch (word[0])
{
case 'A':
NKEY("AttrPrime", class_table[num].attr_prime, fread_number(fp));
NKEY("AttrSecond", class_table[num].attr_second, fread_number(fp));
break;
case 'B':
if ( !strcasecmp( word, "BonusFeat" ) )
{
int sn;
int value;
value = fread_number( fp );
sn = skill_lookup( fread_word( fp ) );
if (sn < 0)
{
bug("fread_class: %s - unknown skill.", class_table[num].who_name_long);
}
else if (skill_table[sn].skilltype == FSKILL_FEAT)
{
skill_table[sn].bonus_feat[num] = value;
}
fMatch = TRUE;
break;
}
NKEY("BAB", class_table[num].base_attack, fread_number(fp));
break;
case 'E':
NKEY( "EntryLvl", class_table[num].pc_class, fread_number(fp));
if (!strcmp(word, "EndClass"))
return;
break;
case 'F':
NKEY( "FORTSave", class_table[num].fort_save, fread_number(fp));
NKEY( "FirstFeat", class_table[num].first_bonus, fread_number(fp));
NKEY( "FeatLevel", class_table[num].bonus_lvl, fread_number(fp));
break;
case 'H':
NKEY( "HitDice", class_table[num].hp_max, fread_number(fp));
break;
case 'M':
NKEY( "Mana", class_table[num].mana_table, fread_number(fp));
NKEY( "MaxLevel", class_table[num].max_level, fread_number(fp));
break;
case 'N':
if ( !strcasecmp( word, "Name" ) )
{
char *name = STRALLOC(fread_string(fp));
if (!is_string(name))
sprintf(class_table[num].who_name_long, "%s", strlower(bits_to_str(num, "CLASS_")));
else
sprintf(class_table[num].who_name_long, "%s", name);
fMatch = TRUE;
break;
}
break;
case 'P':
NKEY( "PriMod", class_table[num].prime_mod, fread_number(fp));
case 'R':
NKEY( "REFLSave", class_table[num].refl_save, fread_number(fp));
case 'S':
if ( !strcasecmp( word, "Skill" ) )
{
int sn;
int value;
value = fread_number( fp );
sn = skill_lookup( fread_word( fp ) );
if (sn < 0)
{
bug("fread_class: %s - unknown skill.", class_table[num].who_name_long);
}
else
{
skill_table[sn].skill_level[num] = value;
}
fMatch = TRUE;
break;
}
NKEY( "SecMod", class_table[num].sec_mod, fread_number(fp));
NKEY( "SkillPts", class_table[num].skill_pts, fread_number(fp));
break;
case 'W':
if ( !strcasecmp( word, "WhoName" ) )
{
char *name = STRALLOC(fread_string(fp));
if (!is_string(name))
sprintf(class_table[num].who_name, "???");
else
sprintf(class_table[num].who_name, "%s", name);
fMatch = TRUE;
break;
}
NKEY( "WILLSave", class_table[num].will_save, fread_number(fp));
break;
}
if (fMatch == FALSE)
{
log_printf("fread_class: no match: %s %s", word, fread_line(fp));
}
}
my_fclose (fp);
open_reserve();
}
void load_classes ()
{
int cls,sn;
log_string("Loading Class Table...");
for (cls = 0; cls < MAX_CLASS; cls++)
{
for (sn = 0; *skill_table[sn].name != '\0' ; sn++)
{
skill_table[sn].skill_level[cls] = LEVEL_IMMORTAL;
skill_table[sn].bonus_feat[cls] = LEVEL_IMMORTAL;
}
fread_class(cls);
}
// for (sn = 0; *skill_table[sn].name != '\0' ; sn++)
// {
// if (skill_table[sn].skilltype != FSKILL_FEAT)
// continue;
// if (IS_SET(skill_table[sn].spell_school, FEAT_ROGUE))
// {
// skill_table[sn].bonus_feat[CLASS_ROGUE] = IS_SET(skill_table[sn].spell_school, FEAT_ADVANCED) ? 10 : 1;
// }
// if (IS_SET(skill_table[sn].spell_school, FEAT_METAMAGIC|FEAT_CREATION|FEAT_WIZARD))
// {
// skill_table[sn].bonus_feat[CLASS_WIZARD] = 1;
// skill_table[sn].bonus_feat[CLASS_LOREMASTER] = 1;
// }
// if (IS_SET(skill_table[sn].spell_school, FEAT_FIGHTER))
// {
// skill_table[sn].bonus_feat[CLASS_FIGHTER] = 1;
// skill_table[sn].bonus_feat[CLASS_ELDRITCH_KNIGHT] = 1;
// }
// if (IS_SET(skill_table[sn].spell_school, FEAT_PALADIN))
// {
// skill_table[sn].bonus_feat[CLASS_PALADIN] = 1;
// skill_table[sn].bonus_feat[CLASS_BLACKGUARD] = 1;
// }
// }
}
/* Save this domain skill table */
void save_domain (int num)
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
int lev, i;
sprintf (buf, "%s/%s.txt", DOMAIN_DIR, domain_types[num]);
close_reserve();
if ((fp = my_fopen(buf, "w", FALSE)) == NULL)
{
log_printf("Could not open file %s in order to save domain %s.", buf, domain_types[num]);
return;
}
for (lev = 0; lev < LEVEL_IMMORTAL; lev++)
{
for (i = 0; *skill_table[i].name != '\0'; i++)
{
if (!skill_table[i].name || !skill_table[i].name[0])
continue;
if (skill_table[i].domains[num] == lev)
fprintf (fp, "%d %s\n", lev, skill_table[i].name);
}
}
fprintf (fp, "-1"); /* EOF -1 */
my_fclose (fp);
open_reserve();
}
void save_domains()
{
int i;
for (i = 0; i < MAX_DOMAIN; i++)
save_domain (i);
}
/* Load a domain skill table */
void load_domain (int num)
{
char buf[MAX_STRING_LENGTH];
int level,n;
FILE *fp;
sprintf (buf, "%s/%s.txt", DOMAIN_DIR, domain_types[num]);
close_reserve();
if ((fp = my_fopen(buf, "r", FALSE)) == NULL)
{
log_printf ("Could not open file %s in order to load domain %s.", buf, domain_types[num]);
return;
}
fscanf (fp, "%d", &level);
while (level != -1)
{
fscanf (fp, " %[^\n]\n", buf); /* read name of skill into buf */
n = skill_lookup (buf); /* find index */
if (n == -1)
{
char buf2[200];
sprintf (buf2, "Domain %s: unknown skill/spell %s", domain_types[num], buf);
log_printf (buf2, 0);
}
else
skill_table[n].domains[num] = level;
fscanf (fp, "%d", &level);
}
my_fclose (fp);
open_reserve();
}
void load_domains ()
{
int i,j;
log_string("Skill Table: Domains...");
for (i = 0; i < MAX_DOMAIN; i++)
{
for (j = 0; *skill_table[j].name != '\0'; j++)
{
skill_table[j].domains[i] = LEVEL_IMMORTAL;
}
load_domain (i);
}
}
/* Save this style */
void save_style (int num)
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
int lev, i;
sprintf (buf, "%s/%s.txt", STYLE_DIR, combat_styles[num]);
close_reserve();
if ((fp = my_fopen(buf, "w", FALSE)) == NULL)
{
log_printf("Could not open file %s in order to save style %s.", buf, combat_styles[num]);
return;
}
for (lev = 0; lev < LEVEL_IMMORTAL; lev++)
{
for (i = 0; *skill_table[i].name != '\0' ; i++)
{
if (!skill_table[i].name || !skill_table[i].name[0])
continue;
if (skill_table[i].styles[num] == lev)
fprintf (fp, "%d %s\n", lev, skill_table[i].name);
}
}
fprintf (fp, "-1"); /* EOF -1 */
my_fclose (fp);
open_reserve();
}
void save_styles()
{
int i;
for (i = 0; i < STYLE_MAX; i++)
save_style (i);
}
/* Load a style */
void load_style (int num)
{
char buf[MAX_STRING_LENGTH];
int level,n;
FILE *fp;
sprintf (buf, "%s/%s.txt", STYLE_DIR, combat_styles[num]);
close_reserve();
if ((fp = my_fopen(buf, "r", FALSE)) == NULL)
{
log_printf ("Could not open file %s in order to load style %s.", buf, combat_styles[num]);
return;
}
fscanf (fp, "%d", &level);
while (level != -1)
{
fscanf (fp, " %[^\n]\n", buf); /* read name of skill into buf */
n = skill_lookup (buf); /* find index */
if (n == -1)
{
char buf2[200];
sprintf (buf2, "Style %s: unknown skill/spell %s", combat_styles[num], buf);
log_printf (buf2, 0);
}
else
skill_table[n].styles[num] = level;
fscanf (fp, "%d", &level);
}
my_fclose (fp);
open_reserve();
}
void load_styles ()
{
int i,j;
log_string("Skill Table: Combat Styles...");
for (i = 0; i < STYLE_MAX; i++)
{
for (j = 0; *skill_table[j].name != '\0' ; j++)
{
skill_table[j].styles[i] = LEVEL_IMMORTAL;
}
load_style (i);
}
}
/* Save this race */
void fwrite_race (int num)
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
int sn;
sprintf (buf, "%s/%s.txt", RACE_DIR, bits_to_str(num, "RACE_"));
close_reserve();
if ((fp = my_fopen(buf, "w", FALSE)) == NULL)
{
log_printf("Could not open file %s in order to save race.", buf);
}
fprintf( fp, "Name %s~\n", !is_string(race_table[num].race_name) ? strlower(bits_to_str(num, "RACE_")) : race_table[num].race_name);
fprintf( fp, "Size ");
break_bits( fp, race_table[num].size, "SIZE_", TRUE);
fprintf( fp, "\n" );
fprintf( fp, "RaceType ");
break_bits( fp, race_table[num].type, "RTYPE_", TRUE);
fprintf( fp, "\n" );
fprintf( fp, "BodyType ");
break_bits( fp, race_table[num].body_type, "BTYPE_", TRUE);
fprintf( fp, "\n" );
fprintf( fp, "HitDice %d\n", race_table[num].hit_dice );
fprintf( fp, "SpeedLand %d\n", race_table[num].land_speed );
fprintf( fp, "SpeedBurrow %d\n", race_table[num].burrow_speed );
fprintf( fp, "SpeedClimb %d\n", race_table[num].climb_speed );
fprintf( fp, "SpeedFly %d\n", race_table[num].fly_speed );
fprintf( fp, "SpeedSwim %d\n", race_table[num].swim_speed );
fprintf( fp, "NaturalAC %d\n", race_table[num].nat_armor );
fprintf( fp, "DeflectAC %d\n", race_table[num].deflection );
fprintf( fp, "PCRace %d\n", race_table[num].pcrace );
fprintf( fp, "Align %d\n", race_table[num].alignment );
fprintf( fp, "Ethos %d\n", race_table[num].ethos );
fprintf( fp, "AttrMod %d %d %d %d %d %d\n", race_table[num].race_mod[0], race_table[num].race_mod[1], race_table[num].race_mod[2], race_table[num].race_mod[3], race_table[num].race_mod[4], race_table[num].race_mod[5] );
fprintf( fp, "Nonabil %d %d %d %d %d %d\n", race_table[num].nonability[0], race_table[num].nonability[1], race_table[num].nonability[2], race_table[num].nonability[3], race_table[num].nonability[4], race_table[num].nonability[5] );
fprintf( fp, "Weight %d\n", race_table[num].weight );
fprintf( fp, "Height %d\n", race_table[num].height );
fprintf( fp, "ParentRace ");
break_bits( fp, race_table[num].parent_race, "RACE_", TRUE);
fprintf( fp, "\n" );
fprintf( fp, "Material ");
break_bits( fp, race_table[num].material, "MATERIAL_", TRUE);
fprintf( fp, "\n" );
fprintf( fp, "Vulnerable ");
break_bits( fp, race_table[num].vulnerability, "DAM_", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "AffectedBy ");
break_bits( fp, race_table[num].affected_by, "AFF_", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "Speaks ");
break_bits( fp, race_table[num].speaks, "LANG_", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "Understands ");
break_bits( fp, race_table[num].understands, "LANG_", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "BonusLangs ");
break_bits( fp, race_table[num].bonus_langs, "LANG_", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "Specials ");
break_bits( fp, race_table[num].flags, "RSPEC_", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "Sectors ");
break_bits( fp, race_table[num].sectors, "RACESECT_", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "WearLocs ");
break_bits( fp, race_table[num].wear_locs, "CAN_WEAR", FALSE);
fprintf( fp, "\n" );
if (race_table[num].poison)
{
fprintf( fp, "Poison ");
break_bits( fp, race_table[num].poison_part, "ATTK_", TRUE);
fprintf( fp, " " );
break_bits( fp, race_table[num].poison, "POISON_", TRUE);
fprintf( fp, "\n" );
}
if (race_table[num].disease)
{
fprintf( fp, "Disease ");
break_bits( fp, race_table[num].disease_part, "ATTK_", TRUE);
fprintf( fp, " " );
break_bits( fp, race_table[num].disease, "DIS_", TRUE);
fprintf( fp, "\n" );
}
fprintf( fp, "FavoredCls ");
break_bits( fp, race_table[num].favored_class, "CLASS_", TRUE);
fprintf( fp, "\n" );
fprintf( fp, "LevelAdj %d\n", race_table[num].lvl_adj );
fprintf( fp, "Align %d\n", race_table[num].alignment );
fprintf( fp, "Ethos %d\n", race_table[num].ethos );
for (sn = 0; *skill_table[sn].name != '\0' ; sn++)
{
if (skill_table[sn].name == NULL)
continue;
if (skill_table[sn].race_skill[num])
fprintf (fp, "Skill %d '%s'\n", skill_table[sn].race_skill[num], skill_table[sn].name);
}
for (sn = 0; sn < MAX_APPLY; sn++)
{
if (race_table[num].apply[sn])
{
fprintf (fp, "Apply ");
break_bits( fp, sn, "APPLY_", TRUE);
fprintf( fp, " %d\n", race_table[num].apply[sn] );
}
}
for (sn = 0; sn < ATTK_MAX; sn++)
{
if (race_table[num].attacks[sn])
{
fprintf (fp, "Attack ");
break_bits( fp, sn, "ATTK_", TRUE);
fprintf( fp, " %d\n", race_table[num].attacks[sn] );
}
}
fprintf( fp, "%s", "EndRace\n\n" );
my_fclose (fp);
open_reserve();
}
void save_races()
{
int i;
for (i = 0; i < MAX_RACE; i++)
{
fwrite_race(i);
}
}
/* Load a race */
void fread_race (int num)
{
char buf[MAX_STRING_LENGTH];
char *word;
char *line;
bool fMatch;
int x1,x2,x3,x4,x5,x6;
int cnt;
FILE *fp;
sprintf (buf, "%s/%s.txt", RACE_DIR, bits_to_str(num, "RACE_"));
close_reserve();
if ((fp = my_fopen(buf, "r", FALSE)) == NULL)
{
fwrite_race(num);
fread_race(num);
return;
}
for ( ; ; )
{
word = feof(fp) ? "EndRace" : fread_word(fp);
fMatch = FALSE;
// if (!is_string(race_table[num].race_name))
// sprintf(race_table[num].race_name, strlower(bits_to_str(num, "RACE")));
//
switch (word[0])
{
case 'A':
if ( !strcasecmp( word, "AttParts" ) )
{
fMatch = TRUE;
break;
}
NKEY("Align", race_table[num].alignment, fread_number(fp));
AKEY("Apply", race_table[num].apply, fread_number(fp));
AKEY("Attack", race_table[num].attacks, fread_number(fp));
NKEY("AffectedBy",race_table[num].affected_by, fread_number(fp));
if ( !strcasecmp( word, "AttrMod" ) )
{
line = fread_line( fp );
x1=x2=x3=x4=x5=x6=0;
sscanf( line, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 );
race_table[num].race_mod[0] = x1;
race_table[num].race_mod[1] = x2;
race_table[num].race_mod[2] = x3;
race_table[num].race_mod[3] = x4;
race_table[num].race_mod[4] = x5;
race_table[num].race_mod[5] = x6;
fMatch = TRUE;
break;
}
break;
case 'B':
NKEY("BonusLangs", race_table[num].bonus_langs, fread_number(fp));
NKEY("BodyType", race_table[num].body_type, fread_number(fp));
break;
case 'D':
if ( !strcasecmp( word, "Disease" ) )
{
int body;
int value;
body = fread_number( fp );
value = fread_number( fp );
if (!race_table[num].attacks)
{
bug("fread_race: %s - poisoned part not set in attack parts.", race_table[num].race_name);
break;
}
if (disease_table[value].name == NULL)
{
bug("fread_race: %s - unknown disease type.", race_table[num].race_name);
break;
}
race_table[num].disease_part = body;
race_table[num].disease = value;
fMatch = TRUE;
break;
}
NKEY( "DeflectAC", race_table[num].deflection, fread_number(fp));
break;
case 'E':
NKEY( "Ethos", race_table[num].ethos, fread_number(fp));
if (!strcmp(word, "EndRace"))
return;
break;
case 'F':
NKEY( "FavoredCls", race_table[num].favored_class, fread_number(fp));
break;
case 'H':
NKEY( "Height", race_table[num].height, fread_number(fp));
NKEY( "HitDice", race_table[num].hit_dice, fread_number(fp));
break;
case 'L':
NKEY( "LevelAdj", race_table[num].lvl_adj, fread_number(fp));
break;
case 'M':
NKEY( "Material", race_table[num].material, fread_number(fp));
break;
case 'N':
NKEY( "NaturalAC", race_table[num].nat_armor, fread_number(fp));
if ( !strcasecmp( word, "Name" ) )
{
char *name = STRALLOC(fread_string(fp));
if (!is_string(name))
sprintf(race_table[num].race_name, "%s", strlower(bits_to_str(num, "RACE_")));
else
sprintf(race_table[num].race_name, "%s", name);
fMatch = TRUE;
break;
}
if ( !strcasecmp( word, "Nonabil" ) )
{
line = fread_line( fp );
x1=x2=x3=x4=x5=x6=0;
sscanf( line, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 );
race_table[num].nonability[0] = x1;
race_table[num].nonability[1] = x2;
race_table[num].nonability[2] = x3;
race_table[num].nonability[3] = x4;
race_table[num].nonability[4] = x5;
race_table[num].nonability[5] = x6;
fMatch = TRUE;
break;
}
break;
case 'P':
if ( !strcasecmp( word, "PriPart" ) )
{
fMatch = TRUE;
break;
}
NKEY( "PCRace", race_table[num].pcrace, fread_number(fp));
NKEY( "ParentRace", race_table[num].parent_race, fread_number(fp));
if ( !strcasecmp( word, "Poison" ) )
{
int body;
int value;
body = fread_number( fp );
value = fread_number( fp );
if (!race_table[num].attacks)
{
bug("fread_race: %s - poisoned part not set in attack parts.", race_table[num].race_name);
break;
}
if (poison_table[value].name == NULL)
{
bug("fread_race: %s - unknown poison type.", race_table[num].race_name);
break;
}
race_table[num].poison_part = body;
race_table[num].poison = value;
fMatch = TRUE;
break;
}
break;
case 'R':
NKEY( "RaceType", race_table[num].type, fread_number(fp));
break;
case 'S':
NKEY( "Size", race_table[num].size, fread_number(fp));
NKEY( "Speaks", race_table[num].speaks, fread_number(fp));
NKEY( "Specials", race_table[num].flags, fread_number(fp));
NKEY( "SpeedBurrow", race_table[num].burrow_speed, fread_number(fp));
NKEY( "SpeedClimb", race_table[num].climb_speed, fread_number(fp));
NKEY( "SpeedFly", race_table[num].fly_speed, fread_number(fp));
NKEY( "SpeedLand", race_table[num].land_speed, fread_number(fp));
NKEY( "SpeedSwim", race_table[num].swim_speed, fread_number(fp));
NKEY( "Sectors", race_table[num].sectors, fread_number(fp));
if ( !strcasecmp( word, "Skill" ) )
{
int sn;
int value;
value = fread_number( fp );
sn = skill_lookup( fread_word( fp ) );
if (sn < 0)
{
bug("fread_race: %s - unknown skill.", race_table[num].race_name);
}
else
{
skill_table[sn].race_skill[num] = value;
}
fMatch = TRUE;
break;
}
break;
case 'U':
NKEY("Understands", race_table[num].understands, fread_number(fp));
break;
case 'V':
NKEY("Vulnerable", race_table[num].vulnerability, fread_number(fp));
break;
case 'W':
NKEY("WearLocs", race_table[num].wear_locs, fread_number(fp));
NKEY("Weight", race_table[num].weight, fread_number(fp));
break;
}
if (fMatch == FALSE)
{
log_printf("fread_race: no match: %s %s", word, fread_line(fp));
}
}
my_fclose (fp);
open_reserve();
}
void load_races ()
{
int i;
// int j;
log_string("Loading Races...");
for (i = 0; i < MAX_RACE; i++)
{
// for (j = 0; *skill_table[j].name != '\0' ; j++)
// {
// skill_table[j].race_skill[i] = 0;
// }
fread_race(i);
}
}
/* Save this god */
void fwrite_god (int num)
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
int cnt;
sprintf (buf, "%s/%s.txt", GOD_DIR, bits_to_str(num, "GOD_"));
close_reserve();
if ((fp = my_fopen(buf, "w", FALSE)) == NULL)
{
log_printf("Could not open file %s in order to save god.", buf);
return;
}
fprintf( fp, "Name %s~\n", !is_string(god_table[num].god_name) ? strlower(bits_to_str(num, "GOD_")) : god_table[num].god_name);
fprintf( fp, "LogMsg %s~\n", god_table[num].logout_msg );
for (cnt = 0; cnt < MAX_DOMAIN; cnt++)
{
if (!god_table[num].domain[cnt])
continue;
fprintf (fp, "Domain ");
break_bits( fp, cnt, "DOMAIN_", TRUE);
fprintf( fp, " 1\n" );
}
fprintf( fp, "Domain1 %d\n", god_table[num].domain1 );
fprintf( fp, "Domain2 %d\n", god_table[num].domain2 );
fprintf( fp, "FaveWeapon ");
break_bits( fp, god_table[num].favored_weapon, "WEAPON_TYPE_", TRUE);
fprintf( fp, "\n" );
fprintf( fp, "Align %d\n", god_table[num].align );
fprintf( fp, "Ethos %d\n", god_table[num].ethos );
fprintf( fp, "AlignHi %d\n", god_table[num].align_hi );
fprintf( fp, "AlignLo %d\n", god_table[num].align_lo );
fprintf( fp, "EthosHi %d\n", god_table[num].ethos_hi );
fprintf( fp, "EthosLo %d\n", god_table[num].ethos_lo );
fprintf( fp, "Race ");
break_bits( fp, god_table[num].race, "RSPEC_", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "PaladinMulti ");
break_bits( fp, god_table[num].paladin_multi, "FLAG_CLASS", FALSE);
fprintf( fp, "\n" );
fprintf( fp, "MonkMulti ");
break_bits( fp, god_table[num].monk_multi, "FLAG_CLASS", FALSE);
fprintf( fp, "\n" );
for (cnt = 0; cnt < MAX_GOD; cnt++)
{
if (god_table[cnt].god_name == NULL)
continue;
if (god_table[num].faith_enemy[cnt] > 0)
{
fprintf (fp, "FaithEnemy ");
break_bits( fp, cnt, "GOD_", TRUE);
fprintf( fp, " 1\n" );
}
}
for (cnt = 0; cnt < MAX_GOD; cnt++)
{
if (god_table[cnt].god_name == NULL)
continue;
if (god_table[num].faith_ally[cnt])
{
fprintf (fp, "FaithAlly ");
break_bits( fp, cnt, "GOD_", TRUE);
fprintf( fp, " 1\n" );
}
}
fprintf( fp, "%s", "EndGod\n\n" );
my_fclose (fp);
open_reserve();
}
void save_gods()
{
int i;
for (i = 0; i < MAX_GOD; i++)
{
fwrite_god(i);
}
}
/* Load a god */
void fread_god (int num)
{
char buf[MAX_STRING_LENGTH];
char *word;
bool fMatch;
int cnt;
FILE *fp;
sprintf (buf, "%s/%s.txt", GOD_DIR, bits_to_str(num, "GOD_"));
close_reserve();
if ((fp = my_fopen(buf, "r", FALSE)) == NULL)
{
fwrite_god(num);
fread_god(num);
return;
}
for (cnt = 0 ; cnt < 5 ; cnt++)
RESTRING(god_table[num].ranking[cnt], str_empty);
for ( ; ; )
{
word = feof(fp) ? "EndGod" : fread_word(fp);
fMatch = FALSE;
// if (!is_string(god_table[num].god_name))
// sprintf(god_table[num].god_name, strlower(bits_to_str(num, "GOD_")));
//
switch (word[0])
{
case 'A':
NKEY("Align", god_table[num].align, fread_number(fp));
NKEY("AlignHi", god_table[num].align_hi, fread_number(fp));
NKEY("AlignLo", god_table[num].align_lo, fread_number(fp));
break;
case 'D':
NKEY( "Domain1", god_table[num].domain1, fread_number(fp));
NKEY( "Domain2", god_table[num].domain2, fread_number(fp));
AKEY( "Domain", god_table[num].domain, fread_number(fp));
break;
case 'E':
NKEY( "Ethos", god_table[num].ethos, fread_number(fp));
NKEY( "EthosHi", god_table[num].ethos_hi, fread_number(fp));
NKEY( "EthosLo", god_table[num].ethos_lo, fread_number(fp));
if (!strcmp(word, "EndGod"))
{
return;
}
break;
case 'F':
NKEY( "FaveWeapon", god_table[num].favored_weapon, fread_number(fp));
AKEY( "FaithEnemy", god_table[num].faith_enemy, fread_number(fp));
AKEY( "FaithAlly", god_table[num].faith_ally, fread_number(fp));
break;
case 'L':
if ( !strcasecmp( word, "LogMsg" ) )
{
char *msg = STRALLOC(fread_string(fp));
sprintf(god_table[num].logout_msg, "%s", msg);
fMatch = TRUE;
}
break;
case 'M':
NKEY( "MonkMulti", god_table[num].monk_multi, fread_number(fp));
break;
case 'N':
if ( !strcasecmp( word, "Name" ) )
{
char *name = STRALLOC(fread_string(fp));
if (!is_string(name))
sprintf(god_table[num].god_name, "%s", strlower(bits_to_str(num, "GOD_")));
else
sprintf(god_table[num].god_name, "%s", name);
fMatch = TRUE;
}
break;
case 'P':
NKEY( "PaladinMulti", god_table[num].paladin_multi, fread_number(fp));
break;
case 'R':
NKEY( "Race", god_table[num].race, fread_number(fp));
break;
}
if (fMatch == FALSE)
{
log_printf("fread_god: no match: %s %s", word, fread_line(fp));
}
}
my_fclose (fp);
open_reserve();
}
void load_gods ()
{
int i;
log_string("Loading Gods...");
for (i = 0; i < MAX_GOD; i++)
{
fread_god(i);
}
}
/* Save the components table */
void fwrite_components (void)
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
int i, j;
sprintf (buf, "../skilltables/components.txt");
close_reserve();
if ((fp = my_fopen(buf, "w", FALSE)) == NULL)
{
log_printf("Could not open file %s in order to save components table.", buf);
return;
}
for (i = 0; *skill_table[i].name != '\0'; i++)
{
if (!skill_table[i].name || !skill_table[i].name[0])
continue;
if (skill_table[i].components[0] == 0)
continue;
fprintf (fp, "'%s'", skill_table[i].name);
for (j = 0 ; j < 5 ;j++)
{
fprintf (fp, " ");
break_bits( fp, skill_table[i].components[j], "COMP_", TRUE);
}
fprintf (fp, "\n\r");
}
fprintf (fp, "End\n\r"); /* EOF */
my_fclose (fp);
open_reserve();
}
/* Load the components table */
void fread_components (void)
{
char buf[MAX_STRING_LENGTH];
char *word;
int sn;
FILE *fp;
sprintf (buf, "../skilltables/components.txt");
close_reserve();
if ((fp = my_fopen(buf, "r", FALSE)) == NULL)
{
log_printf ("Could not open file %s in order to load components.", buf);
// abort();
return;
}
log_printf ("Loading components...");
for ( ; ; )
{
word = feof(fp) ? "End" : fread_word(fp);
if (!strcmp(word, "End"))
return;
if ((sn = skill_lookup(word)) == -1)
{
log_printf("fread_components: no such skill: %s %s", word, fread_line(fp));
continue;
}
skill_table[sn].components[0] = fread_number(fp);
skill_table[sn].components[1] = fread_number(fp);
skill_table[sn].components[2] = fread_number(fp);
skill_table[sn].components[3] = fread_number(fp);
skill_table[sn].components[4] = fread_number(fp);
}
my_fclose (fp);
open_reserve();
}
/* Save the bloodline table */
void fwrite_bloodlines (void)
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
int i, j;
sprintf (buf, "../skilltables/bloodline.txt");
close_reserve();
if ((fp = my_fopen(buf, "w", FALSE)) == NULL)
{
log_printf("Could not open file %s in order to save bloodline table.", buf);
return;
}
for (i = 0; *skill_table[i].name != '\0'; i++)
{
if (!skill_table[i].name || !skill_table[i].name[0])
continue;
for (j = 0 ; j < BLOODLINE_MAX ;j++)
{
if (skill_table[i].bloodline[j] >= 75)
continue;
fprintf (fp, "'%s'", skill_table[i].name);
fprintf (fp, " ");
break_bits( fp, j, "BLOODLINE_", TRUE);
fprintf (fp, " %d \n", skill_table[i].bloodline[j]);
}
}
fprintf (fp, "End\n\r"); /* EOF */
my_fclose (fp);
open_reserve();
}
/* Load the bloodline table */
void fread_bloodlines (void)
{
char buf[MAX_STRING_LENGTH];
char *word;
int sn, i, j;
FILE *fp;
// initialize all skills to immortal first.
for (i = 0; *skill_table[i].name != '\0'; i++)
{
if (!skill_table[i].name || !skill_table[i].name[0])
continue;
for (j = 0 ; j < BLOODLINE_MAX ;j++)
{
skill_table[i].bloodline[j] = LEVEL_IMMORTAL;
}
}
sprintf (buf, "../skilltables/bloodline.txt");
close_reserve();
if ((fp = my_fopen(buf, "r", FALSE)) == NULL)
{
log_printf ("Could not open file %s in order to load bloodline.", buf);
// abort();
return;
}
log_printf ("Loading bloodline skill table...");
for ( ; ; )
{
word = feof(fp) ? "End" : fread_word(fp);
if (!strcmp(word, "End"))
return;
if ((sn = skill_lookup(word)) == -1)
{
log_printf("fread_bloodline: no such skill: %s %s", word, fread_line(fp));
continue;
}
skill_table[sn].bloodline[fread_number(fp)] = fread_number(fp);
}
my_fclose (fp);
open_reserve();
}