/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.0 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
* ------------------------------------------------------------------------ *
* 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{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* Database management module *
* ------------------------------------------------------------------------ *
* capsule/corp (C)2016, 2017 *
* case@capsulecorp.org *
****************************************************************************/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdbool.h>
#include <syslog.h>
#include <time.h>
#include <sys/stat.h>
#include <dirent.h>
#define strcasecmp strcmp
#include "mud.h"
extern int _filbuf args((FILE *));
#if defined(KEY)
#undef KEY
#endif
void init_supermob();
#define KEY( literal, field, value ) \
if ( !str_cmp( word, literal ) ) \
{ \
field = value; \
fMatch = true; \
break; \
}
/*
* Globals.
*/
WIZENT *first_wiz;
WIZENT *last_wiz;
time_t last_restore_all_time = 0;
HELP_DATA *first_help;
HELP_DATA *last_help;
SHOP_DATA *first_shop;
SHOP_DATA *last_shop;
REPAIR_DATA *first_repair;
REPAIR_DATA *last_repair;
TELEPORT_DATA *first_teleport;
TELEPORT_DATA *last_teleport;
PROJECT_DATA *first_project;
PROJECT_DATA *last_project;
OBJ_DATA *extracted_obj_queue;
EXTRACT_CHAR_DATA *extracted_char_queue;
char bug_buf[2 * MAX_INPUT_LENGTH];
CHAR_DATA *first_char;
CHAR_DATA *last_char;
char *help_greeting;
char log_buf[2 * MAX_INPUT_LENGTH];
OBJ_DATA *first_object;
OBJ_DATA *last_object;
TIME_INFO_DATA time_info;
WEATHER_DATA weather_info;
int weath_unit; /* global weather param */
int rand_factor;
int climate_factor;
int neigh_factor;
int max_vector;
int cur_qobjs;
int cur_qchars;
int nummobsloaded;
int numobjsloaded;
int physicalobjects;
int last_pkroom;
MAP_INDEX_DATA *first_map; /* maps */
AUCTION_DATA *auction; /* auctions */
FILE *fpLOG;
char *GfpName = NULL;
bool StopFP = false;
/* Buu */
sh_int gsn_demonwave;
sh_int gsn_candyblast;
sh_int gsn_tentacle;
sh_int gsn_skin_trap;
sh_int gsn_thin_trans;
sh_int gsn_super_trans;
sh_int gsn_kid_trans;
/* weaponry */
sh_int gsn_pugilism;
sh_int gsn_long_blades;
sh_int gsn_short_blades;
sh_int gsn_flexible_arms;
sh_int gsn_talonous_arms;
sh_int gsn_bludgeons;
sh_int gsn_missile_weapons;
/* thief */
sh_int gsn_detrap;
sh_int gsn_backstab;
sh_int gsn_circle;
sh_int gsn_dodge;
sh_int gsn_block;
sh_int gsn_dcd;
sh_int gsn_hide;
sh_int gsn_peek;
sh_int gsn_pick_lock;
sh_int gsn_sneak;
sh_int gsn_steal;
sh_int gsn_gouge;
sh_int gsn_poison_weapon;
/* thief & warrior */
sh_int gsn_disarm;
sh_int gsn_enhanced_damage;
sh_int gsn_kick;
sh_int gsn_parry;
sh_int gsn_rescue;
sh_int gsn_second_attack;
sh_int gsn_third_attack;
sh_int gsn_fourth_attack;
sh_int gsn_fifth_attack;
sh_int gsn_dual_wield;
sh_int gsn_punch;
sh_int gsn_bash;
sh_int gsn_stun;
sh_int gsn_bashdoor;
sh_int gsn_grip;
sh_int gsn_berserk;
sh_int gsn_hitall;
sh_int gsn_tumble;
/* vampire */
sh_int gsn_feed;
sh_int gsn_bloodlet;
sh_int gsn_broach;
sh_int gsn_mistwalk;
/* other */
sh_int gsn_aid;
sh_int gsn_search;
sh_int gsn_dig;
sh_int gsn_mount;
sh_int gsn_bite;
sh_int gsn_claw;
sh_int gsn_sting;
sh_int gsn_tail;
sh_int gsn_scribe;
sh_int gsn_brew;
sh_int gsn_climb;
sh_int gsn_cook;
sh_int gsn_slice;
sh_int gsn_sensu_bean;
sh_int gsn_kaioken;
sh_int gsn_ssj;
sh_int gsn_ssj2;
sh_int gsn_ssj3;
sh_int gsn_ssj4;
sh_int gsn_sgod;
sh_int gsn_snamek;
sh_int gsn_icer2;
sh_int gsn_icer3;
sh_int gsn_icer4;
sh_int gsn_icer5;
sh_int gsn_goldenform;
sh_int gsn_semiperfect;
sh_int gsn_perfect;
sh_int gsn_ultraperfect;
sh_int gsn_fly;
sh_int gsn_energy_ball;
sh_int gsn_kamehameha;
sh_int gsn_masenko;
sh_int gsn_sbc;
sh_int gsn_dd;
sh_int gsn_ff;
sh_int gsn_suppress;
sh_int gsn_meditate;
sh_int gsn_scatter_shot;
sh_int gsn_sense;
sh_int gsn_uppercut;
sh_int gsn_tail_attack;
sh_int gsn_eye_beam;
sh_int gsn_finger_beam;
sh_int gsn_ddd;
sh_int gsn_death_ball;
sh_int gsn_preservation;
sh_int gsn_regeneration;
sh_int gsn_multi_eye;
sh_int gsn_ssd_bomber;
sh_int gsn_absorb;
sh_int gsn_absorb2;
sh_int gsn_battery;
sh_int gsn_rocket_punch;
sh_int gsn_drp;
sh_int gsn_bz;
sh_int gsn_enhance;
sh_int gsn_railgun;
sh_int gsn_cruise_punch;
sh_int gsn_electric_shield;
sh_int gsn_electric_shield2;
sh_int gsn_electric_shield3;
sh_int gsn_electric_shield4;
sh_int gsn_self_destruct;
sh_int gsn_duplicate;
sh_int gsn_extreme;
sh_int gsn_tribeam;
sh_int gsn_solar_flare;
sh_int gsn_multi_form;
sh_int gsn_tri_form;
sh_int gsn_split_form;
sh_int gsn_hyper;
sh_int gsn_instant_trans;
sh_int gsn_mystic;
sh_int gsn_skga;
sh_int gsn_charge2;
sh_int gsn_charge3;
sh_int gsn_charge4;
sh_int gsn_charge5;
sh_int gsn_multi_disk;
sh_int gsn_ki_absorb;
sh_int gsn_hells_flash;
sh_int gsn_ki_burst;
sh_int gsn_ki_heal;
sh_int gsn_growth;
sh_int gsn_giant;
sh_int gsn_destructive_wave;
sh_int gsn_dodon_ray;
sh_int gsn_spirit_ball;
sh_int gsn_big_bang;
sh_int gsn_bbk;
sh_int gsn_monkey_gun;
sh_int gsn_gallic_gun;
sh_int gsn_burning_attack;
sh_int gsn_finishing_buster;
sh_int gsn_heaven_splitter_cannon;
sh_int gsn_hellzone_grenade;
sh_int gsn_makosen;
sh_int gsn_trap_ball;
sh_int gsn_scattered_finger_beam;
sh_int gsn_spirit_bomb;
sh_int gsn_shockwave;
sh_int gsn_psiblast;
sh_int gsn_divine;
sh_int gsn_kaiocreate;
sh_int gsn_superandroid;
sh_int gsn_ehb;
sh_int gsn_evilboost;
sh_int gsn_evilsurge;
sh_int gsn_eviloverload;
sh_int gsn_demonweapon;
sh_int gsn_wss;
sh_int gsn_darkness_flare;
sh_int gsn_cleaver;
sh_int gsn_maliceray;
sh_int gsn_demonic_eclipse;
sh_int gsn_clone;
sh_int gsn_ussj;
sh_int gsn_ussj2;
/* spells */
sh_int gsn_aqua_breath;
sh_int gsn_blindness;
sh_int gsn_charm_person;
sh_int gsn_curse;
sh_int gsn_invis;
sh_int gsn_mass_invis;
sh_int gsn_poison;
sh_int gsn_sleep;
sh_int gsn_possess;
sh_int gsn_fireball;
sh_int gsn_chill_touch;
sh_int gsn_lightning_bolt;
/* languages */
sh_int gsn_common;
sh_int gsn_saiyan;
sh_int gsn_halfbreed;
sh_int gsn_namek;
sh_int gsn_android;
sh_int gsn_icer;
sh_int gsn_bio_android;
//sh_int gsn_halfling;
sh_int gsn_kaio;
sh_int gsn_demon;
sh_int gsn_wizard;
/* for searching */
sh_int gsn_first_spell;
sh_int gsn_first_skill;
sh_int gsn_first_ability;
sh_int gsn_first_weapon;
sh_int gsn_first_tongue;
sh_int gsn_top_sn;
/* For styles? Trying to rebuild from some kind of accident here - Blod */
sh_int gsn_style_evasive;
sh_int gsn_style_defensive;
sh_int gsn_style_standard;
sh_int gsn_style_aggressive;
sh_int gsn_style_berserk;
/*
* Locals.
*/
MOB_INDEX_DATA *mob_index_hash[MAX_KEY_HASH];
OBJ_INDEX_DATA *obj_index_hash[MAX_KEY_HASH];
ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH];
AREA_DATA *first_area;
AREA_DATA *last_area;
AREA_DATA *first_area_name; /* Used for alphanum. sort */
AREA_DATA *last_area_name;
AREA_DATA *first_build;
AREA_DATA *last_build;
AREA_DATA *first_asort;
AREA_DATA *last_asort;
AREA_DATA *first_bsort;
AREA_DATA *last_bsort;
SYSTEM_DATA sysdata;
int top_affect;
int top_area;
int top_ed;
int top_exit;
int top_help;
int top_mob_index;
int top_obj_index;
int top_reset;
int top_room;
int top_shop;
int top_repair;
int top_vroom;
/*
* Semi-locals.
*/
bool log_debug;
bool fBootDb;
FILE *fpArea;
char strArea[MAX_INPUT_LENGTH];
void shop_inventory_update(void);
/*
* Local booting procedures.
*/
void boot_log args((const char *str,...));
void load_area args((FILE *fp));
void load_author args((AREA_DATA * tarea, FILE *fp));
void load_economy(void);
void load_resetmsg args((AREA_DATA * tarea, FILE *fp)); /* Rennard */
void load_flags args((AREA_DATA * tarea, FILE *fp));
void load_helps args((AREA_DATA * tarea, FILE *fp));
void load_mobiles args((AREA_DATA * tarea, FILE *fp));
void load_objects args((AREA_DATA * tarea, FILE *fp));
void load_projects args((void));
void load_resets args((AREA_DATA * tarea, FILE *fp));
void load_rooms args((AREA_DATA * tarea, FILE *fp));
void load_shops args((AREA_DATA * tarea, FILE *fp));
void load_repairs args((AREA_DATA * tarea, FILE *fp));
void load_specials args((AREA_DATA * tarea, FILE *fp));
void load_ranges args((AREA_DATA * tarea, FILE *fp));
void load_climate args((AREA_DATA * tarea, FILE *fp)); /* FB */
void load_neighbor args((AREA_DATA * tarea, FILE *fp));
void load_buildlist args((void));
bool load_systemdata args((SYSTEM_DATA * sys));
void load_version args((AREA_DATA * tarea, FILE *fp));
void load_reserved args((void));
void initialize_economy args((void));
void fix_exits args((void));
void sort_reserved args((RESERVE_DATA * pRes));
void init_area_weather args((void));
void load_weatherdata args((void));
PROJECT_DATA *read_project args((char *filename, FILE *fp));
NOTE_DATA *read_log args((FILE *fp));
void load_areaPlanet args((AREA_DATA * tarea, FILE *fp));
char *fread_string_wspace args((FILE *fp));
/*
* External booting function
*/
void load_corpses args((void));
void renumber_put_resets args((AREA_DATA * pArea));
void load_colors args((void));
/*
* MUDprogram locals
*/
int mprog_name_to_type args((char *name));
MPROG_DATA *mprog_file_read args((char *f, MPROG_DATA * mprg, MOB_INDEX_DATA * pMobIndex));
MPROG_DATA *oprog_file_read args((char *f, MPROG_DATA * mprg, OBJ_INDEX_DATA * pObjIndex));
MPROG_DATA *rprog_file_read args((char *f, MPROG_DATA * mprg, ROOM_INDEX_DATA * pRoomIndex));
void load_mudprogs args((AREA_DATA * tarea, FILE *fp));
void load_objprogs args((AREA_DATA * tarea, FILE *fp));
void load_roomprogs args((AREA_DATA * tarea, FILE *fp));
void mprog_read_programs args((FILE *fp, MOB_INDEX_DATA * pMobIndex));
void oprog_read_programs args((FILE *fp, OBJ_INDEX_DATA * pObjIndex));
void rprog_read_programs args((FILE *fp, ROOM_INDEX_DATA * pRoomIndex));
void
shutdown_mud(char *reason)
{
FILE *fp;
if ((fp = fopen(SHUTDOWN_FILE, "a")) != NULL) {
fprintf(fp, "%s\n", reason);
fclose(fp);
}
}
/*
* Big mama top level function.
*/
void
boot_db()
{
sh_int wear, x;
fpArea = NULL;
show_hash(32);
unlink(BOOTLOG_FILE);
boot_log("---------------------[ Boot Log ]--------------------");
log_string("Loading commands");
load_commands();
log_string("Loading sysdata configuration...");
/* default values */
sysdata.read_all_mail = LEVEL_DEMI;
sysdata.read_mail_free = LEVEL_IMMORTAL;
sysdata.write_mail_free = LEVEL_IMMORTAL;
sysdata.take_others_mail = LEVEL_DEMI;
sysdata.muse_level = LEVEL_DEMI;
sysdata.think_level = LEVEL_HIGOD;
sysdata.build_level = LEVEL_DEMI;
sysdata.log_level = LEVEL_LOG;
sysdata.level_modify_proto = LEVEL_LESSER;
sysdata.level_override_private = LEVEL_GREATER;
sysdata.level_mset_player = LEVEL_LESSER;
sysdata.stun_plr_vs_plr = 65;
sysdata.stun_regular = 15;
sysdata.gouge_nontank = 0;
sysdata.gouge_plr_vs_plr = 0;
sysdata.bash_nontank = 0;
sysdata.bash_plr_vs_plr = 0;
sysdata.dodge_mod = 2;
sysdata.parry_mod = 2;
sysdata.tumble_mod = 4;
sysdata.dam_plr_vs_plr = 100;
sysdata.dam_plr_vs_mob = 100;
sysdata.dam_mob_vs_plr = 100;
sysdata.dam_mob_vs_mob = 100;
sysdata.level_getobjnotake = LEVEL_GREATER;
sysdata.save_frequency = 20; /* minutes */
sysdata.bestow_dif = 5;
sysdata.check_imm_host = 1;
sysdata.morph_opt = 1;
sysdata.save_pets = 0;
sysdata.pk_loot = 1;
sysdata.stall_hiscores = 0;
sysdata.rpChannel = 0;
sysdata.save_flags = SV_DEATH | SV_PASSCHG | SV_AUTO
| SV_PUT | SV_DROP | SV_GIVE
| SV_AUCTION | SV_ZAPDROP | SV_IDLE;
sysdata.kaiRestoreTimer = 0;
if (!load_systemdata(&sysdata)) {
log_string("Not found. Creating new configuration.");
sysdata.alltimemax = 0;
sysdata.mud_name = str_dup("(Name not set)");
}
log_string("Loading socials");
load_socials();
log_string("Loading skill table");
load_skill_table();
sort_skill_table();
remap_slot_numbers(); /* must be after the sort */
gsn_first_spell = 0;
gsn_first_skill = 0;
gsn_first_ability = 0;
gsn_first_weapon = 0;
gsn_first_tongue = 0;
gsn_top_sn = top_sn;
for (x = 0; x < top_sn; x++)
if (!gsn_first_spell && skill_table[x]->type == SKILL_SPELL)
gsn_first_spell = x;
else if (!gsn_first_skill && skill_table[x]->type == SKILL_SKILL)
gsn_first_skill = x;
else if (!gsn_first_ability && skill_table[x]->type == SKILL_ABILITY)
gsn_first_ability = x;
else if (!gsn_first_weapon && skill_table[x]->type == SKILL_WEAPON)
gsn_first_weapon = x;
else if (!gsn_first_tongue && skill_table[x]->type == SKILL_TONGUE)
gsn_first_tongue = x;
log_string("Loading classes");
load_classes();
log_string("Loading races");
load_races();
log_string("Loading herb table");
load_herb_table();
log_string("Loading tongues");
load_tongues();
log_string("Making wizlist");
make_wizlist();
log_string("Building wizinfo");
build_wizinfo(true);
log_string("Initializing request pipe");
init_request_pipe();
fBootDb = true;
nummobsloaded = 0;
numobjsloaded = 0;
physicalobjects = 0;
sysdata.maxplayers = 0;
first_object = NULL;
last_object = NULL;
first_char = NULL;
last_char = NULL;
first_area = NULL;
first_area_name = NULL; /* Used for alphanum. sort */
last_area_name = NULL;
last_area = NULL;
first_build = NULL;
last_area = NULL;
first_shop = NULL;
last_shop = NULL;
first_repair = NULL;
last_repair = NULL;
first_teleport = NULL;
last_teleport = NULL;
first_asort = NULL;
last_asort = NULL;
extracted_obj_queue = NULL;
extracted_char_queue = NULL;
cur_qobjs = 0;
cur_qchars = 0;
cur_char = NULL;
cur_obj = 0;
cur_obj_serial = 0;
cur_char_died = false;
cur_obj_extracted = false;
cur_room = NULL;
quitting_char = NULL;
loading_char = NULL;
saving_char = NULL;
last_pkroom = 1;
top_mob_serial = 0;
CREATE(auction, AUCTION_DATA, 1);
auction->item = NULL;
auction->hist_timer = 0;
for (x = 0; x < AUCTION_MEM; x++)
auction->history[x] = NULL;
auction->freeQueSlot = -1;
auction->queued_obj[0] = NULL;
auction->queued_char[0] = NULL;
auction->queued_starting_bid[0] = 0;
auction->queued_obj[1] = NULL;
auction->queued_char[1] = NULL;
auction->queued_starting_bid[1] = 0;
auction->queued_obj[2] = NULL;
auction->queued_char[2] = NULL;
auction->queued_starting_bid[2] = 0;
auction->queued_obj[3] = NULL;
auction->queued_char[3] = NULL;
auction->queued_starting_bid[3] = 0;
weath_unit = 10;
rand_factor = 2;
climate_factor = 1;
neigh_factor = 3;
max_vector = weath_unit * 3;
for (wear = 0; wear < MAX_WEAR; wear++)
for (x = 0; x < MAX_LAYERS; x++)
save_equipment[wear][x] = NULL;
/*
* Set time and weather.
*/
{
long lhour, lday, lmonth;
log_string("Setting time and weather");
if (!load_timedata()) {
lhour = (current_time - 650336715)
/ (PULSE_TICK / PULSE_PER_SECOND);
time_info.hour = lhour % 24;
lday = lhour / 24;
time_info.day = lday % 35;
lmonth = lday / 35;
time_info.month = lmonth % 17;
time_info.year = lmonth / 17;
}
if (time_info.hour < 5)
time_info.sunlight = SUN_DARK;
else if (time_info.hour < 6)
time_info.sunlight = SUN_RISE;
else if (time_info.hour < 19)
time_info.sunlight = SUN_LIGHT;
else if (time_info.hour < 20)
time_info.sunlight = SUN_SET;
else
time_info.sunlight = SUN_DARK;
}
/*
* Assign gsn's for skills which need them.
*/
{
log_string("Assigning gsn's");
ASSIGN_GSN(gsn_style_evasive, "evasive style");
ASSIGN_GSN(gsn_style_defensive, "defensive style");
ASSIGN_GSN(gsn_style_standard, "standard style");
ASSIGN_GSN(gsn_style_aggressive, "aggressive style");
ASSIGN_GSN(gsn_style_berserk, "berserk style");
ASSIGN_GSN(gsn_dodge, "dodge");
ASSIGN_GSN(gsn_block, "block");
ASSIGN_GSN(gsn_dcd, "dcd");
ASSIGN_GSN(gsn_hide, "hide");
ASSIGN_GSN(gsn_sneak, "sneak");
ASSIGN_GSN(gsn_gouge, "gouge");
ASSIGN_GSN(gsn_enhanced_damage, "enhanced damage");
ASSIGN_GSN(gsn_kick, "kick");
ASSIGN_GSN(gsn_rescue, "rescue");
ASSIGN_GSN(gsn_second_attack, "second attack");
ASSIGN_GSN(gsn_third_attack, "third attack");
ASSIGN_GSN(gsn_fourth_attack, "fourth attack");
ASSIGN_GSN(gsn_fifth_attack, "fifth attack");
ASSIGN_GSN(gsn_bash, "bash");
ASSIGN_GSN(gsn_stun, "stun");
ASSIGN_GSN(gsn_hitall, "hitall");
ASSIGN_GSN(gsn_aid, "aid");
ASSIGN_GSN(gsn_search, "search");
ASSIGN_GSN(gsn_claw, "claw");
ASSIGN_GSN(gsn_tail, "tail");
ASSIGN_GSN(gsn_mass_invis, "mass invis");
ASSIGN_GSN(gsn_sensu_bean, "sensu bean");
ASSIGN_GSN(gsn_charge2, "charge L1");
ASSIGN_GSN(gsn_charge3, "charge L2");
ASSIGN_GSN(gsn_charge4, "charge L3");
ASSIGN_GSN(gsn_charge5, "charge L4");
ASSIGN_GSN(gsn_kaioken, "kaioken");
ASSIGN_GSN(gsn_ssj, "ssj1");
ASSIGN_GSN(gsn_ssj2, "ssj2");
ASSIGN_GSN(gsn_ssj3, "ssj3");
ASSIGN_GSN(gsn_ssj4, "ssj4");
ASSIGN_GSN(gsn_sgod, "sgod");
ASSIGN_GSN(gsn_snamek, "super namek");
ASSIGN_GSN(gsn_icer2, "2nd form");
ASSIGN_GSN(gsn_icer3, "3rd form");
ASSIGN_GSN(gsn_icer4, "4th form");
ASSIGN_GSN(gsn_icer5, "5th form");
ASSIGN_GSN(gsn_goldenform, "golden form");
ASSIGN_GSN(gsn_semiperfect, "semi-perfect form");
ASSIGN_GSN(gsn_perfect, "perfect form");
ASSIGN_GSN(gsn_ultraperfect, "ultra-perfect form");
ASSIGN_GSN(gsn_punch, "punch");
ASSIGN_GSN(gsn_fly, "fly");
ASSIGN_GSN(gsn_energy_ball, "energy ball");
ASSIGN_GSN(gsn_kamehameha, "kamehameha");
ASSIGN_GSN(gsn_masenko, "masenko");
ASSIGN_GSN(gsn_sbc, "special beam cannon");
ASSIGN_GSN(gsn_dd, "destructo disk");
ASSIGN_GSN(gsn_ff, "final flash");
ASSIGN_GSN(gsn_suppress, "suppress");
ASSIGN_GSN(gsn_meditate, "meditate");
ASSIGN_GSN(gsn_scatter_shot, "scatter shot");
ASSIGN_GSN(gsn_sense, "sense");
ASSIGN_GSN(gsn_uppercut, "uppercut");
ASSIGN_GSN(gsn_tail_attack, "tail attack");
ASSIGN_GSN(gsn_eye_beam, "eye beam");
ASSIGN_GSN(gsn_finger_beam, "finger beam");
ASSIGN_GSN(gsn_ddd, "dual destructo disk");
ASSIGN_GSN(gsn_death_ball, "death ball");
ASSIGN_GSN(gsn_preservation, "preservation");
ASSIGN_GSN(gsn_regeneration, "regeneration");
ASSIGN_GSN(gsn_multi_eye, "multi eye beam");
ASSIGN_GSN(gsn_ssd_bomber, "ssd bomber");
ASSIGN_GSN(gsn_absorb, "absorb");
ASSIGN_GSN(gsn_absorb2, "upgraded absorb L1");
ASSIGN_GSN(gsn_battery, "battery");
ASSIGN_GSN(gsn_rocket_punch, "rocket punch");
ASSIGN_GSN(gsn_drp, "double rocket punch");
ASSIGN_GSN(gsn_bz, "blast zone");
ASSIGN_GSN(gsn_enhance, "enhance");
ASSIGN_GSN(gsn_railgun, "railgun");
ASSIGN_GSN(gsn_cruise_punch, "cruise punch");
ASSIGN_GSN(gsn_electric_shield, "electric shield");
ASSIGN_GSN(gsn_electric_shield2, "upgraded shield L1");
ASSIGN_GSN(gsn_electric_shield3, "upgraded shield L2");
ASSIGN_GSN(gsn_electric_shield4, "upgraded shield L3");
ASSIGN_GSN(gsn_self_destruct, "self destruct");
ASSIGN_GSN(gsn_duplicate, "duplicate");
ASSIGN_GSN(gsn_extreme, "extreme");
ASSIGN_GSN(gsn_tribeam, "tri-beam");
ASSIGN_GSN(gsn_solar_flare, "solar flare");
ASSIGN_GSN(gsn_multi_form, "multi-form");
ASSIGN_GSN(gsn_tri_form, "tri-form");
ASSIGN_GSN(gsn_hyper, "hyper");
ASSIGN_GSN(gsn_instant_trans, "instant transmission");
ASSIGN_GSN(gsn_mystic, "mystic");
ASSIGN_GSN(gsn_skga, "skga");
ASSIGN_GSN(gsn_common, "common");
ASSIGN_GSN(gsn_saiyan, "saiyan");
ASSIGN_GSN(gsn_halfbreed, "halfbreed");
ASSIGN_GSN(gsn_namek, "namek");
ASSIGN_GSN(gsn_android, "android");
ASSIGN_GSN(gsn_icer, "icer");
ASSIGN_GSN(gsn_bio_android, "bio-android");
ASSIGN_GSN(gsn_kaio, "kaio");
ASSIGN_GSN(gsn_demon, "demon");
ASSIGN_GSN(gsn_wizard, "wizard");
ASSIGN_GSN(gsn_multi_disk, "multi disk");
ASSIGN_GSN(gsn_ki_absorb, "ki absorb");
ASSIGN_GSN(gsn_hells_flash, "hells flash");
ASSIGN_GSN(gsn_ki_burst, "ki burst");
ASSIGN_GSN(gsn_ki_heal, "ki heal");
ASSIGN_GSN(gsn_growth, "growth");
ASSIGN_GSN(gsn_giant, "giant size");
ASSIGN_GSN(gsn_split_form, "split-form");
ASSIGN_GSN(gsn_destructive_wave, "destructive wave");
ASSIGN_GSN(gsn_dodon_ray, "dodon ray");
ASSIGN_GSN(gsn_spirit_ball, "spirit ball");
ASSIGN_GSN(gsn_big_bang, "bigbang");
ASSIGN_GSN(gsn_bbk, "big bang kamehameha");
ASSIGN_GSN(gsn_monkey_gun, "oozaru mouth cannon");
ASSIGN_GSN(gsn_gallic_gun, "gallic gun");
ASSIGN_GSN(gsn_burning_attack, "burning attack");
ASSIGN_GSN(gsn_finishing_buster, "finishing buster");
ASSIGN_GSN(gsn_heaven_splitter_cannon, "heaven-splitter cannon");
ASSIGN_GSN(gsn_hellzone_grenade, "hellzone grenade");
ASSIGN_GSN(gsn_makosen, "makosen");
ASSIGN_GSN(gsn_trap_ball, "trap ball");
ASSIGN_GSN(gsn_scattered_finger_beam, "scattered finger beam");
ASSIGN_GSN(gsn_spirit_bomb, "spirit bomb");
ASSIGN_GSN(gsn_shockwave, "shockwave");
ASSIGN_GSN(gsn_psiblast, "psionic blast");
ASSIGN_GSN(gsn_divine, "divine wrath");
ASSIGN_GSN(gsn_kaiocreate, "kaio create");
ASSIGN_GSN(gsn_superandroid, "super android");
ASSIGN_GSN(gsn_ehb, "electric hell ball");
ASSIGN_GSN(gsn_evilboost, "evil boost");
ASSIGN_GSN(gsn_evilsurge, "evil surge");
ASSIGN_GSN(gsn_eviloverload, "evil overload");
ASSIGN_GSN(gsn_demonweapon, "demon weapon");
ASSIGN_GSN(gsn_wss, "weapon soul seppuku");
ASSIGN_GSN(gsn_darkness_flare, "darkness flare");
ASSIGN_GSN(gsn_cleaver, "cleaver");
ASSIGN_GSN(gsn_maliceray, "malice ray");
ASSIGN_GSN(gsn_demonic_eclipse, "demonic eclipse");
ASSIGN_GSN(gsn_clone, "clone");
ASSIGN_GSN(gsn_ussj, "ussj1");
ASSIGN_GSN(gsn_ussj2, "ussj2");
ASSIGN_GSN(gsn_thin_trans, "thin transformation");
ASSIGN_GSN(gsn_super_trans, "super transformation");
ASSIGN_GSN(gsn_kid_trans, "kid transformation");
ASSIGN_GSN(gsn_demonwave, "demon wave");
ASSIGN_GSN(gsn_candyblast, "candy blast");
ASSIGN_GSN(gsn_tentacle, "tentacle attack");
ASSIGN_GSN(gsn_skin_trap, "skin trap");
}
log_string("Loading DNS cache...");
load_dns();
/* log_string("Reading in plane file..."); */
/* load_planes(); */
/*
* Read in all the area files.
*/
{
FILE *fpList;
char area[MAX_STRING_LENGTH];
log_string("Reading in area files...");
if ((fpList = fopen(AREA_LIST, "r")) == NULL) {
perror(AREA_LIST);
shutdown_mud("Unable to open area list");
exit(1);
}
for (;;) {
snprintf(area, sizeof(strArea), "%s", fread_word(fpList));
snprintf(strArea, sizeof(strArea), "%s%s", AREA_DIR, area);
if (area[0] == '$') {
memset(area, 0, sizeof(area));
break;
}
load_area_file(last_area, strArea);
memset(area, 0, sizeof(area));
}
fclose(fpList);
}
/* log_string("Making sure rooms are planed..."); */
/* check_planes(NULL); */
/*
* initialize supermob.
* must be done before reset_area!
*/
init_supermob();
/*
* Fix up exits.
* Declare db booting over.
* Reset all areas once.
* Load up the notes file.
*/
{
log_string("Fixing exits");
fix_exits();
fBootDb = false;
log_string("Loading economy");
load_economy();
log_string("Initializing economy");
initialize_economy();
log_string("Resetting areas");
area_update();
log_string("Stocking RTG Shopkeepers");
shop_inventory_update();
log_string("Loading buildlist");
load_buildlist();
log_string("Loading boards");
load_boards();
log_string("Loading Global Boards");
load_global_boards();
log_string("Loading clans");
load_clans();
log_string("Loading deities");
load_deity();
log_string("Loading councils");
load_councils();
log_string("Loading reserved names");
load_reserved();
log_string("Loading auth namelist");
scan_equipment();
log_string("Loading corpses");
load_corpses();
log_string("Loading space");
load_space();
log_string("Loading ships");
load_ships();
log_string("Loading governments");
load_planets();
log_string("Loading Projects");
load_projects();
log_string("Loading Colors");
load_colors();
log_string("Loading Housing System, Home Accessories Data,"
" and Home Auctioning System");
load_homedata();
load_accessories();
load_homebuy();
MOBtrigger = true;
/* cronel hiscore */
log_string("Loading hiscore tables");
load_hiscores();
}
/* Initialize area weather data */
load_weatherdata();
init_area_weather();
return;
}
/*
* Load an 'area' header line.
*/
void
load_area(FILE *fp)
{
AREA_DATA *pArea;
CREATE(pArea, AREA_DATA, 1);
pArea->first_reset = NULL;
pArea->last_reset = NULL;
pArea->name = fread_string_nohash(fp);
pArea->author = STRALLOC("unknown");
pArea->filename = str_dup(strArea);
pArea->age = 15;
pArea->nplayer = 0;
pArea->low_r_vnum = 0;
pArea->low_o_vnum = 0;
pArea->low_m_vnum = 0;
pArea->hi_r_vnum = 0;
pArea->hi_o_vnum = 0;
pArea->hi_m_vnum = 0;
pArea->low_soft_range = 0;
pArea->hi_soft_range = MAX_LEVEL;
pArea->low_hard_range = 0;
pArea->hi_hard_range = MAX_LEVEL;
pArea->spelllimit = 0;
/* initialize weather data - FB */
CREATE(pArea->weather, WEATHER_DATA, 1);
pArea->weather->temp = 0;
pArea->weather->precip = 0;
pArea->weather->wind = 0;
pArea->weather->temp_vector = 0;
pArea->weather->precip_vector = 0;
pArea->weather->wind_vector = 0;
pArea->weather->climate_temp = 2;
pArea->weather->climate_precip = 2;
pArea->weather->climate_wind = 2;
pArea->weather->first_neighbor = NULL;
pArea->weather->last_neighbor = NULL;
pArea->weather->echo = NULL;
pArea->weather->echo_color = AT_GREY;
area_version = 0;
LINK(pArea, first_area, last_area, next, prev);
top_area++;
return;
}
/* Load the version number of the area file if none exists, then it
* is set to version 0 when #AREA is read in which is why we check for
* the #AREA here. --Shaddai
*/
void
load_version(AREA_DATA * tarea, FILE *fp)
{
if (!tarea) {
bug("Load_author: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
area_version = fread_number(fp);
return;
}
/*
* Load an author section. Scryn 2/1/96
*/
void
load_author(AREA_DATA * tarea, FILE *fp)
{
if (!tarea) {
bug("Load_author: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
if (tarea->author)
STRFREE(tarea->author);
tarea->author = fread_string(fp);
return;
}
/*
* Load an economy section. Thoric
*/
void
load_economy(void)
{
AREA_DATA *tarea;
char buf[MAX_STRING_LENGTH];
FILE *fpout;
for (tarea = first_area; tarea; tarea = tarea->next) {
sprintf(buf, "%s.econ", tarea->filename);
if ((fpout = fopen(buf, "r")) == NULL) {
bug("load_economy: fopen", 0);
perror(buf);
return;
}
tarea->economy = fread_number_skill(fpout);
fclose(fpout);
}
return;
}
/*
* Load what planet the area is on
*/
void
load_areaPlanet(AREA_DATA * tarea, FILE *fp)
{
if (!tarea) {
bug("Load_areaPlanet: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
tarea->areaPlanet = fread_number(fp);
return;
}
/* Reset Message Load, Rennard */
void
load_resetmsg(AREA_DATA * tarea, FILE *fp)
{
if (!tarea) {
bug("Load_resetmsg: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
if (tarea->resetmsg)
DISPOSE(tarea->resetmsg);
tarea->resetmsg = fread_string_nohash(fp);
return;
}
/*
* Load area flags. Narn, Mar/96
*/
void
load_flags(AREA_DATA * tarea, FILE *fp)
{
char *ln;
int x1, x2;
if (!tarea) {
bug("Load_flags: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
ln = fread_line(fp);
x1 = x2 = 0;
sscanf(ln, "%d %d",
&x1, &x2);
tarea->flags = x1;
tarea->reset_frequency = x2;
if (x2)
tarea->age = x2;
return;
}
/*
* Adds a help page to the list if it is not a duplicate of an existing page.
* Page is insert-sorted by keyword. -Thoric
* (The reason for sorting is to keep do_hlist looking nice)
*/
void
add_help(HELP_DATA * pHelp)
{
HELP_DATA *tHelp;
int match;
for (tHelp = first_help; tHelp; tHelp = tHelp->next)
if (pHelp->level == tHelp->level
&& strcmp(pHelp->keyword, tHelp->keyword) == 0) {
bug("add_help: duplicate: %s. Deleting.", pHelp->keyword);
STRFREE(pHelp->text);
STRFREE(pHelp->keyword);
DISPOSE(pHelp);
return;
} else if ((match = strcmp(pHelp->keyword[0] == '\'' ? pHelp->keyword + 1 : pHelp->keyword,
tHelp->keyword[0] == '\'' ? tHelp->keyword + 1 : tHelp->keyword)) < 0
|| (match == 0 && pHelp->level > tHelp->level)) {
if (!tHelp->prev)
first_help = pHelp;
else
tHelp->prev->next = pHelp;
pHelp->prev = tHelp->prev;
pHelp->next = tHelp;
tHelp->prev = pHelp;
break;
}
if (!tHelp)
LINK(pHelp, first_help, last_help, next, prev);
top_help++;
}
/*
* Load a help section.
*/
void
load_helps(AREA_DATA * tarea, FILE *fp)
{
HELP_DATA *pHelp;
for (;;) {
CREATE(pHelp, HELP_DATA, 1);
pHelp->level = fread_number(fp);
pHelp->keyword = fread_string(fp);
if (pHelp->keyword[0] == '$') {
STRFREE(pHelp->keyword);
DISPOSE(pHelp);
break;
}
pHelp->text = fread_string(fp);
if (pHelp->keyword[0] == '\0') {
STRFREE(pHelp->text);
STRFREE(pHelp->keyword);
DISPOSE(pHelp);
continue;
}
if (!str_cmp(pHelp->keyword, "greeting"))
help_greeting = pHelp->text;
add_help(pHelp);
}
return;
}
/*
* Add a character to the list of all characters -Thoric
*/
void
add_char(CHAR_DATA * ch)
{
LINK(ch, first_char, last_char, next, prev);
}
/*
* Load a mob section.
*/
void
load_mobiles(AREA_DATA * tarea, FILE *fp)
{
MOB_INDEX_DATA *pMobIndex;
char *ln;
int x1, x2, x3, x4, x5, x6, x7, x8;
if (!tarea) {
bug("Load_mobiles: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
for (;;) {
char buf[MAX_STRING_LENGTH];
int vnum;
char letter;
int iHash;
bool oldmob;
bool tmpBootDb;
letter = fread_letter(fp);
if (letter != '#') {
bug("Load_mobiles: # not found.");
if (fBootDb) {
shutdown_mud("# not found");
exit(1);
} else
return;
}
vnum = fread_number(fp);
if (vnum == 0)
break;
tmpBootDb = fBootDb;
fBootDb = false;
if (get_mob_index(vnum)) {
if (tmpBootDb) {
bug("Load_mobiles: vnum %d duplicated.", vnum);
shutdown_mud("duplicate vnum");
exit(1);
} else {
pMobIndex = get_mob_index(vnum);
sprintf(buf, "Cleaning mobile: %d", vnum);
clean_mob(pMobIndex);
oldmob = true;
}
} else {
oldmob = false;
CREATE(pMobIndex, MOB_INDEX_DATA, 1);
}
fBootDb = tmpBootDb;
pMobIndex->vnum = vnum;
if (fBootDb) {
if (!tarea->low_m_vnum)
tarea->low_m_vnum = vnum;
if (vnum > tarea->hi_m_vnum)
tarea->hi_m_vnum = vnum;
}
pMobIndex->player_name = fread_string(fp);
pMobIndex->short_descr = fread_string(fp);
pMobIndex->long_descr = fread_string(fp);
pMobIndex->description = fread_string(fp);
pMobIndex->long_descr[0] = UPPER(pMobIndex->long_descr[0]);
pMobIndex->description[0] = UPPER(pMobIndex->description[0]);
pMobIndex->act = fread_bitvector(fp);
xSET_BIT(pMobIndex->act, ACT_IS_NPC);
pMobIndex->affected_by = fread_bitvector(fp);
pMobIndex->pShop = NULL;
pMobIndex->rShop = NULL;
pMobIndex->alignment = fread_number(fp);
letter = fread_letter(fp);
pMobIndex->worth = fread_number_ll(fp);
pMobIndex->level = fread_number(fp);
pMobIndex->mobthac0 = fread_number(fp);
pMobIndex->ac = fread_number(fp);
pMobIndex->hitnodice = fread_number(fp);
/* 'd' */ fread_letter(fp);
pMobIndex->hitsizedice = fread_number(fp);
/* '+' */ fread_letter(fp);
pMobIndex->hitplus = fread_number(fp);
pMobIndex->damnodice = fread_number(fp);
/* 'd' */ fread_letter(fp);
pMobIndex->damsizedice = fread_number(fp);
/* '+' */ fread_letter(fp);
pMobIndex->damplus = fread_number(fp);
/* pMobIndex->gold = */ fread_number(fp);
/* All mobs should use the rtg -Goku 09.28.04 */
pMobIndex->gold = -1;
pMobIndex->exp = fread_number_ld(fp);
/* pMobIndex->position = fread_number( fp ); */
pMobIndex->position = fread_number(fp);
if (pMobIndex->position < 100) {
switch (pMobIndex->position) {
default:
case 0:
case 1:
case 2:
case 3:
case 4:
break;
case 5:
pMobIndex->position = 6;
break;
case 6:
pMobIndex->position = 8;
break;
case 7:
pMobIndex->position = 9;
break;
case 8:
pMobIndex->position = 12;
break;
case 9:
pMobIndex->position = 13;
break;
case 10:
pMobIndex->position = 14;
break;
case 11:
pMobIndex->position = 15;
break;
}
} else {
pMobIndex->position -= 100;
}
/*
* pMobIndex->defposition = fread_number( fp
* );
*/
pMobIndex->defposition = fread_number(fp);
if (pMobIndex->defposition < 100) {
switch (pMobIndex->defposition) {
default:
case 0:
case 1:
case 2:
case 3:
case 4:
break;
case 5:
pMobIndex->defposition = 6;
break;
case 6:
pMobIndex->defposition = 8;
break;
case 7:
pMobIndex->defposition = 9;
break;
case 8:
pMobIndex->defposition = 12;
break;
case 9:
pMobIndex->defposition = 13;
break;
case 10:
pMobIndex->defposition = 14;
break;
case 11:
pMobIndex->defposition = 15;
break;
}
} else {
pMobIndex->defposition -= 100;
}
/*
* Back to meaningful values.
*/
pMobIndex->sex = fread_number(fp);
if (letter != 'S' && letter != 'C') {
bug("Load_mobiles: vnum %d: letter '%c' not S or C.", vnum,
letter);
shutdown_mud("bad mob data");
exit(1);
}
if (letter == 'C') { /* Realms complex mob -Thoric */
if (area_version < 250) {
pMobIndex->perm_str = fread_number(fp);
pMobIndex->perm_int = fread_number(fp);
pMobIndex->perm_dex = fread_number(fp);
pMobIndex->perm_dex = fread_number(fp);
pMobIndex->perm_con = fread_number(fp);
pMobIndex->perm_lck = fread_number(fp);
pMobIndex->perm_lck = fread_number(fp);
} else {
pMobIndex->perm_str = fread_number(fp);
pMobIndex->perm_int = fread_number(fp);
pMobIndex->perm_dex = fread_number(fp);
pMobIndex->perm_con = fread_number(fp);
pMobIndex->perm_lck = fread_number(fp);
}
pMobIndex->saving_poison_death = fread_number(fp);
pMobIndex->saving_wand = fread_number(fp);
pMobIndex->saving_para_petri = fread_number(fp);
pMobIndex->saving_breath = fread_number(fp);
pMobIndex->saving_spell_staff = fread_number(fp);
ln = fread_line(fp);
x1 = x2 = x3 = x4 = x5 = x6 = x7 = x8 = 0;
sscanf(ln, "%d %d %d %d %d %d %d",
&x1, &x2, &x3, &x4, &x5, &x6, &x7);
pMobIndex->race = x1;
pMobIndex->class = x2;
pMobIndex->height = x3;
pMobIndex->weight = x4;
pMobIndex->speaks = x5;
pMobIndex->speaking = x6;
pMobIndex->numattacks = x7;
/*
* Thanks to Nick Gammon for noticing this. if (
* !pMobIndex->speaks ) pMobIndex->speaks =
* race_table[pMobIndex->race]->language |
* LANG_COMMON; if ( !pMobIndex->speaking )
* pMobIndex->speaking =
* race_table[pMobIndex->race]->language;
*/
if (!pMobIndex->speaks)
pMobIndex->speaks = LANG_COMMON;
if (!pMobIndex->speaking)
pMobIndex->speaking = LANG_COMMON;
#ifndef XBI
ln = fread_line(fp);
x1 = x2 = x3 = x4 = x5 = x6 = x7 = x8 = 0;
sscanf(ln, "%d %d %d %d %d %d %d %d",
&x1, &x2, &x3, &x4, &x5, &x6, &x7, &x8);
pMobIndex->hitroll = x1;
pMobIndex->damroll = x2;
pMobIndex->xflags = x3;
pMobIndex->resistant = x4;
pMobIndex->immune = x5;
pMobIndex->susceptible = x6;
pMobIndex->attacks = x7;
pMobIndex->defenses = x8;
#else
pMobIndex->hitroll = fread_number(fp);
pMobIndex->damroll = fread_number(fp);
pMobIndex->xflags = fread_number(fp);
pMobIndex->resistant = fread_number(fp);
pMobIndex->immune = fread_number(fp);
pMobIndex->susceptible = fread_number(fp);
pMobIndex->attacks = fread_bitvector(fp);
pMobIndex->defenses = fread_bitvector(fp);
#endif
} else {
pMobIndex->perm_str = 10;
pMobIndex->perm_dex = 10;
pMobIndex->perm_int = 10;
pMobIndex->perm_con = 10;
pMobIndex->perm_lck = 10;
pMobIndex->race = 0;
pMobIndex->class = 0;
pMobIndex->xflags = 0;
pMobIndex->resistant = 0;
pMobIndex->immune = 0;
pMobIndex->susceptible = 0;
pMobIndex->numattacks = 0;
#ifdef XBI
xCLEAR_BITS(pMobIndex->attacks);
xCLEAR_BITS(pMobIndex->defenses);
#else
pMobIndex->attacks = 0;
pMobIndex->defenses = 0;
#endif
}
letter = fread_letter(fp);
if (letter == '>') {
ungetc(letter, fp);
mprog_read_programs(fp, pMobIndex);
} else
ungetc(letter, fp);
if (!oldmob) {
iHash = vnum % MAX_KEY_HASH;
pMobIndex->next = mob_index_hash[iHash];
mob_index_hash[iHash] = pMobIndex;
top_mob_index++;
}
}
return;
}
/*
* Load an obj section.
*/
void
load_objects(AREA_DATA * tarea, FILE *fp)
{
OBJ_INDEX_DATA *pObjIndex;
char letter;
char *ln;
int x1, x2, x3, x4, x5, x6;
if (!tarea) {
bug("Load_objects: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
for (;;) {
char buf[MAX_STRING_LENGTH];
int vnum;
int iHash;
bool tmpBootDb;
bool oldobj;
letter = fread_letter(fp);
if (letter != '#') {
bug("Load_objects: # not found.");
if (fBootDb) {
shutdown_mud("# not found");
exit(1);
} else
return;
}
vnum = fread_number(fp);
if (vnum == 0)
break;
tmpBootDb = fBootDb;
fBootDb = false;
if (get_obj_index(vnum)) {
if (tmpBootDb) {
bug("Load_objects: vnum %d duplicated.", vnum);
shutdown_mud("duplicate vnum");
exit(1);
} else {
pObjIndex = get_obj_index(vnum);
sprintf(buf, "Cleaning object: %d", vnum);
clean_obj(pObjIndex);
oldobj = true;
}
} else {
oldobj = false;
CREATE(pObjIndex, OBJ_INDEX_DATA, 1);
}
fBootDb = tmpBootDb;
pObjIndex->vnum = vnum;
if (fBootDb) {
if (!tarea->low_o_vnum)
tarea->low_o_vnum = vnum;
if (vnum > tarea->hi_o_vnum)
tarea->hi_o_vnum = vnum;
}
pObjIndex->name = fread_string(fp);
pObjIndex->short_descr = fread_string(fp);
pObjIndex->description = fread_string(fp);
pObjIndex->action_desc = fread_string(fp);
/*
* Commented out by Narn, Apr/96 to allow item short descs
* like Bonecrusher and Oblivion
*/
/*
* pObjIndex->short_descr[0] =
* LOWER(pObjIndex->short_descr[0]);
*/
pObjIndex->description[0] = UPPER(pObjIndex->description[0]);
pObjIndex->item_type = fread_number(fp);
pObjIndex->extra_flags = fread_bitvector(fp);
ln = fread_line(fp);
x1 = x2 = 0;
sscanf(ln, "%d %d",
&x1, &x2);
pObjIndex->wear_flags = x1;
pObjIndex->layers = x2;
ln = fread_line(fp);
x1 = x2 = x3 = x4 = x5 = x6 = 0;
sscanf(ln, "%d %d %d %d %d %d",
&x1, &x2, &x3, &x4, &x5, &x6);
pObjIndex->value[0] = x1;
pObjIndex->value[1] = x2;
pObjIndex->value[2] = x3;
pObjIndex->value[3] = x4;
pObjIndex->value[4] = x5;
pObjIndex->value[5] = x6;
if (area_version < 251) {
ln = fread_line(fp);
x1 = x2 = x3 = x4 = 0;
sscanf(ln, "%d %d %d %d",
&x1, &x2, &x3, &x4);
pObjIndex->weight = x1;
pObjIndex->weight = UMAX(1, pObjIndex->weight);
pObjIndex->cost = x2;
pObjIndex->rent = x3; /* unused */
pObjIndex->level = x4;
} else {
ln = fread_line(fp);
x1 = x2 = x3 = 0;
sscanf(ln, "%d %d %d",
&x1, &x2, &x3);
pObjIndex->weight = x1;
pObjIndex->weight = UMAX(1, pObjIndex->weight);
pObjIndex->cost = x2;
pObjIndex->rent = x3; /* unused */
pObjIndex->level = fread_number_ld(fp);
}
if (area_version >= 1) {
switch (pObjIndex->item_type) {
case ITEM_PILL:
case ITEM_POTION:
case ITEM_SCROLL:
pObjIndex->value[1] = skill_lookup(fread_word(fp));
pObjIndex->value[2] = skill_lookup(fread_word(fp));
pObjIndex->value[3] = skill_lookup(fread_word(fp));
break;
case ITEM_STAFF:
case ITEM_WAND:
pObjIndex->value[3] = skill_lookup(fread_word(fp));
break;
case ITEM_SALVE:
pObjIndex->value[4] = skill_lookup(fread_word(fp));
pObjIndex->value[5] = skill_lookup(fread_word(fp));
break;
}
}
for (;;) {
letter = fread_letter(fp);
if (letter == 'A') {
AFFECT_DATA *paf;
CREATE(paf, AFFECT_DATA, 1);
paf->type = -1;
paf->duration = -1;
paf->location = fread_number(fp);
if (paf->location == APPLY_WEAPONSPELL
|| paf->location == APPLY_WEARSPELL
|| paf->location == APPLY_REMOVESPELL
|| paf->location == APPLY_STRIPSN
|| paf->location == APPLY_RECURRINGSPELL)
paf->modifier = slot_lookup(fread_number(fp));
else
paf->modifier = fread_number(fp);
xCLEAR_BITS(paf->bitvector);
LINK(paf, pObjIndex->first_affect, pObjIndex->last_affect,
next, prev);
top_affect++;
} else if (letter == 'E') {
EXTRA_DESCR_DATA *ed;
CREATE(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);
top_ed++;
} else if (letter == '>') {
ungetc(letter, fp);
oprog_read_programs(fp, pObjIndex);
} else {
ungetc(letter, fp);
break;
}
}
/*
* Translate spell "slot numbers" to internal "skill numbers."
*/
if (area_version == 0)
switch (pObjIndex->item_type) {
case ITEM_PILL:
case ITEM_POTION:
case ITEM_SCROLL:
pObjIndex->value[1] = slot_lookup(pObjIndex->value[1]);
pObjIndex->value[2] = slot_lookup(pObjIndex->value[2]);
pObjIndex->value[3] = slot_lookup(pObjIndex->value[3]);
break;
case ITEM_STAFF:
case ITEM_WAND:
pObjIndex->value[3] = slot_lookup(pObjIndex->value[3]);
break;
case ITEM_SALVE:
pObjIndex->value[4] = slot_lookup(pObjIndex->value[4]);
pObjIndex->value[5] = slot_lookup(pObjIndex->value[5]);
break;
}
if (!oldobj) {
iHash = vnum % MAX_KEY_HASH;
pObjIndex->next = obj_index_hash[iHash];
obj_index_hash[iHash] = pObjIndex;
top_obj_index++;
}
}
return;
}
/*
* Load a reset section.
*/
void
load_resets(AREA_DATA * tarea, FILE *fp)
{
char buf[MAX_STRING_LENGTH];
bool not01 = false;
int count = 0;
if (!tarea) {
bug("Load_resets: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
if (tarea->first_reset) {
if (fBootDb) {
RESET_DATA *rtmp;
bug("load_resets: WARNING: resets already exist for this area.");
for (rtmp = tarea->first_reset; rtmp; rtmp = rtmp->next)
++count;
} else {
/*
* Clean out the old resets
*/
sprintf(buf, "Cleaning resets: %s", tarea->name);
clean_resets(tarea);
}
}
for (;;) {
ROOM_INDEX_DATA *pRoomIndex;
EXIT_DATA *pexit;
char letter;
int extra, arg1, arg2, arg3;
if ((letter = fread_letter(fp)) == 'S')
break;
if (letter == '*') {
fread_to_eol(fp);
continue;
}
extra = fread_number(fp);
arg1 = fread_number(fp);
arg2 = fread_number(fp);
if (letter == 'E')
arg2 = 1;
arg3 = (letter == 'G' || letter == 'R')
? 0 : fread_number(fp);
fread_to_eol(fp);
++count;
/*
* Validate parameters.
* We're calling the index functions for the side effect.
*/
switch (letter) {
default:
bug("Load_resets: bad command '%c'.", letter);
if (fBootDb)
boot_log("Load_resets: %s (%d) bad command '%c'.", tarea->filename, count, letter);
return;
case 'M':
if (get_mob_index(arg1) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) 'M': mobile %d doesn't exist.",
tarea->filename, count, arg1);
if (get_room_index(arg3) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) 'M': room %d doesn't exist.",
tarea->filename, count, arg3);
break;
case 'O':
if (get_obj_index(arg1) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) '%c': object %d doesn't exist.",
tarea->filename, count, letter, arg1);
if (get_room_index(arg3) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) '%c': room %d doesn't exist.",
tarea->filename, count, letter, arg3);
break;
case 'P':
if (get_obj_index(arg1) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) '%c': object %d doesn't exist.", tarea->filename, count, letter, arg1);
if (arg3 > 0) {
if (get_obj_index(arg3) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) 'P': destination object %d doesn't exist.", tarea->filename, count, arg3);
} else {
if (extra > 1)
not01 = true;
}
break;
case 'G':
case 'E':
if (get_obj_index(arg1) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) '%c': object %d doesn't exist.",
tarea->filename, count, letter, arg1);
break;
case 'T':
break;
case 'H':
if (arg1 > 0)
if (get_obj_index(arg1) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) 'H': object %d doesn't exist.",
tarea->filename, count, arg1);
break;
case 'B':
switch (arg2 & BIT_RESET_TYPE_MASK) {
case BIT_RESET_DOOR:
{
int door;
pRoomIndex = get_room_index(arg1);
if (!pRoomIndex) {
bug("Load_resets: 'B': room %d doesn't exist.", arg1);
bug("Reset: %c %d %d %d %d", letter, extra, arg1, arg2,
arg3);
if (fBootDb)
boot_log("Load_resets: %s (%d) 'B': room %d doesn't exist.",
tarea->filename, count, arg1);
}
door = (arg2 & BIT_RESET_DOOR_MASK) >> BIT_RESET_DOOR_THRESHOLD;
if (!(pexit = get_exit(pRoomIndex, door))) {
bug("Load_resets: 'B': exit %d not door.", door);
bug("Reset: %c %d %d %d %d", letter, extra, arg1, arg2,
arg3);
if (fBootDb)
boot_log("Load_resets: %s (%d) 'B': exit %d not door.",
tarea->filename, count, door);
}
}
break;
case BIT_RESET_ROOM:
if (get_room_index(arg1) == NULL) {
bug("Load_resets: 'B': room %d doesn't exist.", arg1);
bug("Reset: %c %d %d %d %d", letter, extra, arg1, arg2,
arg3);
if (fBootDb)
boot_log("Load_resets: %s (%d) 'B': room %d doesn't exist.",
tarea->filename, count, arg1);
}
break;
case BIT_RESET_OBJECT:
if (arg1 > 0)
if (get_obj_index(arg1) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) 'B': object %d doesn't exist.",
tarea->filename, count, arg1);
break;
case BIT_RESET_MOBILE:
if (arg1 > 0)
if (get_mob_index(arg1) == NULL && fBootDb)
boot_log("Load_resets: %s (%d) 'B': mobile %d doesn't exist.",
tarea->filename, count, arg1);
break;
default:
boot_log("Load_resets: %s (%d) 'B': bad type flag (%d).",
tarea->filename, count, arg2 & BIT_RESET_TYPE_MASK);
break;
}
break;
case 'D':
pRoomIndex = get_room_index(arg1);
if (!pRoomIndex) {
bug("Load_resets: 'D': room %d doesn't exist.", arg1);
bug("Reset: %c %d %d %d %d", letter, extra, arg1, arg2,
arg3);
if (fBootDb)
boot_log("Load_resets: %s (%d) 'D': room %d doesn't exist.",
tarea->filename, count, arg1);
break;
}
if (arg2 < 0
|| arg2 > MAX_DIR + 1
|| (pexit = get_exit(pRoomIndex, arg2)) == NULL
|| !IS_SET(pexit->exit_info, EX_ISDOOR)) {
bug("Load_resets: 'D': exit %d not door.", arg2);
bug("Reset: %c %d %d %d %d", letter, extra, arg1, arg2,
arg3);
if (fBootDb)
boot_log("Load_resets: %s (%d) 'D': exit %d not door.",
tarea->filename, count, arg2);
}
if (arg3 < 0 || arg3 > 2) {
bug("Load_resets: 'D': bad 'locks': %d.", arg3);
if (fBootDb)
boot_log("Load_resets: %s (%d) 'D': bad 'locks': %d.",
tarea->filename, count, arg3);
}
break;
case 'R':
pRoomIndex = get_room_index(arg1);
if (!pRoomIndex && fBootDb)
boot_log("Load_resets: %s (%d) 'R': room %d doesn't exist.",
tarea->filename, count, arg1);
if (arg2 < 0 || arg2 > 10) {
bug("Load_resets: 'R': bad exit %d.", arg2);
if (fBootDb)
boot_log("Load_resets: %s (%d) 'R': bad exit %d.",
tarea->filename, count, arg2);
break;
}
break;
}
/* finally, add the reset */
add_reset(tarea, letter, extra, arg1, arg2, arg3);
}
if (!not01)
renumber_put_resets(tarea);
return;
}
/*
* Load a room section.
*/
void
load_rooms(AREA_DATA * tarea, FILE *fp)
{
ROOM_INDEX_DATA *pRoomIndex;
char buf[MAX_STRING_LENGTH];
char *ln;
if (!tarea) {
bug("Load_rooms: no #AREA seen yet.");
shutdown_mud("No #AREA");
exit(1);
}
for (;;) {
int vnum;
char letter;
int door;
int iHash;
bool tmpBootDb;
bool oldroom;
int x1, x2, x3, x4, x5, x6;
letter = fread_letter(fp);
if (letter != '#') {
bug("Load_rooms: # not found.");
if (fBootDb) {
shutdown_mud("# not found");
exit(1);
} else
return;
}
vnum = fread_number(fp);
if (vnum == 0)
break;
tmpBootDb = fBootDb;
fBootDb = false;
if (get_room_index(vnum) != NULL) {
if (tmpBootDb) {
bug("Load_rooms: vnum %d duplicated.", vnum);
shutdown_mud("duplicate vnum");
exit(1);
} else {
pRoomIndex = get_room_index(vnum);
sprintf(buf, "Cleaning room: %d", vnum);
clean_room(pRoomIndex);
oldroom = true;
}
} else {
oldroom = false;
CREATE(pRoomIndex, ROOM_INDEX_DATA, 1);
pRoomIndex->first_person = NULL;
pRoomIndex->last_person = NULL;
pRoomIndex->first_content = NULL;
pRoomIndex->last_content = NULL;
}
fBootDb = tmpBootDb;
pRoomIndex->area = tarea;
pRoomIndex->vnum = vnum;
pRoomIndex->first_extradesc = NULL;
pRoomIndex->last_extradesc = NULL;
if (fBootDb) {
if (!tarea->low_r_vnum)
tarea->low_r_vnum = vnum;
if (vnum > tarea->hi_r_vnum)
tarea->hi_r_vnum = vnum;
}
pRoomIndex->name = fread_string(fp);
pRoomIndex->description = fread_string_wspace(fp);
/* Area number fread_number( fp ); */
x1 = x2 = x3 = x4 = x5 = x6 = 0;
fread_number(fp);
pRoomIndex->room_flags = fread_bitvector(fp);
ln = fread_line(fp);
sscanf(ln, "%d %d %d %d", &x3, &x4, &x5, &x6);
pRoomIndex->sector_type = x3;
pRoomIndex->tele_delay = x4;
pRoomIndex->tele_vnum = x5;
pRoomIndex->tunnel = x6;
if (pRoomIndex->sector_type < 0 || pRoomIndex->sector_type == SECT_MAX) {
bug("Fread_rooms: vnum %d has bad sector_type %d.", vnum,
pRoomIndex->sector_type);
pRoomIndex->sector_type = 1;
}
pRoomIndex->light = 0;
pRoomIndex->first_exit = NULL;
pRoomIndex->last_exit = NULL;
for (;;) {
letter = fread_letter(fp);
if (letter == 'S')
break;
if (letter == 'D') {
EXIT_DATA *pexit;
int locks;
door = fread_number(fp);
if (door < 0 || door > 10) {
bug("Fread_rooms: vnum %d has bad door number %d.", vnum,
door);
if (fBootDb)
exit(1);
} else {
pexit = make_exit(pRoomIndex, NULL, door);
pexit->description = fread_string(fp);
pexit->keyword = fread_string(fp);
pexit->exit_info = 0;
ln = fread_line(fp);
x1 = x2 = x3 = x4 = x5 = x6 = 0;
sscanf(ln, "%d %d %d %d %d %d",
&x1, &x2, &x3, &x4, &x5, &x6);
locks = x1;
pexit->key = x2;
pexit->vnum = x3;
pexit->vdir = door;
pexit->distance = x4;
pexit->pulltype = x5;
pexit->pull = x6;
switch (locks) {
case 1:
pexit->exit_info = EX_ISDOOR;
break;
case 2:
pexit->exit_info = EX_ISDOOR | EX_PICKPROOF;
break;
default:
pexit->exit_info = locks;
}
}
} else if (letter == 'E') {
EXTRA_DESCR_DATA *ed;
CREATE(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);
top_ed++;
} else if (letter == 'M') { /* maps */
MAP_DATA *map;
MAP_INDEX_DATA *map_index;
int i , j;
CREATE(map, MAP_DATA, 1);
map->vnum = fread_number(fp);
map->x = fread_number(fp);
map->y = fread_number(fp);
map->entry = fread_letter(fp);
pRoomIndex->map = map;
if ((map_index = get_map_index(map->vnum)) == NULL) {
CREATE(map_index, MAP_INDEX_DATA, 1);
map_index->vnum = map->vnum;
map_index->next = first_map;
first_map = map_index;
for (i = 0; i < 49; i++) {
for (j = 0; j < 79; j++) {
map_index->map_of_vnums[i][j] = -1;
/*
* map_index->map_of_
* ptrs[i][j] =
* NULL;
*/
}
}
}
if ((map->y < 0) || (map->y > 48)) {
bug("Map y coord out of range. Room %d\n\r", map->y);
}
if ((map->x < 0) || (map->x > 78)) {
bug("Map x coord out of range. Room %d\n\r", map->x);
}
if ((map->x > 0)
&& (map->x < 80)
&& (map->y > 0)
&& (map->y < 48))
map_index->map_of_vnums[map->y][map->x] = pRoomIndex->vnum;
} else if (letter == '>') {
ungetc(letter, fp);
rprog_read_programs(fp, pRoomIndex);
} else {
bug("Load_rooms: vnum %d has flag '%c' not 'DES'.", vnum,
letter);
shutdown_mud("Room flag not DES");
exit(1);
}
}
if (!oldroom) {
iHash = vnum % MAX_KEY_HASH;
pRoomIndex->next = room_index_hash[iHash];
room_index_hash[iHash] = pRoomIndex;
top_room++;
}
}
return;
}
/*
* Load a shop section.
*/
void
load_shops(AREA_DATA * tarea, FILE *fp)
{
SHOP_DATA *pShop;
for (;;) {
MOB_INDEX_DATA *pMobIndex;
int iTrade;
CREATE(pShop, SHOP_DATA, 1);
pShop->keeper = fread_number(fp);
if (pShop->keeper == 0) {
DISPOSE(pShop);
break;
}
for (iTrade = 0; iTrade < MAX_TRADE; iTrade++)
pShop->buy_type[iTrade] = fread_number(fp);
pShop->profit_buy = fread_number(fp);
pShop->profit_sell = fread_number(fp);
pShop->profit_buy = URANGE(pShop->profit_sell + 5, pShop->profit_buy, 1000);
pShop->profit_sell = URANGE(0, pShop->profit_sell, pShop->profit_buy - 5);
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;
if (!first_shop)
first_shop = pShop;
else
last_shop->next = pShop;
pShop->next = NULL;
pShop->prev = last_shop;
last_shop = pShop;
top_shop++;
}
return;
}
/*
* Load a repair shop section. -Thoric
*/
void
load_repairs(AREA_DATA * tarea, FILE *fp)
{
REPAIR_DATA *rShop;
for (;;) {
MOB_INDEX_DATA *pMobIndex;
int iFix;
CREATE(rShop, REPAIR_DATA, 1);
rShop->keeper = fread_number(fp);
if (rShop->keeper == 0) {
DISPOSE(rShop);
break;
}
for (iFix = 0; iFix < MAX_FIX; iFix++)
rShop->fix_type[iFix] = fread_number(fp);
rShop->profit_fix = fread_number(fp);
rShop->shop_type = fread_number(fp);
rShop->open_hour = fread_number(fp);
rShop->close_hour = fread_number(fp);
fread_to_eol(fp);
pMobIndex = get_mob_index(rShop->keeper);
pMobIndex->rShop = rShop;
if (!first_repair)
first_repair = rShop;
else
last_repair->next = rShop;
rShop->next = NULL;
rShop->prev = last_repair;
last_repair = rShop;
top_repair++;
}
return;
}
/*
* Load spec proc declarations.
*/
void
load_specials(AREA_DATA * tarea, FILE *fp)
{
for (;;) {
MOB_INDEX_DATA *pMobIndex;
char letter;
switch (letter = fread_letter(fp)) {
default:
bug("Load_specials: letter '%c' not *MS.", letter);
exit(1);
case 'S':
return;
case '*':
break;
case 'M':
pMobIndex = get_mob_index(fread_number(fp));
pMobIndex->spec_fun = spec_lookup(fread_word(fp));
if (pMobIndex->spec_fun == 0) {
bug("Load_specials: 'M': vnum %d.", pMobIndex->vnum);
exit(1);
}
break;
}
fread_to_eol(fp);
}
}
/*
* Load soft / hard area ranges.
*/
void
load_ranges(AREA_DATA * tarea, FILE *fp)
{
int x1, x2, x3, x4;
char *ln;
if (!tarea) {
bug("Load_ranges: no #AREA seen yet.");
shutdown_mud("No #AREA");
exit(1);
}
for (;;) {
ln = fread_line(fp);
if (ln[0] == '$')
break;
x1 = x2 = x3 = x4 = 0;
sscanf(ln, "%d %d %d %d",
&x1, &x2, &x3, &x4);
tarea->low_soft_range = x1;
tarea->hi_soft_range = x2;
tarea->low_hard_range = x3;
tarea->hi_hard_range = x4;
}
return;
}
/*
* Load climate information for the area
* Last modified: July 13, 1997
* Fireblade
*/
void
load_climate(AREA_DATA * tarea, FILE *fp)
{
if (!tarea) {
bug("load_climate: no #AREA seen yet");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
tarea->weather->climate_temp = fread_number(fp);
tarea->weather->climate_precip = fread_number(fp);
tarea->weather->climate_wind = fread_number(fp);
return;
}
/*
* Load data for a neghboring weather system
* Last modified: July 13, 1997
* Fireblade
*/
void
load_neighbor(AREA_DATA * tarea, FILE *fp)
{
NEIGHBOR_DATA *new;
if (!tarea) {
bug("load_neighbor: no #AREA seen yet.");
if (fBootDb) {
shutdown_mud("No #AREA");
exit(1);
} else
return;
}
CREATE(new, NEIGHBOR_DATA, 1);
new->next = NULL;
new->prev = NULL;
new->address = NULL;
new->name = fread_string(fp);
LINK(new,
tarea->weather->first_neighbor,
tarea->weather->last_neighbor,
next, prev);
return;
}
/*
* Go through all areas, and set up initial economy based on mob
* levels and gold
*/
void
initialize_economy(void)
{
AREA_DATA *tarea;
int low_random = 10000;
//10 k
int high_random = 10000000;
//10 m
for (tarea = first_area; tarea; tarea = tarea->next) {
/* skip area if they already got some gold */
if (tarea->economy > low_random)
continue;
boost_economy(tarea, number_range(low_random, high_random));
}
}
/*
* Translate all room exits from virtual to real.
* Has to be done after all rooms are read in.
* Check for bad reverse exits.
*/
void
fix_exits(void)
{
ROOM_INDEX_DATA *pRoomIndex;
EXIT_DATA *pexit, *pexit_next, *rev_exit;
int iHash;
for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) {
for (pRoomIndex = room_index_hash[iHash];
pRoomIndex;
pRoomIndex = pRoomIndex->next) {
bool fexit;
fexit = false;
for (pexit = pRoomIndex->first_exit; pexit; pexit = pexit_next) {
pexit_next = pexit->next;
pexit->rvnum = pRoomIndex->vnum;
if (pexit->vnum <= 0
|| (pexit->to_room = get_room_index(pexit->vnum)) == NULL) {
if (fBootDb)
boot_log("Fix_exits: room %d, exit %s leads to bad vnum (%d)",
pRoomIndex->vnum, dir_name[pexit->vdir], pexit->vnum);
bug("Deleting %s exit in room %d", dir_name[pexit->vdir],
pRoomIndex->vnum);
extract_exit(pRoomIndex, pexit);
} else
fexit = true;
}
if (!fexit)
xSET_BIT(pRoomIndex->room_flags, ROOM_NO_MOB);
}
}
/* Set all the rexit pointers -Thoric */
for (iHash = 0; iHash < MAX_KEY_HASH; iHash++) {
for (pRoomIndex = room_index_hash[iHash];
pRoomIndex;
pRoomIndex = pRoomIndex->next) {
for (pexit = pRoomIndex->first_exit; pexit; pexit = pexit->next) {
if (pexit->to_room && !pexit->rexit) {
rev_exit = get_exit_to(pexit->to_room, rev_dir[pexit->vdir], pRoomIndex->vnum);
if (rev_exit) {
pexit->rexit = rev_exit;
rev_exit->rexit = pexit;
}
}
}
}
}
return;
}
/*
* Get diku-compatable exit by number -Thoric
*/
EXIT_DATA *
get_exit_number(ROOM_INDEX_DATA * room, int xit)
{
EXIT_DATA *pexit;
int count;
count = 0;
for (pexit = room->first_exit; pexit; pexit = pexit->next)
if (++count == xit)
return pexit;
return NULL;
}
/*
* (prelude...) This is going to be fun... NOT!
* (conclusion) QSort is f*cked!
*/
int
exit_comp(EXIT_DATA ** xit1, EXIT_DATA ** xit2)
{
int d1, d2;
d1 = (*xit1)->vdir;
d2 = (*xit2)->vdir;
if (d1 < d2)
return -1;
if (d1 > d2)
return 1;
return 0;
}
void
sort_exits(ROOM_INDEX_DATA * room)
{
EXIT_DATA *pexit; /* *texit *//* Unused */
EXIT_DATA *exits[MAX_REXITS];
int x , nexits;
nexits = 0;
for (pexit = room->first_exit; pexit; pexit = pexit->next) {
exits[nexits++] = pexit;
if (nexits > MAX_REXITS) {
bug("sort_exits: more than %d exits in room... fatal", nexits);
return;
}
}
qsort(&exits[0], nexits, sizeof(EXIT_DATA *),
(int (*) (const void *, const void *)) exit_comp);
for (x = 0; x < nexits; x++) {
if (x > 0)
exits[x]->prev = exits[x - 1];
else {
exits[x]->prev = NULL;
room->first_exit = exits[x];
}
if (x >= (nexits - 1)) {
exits[x]->next = NULL;
room->last_exit = exits[x];
} else
exits[x]->next = exits[x + 1];
}
}
void
randomize_exits(ROOM_INDEX_DATA * room, sh_int maxdir)
{
EXIT_DATA *pexit;
int nexits, /* maxd, */ d0, d1, count, door; /* Maxd unused */
int vdirs[MAX_REXITS];
nexits = 0;
for (pexit = room->first_exit; pexit; pexit = pexit->next)
vdirs[nexits++] = pexit->vdir;
for (d0 = 0; d0 < nexits; d0++) {
if (vdirs[d0] > maxdir)
continue;
count = 0;
while (vdirs[(d1 = number_range(d0, nexits - 1))] > maxdir
|| ++count > 5);
if (vdirs[d1] > maxdir)
continue;
door = vdirs[d0];
vdirs[d0] = vdirs[d1];
vdirs[d1] = door;
}
count = 0;
for (pexit = room->first_exit; pexit; pexit = pexit->next)
pexit->vdir = vdirs[count++];
sort_exits(room);
}
/*
* Repopulate areas periodically.
*/
void
area_update(void)
{
AREA_DATA *pArea;
for (pArea = first_area; pArea; pArea = pArea->next) {
CHAR_DATA *pch;
int reset_age = pArea->reset_frequency ? pArea->reset_frequency : 15;
if ((reset_age == -1 && pArea->age == -1)
|| ++pArea->age < (reset_age - 1))
continue;
/*
* Check for PC's.
*/
if (pArea->nplayer > 0 && pArea->age == (reset_age - 1)) {
char buf[MAX_STRING_LENGTH];
/* Rennard */
if (pArea->resetmsg)
sprintf(buf, "%s\n\r", pArea->resetmsg);
else
strcpy(buf, "You hear some squeaking sounds...\n\r");
for (pch = first_char; pch; pch = pch->next) {
if (!IS_NPC(pch)
&& IS_AWAKE(pch)
&& pch->in_room
&& pch->in_room->area == pArea) {
set_char_color(AT_RESET, pch);
send_to_char(buf, pch);
}
}
}
/*
* Check age and reset.
* Note: Mud Academy resets every 3 minutes (not 15).
*/
if (pArea->nplayer == 0 || pArea->age >= reset_age) {
ROOM_INDEX_DATA *pRoomIndex;
fprintf(stderr, "Resetting: %s\n", pArea->filename);
reset_area(pArea);
if (reset_age == -1)
pArea->age = -1;
else
pArea->age = number_range(0, reset_age / 5);
pRoomIndex = get_room_index(ROOM_VNUM_SCHOOL);
if (pRoomIndex != NULL && pArea == pRoomIndex->area
&& pArea->reset_frequency == 0)
pArea->age = 15 - 3;
}
}
return;
}
/*
* Create an instance of a mobile.
*/
CHAR_DATA *
create_mobile(MOB_INDEX_DATA * pMobIndex)
{
CHAR_DATA *mob;
if (!pMobIndex) {
bug("Create_mobile: NULL pMobIndex.");
exit(1);
}
CREATE(mob, CHAR_DATA, 1);
clear_char(mob);
mob->pIndexData = pMobIndex;
mob->mob_serial = -1;
mob->editor = NULL;
mob->name = QUICKLINK(pMobIndex->player_name);
mob->short_descr = QUICKLINK(pMobIndex->short_descr);
mob->long_descr = QUICKLINK(pMobIndex->long_descr);
mob->description = QUICKLINK(pMobIndex->description);
mob->spec_fun = pMobIndex->spec_fun;
mob->mpscriptpos = 0;
mob->level = number_fuzzy(pMobIndex->level);
mob->act = pMobIndex->act;
if (xIS_SET(mob->act, ACT_MOBINVIS))
mob->mobinvis = mob->level;
mob->affected_by = pMobIndex->affected_by;
mob->alignment = pMobIndex->alignment;
mob->sex = pMobIndex->sex;
if (pMobIndex->ac)
mob->armor = pMobIndex->ac;
else
mob->armor = 100;
if (!pMobIndex->hitnodice)
mob->max_hit = (mob->perm_con + 100);
mob->hit = mob->max_hit;
/* lets put things back the way they used to be! -Thoric */
mob->gold = pMobIndex->gold;
if (mob->gold > -1)
bug("mob(%d)zeni not -1", pMobIndex->vnum);
mob->exp = pMobIndex->exp;
/* Add's some varity to mobs power level -Goku 09.25.04 */
if (xIS_SET(mob->act, ACT_RANDOMIZE_PL)) {
switch (number_range(1, 10)) {
case 1:
mob->exp = (double) number_range(7500, 9000) / 10000 * mob->exp;
break;
case 6:
case 7:
mob->exp = (double) number_range(11000, 12000) / 10000 * mob->exp;
break;
case 8:
mob->exp = (double) number_range(12000, 13000) / 10000 * mob->exp;
break;
case 9:
mob->exp = (double) number_range(13000, 14000) / 10000 * mob->exp;
break;
case 10:
mob->exp = (double) number_range(14000, 15000) / 10000 * mob->exp;
break;
default:
mob->exp = (double) number_range(9000, 11000) / 10000 * mob->exp;
break;
}
}
mob->pl = mob->exp;
// new method of setting the mob 's mana/energy values
if (mob->exp < 1000000) {
mob->mana = 5000;
mob->max_mana = 5000;
} else if (mob->exp < 10000000) {
mob->mana = 10000;
mob->max_mana = 10000;
} else if (mob->exp < 100000000) {
mob->mana = 15000;
mob->max_mana = 15000;
} else if (mob->exp < 1000000000) {
mob->mana = 25000;
mob->max_mana = 25000;
} else if (mob->exp < 10000000000ULL) {
mob->mana = 50000;
mob->max_mana = 50000;
} else {
mob->mana = 99999;
mob->max_mana = 99999;
}
mob->worth = pMobIndex->worth;
mob->position = pMobIndex->position;
mob->defposition = pMobIndex->defposition;
mob->barenumdie = pMobIndex->damnodice;
mob->baresizedie = pMobIndex->damsizedice;
mob->mobthac0 = pMobIndex->mobthac0;
mob->hitplus = pMobIndex->hitplus;
mob->damplus = pMobIndex->damplus;
mob->perm_str = pMobIndex->perm_str;
mob->perm_dex = pMobIndex->perm_dex;
mob->perm_int = pMobIndex->perm_int;
mob->perm_con = pMobIndex->perm_con;
mob->perm_lck = pMobIndex->perm_lck;
mob->hitroll = pMobIndex->hitroll;
mob->damroll = pMobIndex->damroll;
mob->race = pMobIndex->race;
mob->class = pMobIndex->class;
mob->xflags = pMobIndex->xflags;
mob->saving_poison_death = pMobIndex->saving_poison_death;
mob->saving_wand = pMobIndex->saving_wand;
mob->saving_para_petri = pMobIndex->saving_para_petri;
mob->saving_breath = pMobIndex->saving_breath;
mob->saving_spell_staff = pMobIndex->saving_spell_staff;
mob->height = pMobIndex->height;
mob->weight = pMobIndex->weight;
mob->resistant = pMobIndex->resistant;
mob->immune = pMobIndex->immune;
mob->susceptible = pMobIndex->susceptible;
mob->attacks = pMobIndex->attacks;
mob->defenses = pMobIndex->defenses;
mob->numattacks = pMobIndex->numattacks;
mob->speaks = pMobIndex->speaks;
mob->speaking = pMobIndex->speaking;
/*
* Perhaps add this to the index later --Shaddai
*/
xCLEAR_BITS(mob->no_affected_by);
mob->no_resistant = 0;
mob->no_immune = 0;
mob->no_susceptible = 0;
/*
* Insert in list.
*/
add_char(mob);
pMobIndex->count++;
nummobsloaded++;
return mob;
}
OBJ_DATA *
create_object(OBJ_INDEX_DATA * pObjIndex, int level)
{
OBJ_DATA *obj;
char originText[MAX_STRING_LENGTH];
if (!pObjIndex) {
bug("Create_object: NULL pObjIndex.");
exit(1);
}
CREATE(obj, OBJ_DATA, 1);
obj->pIndexData = pObjIndex;
obj->in_room = NULL;
obj->level = pObjIndex->level;
obj->wear_loc = -1;
obj->count = 1;
cur_obj_serial = UMAX((cur_obj_serial + 1) & (BV30 - 1), 1);
obj->serial = obj->pIndexData->serial = cur_obj_serial;
obj->name = QUICKLINK(pObjIndex->name);
obj->short_descr = QUICKLINK(pObjIndex->short_descr);
obj->description = QUICKLINK(pObjIndex->description);
obj->action_desc = QUICKLINK(pObjIndex->action_desc);
obj->item_type = pObjIndex->item_type;
obj->extra_flags = pObjIndex->extra_flags;
obj->wear_flags = pObjIndex->wear_flags;
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->weight = pObjIndex->weight;
obj->cost = pObjIndex->cost;
sprintf(originText, "%d, UNKNOWN", ORIGIN_DBSCODE);
obj->origin = STRALLOC(originText);
/*
* Mess with object properties.
*/
switch (obj->item_type) {
default:
bug("Read_object: vnum %d bad type.", pObjIndex->vnum);
bug("------------------------> %d ", obj->item_type);
break;
case ITEM_LIGHT:
case ITEM_SCOUTER:
case ITEM_DRAGONBALL:
case ITEM_DRAGONRADAR:
case ITEM_ARMOR:
case ITEM_TREASURE:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_CONTAINER:
case ITEM_DRINK_CON:
case ITEM_KEY:
case ITEM_KEYRING:
case ITEM_ODOR:
case ITEM_CHANCE:
break;
case ITEM_COOK:
case ITEM_FOOD:
/*
* optional food condition (rotting food) -Thoric
* value1 is the max condition of the food
* value4 is the optional initial condition
*/
if (obj->value[4])
obj->timer = obj->value[4];
else
obj->timer = obj->value[1];
break;
case ITEM_BOAT:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_FOUNTAIN:
case ITEM_BLOOD:
case ITEM_BLOODSTAIN:
case ITEM_SCRAPS:
case ITEM_PIPE:
case ITEM_HERB_CON:
case ITEM_HERB:
case ITEM_INCENSE:
case ITEM_FIRE:
case ITEM_BOOK:
case ITEM_SWITCH:
case ITEM_LEVER:
case ITEM_PULLCHAIN:
case ITEM_BUTTON:
case ITEM_DIAL:
case ITEM_RUNE:
case ITEM_RUNEPOUCH:
case ITEM_MATCH:
case ITEM_TRAP:
case ITEM_MAP:
case ITEM_PORTAL:
case ITEM_PAPER:
case ITEM_PEN:
case ITEM_TINDER:
case ITEM_LOCKPICK:
case ITEM_SPIKE:
case ITEM_DISEASE:
case ITEM_OIL:
case ITEM_FUEL:
case ITEM_QUIVER:
case ITEM_SHOVEL:
break;
case ITEM_SALVE:
obj->value[3] = number_fuzzy(obj->value[3]);
break;
case ITEM_SCROLL:
obj->value[0] = number_fuzzy(obj->value[0]);
break;
case ITEM_WAND:
case ITEM_STAFF:
obj->value[0] = number_fuzzy(obj->value[0]);
obj->value[1] = number_fuzzy(obj->value[1]);
obj->value[2] = obj->value[1];
break;
case ITEM_WEAPON:
case ITEM_MISSILE_WEAPON:
case ITEM_PROJECTILE:
if (obj->value[1] && obj->value[2])
obj->value[2] *= obj->value[1];
else {
obj->value[1] = number_fuzzy(number_fuzzy(1 * level / 4 + 2));
obj->value[2] = number_fuzzy(number_fuzzy(3 * level / 4 + 6));
}
if (obj->value[0] == 0)
obj->value[0] = INIT_WEAPON_CONDITION;
break;
case ITEM_POTION:
case ITEM_PILL:
obj->value[0] = number_fuzzy(number_fuzzy(obj->value[0]));
break;
case ITEM_MONEY:
obj->value[0] = obj->cost;
if (obj->value[0] == 0)
obj->value[0] = 1;
break;
}
LINK(obj, first_object, last_object, next, prev);
++pObjIndex->count;
++numobjsloaded;
++physicalobjects;
return obj;
}
/*
* Create an instance of an object.
*/
OBJ_DATA *
create_object_new(OBJ_INDEX_DATA * pObjIndex, int level, int originCode, char *originNote)
{
OBJ_DATA *obj;
char originText[MAX_STRING_LENGTH];
if (!pObjIndex) {
bug("Create_object: NULL pObjIndex.");
exit(1);
}
CREATE(obj, OBJ_DATA, 1);
obj->pIndexData = pObjIndex;
obj->in_room = NULL;
obj->level = pObjIndex->level;
obj->wear_loc = -1;
obj->count = 1;
cur_obj_serial = UMAX((cur_obj_serial + 1) & (BV30 - 1), 1);
obj->serial = obj->pIndexData->serial = cur_obj_serial;
obj->name = QUICKLINK(pObjIndex->name);
obj->short_descr = QUICKLINK(pObjIndex->short_descr);
obj->description = QUICKLINK(pObjIndex->description);
obj->action_desc = QUICKLINK(pObjIndex->action_desc);
obj->item_type = pObjIndex->item_type;
obj->extra_flags = pObjIndex->extra_flags;
obj->wear_flags = pObjIndex->wear_flags;
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->weight = pObjIndex->weight;
obj->cost = pObjIndex->cost;
sprintf(originText, "%d, %s", originCode, originNote);
obj->origin = STRALLOC(originText);
/*
* Mess with object properties.
*/
switch (obj->item_type) {
default:
bug("Read_object: vnum %d bad type.", pObjIndex->vnum);
bug("------------------------> %d ", obj->item_type);
break;
case ITEM_LIGHT:
case ITEM_SCOUTER:
case ITEM_DRAGONBALL:
case ITEM_DRAGONRADAR:
case ITEM_ARMOR:
case ITEM_TREASURE:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_CONTAINER:
case ITEM_DRINK_CON:
case ITEM_KEY:
case ITEM_KEYRING:
case ITEM_ODOR:
case ITEM_CHANCE:
break;
case ITEM_COOK:
case ITEM_FOOD:
/*
* optional food condition (rotting food) -Thoric
* value1 is the max condition of the food
* value4 is the optional initial condition
*/
if (obj->value[4])
obj->timer = obj->value[4];
else
obj->timer = obj->value[1];
break;
case ITEM_BOAT:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_FOUNTAIN:
case ITEM_BLOOD:
case ITEM_BLOODSTAIN:
case ITEM_SCRAPS:
case ITEM_PIPE:
case ITEM_HERB_CON:
case ITEM_HERB:
case ITEM_INCENSE:
case ITEM_FIRE:
case ITEM_BOOK:
case ITEM_SWITCH:
case ITEM_LEVER:
case ITEM_PULLCHAIN:
case ITEM_BUTTON:
case ITEM_DIAL:
case ITEM_RUNE:
case ITEM_RUNEPOUCH:
case ITEM_MATCH:
case ITEM_TRAP:
case ITEM_MAP:
case ITEM_PORTAL:
case ITEM_PAPER:
case ITEM_PEN:
case ITEM_TINDER:
case ITEM_LOCKPICK:
case ITEM_SPIKE:
case ITEM_DISEASE:
case ITEM_OIL:
case ITEM_FUEL:
case ITEM_QUIVER:
case ITEM_SHOVEL:
break;
case ITEM_SALVE:
obj->value[3] = number_fuzzy(obj->value[3]);
break;
case ITEM_SCROLL:
obj->value[0] = number_fuzzy(obj->value[0]);
break;
case ITEM_WAND:
case ITEM_STAFF:
obj->value[0] = number_fuzzy(obj->value[0]);
obj->value[1] = number_fuzzy(obj->value[1]);
obj->value[2] = obj->value[1];
break;
case ITEM_WEAPON:
case ITEM_MISSILE_WEAPON:
case ITEM_PROJECTILE:
if (obj->value[1] && obj->value[2])
obj->value[2] *= obj->value[1];
else {
obj->value[1] = number_fuzzy(number_fuzzy(1 * level / 4 + 2));
obj->value[2] = number_fuzzy(number_fuzzy(3 * level / 4 + 6));
}
if (obj->value[0] == 0)
obj->value[0] = INIT_WEAPON_CONDITION;
break;
case ITEM_POTION:
case ITEM_PILL:
obj->value[0] = number_fuzzy(number_fuzzy(obj->value[0]));
break;
case ITEM_MONEY:
obj->value[0] = obj->cost;
if (obj->value[0] == 0)
obj->value[0] = 1;
break;
}
LINK(obj, first_object, last_object, next, prev);
++pObjIndex->count;
++numobjsloaded;
++physicalobjects;
return obj;
}
/*
* Clear a new character.
*/
void
clear_char(CHAR_DATA * ch)
{
ch->editor = NULL;
ch->hunting = NULL;
ch->fearing = NULL;
ch->hating = NULL;
ch->mob_serial = -1;
ch->name = NULL;
ch->short_descr = NULL;
ch->long_descr = NULL;
ch->next = NULL;
ch->prev = NULL;
ch->reply = NULL;
ch->retell = NULL;
ch->first_carrying = NULL;
ch->last_carrying = NULL;
ch->next_in_room = NULL;
ch->prev_in_room = NULL;
ch->fighting = NULL;
ch->switched = NULL;
ch->first_affect = NULL;
ch->last_affect = NULL;
ch->prev_cmd = NULL; /* maps */
ch->last_cmd = NULL;
ch->dest_buf = NULL;
ch->alloc_ptr = NULL;
ch->spare_ptr = NULL;
ch->mount = NULL;
ch->morph = NULL;
xCLEAR_BITS(ch->affected_by);
ch->logon = current_time;
ch->armor = 100;
ch->position = POS_STANDING;
ch->practice = 2;
ch->max_prac = 2;
ch->worth = 1;
ch->train = 4;
ch->max_train = 4;
ch->hit = 100;
ch->max_hit = 100;
ch->mana = 100;
ch->max_mana = 100;
ch->max_energy = 1;
ch->move = 100;
ch->max_move = 100;
ch->powerup = 0;
ch->height = 72;
ch->weight = 180;
ch->xflags = 0;
ch->race = 0;
ch->class = 0;
ch->speaking = LANG_COMMON;
ch->speaks = LANG_COMMON;
ch->barenumdie = 2;
ch->baresizedie = 4;
ch->substate = 0;
ch->tempnum = 0;
ch->perm_str = 10;
ch->perm_dex = 10;
ch->perm_int = 10;
ch->perm_con = 10;
ch->perm_lck = 0;
ch->mod_str = 0;
ch->mod_dex = 0;
ch->mod_int = 0;
ch->mod_con = 0;
ch->mod_lck = 0;
ch->teaching = NULL;
ch->tmystic = 0;
ch->pagelen = 24; /* BUILD INTERFACE */
ch->inter_page = NO_PAGE; /* BUILD INTERFACE */
ch->inter_type = NO_TYPE; /* BUILD INTERFACE */
ch->inter_editing = NULL; /* BUILD INTERFACE */
ch->inter_editing_vnum = -1; /* BUILD INTERFACE */
ch->inter_substate = SUB_NORTH; /* BUILD INTERFACE */
}
/*
* Free a character.
*/
void
free_char(CHAR_DATA * ch)
{
OBJ_DATA *obj;
AFFECT_DATA *paf;
TIMER *timer;
MPROG_ACT_LIST *mpact, *mpact_next;
NOTE_DATA *comments, *comments_next;
if (!ch) {
bug("Free_char: null ch!");
return;
}
if (ch->desc)
bug("Free_char: char still has descriptor.");
while ((obj = ch->last_carrying) != NULL)
extract_obj(obj);
while ((paf = ch->last_affect) != NULL)
affect_remove(ch, paf);
while ((timer = ch->first_timer) != NULL)
extract_timer(ch, timer);
if (ch->editor)
stop_editing(ch);
STRFREE(ch->name);
STRFREE(ch->short_descr);
STRFREE(ch->long_descr);
STRFREE(ch->description);
if (ch->inter_editing)
DISPOSE(ch->inter_editing);
stop_hunting(ch);
stop_hating(ch);
stop_fearing(ch);
free_fight(ch);
if (ch->pnote)
free_note(ch->pnote);
if (ch->pcdata) {
IGNORE_DATA *temp, *next;
/* free up memory allocated to stored ignored names */
for (temp = ch->pcdata->first_ignored; temp; temp = next) {
next = temp->next;
UNLINK(temp, ch->pcdata->first_ignored,
ch->pcdata->last_ignored, next, prev);
STRFREE(temp->name);
DISPOSE(temp);
}
STRFREE(ch->pcdata->filename);
STRFREE(ch->pcdata->deity_name);
STRFREE(ch->pcdata->clan_name);
STRFREE(ch->pcdata->council_name);
DISPOSE(ch->pcdata->pwd); /* no hash */
DISPOSE(ch->pcdata->bamfin); /* no hash */
DISPOSE(ch->pcdata->bamfout); /* no hash */
DISPOSE(ch->pcdata->rank);
if (ch->level >= LEVEL_IMMORTAL && ch->pcdata->pretitle
&& ch->pcdata->pretitle[0] != '\0')
STRFREE(ch->pcdata->pretitle);
STRFREE(ch->pcdata->title);
STRFREE(ch->pcdata->description1);
STRFREE(ch->pcdata->description2);
STRFREE(ch->pcdata->description3);
STRFREE(ch->pcdata->description4);
STRFREE(ch->pcdata->description5);
STRFREE(ch->pcdata->bio);
DISPOSE(ch->pcdata->bestowments); /* no hash */
DISPOSE(ch->pcdata->homepage); /* no hash */
DISPOSE(ch->pcdata->email); /* no hash */
STRFREE(ch->pcdata->prompt);
STRFREE(ch->pcdata->fprompt);
if (ch->pcdata->bounty_by)
DISPOSE(ch->pcdata->bounty_by);
if (ch->pcdata->hunting)
DISPOSE(ch->pcdata->hunting);
if (ch->pcdata->spouse)
DISPOSE(ch->pcdata->spouse);
if (ch->pcdata->helled_by)
STRFREE(ch->pcdata->helled_by);
if (ch->pcdata->subprompt)
STRFREE(ch->pcdata->subprompt);
if (ch->pcdata->tell_history) {
int i;
for (i = 0; i < 26; i++) {
if (ch->pcdata->tell_history[i])
STRFREE(ch->pcdata->tell_history[i]);
}
DISPOSE(ch->pcdata->tell_history);
}
STRFREE(ch->pcdata->silencedby);
DISPOSE(ch->pcdata->last_name); /* no hash */
STRFREE(ch->pcdata->lasthost);
DISPOSE(ch->pcdata);
}
for (mpact = ch->mpact; mpact; mpact = mpact_next) {
mpact_next = mpact->next;
DISPOSE(mpact->buf);
DISPOSE(mpact);
}
for (comments = ch->comments; comments; comments = comments_next) {
comments_next = comments->next;
STRFREE(comments->text);
STRFREE(comments->to_list);
STRFREE(comments->subject);
STRFREE(comments->sender);
STRFREE(comments->date);
DISPOSE(comments);
}
DISPOSE(ch);
return;
}
/*
* Get an extra description from a list.
*/
char *
get_extra_descr(const char *name, EXTRA_DESCR_DATA * ed)
{
for (; ed; ed = ed->next)
if (is_name(name, ed->keyword))
return ed->description;
return NULL;
}
/*
* Translates mob virtual number to its mob index struct.
* Hash table lookup.
*/
MOB_INDEX_DATA *
get_mob_index(int vnum)
{
MOB_INDEX_DATA *pMobIndex;
if (vnum < 0)
vnum = 0;
for (pMobIndex = mob_index_hash[vnum % MAX_KEY_HASH];
pMobIndex;
pMobIndex = pMobIndex->next)
if (pMobIndex->vnum == vnum)
return pMobIndex;
if (fBootDb)
bug("Get_mob_index: bad vnum %d.", vnum);
return NULL;
}
/*
* Translates obj virtual number to its obj index struct.
* Hash table lookup.
*/
OBJ_INDEX_DATA *
get_obj_index(int vnum)
{
OBJ_INDEX_DATA *pObjIndex;
if (vnum < 0)
vnum = 0;
for (pObjIndex = obj_index_hash[vnum % MAX_KEY_HASH];
pObjIndex;
pObjIndex = pObjIndex->next)
if (pObjIndex->vnum == vnum)
return pObjIndex;
if (fBootDb)
bug("Get_obj_index: bad vnum %d.", vnum);
return NULL;
}
/*
* Translates room virtual number to its room index struct.
* Hash table lookup.
*/
ROOM_INDEX_DATA *
get_room_index(int vnum)
{
ROOM_INDEX_DATA *pRoomIndex;
if (vnum < 0)
vnum = 0;
for (pRoomIndex = room_index_hash[vnum % MAX_KEY_HASH];
pRoomIndex;
pRoomIndex = pRoomIndex->next)
if (pRoomIndex->vnum == vnum)
return pRoomIndex;
if (fBootDb)
bug("Get_room_index: bad vnum %d.", vnum);
return NULL;
}
/*
* Added lots of EOF checks, as most of the file crashes are based on them.
* If an area file encounters EOF, the fread_* functions will shutdown the
* MUD, as all area files should be read in in full or bad things will
* happen during the game. Any files loaded in without fBootDb which
* encounter EOF will return what they have read so far. These files
* should include player files, and in-progress areas that are not loaded
* upon bootup.
* -- Altrag
*/
/*
* Read a letter from a file.
*/
char
fread_letter(FILE *fp)
{
char c;
char buf[MAX_STRING_LENGTH];
do {
if (feof(fp)) {
bug("fread_letter: EOF encountered on read.\n\r", 0);
if (GfpName) {
sprintf(buf, "[*****] FILE: %s", GfpName);
log_string(buf);
}
if (fBootDb)
exit(1);
else
StopFP = true;
return '\0';
}
c = getc(fp);
}
while (isspace(c));
if (StopFP)
StopFP = false;
return c;
}
/*
* Read a number from a file.
*/
int
fread_number(FILE *fp)
{
int number;
bool sign;
char c;
do {
if (feof(fp)) {
bug("fread_number: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return 0;
}
c = getc(fp);
}
while (isspace(c));
number = 0;
sign = false;
if (c == '+') {
c = getc(fp);
} else if (c == '-') {
sign = true;
c = getc(fp);
}
if (!isdigit(c)) {
bug("Fread_number: bad format. (%c)", c, 0);
if (fBootDb)
exit(1);
return 0;
}
while (isdigit(c)) {
if (feof(fp)) {
bug("fread_number: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return number;
}
number = number * 10 + c - '0';
c = getc(fp);
}
if (sign)
number = 0 - number;
if (c == '|')
number += fread_number(fp);
else if (c != ' ')
ungetc(c, fp);
return number;
}
long long int
fread_number_ll(FILE *fp)
{
long long int number;
bool sign;
char c;
do {
if (feof(fp)) {
bug("fread_number: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return 0;
}
c = getc(fp);
}
while (isspace(c));
number = 0;
sign = false;
if (c == '+') {
c = getc(fp);
} else if (c == '-') {
sign = true;
c = getc(fp);
}
if (!isdigit(c)) {
bug("Fread_number: bad format. (%c)", c, 0);
if (fBootDb)
exit(1);
return 0;
}
while (isdigit(c)) {
if (feof(fp)) {
bug("fread_number: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return number;
}
number = number * 10 + c - '0';
c = getc(fp);
}
if (sign)
number = 0 - number;
if (c == '|')
number += fread_number_ll(fp);
else if (c != ' ')
ungetc(c, fp);
return number;
}
/*
* Read a number from a file.
*/
long double
fread_number_ld(FILE *fp)
{
long double number;
char c;
bool sign;
do {
if (feof(fp)) {
bug("fread_number: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return 0;
}
c = getc(fp);
}
while (isspace(c));
number = 0;
sign = false;
if (c == '+') {
c = getc(fp);
} else if (c == '-') {
sign = true;
c = getc(fp);
}
if (!isdigit(c)) {
bug("Fread_number: bad format. (%c)", c, 0);
if (fBootDb)
exit(1);
return 0;
}
while (isdigit(c)) {
if (feof(fp)) {
bug("fread_number: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return number;
}
number = number * 10 + c - '0';
c = getc(fp);
}
if (sign)
number = 0 - number;
if (c == '|')
number += fread_number(fp);
else if (c != ' ')
ungetc(c, fp);
return number;
}
double
fread_number_skill(FILE *fp)
{
long double number;
char c;
char toLd[MAX_INPUT_LENGTH];
int i = 0;
do {
if (feof(fp)) {
bug("fread_number: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return 0;
}
c = getc(fp);
}
while (isspace(c));
number = 0;
if (!isdigit(c)) {
bug("Fread_number: bad format. (%c)", c, 0);
if (fBootDb)
exit(1);
return 0;
}
while (isdigit(c) || c == '.') {
if (feof(fp)) {
bug("fread_number: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return number;
}
toLd[i] = c;
i++;
c = getc(fp);
}
number = atof(toLd);
if (c == '|')
number += fread_number(fp);
else if (c != ' ')
ungetc(c, fp);
return number;
}
/*
* custom str_dup using create -Thoric
*/
char *
str_dup(char const * str)
{
static char *ret;
int len;
if (!str)
return NULL;
len = strlen(str) + 1;
CREATE(ret, char, len);
strcpy(ret, str);
return ret;
}
/*
* Read a string from file fp (goku hacked verson)
*/
char *
fread_string_wspace(FILE *fp)
{
char buf[MAX_STRING_LENGTH];
char *plast;
char c;
int ln;
plast = buf;
buf[0] = '\0';
ln = 0;
/*
* Don't skip blanks.
* Read first char.
*/
do {
if (feof(fp)) {
bug("fread_string: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return STRALLOC("");
}
c = getc(fp);
}
while (iscntrl(c));
if ((*plast++ = c) == '~')
return STRALLOC("");
for (;;) {
if (ln >= (MAX_STRING_LENGTH - 1)) {
bug("fread_string: string too long", 0);
*plast = '\0';
return STRALLOC(buf);
}
switch (*plast = getc(fp)) {
default:
plast++;
ln++;
break;
case EOF:
bug("Fread_string: EOF", 0);
if (fBootDb)
exit(1);
*plast = '\0';
return STRALLOC(buf);
break;
case '\n':
plast++;
ln++;
*plast++ = '\r';
ln++;
break;
case '\r':
break;
case '~':
*plast = '\0';
return STRALLOC(buf);
}
}
}
/*
* Read a string from file fp
*/
char *
fread_string(FILE *fp)
{
char buf[MAX_STRING_LENGTH];
char *plast;
char c;
int ln;
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", 0);
if (fBootDb)
exit(1);
return STRALLOC("");
}
c = getc(fp);
}
while (isspace(c));
if ((*plast++ = c) == '~')
return STRALLOC("");
for (;;) {
if (ln >= (MAX_STRING_LENGTH - 1)) {
bug("fread_string: string too long", 0);
*plast = '\0';
return STRALLOC(buf);
}
switch (*plast = getc(fp)) {
default:
plast++;
ln++;
break;
case EOF:
bug("Fread_string: EOF", 0);
if (fBootDb)
exit(1);
*plast = '\0';
return STRALLOC(buf);
break;
case '\n':
plast++;
ln++;
*plast++ = '\r';
ln++;
break;
case '\r':
break;
case '~':
*plast = '\0';
return STRALLOC(buf);
}
}
}
/*
* Read a string from file fp using str_dup (ie: no string hashing)
*/
char *
fread_string_nohash(FILE *fp)
{
char buf[MAX_STRING_LENGTH];
char *plast;
char c;
int ln;
plast = buf;
buf[0] = '\0';
ln = 0;
/*
* Skip blanks.
* Read first char.
*/
do {
if (feof(fp)) {
bug("fread_string_no_hash: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return str_dup("");
}
c = getc(fp);
}
while (isspace(c));
if ((*plast++ = c) == '~')
return str_dup("");
for (;;) {
if (ln >= (MAX_STRING_LENGTH - 1)) {
bug("fread_string_no_hash: string too long", 0);
*plast = '\0';
return str_dup(buf);
}
switch (*plast = getc(fp)) {
default:
plast++;
ln++;
break;
case EOF:
bug("Fread_string_no_hash: EOF", 0);
if (fBootDb)
exit(1);
*plast = '\0';
return str_dup(buf);
break;
case '\n':
plast++;
ln++;
*plast++ = '\r';
ln++;
break;
case '\r':
break;
case '~':
*plast = '\0';
return str_dup(buf);
}
}
}
/*
* Read to end of line (for comments).
*/
void
fread_to_eol(FILE *fp)
{
char c;
do {
if (feof(fp)) {
bug("fread_to_eol: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
return;
}
c = getc(fp);
}
while (c != '\n' && c != '\r');
do {
c = getc(fp);
}
while (c == '\n' || c == '\r');
ungetc(c, fp);
return;
}
/*
* Read to end of line into static buffer -Thoric
*/
char *
fread_line(FILE *fp)
{
static char line[MAX_STRING_LENGTH];
char *pline;
char c;
int ln;
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 (fBootDb)
exit(1);
strcpy(line, "");
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 (fBootDb)
exit(1);
*pline = '\0';
return line;
}
c = getc(fp);
*pline++ = c;
ln++;
if (ln >= (MAX_STRING_LENGTH - 1)) {
bug("fread_line: line too long", 0);
break;
}
}
while (c != '\n' && c != '\r');
do {
c = getc(fp);
}
while (c == '\n' || c == '\r');
ungetc(c, fp);
*pline = '\0';
return line;
}
/*
* Read one word (into static buffer).
*/
char *
fread_word(FILE *fp)
{
static char word[MAX_INPUT_LENGTH];
char *pword;
char cEnd;
do {
if (feof(fp)) {
bug("fread_word: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
word[0] = '\0';
return word;
}
cEnd = getc(fp);
}
while (isspace(cEnd));
if (cEnd == '\'' || cEnd == '\"') {
pword = word;
} else {
word[0] = cEnd;
pword = word + 1;
cEnd = ' ';
}
for (; pword < word + MAX_INPUT_LENGTH; pword++) {
if (feof(fp)) {
bug("fread_word: EOF encountered on read.\n\r", 0);
if (fBootDb)
exit(1);
*pword = '\0';
return word;
}
*pword = getc(fp);
if (cEnd == ' ' ? isspace(*pword) : *pword == cEnd) {
if (cEnd == ' ')
ungetc(*pword, fp);
*pword = '\0';
return word;
}
}
bug("Fread_word: word too long.\n\r", 0);
bug("%s", word, 0);
exit(1);
return NULL;
}
void
do_memory(CHAR_DATA * ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
int hash;
set_char_color(AT_PLAIN, ch);
argument = one_argument(argument, arg);
send_to_char_color("\n\r&wSystem Memory [arguments - hash, check, showhigh]\n\r", ch);
ch_printf_color(ch, "&wAffects: &W%5d\t\t\t&wAreas: &W%5d\n\r",
top_affect, top_area);
ch_printf_color(ch, "&wExtDes: &W%5d\t\t\t&wExits: &W%5d\n\r",
top_ed, top_exit);
ch_printf_color(ch, "&wHelps: &W%5d\t\t\t&wResets: &W%5d\n\r",
top_help, top_reset);
ch_printf_color(ch, "&wIdxMobs: &W%5d\t\t\t&wMobiles: &W%5d\n\r",
top_mob_index, nummobsloaded);
ch_printf_color(ch, "&wIdxObjs: &W%5d\t\t\t&wObjs: &W%5d(%d)\n\r",
top_obj_index, numobjsloaded, physicalobjects);
ch_printf_color(ch, "&wRooms: &W%5d\t\t\t&wVRooms: &W%5d\n\r",
top_room, top_vroom);
ch_printf_color(ch, "&wShops: &W%5d\t\t\t&wRepShps: &W%5d\n\r",
top_shop, top_repair);
ch_printf_color(ch, "&wCurOq's: &W%5d\t\t\t&wCurCq's: &W%5d\n\r",
cur_qobjs, cur_qchars);
ch_printf_color(ch, "&wPlayers: &W%5d\t\t\t&wMaxplrs: &W%5d\n\r",
num_descriptors, sysdata.maxplayers);
ch_printf_color(ch, "&wMaxEver: &W%5d\t\t\t&wTopsn: &W%5d(%d)\n\r",
sysdata.alltimemax, top_sn, MAX_SKILL);
ch_printf_color(ch, "&wMaxEver was recorded on: &W%s\n\r\n\r",
sysdata.time_of_max);
ch_printf_color(ch, "&wPotion Val: &W%-16d &wScribe/Brew: &W%d/%d\n\r",
sysdata.upotion_val, sysdata.scribed_used, sysdata.brewed_used);
ch_printf_color(ch, "&wPill Val: &W%-16d &wGlobal loot: &W%d\n\r",
sysdata.upill_val, sysdata.global_looted);
if (!str_cmp(arg, "check")) {
#ifdef HASHSTR
send_to_char(check_hash(argument), ch);
#else
send_to_char("Hash strings not enabled.\n\r", ch);
#endif
return;
}
if (!str_cmp(arg, "showhigh")) {
#ifdef HASHSTR
show_high_hash(atoi(argument));
#else
send_to_char("Hash strings not enabled.\n\r", ch);
#endif
return;
}
if (argument[0] != '\0')
hash = atoi(argument);
else
hash = -1;
if (!str_cmp(arg, "hash")) {
#ifdef HASHSTR
ch_printf(ch, "Hash statistics:\n\r%s", hash_stats());
if (hash != -1)