/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Envy Diku Mud, you must comply with *
* the original Diku license in 'license.doc', the Merc license in *
* 'license.txt', as well as the Envy license in 'license.nvy'. *
* In particular, you may not remove either of these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
* *
* ROM 2.4 is copyright 1993-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
* *
* Code Adapted and Improved by Abandoned Realms Mud *
* and Aabahran: The Forsaken Lands Mud by Virigoth *
* *
* Continued Production of this code is available at www.flcodebase.com *
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <ctype.h>
#include <time.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include "merc.h"
#include "cabal.h"
#include "db.h"
#include "recycle.h"
#include "interp.h"
#include "save_mud.h"
#include "olc.h"
#include "bounty.h"
#include "armies.h"
#include "tome.h"
#include "clan.h"
#if !defined(OLD_RAND)
// asdfg long random();
int getpid();
time_t time(time_t *tloc);
#endif
/* externals for counting purposes */
extern OBJ_DATA *obj_free;
extern CHAR_DATA *char_free;
extern DESCRIPTOR_DATA *descriptor_free;
extern PC_DATA *pcdata_free;
extern AFFECT_DATA *affect_free;
extern AFFECT_DATA *skill_free;
extern EFFECT_DATA *effect_free;
/* Globals. */
HELP_DATA * help_first;
HELP_DATA * help_last;
SHOP_DATA * shop_first;
SHOP_DATA * shop_last;
NOTE_DATA * note_free;
char bug_buf [2*MIL];
CHAR_DATA * char_list;
TRAP_DATA * trap_list;
TRAP_INDEX_DATA * trap_index_list;
CHAR_DATA * player_list;
char * help_greeting;
char log_buf [2*MIL];
KILL_DATA kill_table [MAX_LEVEL];
NOTE_DATA * note_list;
OBJ_DATA * object_list;
int reboot_tick_counter = -1;
char reboot_buffer [MIL];
int restart = 0;
int free_vir_vnums[MAX_FREE_VNUM];
int last_vir_vnum = 0;
PROG_CODE * mprog_list;
PROG_CODE * oprog_list;
PROG_CODE * rprog_list;
int grn_illithid;
int grn_half_elf;
int grn_faerie;
int grn_feral;
int grn_undead;
int grn_demon;
int grn_fire;
int grn_stone;
int grn_werebeast;
int grn_vampire;
int grn_ogre;
int grn_minotaur;
int gcn_monk;
int gcn_psi;
int gcn_vampire;
int gcn_ranger;
int gcn_dk;
int gcn_crusader;
int gcn_ninja;
int gcn_necro;
int gcn_bard;
int gcn_adventurer;
int gcn_blademaster;
int gcn_warrior;
int gcn_shaman;
int gcn_healer;
int gcn_cleric;
int gcn_druid;
int gcn_paladin;
sh_int gsn_backstab;
sh_int gsn_battlesphere;
sh_int gsn_battlefocus;
sh_int gsn_battletrance;
sh_int gsn_bladestorm;
sh_int gsn_behead;
sh_int gsn_baptize;
sh_int gsn_blanket;
sh_int gsn_bladework;
sh_int gsn_battlestance;
sh_int gsn_avatar_of_steel;
sh_int gsn_age;
sh_int gsn_batter;
sh_int gsn_bolo;
sh_int gsn_bribe;
sh_int gsn_breach;
sh_int gsn_2hands;
sh_int gsn_2h_handling;
sh_int gsn_2h_tactics;
sh_int gsn_2h_mastery;
sh_int gsn_dodge;
sh_int gsn_dysentery;
sh_int gsn_doomsinger;
sh_int gsn_dheal;
sh_int gsn_soul_tap;
sh_int gsn_sretrib;
sh_int gsn_subvocal;
sh_int gsn_dwrath;
sh_int gsn_sbane;
sh_int gsn_pwater;
sh_int gsn_probe;
sh_int gsn_predict;
sh_int gsn_icefire;
sh_int gsn_icalm;
sh_int gsn_identify;
sh_int gsn_smight;
sh_int gsn_dmight;
sh_int gsn_envenom;
sh_int gsn_enfeeblement;
sh_int gsn_energy_drain;
sh_int gsn_hide;
sh_int gsn_high_sight;
sh_int gsn_haymaker;
sh_int gsn_harm;
sh_int gsn_peek;
sh_int gsn_protective_shield;
sh_int gsn_push;
sh_int gsn_puppet_master;
sh_int gsn_purity;
sh_int gsn_const;
sh_int gsn_cyclone;
sh_int gsn_cont;
sh_int gsn_epal;
sh_int gsn_pick_lock;
sh_int gsn_sneak;
sh_int gsn_steal;
sh_int gsn_steel_wall;
sh_int gsn_study;
sh_int gsn_pry;
sh_int gsn_plant;
sh_int gsn_planar_seal;
sh_int gsn_preserve;
sh_int gsn_disarm;
sh_int gsn_dispel_magic;
sh_int gsn_disguise;
sh_int gsn_weapon_cleave;
sh_int gsn_webbing;
sh_int gsn_wlock;
sh_int gsn_weaponcraft;
sh_int gsn_weaken;
sh_int gsn_shield_cleave;
sh_int gsn_sheath;
sh_int gsn_enhanced_damage;
sh_int gsn_kick;
sh_int gsn_parry;
sh_int gsn_path_anger;
sh_int gsn_path_fury;
sh_int gsn_path_dev;
sh_int gsn_fpart;
sh_int gsn_fury;
sh_int gsn_first_parry;
sh_int gsn_second_parry;
sh_int gsn_serpent;
sh_int gsn_secret_arts;
sh_int gsn_rapid_fire;
sh_int gsn_rescue;
sh_int gsn_rev_time;
sh_int gsn_resurrection;
sh_int gsn_second_attack;
sh_int gsn_third_attack;
sh_int gsn_tracker;
sh_int gsn_transform;
sh_int gsn_torment_bind;
sh_int gsn_turn_undead;
sh_int gsn_blindness;
sh_int gsn_bloodhaze;
sh_int gsn_bloodvow;
sh_int gsn_chant;
sh_int gsn_charm_person;
sh_int gsn_curse;
sh_int gsn_curse_weapon;
sh_int gsn_invis;
sh_int gsn_invigorate;
sh_int gsn_mark_prey;
sh_int gsn_marksman;
sh_int gsn_maelstrom;
sh_int gsn_mark_fear;
sh_int gsn_mass_invis;
sh_int gsn_masochism;
sh_int gsn_poison;
sh_int gsn_powerstrike;
sh_int gsn_plague;
sh_int gsn_sleep;
sh_int gsn_sanctuary;
sh_int gsn_sacred_runes;
sh_int gsn_fly;
sh_int gsn_adv_handling;
sh_int gsn_adrenaline_rush;
sh_int gsn_apierce;
sh_int gsn_arms_main;
sh_int gsn_archery;
sh_int gsn_armorcraft;
sh_int gsn_armored_rush;
sh_int gsn_armor_enhance;
sh_int gsn_avenger;
sh_int gsn_axe;
sh_int gsn_abduct;
sh_int gsn_dagger;
sh_int gsn_fired;
sh_int gsn_flail;
sh_int gsn_mace;
sh_int gsn_polearm;
sh_int gsn_shield_block;
sh_int gsn_spear;
sh_int gsn_spirit_bind;
sh_int gsn_staff;
sh_int gsn_sword;
sh_int gsn_whip;
sh_int gsn_sword_mastery;
sh_int gsn_dagger_mastery;
sh_int gsn_spear_mastery;
sh_int gsn_mace_mastery;
sh_int gsn_axe_mastery;
sh_int gsn_flail_mastery;
sh_int gsn_whip_mastery;
sh_int gsn_staff_mastery;
sh_int gsn_exotic_mastery;
sh_int gsn_exile;
sh_int gsn_shield_expert;
sh_int gsn_sword_expert;
sh_int gsn_dagger_expert;
sh_int gsn_mace_expert;
sh_int gsn_spear_expert;
sh_int gsn_axe_expert;
sh_int gsn_flail_expert;
sh_int gsn_staff_expert;
sh_int gsn_whip_expert;
sh_int gsn_polearm_expert;
sh_int gsn_exotic_expert;
sh_int gsn_polearm_mastery;
sh_int gsn_bash;
sh_int gsn_basic_armor;
sh_int gsn_adv_armor;
sh_int gsn_berserk;
sh_int gsn_dirt;
sh_int gsn_hand_to_hand;
sh_int gsn_trip;
sh_int gsn_trample;
sh_int gsn_lash;
sh_int gsn_fast_healing;
sh_int gsn_false_weapon;
sh_int gsn_fade;
sh_int gsn_haggle;
sh_int gsn_lore;
sh_int gsn_lotus_sc;
sh_int gsn_meditation;
sh_int gsn_melee;
sh_int gsn_scrolls;
sh_int gsn_scourge;
sh_int gsn_staves;
sh_int gsn_stand_ground;
sh_int gsn_wands;
sh_int gsn_wanted;
sh_int gsn_recall;
sh_int gsn_hunt;
sh_int gsn_dual_wield;
sh_int gsn_death_grasp;
sh_int gsn_deathweaver;
sh_int gsn_death_kiss;
sh_int gsn_death_shroud;
sh_int gsn_deteriorate;
sh_int gsn_detect_traps;
sh_int gsn_phantasmal_griffon;
sh_int gsn_illusionary_spectre;
sh_int gsn_phantom_dragon;
sh_int gsn_trance;
sh_int gsn_blind_fighting;
sh_int gsn_shield_disarm;
sh_int gsn_rake;
sh_int gsn_raise_morale;
sh_int gsn_misdirection;
sh_int gsn_missile_shield;
sh_int gsn_shadowform;
sh_int gsn_shadowdancer;
sh_int gsn_shadow_door;
sh_int gsn_shadowmaster;
sh_int gsn_shadow_strike;
sh_int gsn_treeform;
sh_int gsn_fourth_attack;
sh_int gsn_footwork;
sh_int gsn_forestmeld;
sh_int gsn_deathblow;
sh_int gsn_com_lan;
sh_int gsn_counter;
sh_int gsn_lay_on_hands;
sh_int gsn_detect_hidden;
sh_int gsn_cleave;
sh_int gsn_assassinate;
sh_int gsn_blackjack;
sh_int gsn_gag;
sh_int gsn_strangle;
sh_int gsn_acupuncture;
sh_int gsn_herb;
sh_int gsn_hex;
sh_int gsn_tame;
sh_int gsn_beast_call;
sh_int gsn_rage;
sh_int gsn_regeneration;
sh_int gsn_bodyslam;
sh_int gsn_dual_backstab;
sh_int gsn_grapple;
sh_int gsn_greenheart;
sh_int gsn_charge;
sh_int gsn_shoot;
sh_int gsn_ambush;
sh_int gsn_endure;
sh_int gsn_barkskin;
sh_int gsn_warcry;
sh_int gsn_circle;
sh_int gsn_swing;
sh_int gsn_headbutt;
sh_int gsn_camouflage;
sh_int gsn_chameleon;
sh_int gsn_quiet_movement;
sh_int gsn_keen_sight;
sh_int gsn_vanish;
sh_int gsn_vredem;
sh_int gsn_virtues;
sh_int gsn_vitality;
sh_int gsn_voodoo_spell;
sh_int gsn_chii;
sh_int gsn_blindness_dust;
sh_int gsn_poison_smoke;
sh_int gsn_pugil;
sh_int gsn_butcher;
sh_int gsn_dual_parry;
sh_int gsn_caltraps;
sh_int gsn_nerve;
sh_int gsn_nerve_amp;
sh_int gsn_numbness;
sh_int gsn_righteous;
sh_int gsn_riposte;
sh_int gsn_ripple;
sh_int gsn_truesight;
sh_int gsn_trophy;
sh_int gsn_spellbane;
sh_int gsn_spellkiller;
sh_int gsn_spell_blast;
sh_int gsn_spell_trap;
sh_int gsn_mana_trap;
sh_int gsn_doppelganger;
sh_int gsn_mirror_image;
sh_int gsn_mirage;
sh_int gsn_mirror_cloak;
sh_int gsn_cognizance;
sh_int gsn_stance;
sh_int gsn_forms;
sh_int gsn_wanted;
sh_int gsn_judge;
sh_int gsn_spy;
sh_int gsn_knight;
sh_int gsn_guard;
sh_int gsn_stallion;
sh_int gsn_relax;
sh_int gsn_garble;
sh_int gsn_brew;
sh_int gsn_challenge;
sh_int gsn_bounty_collect;
sh_int gsn_fatality;
sh_int gsn_climb;
sh_int gsn_damnation;
sh_int gsn_dam_masteryB;
sh_int gsn_dam_masteryS;
sh_int gsn_dam_masteryP;
sh_int gsn_flashfire;
sh_int gsn_drained;
sh_int gsn_dreamprobe;
sh_int gsn_mortally_wounded;
sh_int gsn_mercy_wait;
sh_int gsn_mounted;
sh_int gsn_ancient_lore;
sh_int gsn_invoke;
sh_int gsn_mimic;
sh_int gsn_camp;
sh_int gsn_scout;
sh_int gsn_throw;
sh_int gsn_roar;
sh_int gsn_edge_craft;
sh_int gsn_counterfeit;
sh_int gsn_ranger_staff;
sh_int gsn_healer_staff;
sh_int gsn_heal;
sh_int gsn_familiar_link;
sh_int gsn_extort;
sh_int gsn_squire;
sh_int gsn_silence;
sh_int gsn_blasphemy;
sh_int gsn_blink;
sh_int gsn_defecate;
sh_int gsn_vomit;
sh_int gsn_insomnia;
sh_int gsn_insight;
sh_int gsn_mystic_healing;
sh_int gsn_shield_of_words;
sh_int gsn_children_sky;
sh_int gsn_pilfer;
sh_int gsn_mind_link;
sh_int gsn_mindsurge;
sh_int gsn_mind_disrupt;
sh_int gsn_linked_mind;
sh_int gsn_ensnare;
sh_int gsn_timer;
sh_int gsn_time_comp;
sh_int gsn_pixie_dust;
sh_int gsn_bat_form;
sh_int gsn_wolf_form;
sh_int gsn_mist_form;
sh_int gsn_double_kick;
sh_int gsn_coffin;
sh_int gsn_stake;
sh_int gsn_eavesdrop;
sh_int gsn_kinetics;
sh_int gsn_thrust;
sh_int gsn_ecstacy;
sh_int gsn_anatomy;
sh_int gsn_beads;
sh_int gsn_martial_arts_b;
sh_int gsn_martial_arts_a;
sh_int gsn_kickboxing_b;
sh_int gsn_kickboxing_a;
sh_int gsn_double_grip;
sh_int gsn_monkey;
sh_int gsn_tiger;
sh_int gsn_crane;
sh_int gsn_mantis;
sh_int gsn_drunken;
sh_int gsn_horse;
sh_int gsn_holy_hands;
sh_int gsn_dragon;
sh_int gsn_buddha;
sh_int gsn_aura;
sh_int gsn_balance;
sh_int gsn_sense_motion;
sh_int gsn_catalepsy;
sh_int gsn_healing;
sh_int gsn_kinesis;
sh_int gsn_mind_thrust;
sh_int gsn_mind_disruption;
sh_int gsn_mind_blast;
sh_int gsn_psalm_master;
sh_int gsn_psychic_crush;
sh_int gsn_psionic_blast;
sh_int gsn_psi_amp;
sh_int gsn_psychic_purge;
sh_int gsn_photon;
sh_int gsn_flesh_armor;
sh_int gsn_detect_aura;
sh_int gsn_displacement;
sh_int gsn_dvoid;
sh_int gsn_iron_will;
sh_int gsn_ironarm;
sh_int gsn_iron_curtain;
sh_int gsn_bio_manipulation;
sh_int gsn_ego_whip;
sh_int gsn_tele_lock;
sh_int gsn_telepathy;
sh_int gsn_temp_storm;
sh_int gsn_there_not_there;
sh_int gsn_levitate;
sh_int gsn_leash;
sh_int gsn_leadership;
sh_int gsn_gravitate;
sh_int gsn_bio_feedback;
sh_int gsn_pyramid_of_force;
sh_int gsn_body_weaponry;
sh_int gsn_ectoplasm;
sh_int gsn_hypnosis;
sh_int gsn_forget;
sh_int gsn_graft_weapon;
sh_int gsn_mental_barrier;
sh_int gsn_mental_knife;
sh_int gsn_empower;
sh_int gsn_ogtrium;
sh_int gsn_onslaught;
sh_int gsn_omnipotence;
sh_int gsn_ocularis;
sh_int gsn_strium;
sh_int gsn_ptrium;
sh_int gsn_uorder;
sh_int gsn_unminding;
sh_int gsn_istrength;
sh_int gsn_offensive;
sh_int gsn_orealts_1st;
sh_int gsn_orealts_2nd;
sh_int gsn_defensive;
sh_int gsn_chii_bolt;
sh_int gsn_thrash;
sh_int gsn_deadfall;
sh_int gsn_windmill;
sh_int gsn_cusinart;
sh_int gsn_cure_light;
sh_int gsn_wire_delay;
sh_int gsn_siege_delay;
sh_int gsn_ghoul_touch;
sh_int gsn_paralyze;
sh_int gsn_entomb;
sh_int gsn_insect_swarm;
sh_int gsn_feedback;
sh_int gsn_feign;
sh_int gsn_con_damage;
sh_int gsn_cone;
sh_int gsn_dark_ritual;
sh_int gsn_covenant;
sh_int gsn_burrow;
sh_int gsn_cutpurse;
sh_int gsn_cutter;
sh_int gsn_offhand_disarm;
sh_int gsn_werepower;
sh_int gsn_weretiger;
sh_int gsn_werewolf;
sh_int gsn_werebear;
sh_int gsn_werefalcon;
sh_int gsn_fasting;
sh_int gsn_shed_skin;
sh_int gsn_crusade;
sh_int gsn_heroism;
sh_int gsn_decoy;
sh_int gsn_prayer;
sh_int gsn_refrain;
sh_int gsn_lullaby;
sh_int gsn_tarot;
sh_int gsn_tko;
sh_int gsn_leech;
sh_int gsn_noquit;
sh_int gsn_nolearn;
sh_int gsn_duplicate;
sh_int gsn_dance_song;
sh_int gsn_attract;
sh_int gsn_uppercut;
sh_int gsn_taunt;
sh_int gsn_condor;
sh_int gsn_disorient;
sh_int gsn_concen;
sh_int gsn_seasons;
sh_int gsn_hysteria;
sh_int gsn_lust;
sh_int gsn_reputation;
sh_int gsn_unforgiven;
sh_int gsn_phoenix;
sh_int gsn_brawl;
sh_int gsn_brain_death;
sh_int gsn_unholy_strength;
sh_int gsn_ram;
sh_int gsn_embrace;
sh_int gsn_embrace_poison;
sh_int gsn_secarts;
sh_int gsn_continuum;
sh_int gsn_tear;
sh_int gsn_unholy_gift;
sh_int gsn_mana_charge;
sh_int gsn_warmaster_code;
sh_int gsn_call_roc;
sh_int gsn_corrupt;
sh_int gsn_lifeforce;
sh_int gsn_life_insurance;
sh_int gsn_lifedrain;
sh_int gsn_entangle;
sh_int gsn_forest_mist;
sh_int gsn_forest_walk;
sh_int gsn_druid_staff;
sh_int gsn_trap_silvanus;
sh_int gsn_circle_of_protection;
sh_int gsn_field_fear;
sh_int gsn_fear;
sh_int gsn_drug_use;
sh_int gsn_research;
sh_int gsn_decipher;
/* BATTLE MAGES */
sh_int gsn_forcefield;
sh_int gsn_terra_shield;
sh_int gsn_rust;
sh_int gsn_air_shield;
sh_int gsn_blades;
sh_int gsn_field_dress;
sh_int gsn_plumbum;
sh_int gsn_dan_blade;
sh_int gsn_mana_lock;
sh_int gsn_ref_shield;
/* Miners */
sh_int gsn_sense_vein;
sh_int gsn_dig;
sh_int gsn_gemlore;
sh_int gsn_extrude;
/* anatmy masteries */
sh_int gsn_mob_expert;
sh_int gsn_human_expert;
sh_int gsn_elf_expert;
sh_int gsn_giant_expert;
sh_int gsn_dwarf_expert;
sh_int gsn_demihuman_expert;
sh_int gsn_flying_expert;
sh_int gsn_beast_expert;
sh_int gsn_unique_expert;
sh_int gsn_mob_master;
sh_int gsn_human_master;
sh_int gsn_elf_master;
sh_int gsn_dwarf_master;
sh_int gsn_giant_master;
sh_int gsn_beast_master;
sh_int gsn_demihuman_master;
sh_int gsn_flying_master;
sh_int gsn_unique_master;
/* MOBprogram locals */
int mprog_name_to_type args ( ( char* name ) );
MPROG_DATA * mprog_file_read args ( ( char* f, MPROG_DATA* mprg, MOB_INDEX_DATA *pMobIndex ) );
void load_mobprogs args ( ( FILE* fp ) );
void mprog_read_programs args ( ( FILE* fp, MOB_INDEX_DATA *pMobIndex ) );
/* 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 * area_first;
AREA_DATA * area_last;
extern char str_empty [1];
extern int sOverFlowString;
extern int nOverFlowString;
extern bool Full;
char * daPrompt;
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_vir_room = 0;
int top_shop;
int top_vnum_room;
int top_vnum_mob;
int top_vnum_obj;
int top_mprog_index;
int top_oprog_index;
int top_rprog_index;
int top_trap_index;
int top_cabal_index = 0;
int mobile_count = 0;
int newmobs = 0;
int newobjs = 0;
bool loadallmobs = TRUE;
/* Memory management. *
* Increase MAX_STRING if you have too. *
* Tune the others only if you understand what you're doing. */
#define MAX_MEM_LIST 11
void * rgFreeList [MAX_MEM_LIST];
const int rgSizeList [MAX_MEM_LIST] =
{ 16, 32, 64, 128, 256, 1024, 2048, 4096, 8192, 16384, 32768-64 };
extern int nAllocString;
extern int sAllocString;
int nAllocPerm;
int sAllocPerm;
/* Semi-locals. */
bool fBootDb;
FILE * fpArea;
char strArea[MIL];
extern int MAX_STRING;
void init_string_space( void );
void boot_done( void );
struct social_type social_table [MAX_SOCIALS];
int social_count;
int night_count;
int mprog_count;
int mprogf_count;
/* Local booting procedures. */
void init_mm args( ( void ) );
void load_area args( ( FILE *fp ) );
void new_load_area args( ( FILE *fp ) );
void load_helps args( ( FILE *fp ) );
void load_helps_new args( ( void ) );
void load_old_mob args( ( FILE *fp ) );
void load_mobiles args( ( FILE *fp ) );
void load_army_indexes args( ( FILE *fp ) );
void load_cabal_indexes args( ( FILE *fp ) );
void load_old_obj 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_socials args( ( FILE *fp ) );
void load_specials args( ( FILE *fp ) );
void load_notes args( ( void ) );
void load_bans args( ( void ) );
void load_objprogs args(( FILE *fp ));
void load_roomprogs args(( FILE *fp ));
void load_traps args(( FILE *fp ));
void fix_exits args( ( void ) );
void fix_mobprogs args( ( void ) );
void fix_objprogs args( ( void ) );
void fix_roomprogs args( ( void ) );
void reset_area args( ( AREA_DATA * pArea ) );
void load_limits args( ( void ) );
void color_rooms args( ( void ) );
/* extern functions */
extern void make_html_helps();
/* seeds a single object as based on entry in objseed table */
void seed_object( int i ){
OID* pOI = get_obj_index( objseed_table[i].vnum );
if (pOI == NULL){
bug("seed_objects: could not load obj index.", objseed_table[i].vnum);
return;
}
/* check if we need to load one of these */
if (objseed_table[i].num > pOI->count){
int j = pOI->count;
for (; j < objseed_table[i].num; j++){
OBJ_DATA* pO; //object
ROOM_INDEX_DATA* pR; //room to be put in
/* check the chance to load */
if (number_percent() > objseed_table[i].chance)
continue;
/* load the object */
pR = get_rand_room(objseed_table[i].amin,
objseed_table[i].amax,
objseed_table[i].rmin,
objseed_table[i].rmax,
objseed_table[i].i_area,
objseed_table[i].ia_num,
objseed_table[i].e_area,
objseed_table[i].ea_num,
objseed_table[i].i_sect,
objseed_table[i].is_num,
objseed_table[i].e_sect,
objseed_table[i].es_num,
objseed_table[i].i_rom1,
objseed_table[i].ir1_num,
objseed_table[i].e_rom1,
objseed_table[i].er1_num,
objseed_table[i].i_rom2,
objseed_table[i].ir2_num,
objseed_table[i].e_rom2,
objseed_table[i].er2_num,
objseed_table[i].pool,
objseed_table[i].fExit,
FALSE, NULL);
if (pR == NULL){
bug("seed_obj: NULL room for obj %d.", objseed_table[i].vnum);
continue;
}
/* get the objects */
if ( (pO = create_object( pOI, pOI->level)) == NULL){
bug("seed_obj: NULL object for vnum: %d", pOI->vnum);
continue;
}
/* got room and got objects, we put on in the other */
obj_to_room(pO, pR);
pO->homevnum = pR->vnum;
}//END for each unloaded objects
}//END if
}
/* following seeds random objects into the world */
/* the objseed_table contains all info. The function */
/* runs once after each reboot and loads objects into */
/* appropriate rooms IF they do not exists. */
void seed_objects(){
int i = 0;
/* run through the objseed table till we hit a 0 vnum entry */
for (i =0; objseed_table[i].vnum > 0; i++){
/* DEBUG
nlogf("seeding entry %d of vnum %d", i, objseed_table[i].vnum);
*/
seed_object ( i );
}//END for each table entry
}
/* Following struct is used to record player stats. */
#define MAX_COUNT 32
struct class_info_type {
int class_count[MAX_CLASS]; //count for each class
int race_count[MAX_PC_RACE]; //count for each race
/* quest stuff to keep track of quest players with counts*/
char vamp_name[MAX_COUNT][MIL];
int vamp;
char crus_name[MAX_COUNT][MIL];
int crus;
char psi_name[MAX_COUNT][MIL];
int psis;
char lich_name[MAX_COUNT][MIL];
int lich;
char undead_name[MAX_COUNT][MIL];
int undead;
char demon_name[MAX_COUNT][MIL];
int demon;
char avatar_name[MAX_COUNT][MIL];
int avatar;
char tatto_name[MAX_COUNT][MIL]; //lists players with tats
int tatto;
};
/* sends not to immortal with files purged etc. */
void send_pfile_stats(int pfiles, int purged, int wiped, int total){
char *strtime, *namelist;
char buf[MSL],arg[MIL];
char* sender = "`!HAL 1000``";
BUFFER *buffer;
NOTE_DATA *note;
buffer = new_buf();
sprintf(buf,"`!Following generated at %s.``\n\r\n\r",((char *) ctime( &mud_data.current_time )));
add_buf(buffer,buf);
sprintf(buf, "Total pfiles checked: %-25d\n\r"\
"Pfiles purged: %-25d\n\r"\
"Pfiles deleted: %-25d\n\r"\
"Pfiles above level 15 (used for limit count): %d\n\r",
total, purged, wiped, pfiles);
add_buf(buffer,buf);
namelist = str_dup("immortal");
for (;;)
{
namelist = one_argument(namelist,arg);
if (arg[0] == '\0')
break;
note = new_note();
note->prefix = 0;
note->next = NULL;
note->type = NOTE_NOTE;
free_string(note->sender);
note->sender = str_dup( sender );
free_string(note->subject);
note->subject = str_dup("Pfile Statistics");
free_string(note->text);
note->text = str_dup(buf_string(buffer));
strtime = ctime( &mud_data.current_time );
strtime[strlen(strtime)-1] = '\0';
note->date = str_dup( strtime );
note->date_stamp = mud_data.current_time + 2;
free_string(note->to_list);
note->to_list = str_dup(arg);
append_note(note);
}
free_buf(buffer);
}
/* constructs a note based on structures passed and sends to "immortal" */
void send_stats(struct class_info_type *cl_info){
char *strtime, *namelist;
char buf[MSL],arg[MIL];
char* sender = "`!HAL 1000``";
BUFFER *buffer;
NOTE_DATA *note;
int i = 0;
int j = 0;
int count = 0;
int race = 0;
int class = 0;
/* begin to generate stats */
buffer = new_buf();
sprintf(buf,"`!Following generated at %s.``\n\r\n\r",((char *) ctime( &mud_data.current_time )));
add_buf(buffer,buf);
sprintf(buf, "CLASS\t\t\tCOUNT\t\tRACE\t\t\tCOUNT\n\r");
add_buf(buffer,buf);
if (MAX_CLASS > MAX_PC_RACE)
j = MAX_CLASS;
else
j = MAX_PC_RACE;
for (i = 0; i< j; i++){
bool fLine = FALSE;
if (class < MAX_CLASS && !IS_NULLSTR(class_table[class].name) ){
sprintf(buf,"%-25s %-10d", class_table[class].name, cl_info->class_count[class]);
add_buf(buffer, buf);
fLine = TRUE;
}
class++;
if (race < MAX_PC_RACE && cl_info->race_count[race] > 0){
sprintf(buf,"%-25s %-10d", pc_race_table[race].name, cl_info->race_count[race]);
add_buf(buffer, buf);
fLine = TRUE;
}
race++;
if (fLine){
add_buf(buffer, "\n\r");
if (count % 5 == 0)
add_buf(buffer, "\n\r");
count++;
}
}
/* show quest races/classes */
add_buf(buffer, "\n\r\n\rVampires:");
for (i = 0; i < cl_info->vamp; i++){
if (i % 6 == 0 && i + 1 < cl_info->vamp)
add_buf(buffer, "\n\r");
sprintf(buf, "%s ", cl_info->vamp_name[i]);
add_buf(buffer, buf);
}
add_buf(buffer, "\n\r\n\rCrusaders:");
for (i = 0; i < cl_info->crus; i++){
if (i % 6 == 0 && i + 1 < cl_info->crus)
add_buf(buffer, "\n\r");
sprintf(buf, "%s ", cl_info->crus_name[i]);
add_buf(buffer, buf);
}
add_buf(buffer, "\n\r\n\rPsionicists:");
for (i = 0; i < cl_info->psis; i++){
if (i % 6 == 0 && i + 1 < cl_info->psis)
add_buf(buffer, "\n\r");
sprintf(buf, "%s ", cl_info->psi_name[i]);
add_buf(buffer, buf);
}
add_buf(buffer, "\n\r\n\rLiches:");
for (i = 0; i < cl_info->lich; i++){
if (i % 6 == 0 && i + 1 < cl_info->lich)
add_buf(buffer, "\n\r");
sprintf(buf, "%s ", cl_info->lich_name[i]);
add_buf(buffer, buf);
}
add_buf(buffer, "\n\r\n\rUndead:");
for (i = 0; i < cl_info->undead; i++){
if (i % 6 == 0 && i + 1 < cl_info->undead)
add_buf(buffer, "\n\r");
sprintf(buf, "%s ", cl_info->undead_name[i]);
add_buf(buffer, buf);
}
add_buf(buffer, "\n\r\n\rDemons:");
for (i = 0; i < cl_info->demon; i++){
if (i % 6 == 0 && i + 1 < cl_info->demon)
add_buf(buffer, "\n\r");
sprintf(buf, "%s ", cl_info->demon_name[i]);
add_buf(buffer, buf);
}
add_buf(buffer, "\n\r\n\rAvatars:");
for (i = 0; i < cl_info->avatar; i++){
if (i % 6 == 0 && i + 1 < cl_info->avatar)
add_buf(buffer, "\n\r");
sprintf(buf, "%s ", cl_info->avatar_name[i]);
add_buf(buffer, buf);
}
add_buf(buffer, "\n\r\n\rTattoos:");
for (i = 0; i < cl_info->tatto; i++){
if (i % 6 == 0 && i + 1 < cl_info->tatto)
add_buf(buffer, "\n\r");
sprintf(buf, "%s ", cl_info->tatto_name[i]);
add_buf(buffer, buf);
}
/* ALL DONE Send the note*/
namelist = str_dup("immortal");
for (;;)
{
namelist = one_argument(namelist,arg);
if (arg[0] == '\0')
break;
note = new_note();
note->prefix = 0;
note->next = NULL;
note->type = NOTE_NOTE;
free_string(note->sender);
note->sender = str_dup( sender );
free_string(note->subject);
note->subject = str_dup("Class/Race Statistics");
free_string(note->text);
note->text = str_dup(buf_string(buffer));
strtime = ctime( &mud_data.current_time );
strtime[strlen(strtime)-1] = '\0';
note->date = str_dup( strtime );
note->date_stamp = mud_data.current_time;
free_string(note->to_list);
note->to_list = str_dup(arg);
append_note(note);
}
free_buf(buffer);
}
/* purges all playes in pflies of rares as per purge_limited in comm.c */
/* returns total pfiles to be used in the game limited item calcs */
/* booleans control which actions are done */
int purge_players(bool fPurge, bool fWipe, bool fCount){
CABAL_DATA* pCab;
DIR *Directory; //Directory
struct dirent *Dir; //Directory entry
struct stat Stat; //File statistics
char pFile[MIL]; //Current pfile name
DESCRIPTOR_DATA *d = new_descriptor();
/*statistical things */
struct class_info_type cl_info;
int tot_count = 0; //Count of all pfiles.
int p_count = 0; //Count of pfiles that can carry rares.
int tot_purged = 0; //Count of pfiles purged.
int tot_wiped = 0; //Count of pfiles wiped.
/* for speed we try to avoid lookups */
const int vamp = class_lookup("vampire");
const int crus = class_lookup("crusader");
const int psi = class_lookup("psionicist");
//const int lich = class_lookup("lich");
const int undead = race_lookup("undead");
const int demon = race_lookup("demon");
/* Zero statistical info just in case */
memset( &cl_info, 0, sizeof( cl_info ));
/* Open dir, get first entry */
if ( (Directory=opendir(PLAYER_DIR)) == NULL){
bug("purge_players: Could not access PLAYER_DIR", 0);
return 0;
}
Dir= (struct dirent*) malloc (sizeof (struct dirent));
Dir->d_name[0] = '\0';
if ( (Dir = readdir(Directory)) == NULL){
bug("purge_players: Could not access first directory entry.", 0);
return 0;
}
while(Dir!=NULL){
int fFound = FALSE; //Tests if char file was loaded
/* Get info/pointer to file entry*/
sprintf(pFile, PLAYER_DIR"%s", (char *) Dir->d_name);
if ( -1 == stat( pFile, &Stat)){
char buf[MIL];
sprintf(buf, "purge_players: stat returned error on file: %s.",
pFile);
bug(buf, 0);
Dir = readdir(Directory);
continue;
}
/* check if "regular" file */
if(S_ISREG(Stat.st_mode)){
/* check for player file name*/
if (Dir->d_name[0] >= 'A' && Dir->d_name[0] <= 'Z') {
fFound = load_char (d, Dir->d_name);
if ( fFound > 0){
ROOM_INDEX_DATA* room;
CHAR_DATA* ch = d->character;
/* Make sure the room is not saved */
d->character->pcdata->roomnum/=-1;
d->character->logon = 0;
load_obj (d->character);
/* put character in a room for proper extraction */
d->character->next = char_list;
char_list = d->character;
d->character->next_player = player_list;
player_list = d->character;
reset_char(d->character);
if ( (room = get_room_index(ROOM_VNUM_PORTAL)) == NULL){
bug("purge_players: could not get indext to ROOM_PORTAL", ROOM_VNUM_PORTAL);
return 0;
}
char_to_room (d->character, room);
/* LIMITED PURGE */
if (fPurge){
if (purge_limited(d->character))
tot_purged ++;
}
/* Save character at this point, ALL things affecting char should be done before this. */
save_char_obj(d->character);
/* FILE WIPE */
if (fWipe){
if (IS_SET(d->character->act, PLR_DENY)
|| (mud_data.current_time - d->character->logoff) > (86400 * (20 + UMIN(100,2*d->character->level)))
){
/* Viri: changed to be shown only for significant players, took up too much time */
if (d->character->level > 15){
nlogf("%s (%d) last logged off %d days ago, and has been removed.",
d->character->name,
d->character->level,
(int) (mud_data.current_time - d->character->logoff) / 86400);
}
tot_wiped ++;
purge_limited(d->character);
if (ch->pCabal)
char_from_cabal( ch );
unlink (pFile);
extract_char(d->character, TRUE);
Dir = readdir(Directory);
continue;
}//END if old enough
}//END WIPE
/* Cabal/Quest/Race Counting */
if (fCount && !IS_IMMORTAL(ch)){
/* count race/class/quest first */
cl_info.class_count[ch->class]++;
cl_info.race_count[ch->race]++;
/* quest race/class members */
if (ch->class == vamp){
sprintf(cl_info.vamp_name[cl_info.vamp++], "%s", ch->name);
}
if (ch->class == crus){
sprintf(cl_info.crus_name[cl_info.crus++], "%s", ch->name);
}
if (ch->class == psi){
sprintf(cl_info.psi_name[cl_info.psis++], "%s", ch->name);
}
/*
if (ch->class == lich){
sprintf(cl_info.lich_name[cl_info.lich++], "%s", ch->name);
*/
if (ch->race == undead){
sprintf(cl_info.undead_name[cl_info.undead++], "%s", ch->name);
}
if (ch->race == demon){
sprintf(cl_info.demon_name[cl_info.demon++], "%s", ch->name);
}
if (IS_AVATAR(ch)){
sprintf(cl_info.avatar_name[cl_info.avatar++], "%s", ch->name);
}
if (ch->tattoo){
sprintf(cl_info.tatto_name[cl_info.tatto++], "%s:%s,", ch->name, deity_table[ch->tattoo].way);
}
}
if (d->character->level > 15)
p_count ++;
/* extract the char */
extract_char(d->character, TRUE);
tot_count++;
}//END if found and loaded
}//END if A to Z
}//END If file is regular
Dir = readdir(Directory);
}//END while loop.
/* Run through cabal members and check if their members exist, if not remove them */
for(pCab = cabal_list; pCab; pCab = pCab->next){
CMEMBER_DATA* cm, *cm_next;
/* reset the member counts */
pCab->cur_member = 0;
pCab->cur_elder = 0;
pCab->cur_leader = 0;
for (cm = pCab->members; cm; cm = cm_next ){
cm_next = cm->next;
/* check if member's file exists if not, remove it */
sprintf(pFile, PLAYER_DIR"%s", cm->name);
if ( -1 == stat( pFile, &Stat)){
cmember_from_cabal( cm, pCab );
continue;
}
/* increae the member counts */
pCab->cur_member ++;
if (cm->rank == RANK_ELDER)
pCab->cur_elder ++;
else if (cm->rank == RANK_LEADER)
pCab->cur_leader ++;
}
}
/* cleanup */
free_descriptor(d);
closedir(Directory);
/* send a note to all about bounties if any */
if (mud_data.bounties >= 10){
char buf[MSL];
sprintf(buf,
"In a gesture of appreciation and gratitude the members of Syndicate wish to\n\r"\
"announce that total of %d bounties have been fulfilled, and thank you for your\n\r"\
"patronage.\n\r", mud_data.bounties);
do_hal("all", "Bounty Report", buf, NOTE_NOTE);
mud_data.bounties = 0;
}
/* return count of pfiles */
if (p_count)
mud_data.pfiles = p_count;
if (fPurge)
nlogf("Total files purged: %d.", tot_purged);
if (fWipe)
nlogf("Total files wiped: %d.", tot_wiped);
if (fCount)
send_stats(&cl_info);
send_pfile_stats(mud_data.pfiles, tot_purged, tot_wiped, tot_count);
nlogf("Total files searched: %d.", tot_count);
nlogf("Current pfile count at: %d.", mud_data.pfiles);
return tot_count;
}
/* initiliazes trap to index data */
void init_trap(TRAP_DATA* tr, TRAP_INDEX_DATA* pTrapIndex){
int i = 0;
if (tr->name == NULL)
tr->name = str_dup(pTrapIndex->name);
if (tr->echo == NULL)
tr->echo = str_dup(pTrapIndex->echo);
if (tr->oEcho == NULL)
tr->oEcho = str_dup(pTrapIndex->oEcho);
tr->armed = IS_SET(pTrapIndex->flags, TRAP_DELAY) ? FALSE : TRUE;
tr->age = 0;
tr->pIndexData = pTrapIndex;
tr->vnum = pTrapIndex->vnum;
tr->area = pTrapIndex->area;
tr->type = pTrapIndex->type;
tr->level = pTrapIndex->level;
tr->duration = -1;
tr->flags = pTrapIndex->flags;
for (i = 0; i < MAX_TRAPVAL; i++)
tr->value[i] = pTrapIndex->value[i];
}
/* Big mama top level function. */
void boot_db( bool fHotReboot )
{
char pFile [MSL];
struct stat Stat; //File statistics
int sn;
/* Init string stuff */
{
log_string("Initializing shared string manager...");
init_string_space();
fBootDb = TRUE;
}
/* Init random number generator. */
{
log_string("Initializing random number generator...");
init_mm( );
}
/* Set mud data */
reset_mdata();
/* restore mud data if any */
read_mud();
/* if this is not hotreboot, reset crash time and deaths */
if (!fHotReboot){
mud_data.crash_time = mud_data.current_time;
mud_data.deaths = 0;
}
/* check master questor */
sprintf(pFile, PLAYER_DIR"%s", mud_data.questor);
if ( -1 != stat( pFile, &Stat))
mud_data.max_quest = 1;
log_string("Assigning GRN's...");
for ( sn = 0; race_table[sn].name; sn++){
if (race_table[sn].grn != NULL)
*race_table[sn].grn = sn;
}
/* assign gcn's for classes which have them */
log_string("Assigning GCN's...");
for ( sn = 0; class_table[sn].name; sn++){
if (class_table[sn].gcn != NULL)
*class_table[sn].gcn = sn;
}
/* Assign gsn's for skills which have them. */
{
log_string("Assigning GSN's...");
for ( sn = 0; sn < MAX_SKILL; sn++ )
if ( skill_table[sn].pgsn != NULL )
*skill_table[sn].pgsn = sn;
/* Assign gen's with values starting at MAX_SKILL */
log_string("Assigning GEN's...");
for ( sn = MAX_SKILL; sn < (MAX_SKILL + MAX_EFFECTS); sn++ )
{
if ( effect_table[gn_pos(sn)].pgen != NULL )
*effect_table[gn_pos(sn)].pgen = sn;
}
/* Assign Songs */
log_string("Assigning SONGS's...");
for ( sn = 0; sn < MAX_SONG; sn++ ){
if ( song_table[sn].pgsn != NULL )
*song_table[sn].pgsn = sn;
}
}
/* Read in all the area files. */
{
FILE *fpList;
log_string("Reading area files...");
if ( ( fpList = fopen( AREA_LIST, "r" ) ) == NULL )
{
perror( AREA_LIST );
fpList = fopen( NULL_FILE, "r" );
fclose( fpList );
exit( 1 );
}
for ( ; ; )
{
strcpy( strArea, fread_word( fpList ) );
if ( strArea[0] == '$' )
break;
if ( strArea[0] == '-' )
{
fpArea = stdin;
}
else if ( ( fpArea = fopen( strArea, "r" ) ) == NULL )
{
perror( strArea );
fpArea = fopen( NULL_FILE, "r" );
fclose( fpArea );
exit( 1 );
}
for ( ; ; )
{
char *word;
if ( fread_letter( fpArea ) != '#' )
{
bug( "Boot_db: # not found.", 0 );
exit( 1 );
}
word = fread_word( fpArea );
if ( word[0] == '$' ) break;
else if ( !str_cmp( word, "AREA" ) ) load_area (fpArea);
else if ( !str_cmp( word, "AREADATA" ) ) new_load_area(fpArea);
else if ( !str_cmp( word, "HELPS" ) ) load_helps (fpArea);
else if ( !str_cmp( word, "MOBOLD" ) ) load_old_mob (fpArea);
else if ( !str_cmp( word, "MOBILES" ) ) load_mobiles (fpArea);
else if ( !str_cmp( word, "CABALS" ) ) load_cabal_indexes(fpArea);
else if ( !str_cmp( word, "ARMIES" ) ) load_army_indexes(fpArea);
else if ( !str_cmp( word, "MOBPROGS" ) ) load_mobprogs(fpArea);
else if ( !str_cmp( word, "OBJPROGS" ) ) load_objprogs(fpArea);
else if ( !str_cmp( word, "ROOMPROGS") ) load_roomprogs(fpArea);
else if ( !str_cmp( word, "TRAPS" ) ) load_traps(fpArea);
else if ( !str_cmp( word, "OBJOLD" ) ) bug("old obj found",0);
else if ( !str_cmp( word, "OBJECTS" ) ) load_objects (fpArea);
else if ( !str_cmp( word, "RESETS" ) ) load_resets (fpArea);
else if ( !str_cmp( word, "ROOMS" ) ) load_rooms (fpArea);
else if ( !str_cmp( word, "SHOPS" ) ) load_shops (fpArea);
else if ( !str_cmp( word, "SOCIALS" ) ) load_socials (fpArea);
else if ( !str_cmp( word, "SPECIALS" ) ) load_specials(fpArea);
else
{
bug( "Boot_db: bad section name.", 0 );
exit( 1 );
}
}
if ( fpArea != stdin )
fclose( fpArea );
fpArea = NULL;
}
fclose( fpList );
}
/* clans need to be loaded before cabals */
log_string("Loading clans...");
LoadClans( );
/* cabals need to be loaded before their armies and rooms being restored */
log_string("Loading cabals...");
load_cabals( );
log_string("Loading pacts...");
load_pacts();
/* area/objects are in, load virtual armies, cabal rooms and objects */
log_string("Loading Virtual Cabal Data...");
load_cvrooms( );
/* Fix up exits. *
* Declare db booting over. *
* Reset all areas once. *
* Load up the notes and ban files. */
{
log_string("Fixing cabals...");
/* this also fixes up virtual cabal rooms */
fix_cabals( );
log_string("Fixing exits...");
fix_exits( );
log_string("Refreshing Support...");
refresh_cabal_support();
log_string("Refreshing Area Distances...");
CalcCabalDistances();
log_string("Fixing mobprogs...");
fix_mobprogs( );
log_string("Fixing objprogs...");
fix_objprogs( );
log_string("Fixing roomprogs...");
fix_roomprogs( );
daPrompt = str_dup( "<%hhp %mm %vmv> " );
/* CLEAR STRING ALOCATION */
fBootDb = FALSE;
boot_done();
log_string("Loading eq limits...");
load_limits();
log_string("Loading bounties...");
load_bounties();
log_string("Loading challenges...");
load_challenges();
if (fHotReboot)
{
log_string("Loading saved items...");
load_obj(NULL);
}
log_string("Seeding objects...");
seed_objects( );
log_string("Refreshing area support values...");
refresh_area_support( );
log_string("Loading armies...");
load_armies();
log_string("Updating areas...");
area_update( );
loadallmobs = FALSE;
log_string("Loading notes...");
load_notes( );
log_string("Loading helps...");
load_helps_new( );
log_string("Loading bans...");
load_bans();
log_string("Loading tomes...");
InitTomes();
/* MAINTANCE */
if (IS_SET(reboot_act, REBOOT_COLOR)){
log_string("COLOR specified: Coloring Rooms...");
color_rooms();
}
if (IS_SET(reboot_act, REBOOT_PURGE)
|| IS_SET(reboot_act, REBOOT_COUNT)
|| IS_SET(reboot_act, REBOOT_WIPE)
|| IS_SET(reboot_act, REBOOT_CABAL)){
if (IS_SET(reboot_act, REBOOT_PURGE))
log_string("PURGE specified: Purging rares...");
if (IS_SET(reboot_act, REBOOT_WIPE))
log_string("WIPE specified: Wiping old pfiles...");
if (IS_SET(reboot_act, REBOOT_WIPE))
log_string("WIPE specified: Wiping counting pfiles...");
if (IS_SET(reboot_act, REBOOT_CABAL))
log_string("CABAL specified: Compiling cabal data...");
/* if PURGE or WIPE is not set, only counting is done */
purge_players(IS_SET(reboot_act, REBOOT_PURGE),
IS_SET(reboot_act, REBOOT_WIPE),
IS_SET(reboot_act, REBOOT_CABAL));
}
if (IS_SET(reboot_act, REBOOT_HELPS)){
log_string("HELP specified: Generating helps...");
make_html_helps();
}
MOBtrigger = TRUE;
if (fHotReboot)
hotreboot_recover();
}
}
void load_area( FILE *fp )
{
AREA_DATA *pArea;
pArea = alloc_perm( sizeof(*pArea) );
pArea->file_name = fread_string(fp);
pArea->area_flags = AREA_LOADING;
pArea->security = 9;
pArea->builders = str_dup( "None" );
pArea->vnum = top_area;
pArea->name = fread_string( fp );
pArea->prefix = fread_string( fp );
pArea->credits = fread_string( fp );
pArea->min_vnum = fread_number(fp);
pArea->max_vnum = fread_number(fp);
pArea->age = 15;
pArea->nplayer = 0;
pArea->empty = FALSE;
pArea->pCabal = NULL;
if ( !area_first )
area_first = pArea;
if ( area_last )
{
area_last->next = pArea;
REMOVE_BIT(area_last->area_flags, AREA_LOADING);
}
area_last = pArea;
pArea->next = NULL;
top_area++;
return;
}
/* OLC - Use these macros to load any new area formats that you *
* choose to support. See the new_load_area format below for a *
* short example. */
#if defined(KEY)
#undef KEY
#endif
#define KEY( literal, field, value ) \
if ( !str_cmp( word, literal ) ) \
{ \
field = value; \
fMatch = TRUE; \
break; \
}
#define SKEY( string, field ) \
if ( !str_cmp( word, string ) ) \
{ \
free_string( field ); \
field = fread_string( fp ); \
fMatch = TRUE; \
break; \
}
/* OLC - Snarf an 'area' header line. *
* #AREAFILE *
* Name { All } Locke Newbie School~ *
* Repop A teacher pops in the room and says, 'Repop coming!'~ *
* Recall 3001 *
* End */
void new_load_area( FILE *fp )
{
AREA_DATA *pArea;
char *word = NULL;
bool fMatch;
int count=0;
pArea = alloc_perm( sizeof(*pArea) );
pArea->age = 15;
pArea->nplayer = 0;
pArea->file_name = str_dup( strArea );
pArea->vnum = top_area;
pArea->name = str_dup( "New Area" );
pArea->builders = str_dup( "" );
pArea->prefix = str_dup( "" );
pArea->security = 9;
pArea->min_vnum = 0;
pArea->max_vnum = 0;
pArea->area_flags = 0;
pArea->pCabal = NULL;
pArea->bastion_max = 0;
pArea->bastion_current = 0;
for (count=0; count < MAX_CRIME; count++) {
pArea->crimes[count] = 0;
}
/* set cabal distances to max */
for (count = 0; count < MAX_CABAL; count++){
pArea->cabal_distance[count] = 999;
}
for ( ; ; )
{
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
switch ( UPPER(word[0]) )
{
case 'B':
SKEY( "Builders", pArea->builders );
break;
case 'C':
SKEY( "Credits", pArea->credits );
if ( !str_cmp( word, "Crimes" ) ){
int max = fread_number( fp );
int i = 0;
for ( i = 0; i < MAX_CRIME; i++){
if (i < max)
pArea->crimes[i] = fread_number( fp );
else
pArea->crimes[i] = 0;
if (i == CRIME_OBSTRUCT)
pArea->crimes[i] = CRIME_HEAVY;
else if (i == CRIME_MURDER)
pArea->crimes[i] = UMAX(CRIME_LIGHT, pArea->crimes[i]);
}
break;
}
break;
case 'N':
SKEY( "Name", pArea->name );
log_string("Loading new area");
break;
case 'P':
SKEY( "Pref", pArea->prefix );
case 'S':
KEY( "Security", pArea->security, fread_number( fp ) );
KEY( "Startroom", pArea->startroom, fread_number( fp ) );
break;
case 'F':
if (!str_cmp( word, "Flags")){
int i = 0, flag = 0;
flag = fread_number( fp );
for (i = 0; area_flags[i].name; i ++){
if (area_flags[i].settable == FALSE)
flag &= ~area_flags[i].bit;
}
pArea->area_flags = flag;
break;
}
break;
case 'V':
if ( !str_cmp( word, "VNUMs" ) )
{
pArea->min_vnum = fread_number( fp );
pArea->max_vnum = fread_number( fp );
}
break;
case 'E':
if ( word != NULL && !str_cmp( word, "End" ) )
{
fMatch = TRUE;
if ( area_first == NULL )
area_first = pArea;
if ( area_last != NULL )
area_last->next = pArea;
area_last = pArea;
pArea->next = NULL;
top_area++;
return;
}
break;
case 'M':
if ( !str_cmp( word, "Max_Bastions" ) ) {
pArea->bastion_max = fread_number( fp );
}
break;
}
}
}
/* Sets vnum range for area using OLC protection features. */
void assign_area_vnum( int vnum )
{
if ( area_last->min_vnum == 0 || area_last->max_vnum == 0 )
area_last->min_vnum = area_last->max_vnum = vnum;
if ( vnum != URANGE( area_last->min_vnum, vnum, area_last->max_vnum ) )
{
if ( vnum < area_last->min_vnum )
area_last->min_vnum = vnum;
else
area_last->max_vnum = vnum;
}
}
void load_helps( FILE *fp )
{
CABAL_INDEX_DATA* pci;
HELP_DATA *pHelp;
char* string;
for ( ; ; )
{
pHelp = alloc_perm( sizeof(*pHelp) );
pHelp->level = fread_number( fp );
/* select type based on level and possible next word following */
switch (pHelp->level){
default:
case HELP_ALL:
pHelp->type = 0;
break;
case HELP_CLASS:
pHelp->type = class_lookup( fread_string (fp ));
break;
case HELP_RACE:
string = fread_string( fp );
if (!str_cmp(string, "avatar"))
pHelp->type = -1;
else
pHelp->type = race_lookup( string );
free_string( string );
break;
case HELP_CABAL:
if ( (pci = get_cabal_index_str( fread_string( fp ))) != NULL)
pHelp->type = pci->vnum;
break;
case HELP_PSALM:
pHelp->type = psalm_lookup( fread_string (fp ));
break;
}
pHelp->keyword = fread_string( fp );
if ( pHelp->keyword[0] == '$' )
break;
pHelp->text = fread_string( fp );
if ( !str_cmp( pHelp->keyword, "greeting" ) )
help_greeting = pHelp->text;
if ( help_first == NULL )
help_first = pHelp;
if ( help_last != NULL )
help_last->next = pHelp;
help_last = pHelp;
pHelp->next = NULL;
top_help++;
}
}
void load_helps_new( ){
HELP_DATA* pHelp;
CABAL_INDEX_DATA* pci;
FILE *fp;
char* string;
fclose( fpReserve );
if ( ( fp = fopen( HELP_FILE, "r" ) ) == NULL ){
fp = fopen( NULL_FILE, "r" );
fclose (fp);
perror( HELP_FILE );
}
else{
for ( ; ; ){
sh_int vnum;
char letter;
letter = fread_letter( fp );
if ( letter != '#' ){
bug( "Load_help: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
if ( get_help_index( vnum ) != NULL ){
bug( "Load_helps: vnum %d duplicated.", vnum );
exit( 1 );
}
pHelp = new_help_index();
pHelp->vnum = vnum;
pHelp->level = fread_number( fp );
/* select type based on level and possible next word following */
switch (pHelp->level){
default:
case HELP_ALL:
pHelp->type = 0;
break;
case HELP_CLASS:
pHelp->type = class_lookup( fread_string (fp ));
break;
case HELP_RACE:
string = fread_string( fp );
if (!str_cmp(string, "avatar"))
pHelp->type = -1;
else
pHelp->type = race_lookup( string );
free_string( string );
break;
case HELP_CABAL:
if ( (pci = get_cabal_index_str( fread_string( fp ))) != NULL)
pHelp->type = pci->vnum;
break;
case HELP_PSALM:
pHelp->type = psalm_lookup( fread_string (fp ));
break;
}
pHelp->keyword = fread_string( fp );
if ( pHelp->keyword[0] == '$' )
break;
pHelp->text = fread_string( fp );
if ( !str_cmp( pHelp->keyword, "greeting" ) )
help_greeting = pHelp->text;
if ( help_first == NULL )
help_first = pHelp;
if ( help_last != NULL )
help_last->next = pHelp;
help_last = pHelp;
pHelp->next = NULL;
}
fclose(fp);
fpReserve = fopen( NULL_FILE, "r" );
}
}
void load_old_mob( FILE *fp )
{
MOB_INDEX_DATA *pMobIndex;
int race;
char name[MSL];
if ( !area_last )
{
bug( "Load_mobiles: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; )
{
sh_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_mobiles: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_mob_index( vnum ) != NULL )
{
bug( "Load_mobiles: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pMobIndex = alloc_perm( sizeof(*pMobIndex) );
pMobIndex->vnum = vnum;
pMobIndex->area = area_last;
pMobIndex->new_format = FALSE;
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_flag( fp ) | ACT_IS_NPC;
pMobIndex->affected_by = fread_flag( fp );
pMobIndex->pShop = NULL;
pMobIndex->alignment = fread_number( fp );
letter = fread_letter( fp );
pMobIndex->level = fread_number( fp );
fread_number( fp );
fread_number( fp );
fread_number( fp );
/* 'd' */ fread_letter( fp );
fread_number( fp );
/* '+' */ fread_letter( fp );
fread_number( fp );
fread_number( fp );
/* 'd' */ fread_letter( fp );
fread_number( fp );
/* '+' */ fread_letter( fp );
fread_number( fp );
pMobIndex->gold = fread_number( fp )/20;
fread_number( fp );
pMobIndex->start_pos = fread_number( fp );
pMobIndex->default_pos = fread_number( fp );
if (pMobIndex->start_pos < POS_SLEEPING)
pMobIndex->start_pos = POS_STANDING;
if (pMobIndex->default_pos < POS_SLEEPING)
pMobIndex->default_pos = POS_STANDING;
if (pMobIndex->start_pos > POS_STANDING)
pMobIndex->start_pos = POS_STANDING;
if (pMobIndex->default_pos > POS_STANDING)
pMobIndex->default_pos = POS_STANDING;
pMobIndex->sex = fread_number( fp );
if (pMobIndex->sex > 3)
pMobIndex->sex = 0;
one_argument(pMobIndex->player_name,name);
if (name[0] == '\0' || (race = race_lookup(name)) == 0)
{
pMobIndex->race = race_lookup("human");
pMobIndex->off_flags = OFF_DODGE|OFF_DISARM|OFF_TRIP|ASSIST_VNUM;
pMobIndex->imm_flags = 0;
pMobIndex->res_flags = 0;
pMobIndex->vuln_flags = 0;
pMobIndex->form = FORM_EDIBLE|FORM_SENTIENT|FORM_BIPED|FORM_MAMMAL;
pMobIndex->parts = PART_HEAD|PART_ARMS|PART_LEGS|PART_HEART|PART_BRAINS|PART_GUTS;
}
else
{
pMobIndex->race = race;
pMobIndex->off_flags = OFF_DODGE|OFF_DISARM|OFF_TRIP|ASSIST_RACE|race_table[race].off;
pMobIndex->imm_flags = race_table[race].imm;
pMobIndex->res_flags = race_table[race].res;
pMobIndex->vuln_flags = race_table[race].vuln;
pMobIndex->form = race_table[race].form;
pMobIndex->parts = race_table[race].parts;
}
if ( letter != 'S' )
{
bug( "Load_mobiles: vnum %d non-S.", vnum );
exit( 1 );
}
convert_mobile( pMobIndex );
iHash = vnum % MAX_KEY_HASH;
pMobIndex->next = mob_index_hash[iHash];
mob_index_hash[iHash] = pMobIndex;
top_mob_index++;
top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob;
assign_area_vnum( vnum );
kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-1)].number++;
}
}
void load_old_obj( FILE *fp )
{
OBJ_INDEX_DATA *pObjIndex;
if ( !area_last )
{
bug( "Load_objects: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; )
{
sh_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_objects: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_obj_index( vnum ) != NULL )
{
bug( "Load_objects: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pObjIndex = alloc_perm( sizeof(*pObjIndex) );
pObjIndex->vnum = vnum;
pObjIndex->area = area_last;
pObjIndex->new_format = FALSE;
pObjIndex->reset_num = 0;
pObjIndex->name = fread_string( fp );
pObjIndex->short_descr = fread_string( fp );
pObjIndex->description = fread_string( fp );
fread_string( fp );
pObjIndex->short_descr[0] = LOWER(pObjIndex->short_descr[0]);
pObjIndex->description[0] = UPPER(pObjIndex->description[0]);
pObjIndex->material = str_dup("");
pObjIndex->class = -1;
pObjIndex->race = 0;
pObjIndex->item_type = fread_number( fp );
pObjIndex->extra_flags = fread_flag( fp );
pObjIndex->wear_flags = fread_flag( fp );
if (pObjIndex->item_type == ITEM_POTION && !CAN_WEAR(pObjIndex, ITEM_HOLD))
SET_BIT(pObjIndex->wear_flags,ITEM_HOLD);
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] = 0;
pObjIndex->level = 0;
pObjIndex->condition = 100;
pObjIndex->weight = fread_number( fp );
pObjIndex->cost = fread_number( fp );
fread_number( fp );
if (pObjIndex->item_type == ITEM_WEAPON
&& (is_name("two",pObjIndex->name) || is_name("two-handed",pObjIndex->name) || is_name("claymore",pObjIndex->name)))
SET_BIT(pObjIndex->value[4],WEAPON_TWO_HANDS);
for ( ; ; )
{
char letter;
letter = fread_letter( fp );
if ( letter == 'A' )
{
AFFECT_DATA *paf;
paf = alloc_perm( sizeof(*paf) );
paf->where = TO_OBJECT;
paf->type = -1;
paf->level = 20;
paf->duration = -1;
paf->location = fread_number( fp );
paf->modifier = fread_number( fp );
paf->bitvector = 0;
paf->next = pObjIndex->affected;
pObjIndex->affected = paf;
top_affect++;
}
else if ( letter == 'E' )
{
EXTRA_DESCR_DATA *ed;
ed = alloc_perm( sizeof(*ed) );
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
ed->next = pObjIndex->extra_descr;
pObjIndex->extra_descr = ed;
top_ed++;
}
else if ( letter == 'O' )
{
PROG_LIST *pOprog;
char *word;
int trigger = 0;
pOprog = alloc_perm(sizeof(*pOprog));
word = fread_word( fp );
if ( !(trigger = flag_lookup( word, oprog_flags )) )
{
bug( "OBJprogs: invalid trigger.",0);
exit(1);
}
SET_BIT( pObjIndex->oprog_flags, trigger );
pOprog->trig_type = trigger;
pOprog->vnum = fread_number( fp );
pOprog->trig_phrase = fread_string( fp );
pOprog->next = pObjIndex->oprogs;
pObjIndex->oprogs = pOprog;
}
else if ( letter == 'T' )
{
OBJ_SPELL_DATA *new_spell;
new_spell = alloc_perm( sizeof( *new_spell ) );
new_spell->spell = fread_number( fp );
new_spell->target = fread_number( fp );
new_spell->percent = fread_number( fp );
new_spell->message = fread_string( fp );
new_spell->message2 = fread_string( fp );
new_spell->next = pObjIndex->spell;
pObjIndex->spell = new_spell;
}
else if ( letter == 'M' )
{
OBJ_MESSAGE_DATA *new_message;
new_message = alloc_perm( sizeof( *new_message ) );
new_message->onself = fread_string( fp );
new_message->onother = fread_string( fp );
new_message->offself = fread_string( fp );
new_message->offother = fread_string( fp );
pObjIndex->message = new_message;
}
else
{
ungetc( letter, fp );
break;
}
}
if (pObjIndex->item_type == ITEM_ARMOR)
{
pObjIndex->value[1] = pObjIndex->value[0];
pObjIndex->value[2] = pObjIndex->value[1];
}
switch ( pObjIndex->item_type )
{
case ITEM_PILL:
case ITEM_POTION:
case ITEM_RELIC:
case ITEM_SOCKET:
case ITEM_ARTIFACT:
case ITEM_SCROLL:
case ITEM_HERB:
pObjIndex->value[1] = slot_lookup( pObjIndex->value[1] );
pObjIndex->value[2] = slot_lookup( pObjIndex->value[2] );
pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] );
pObjIndex->value[4] = slot_lookup( pObjIndex->value[4] );
break;
case ITEM_STAFF:
case ITEM_WAND:
pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] );
break;
}
convert_object( pObjIndex );
iHash = vnum % MAX_KEY_HASH;
pObjIndex->next = obj_index_hash[iHash];
obj_index_hash[iHash] = pObjIndex;
top_obj_index++;
top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj;
assign_area_vnum( vnum );
}
}
/* OLC - Adds a reset to a room. *
* Similar to add_reset in olc.c */
void new_reset( ROOM_INDEX_DATA *pR, RESET_DATA *pReset )
{
RESET_DATA *pr;
if ( !pR )
return;
pr = pR->reset_last;
if ( !pr )
{
pR->reset_first = pReset;
pR->reset_last = pReset;
}
else
{
pR->reset_last->next = pReset;
pR->reset_last = pReset;
pR->reset_last->next = NULL;
}
top_reset++;
}
void load_reset( FILE* fp ){
RESET_DATA *pReset = NULL;
int iLastRoom = 0, iLastObj = 0;
for ( ; ; )
{
ROOM_INDEX_DATA *pRoomIndex;
OBJ_INDEX_DATA *temp_index;
char letter = '\0';
letter = fread_letter (fp);
/* Viri: For some reason compiler thought letter could be uninitilised at this point. */
if (&letter == NULL)
letter = '\0';
if (letter == 'S') {
break;
}
if (letter == '*' ) {
fread_to_eol( fp );
continue;
}
pReset = alloc_perm( sizeof(*pReset) );
pReset->command = letter;
fread_number( fp );
pReset->arg1 = fread_number( fp );
pReset->arg2 = fread_number( fp );
pReset->arg3 = (letter == 'G' || letter == 'R') ? 0 : fread_number( fp );
pReset->arg4 = (letter == 'P' || letter == 'M' || letter == 'T') ? fread_number(fp) : 0;
fread_to_eol( fp );
switch ( letter )
{
default:
bug( "Load_resets: bad command '%c'.", letter );
exit( 1 );
break;
case 'M':
pRoomIndex = get_room_index ( pReset->arg3 );
if ( pRoomIndex )
{
new_reset( pRoomIndex, pReset );
iLastRoom = pReset->arg3;
}
break;
case 'O':
temp_index = get_obj_index ( pReset->arg1 );
temp_index->reset_num++;
if ( ( pRoomIndex = get_room_index ( pReset->arg3 ) ) )
{
new_reset( pRoomIndex, pReset );
iLastObj = pReset->arg3;
}
break;
case 'P':
temp_index = get_obj_index ( pReset->arg1 );
temp_index->reset_num++;
if ( ( pRoomIndex = get_room_index ( iLastObj ) ) )
new_reset( pRoomIndex, pReset );
break;
case 'G':
case 'E':
temp_index = get_obj_index ( pReset->arg1 );
temp_index->reset_num++;
if ( ( pRoomIndex = get_room_index ( iLastRoom ) ) )
{
new_reset( pRoomIndex, pReset );
iLastObj = iLastRoom;
}
break;
case 'D':
/* this is now obsolete
pRoomIndex = get_room_index( pReset->arg1 );
pexit = pRoomIndex->exit[pReset->arg2];
if ( pReset->arg2 < 0 || pReset->arg2 > (MAX_DIR -1) || !pRoomIndex || !pexit || !IS_SET( pexit->rs_flags, EX_ISDOOR ) )
{
bug( "Load_resets: 'D': exit %d not door.", pReset->arg2 );
exit( 1 );
}
switch ( pReset->arg3 )
{
default:
bug( "Load_resets: 'D': bad 'locks': %d." , pReset->arg3);
case 0: break;
case 1: SET_BIT( pexit->rs_flags, EX_CLOSED );
SET_BIT( pexit->exit_info, EX_CLOSED ); break;
case 2: SET_BIT( pexit->rs_flags, EX_CLOSED | EX_LOCKED );
SET_BIT( pexit->exit_info, EX_CLOSED | EX_LOCKED ); break;
}
break;
*/
case 'R':
pRoomIndex = get_room_index( pReset->arg1 );
if ( pReset->arg2 < 0 || pReset->arg2 > MAX_DIR )
{
bug( "Load_resets: 'R': bad exit %d.", pReset->arg2 );
exit( 1 );
}
if ( pRoomIndex )
new_reset( pRoomIndex, pReset );
break;
case 'T':
if ( ( pRoomIndex = get_room_index ( pReset->arg3 ) ) ){
new_reset( pRoomIndex, pReset );
}
break;
}
}
}
void load_resets( FILE *fp )
{
if ( !area_last )
{
bug( "Load_resets: no #AREA seen yet.", 0 );
exit( 1 );
}
load_reset( fp );
}
/* reads a single room's data */
void read_room( FILE *fp, ROOM_INDEX_DATA* pRoomIndex, AREA_DATA* area, int vnum ){
int watch_vnum;
Double_List * tmp_list;
int door = 0;
pRoomIndex->people = NULL;
pRoomIndex->contents = NULL;
pRoomIndex->extra_descr = NULL;
pRoomIndex->area = area;
pRoomIndex->vnum = vnum;
pRoomIndex->watch_vnums = NULL;
tmp_list = pRoomIndex->watch_vnums;
pRoomIndex->name = fread_string( fp );
pRoomIndex->description = fread_string( fp );
pRoomIndex->description2 = fread_string( fp );
if (pRoomIndex->description2[0])
night_count++;
fread_number( fp );
pRoomIndex->room_flags = fread_flag( fp );
pRoomIndex->room_flags2 = fread_flag( fp );
pRoomIndex->sector_type = fread_number( fp );
pRoomIndex->light = 0;
pRoomIndex->psitimer = 0;
pRoomIndex->temp = 72;
for ( door = 0; door <= 5; door++ )
pRoomIndex->exit[door] = NULL;
pRoomIndex->heal_rate = 100;
pRoomIndex->mana_rate = 100;
for ( ; ; ){
char letter = fread_letter( fp );
if ( letter == 'S' )
break;
else if ( letter == 'H')
pRoomIndex->heal_rate = fread_number(fp);
else if ( letter == 'M')
pRoomIndex->mana_rate = fread_number(fp);
else if ( letter == 'W') {
watch_vnum = fread_number(fp);
if (watch_vnum > 0) {
if (pRoomIndex->watch_vnums == NULL) {
pRoomIndex->watch_vnums = (Double_List *) malloc (sizeof (Double_List));
pRoomIndex->watch_vnums->cur_entry = (void *) (long) watch_vnum;
pRoomIndex->watch_vnums->next_node = NULL;
pRoomIndex->watch_vnums->prev_node = NULL;
tmp_list = pRoomIndex->watch_vnums;
}
else {
tmp_list->next_node = (Double_List *) malloc (sizeof (Double_List));
tmp_list->next_node->cur_entry = (void *) (long) watch_vnum;
tmp_list->next_node->next_node = NULL;
tmp_list->next_node->prev_node = tmp_list;
tmp_list = tmp_list->next_node;
}
}
}
else if ( letter == 'C')
{
CABAL_INDEX_DATA* pci;
if (pRoomIndex->pCabal)
{
bug("read_room duplicate cabal fields.",0);
exit(1);
}
else if ( (pci = get_cabal_index_str(fread_string(fp))) != NULL)
pRoomIndex->cabal_vnum = pci->vnum;
}
else if ( letter == 'T')
pRoomIndex->temp = fread_number(fp);
else if ( letter == 'D' )
{
EXIT_DATA *pexit;
door = fread_number( fp );
if ( door < 0 || door >= MAX_DOOR ){
bug( "read_room: vnum %d has bad door number.", vnum );
exit( 1 );
}
pexit = new_exit();
pexit->description = fread_string( fp );
pexit->keyword = fread_string( fp );
pexit->rs_flags = fread_flag( fp );
pexit->exit_info = pexit->rs_flags;
pexit->key = fread_number( fp );
pexit->vnum = fread_number( fp );
pexit->orig_door = door;
pRoomIndex->exit[door] = pexit;
pRoomIndex->old_exit[door] = pexit;
top_exit++;
}
else if ( letter == 'E' )
{
EXTRA_DESCR_DATA *ed;
ed = alloc_perm( sizeof(*ed) );
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
ed->next = pRoomIndex->extra_descr;
pRoomIndex->extra_descr = ed;
top_ed++;
}
else if ( letter == 'O' )
fread_string ( fp );
else if ( letter == 'P' )
{
PROG_LIST *pRprog;
char *word;
int trigger = 0;
pRprog = alloc_perm(sizeof(*pRprog));
word = fread_word( fp );
if ( !(trigger = flag_lookup( word, rprog_flags )) )
{
bug( "ROOMprogs: invalid trigger.",0);
exit(1);
}
SET_BIT( pRoomIndex->rprog_flags, trigger );
pRprog->trig_type = trigger;
pRprog->vnum = fread_number( fp );
pRprog->trig_phrase = fread_string( fp );
pRprog->next = pRoomIndex->rprogs;
pRoomIndex->rprogs = pRprog;
}
else
{
bug( "read_room: vnum %d has flag not recognized.", vnum );
exit( 1 );
}
}
}
/* gets the next free vnum for vir. room */
int get_vir_vnum(){
int vnum = 0;
/* check if there are any unused ones waiting */
if (last_vir_vnum > 0){
vnum = free_vir_vnums[--last_vir_vnum];
}
else{
vnum = MAX_ROOM_VNUM + top_vir_room;
top_vir_room++;
}
return vnum;
}
/* records a vir vnum to be reused */
void free_vir_vnum( int vnum ){
if (last_vir_vnum < MAX_FREE_VNUM)
free_vir_vnums[last_vir_vnum++] = vnum;
}
/* assigns a vnum, hashes, and links a single virtual room to its exits */
void load_vir_room( ROOM_INDEX_DATA* pRoom, AREA_DATA* pArea ){
EXIT_DATA* pexit;
int door = 0;
int players = 0;
int iHash;
/* first we give the room a new vnum which is 1 higher then the last one */
pRoom->vnum = get_vir_vnum();
pRoom->area = pArea;
/* if this room has a cabal, we increase its total */
if (pRoom->pCabal)
get_parent(pRoom->pCabal)->cur_room++;
/* we now hash and link the room to the room index table */
iHash = pRoom->vnum % MAX_KEY_HASH;
pRoom->next = room_index_hash[iHash];
room_index_hash[iHash]= pRoom;
/* refresh resets for new vnum */
fix_resets( pRoom->reset_first, pRoom->vnum );
/* deal with exits now if this is after a normal reboot */
/* during a boot, fix_exits() deals with this */
if (fBootDb)
return;
for ( door = 0; door < MAX_DOOR; door++ ){
if ( ( pexit = pRoom->exit[door] ) == NULL )
continue;
else{
ROOM_INDEX_DATA* pToRoom;
int rev = rev_dir[door];
if ( pexit->vnum <= 0 || (pToRoom = get_room_index(pexit->vnum)) == NULL){
pexit->to_room = NULL;
continue;
}
pexit->to_room = pToRoom;
/* make sure the other side has a free exit */
if (pToRoom->exit[rev] != NULL){
char buf[MIL];
sprintf( buf, "load_vir_room: could not link door %d for vir. room %s to room %d as exit already linked.",
door, pRoom->name, pexit->vnum);
bug( buf, 0);
continue;
}
else{
pToRoom->exit[rev] = new_exit();
pToRoom->exit[rev]->vnum = pRoom->vnum;
pToRoom->exit[rev]->orig_door = rev;
pToRoom->exit[rev]->to_room = pRoom;
pToRoom->exit[rev]->rs_flags = pexit->rs_flags;
pToRoom->exit[rev]->exit_info = pexit->exit_info;
pToRoom->exit[rev]->key = pexit->key;
if (IS_NULLSTR(pToRoom->exit[rev]->keyword))
pToRoom->exit[rev]->keyword = str_dup( pexit->keyword );
}
}//end if exit
}//end for door
/* clear no reset flag if one exists, and reset room since this is after reboot */
REMOVE_BIT( pRoom->room_flags2, ROOM_NO_RESET);
/* we have to cheat here a bit to load objects properly */
players = pRoom->area->nplayer;
pRoom->area->nplayer = 0;
reset_room( pRoom );
pRoom->area->nplayer = players;
}
/* unlinkes and removes a single virtual room, vnum is recorded to be reused */
bool unload_vir_room( ROOM_INDEX_DATA* pRoom ){
EXIT_DATA* pexit;
ROOM_INDEX_DATA* prev;
CHAR_DATA* vch;
int iHash;
int door;
if (!IS_VIRROOM( pRoom))
return FALSE;
/* first we free up the virtual vnum */
free_vir_vnum( pRoom->vnum);
/* if this room has a cabal, we increase its total */
if (pRoom->pCabal)
get_parent(pRoom->pCabal)->cur_room--;
/* unlink the exits, reverse too if any */
for ( door = 0; door < MAX_DOOR; door++ ){
if ( ( pexit = pRoom->exit[door] ) == NULL )
continue;
else{
int rev = rev_dir[door];
/* we free/unlink any reverse exit that leads here */
if (pexit->to_room && pexit->to_room->exit[rev] && pexit->to_room->exit[rev]->to_room == pRoom){
free_exit( pexit->to_room->exit[rev]);
pexit->to_room->exit[rev] = NULL;
}
/* now we free this exit */
free_exit( pexit );
pRoom->exit[door] = NULL;
}
}
/* we now throw any players/mobs out of the room */
if (pRoom->people){
act_new("With a flash of bright light the area around you disappears and you find yourself elsewhere!.",
pRoom->people, NULL, NULL, TO_ALL, POS_DEAD);
while (pRoom->people){
vch = pRoom->people;
char_from_room( vch );
if (!IS_NPC(vch) || (IS_NPC(vch) && IS_AFFECTED(vch, AFF_CHARM) && vch->leader)){
ROOM_INDEX_DATA* was_in_room = IS_NPC( vch ) ? vch->leader->was_in_room : vch->was_in_room;
if (was_in_room)
char_to_room( vch, was_in_room );
else
char_to_room( vch, get_room_index( ROOM_VNUM_TEMPLE ) );
}
else
extract_char( vch, TRUE );
}
}
/* and we extract any objects in there */
while (pRoom->contents){
OBJ_DATA* obj = pRoom->contents;
pRoom->contents = obj->next_content;
obj_from_room( obj );
extract_obj( obj );
}
/* we now remove the room */
iHash = pRoom->vnum % MAX_KEY_HASH;
prev = room_index_hash[iHash];
if (prev == NULL ){
bug("unload_vir_room: error unlinking room vnum %d", pRoom->vnum );
return FALSE;
}
if (prev == pRoom){
room_index_hash[iHash] = prev->next;
}
else{
while ( prev->next != NULL && prev->next != pRoom)
prev = prev->next;
if (prev == NULL){
bug("unlink_vir_room: room not found vnum %d.", pRoom->vnum);
return FALSE;
}
prev->next = prev->next->next;
}
/* free the room now */
free_room_index( pRoom );
return TRUE;
}
void load_rooms( FILE *fp )
{
ROOM_INDEX_DATA *pRoomIndex;
if ( area_last == NULL ){
bug( "Load_resets: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; ){
sh_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_rooms: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_room_index( vnum ) != NULL )
{
bug( "Load_rooms: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pRoomIndex = new_room_index();
read_room( fp, pRoomIndex, area_last, vnum );
iHash = vnum % MAX_KEY_HASH;
pRoomIndex->next = room_index_hash[iHash];
room_index_hash[iHash] = pRoomIndex;
top_room++;
top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room;
}
}
void load_shops( FILE *fp )
{
SHOP_DATA *pShop;
for ( ; ; )
{
MOB_INDEX_DATA *pMobIndex;
int iTrade;
pShop = alloc_perm( sizeof(*pShop) );
pShop->keeper = fread_number( fp );
if ( pShop->keeper == 0 )
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->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 ( shop_first == NULL )
shop_first = pShop;
if ( shop_last != NULL )
shop_last->next = pShop;
shop_last = pShop;
pShop->next = NULL;
top_shop++;
}
}
void load_specials( 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 );
}
}
/* adds an exit to area list of exits */
void add_area_exit( AREA_DATA* pa, EXIT_DATA* pe ){
if (pa->exits == NULL)
pa->exits = pe;
else{
pe->next_in_area = pa->exits;
pa->exits = pe;
}
}
/* 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;
int iHash, door;
for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ){
for ( pRoomIndex = room_index_hash[iHash]; pRoomIndex != NULL; pRoomIndex = pRoomIndex->next ){
bool fexit = FALSE;
bool fVir = IS_VIRROOM( pRoomIndex );
if (pRoomIndex->cabal_vnum)
pRoomIndex->pCabal = get_cabal_vnum( pRoomIndex->cabal_vnum );
for ( door = 0; door <= 5; door++ ){
ROOM_INDEX_DATA* pToRoom;
/* check if this room has an exit in this direction */
if ( ( pexit = pRoomIndex->exit[door] ) == NULL )
continue;
/* if an exit exists, check if the room it leads to exists */
if ( pexit->vnum <= 0 || (pToRoom = get_room_index(pexit->vnum)) == NULL){
char buf[MIL];
sprintf( buf, "fix_exists: could not link room %d to vnum %d", pRoomIndex->vnum, pexit->vnum);
bug(buf, 0);
pexit->to_room = NULL;
continue;
}
else{
fexit = TRUE;
pexit->to_room = pToRoom;
/* check for exit leading out of area */
if (pRoomIndex->area != pToRoom->area)
add_area_exit( pRoomIndex->area, pexit );
/* if we are working on a virtual room, and to_room is not virtual we automaticly link the other room
backwards as well */
if (fVir && !IS_VIRROOM(pToRoom)){
int rev = rev_dir[door];
/* make sure the other side has a free exit */
if (pToRoom->exit[rev] != NULL){
char buf[MIL];
sprintf( buf, "fix_exits: could not link door %d for vir. room %s to room %d as exit already linked.",
door, pRoomIndex->name, pexit->vnum);
bug( buf, 0);
continue;
}
else{
pToRoom->exit[rev] = new_exit();
pToRoom->exit[rev]->orig_door = rev;
pToRoom->exit[rev]->vnum = pRoomIndex->vnum;
pToRoom->exit[rev]->to_room = pRoomIndex;
pToRoom->exit[rev]->rs_flags = pexit->rs_flags;
pToRoom->exit[rev]->exit_info = pexit->exit_info;
pToRoom->exit[rev]->key = pexit->key;
if (pToRoom->exit[rev]->to_room->area != pToRoom->area)
add_area_exit(pToRoom->area, pToRoom->exit[rev]);
}
}
}//end if virtual room
}//end for door
}//end for room in current hash position
}//end for each hash table cell
}
void area_update( void )
{
AREA_DATA *pArea;
int stringdif, permdif;
char buf[MSL];
int hash;
ROOM_INDEX_DATA *room;
for ( pArea = area_first; pArea != NULL; pArea = pArea->next )
{
/* cabal influence check */
AreaInfluenceUpdate( pArea );
//raid update (no repops during a raid)
if (pArea->raid){
raid_update(pArea, pArea->raid );
continue;
}
if ( pArea->idle < 9999 )
pArea->idle++;
if ( ++pArea->age < 5 )
continue;
/* MUDSCHOOL resets every 5 ticks min */
else if (IS_AREA(pArea, AREA_MUDSCHOOL))
pArea->age = 999;
/* Areas with flag of "NOREPOP" do not reset if player is inside */
if (IS_SET(pArea->area_flags, AREA_NOREPOP)
&& pArea->nplayer > 0)
continue;
/* EMPTY means "not-dirty". This flag is set FALSE if a player enters area. It is only set TRUE below. */
if ( (!pArea->empty && (pArea->nplayer == 0 || pArea->age >= 15))
|| pArea->age >= 30)
{
int string_count = nAllocString, perm_count = nAllocPerm, string_size = sAllocString, perm_size = sAllocPerm;
reset_area( pArea );
sprintf(buf,"%s has just been reset.",pArea->name);
wiznet(buf,NULL,NULL,WIZ_RESETS,0,0);
if (string_count != nAllocString || perm_count < nAllocPerm )
{
stringdif = sAllocString - string_size;
permdif = sAllocPerm - perm_size;
sprintf(buf,"Memcheck: strings %d bytes : perms %d bytes : %s : area reset", stringdif, permdif, pArea->name );
wiznet(buf,NULL,NULL,WIZ_MEMORY,0,0);
}
pArea->age = number_range( 0, 5 );
if (pArea->nplayer == 0)
pArea->empty = TRUE;
}
}
/* ROOMprog Triggers and tick updates */
for ( hash = 0; hash < MAX_KEY_HASH; hash++ ){
for ( room = room_index_hash[hash]; room; room = room->next ){
if ( room->area->empty )
continue;
/* echos battle progress if people in room and armies in room */
army_battle_echo( room );
if ( room->rprog_delay > 0 )
{
if ( --room->rprog_delay <= 0 && HAS_TRIGGER_ROOM( room, TRIG_DELAY ))
p_percent_trigger( NULL, NULL, room, NULL, NULL, NULL, TRIG_DELAY );
}
if ( HAS_TRIGGER_ROOM( room, TRIG_RANDOM ) )
p_percent_trigger( NULL, NULL, room, NULL, NULL, NULL, TRIG_RANDOM );
}
}
}
/* OLC reset one room. *
* Called by reset_area and olc. */
void reset_room( ROOM_INDEX_DATA *pRoom )
{
RESET_DATA *pReset;
CHAR_DATA *pMob = NULL, *mob, *LastMob = NULL;
OBJ_DATA *pObj = NULL, *LastObj = NULL;
TRAP_DATA* pTrap;
int iExit, level = 0;
bool last = FALSE;
if ( !pRoom )
return;
/* EXITS */
for ( iExit = 0; iExit < MAX_DIR; iExit++ )
{
EXIT_DATA *pExit;
if ( ( pExit = pRoom->exit[iExit] ) ){
pExit->exit_info = pExit->rs_flags;
if ( ( pExit->to_room != NULL ) && ( ( pExit = pExit->to_room->exit[rev_dir[iExit]] ) ) )
pExit->exit_info = pExit->rs_flags;
}
}
/* CABAL GUARD and ALTAR */
if (pRoom->pCabal && pRoom->pCabal->anchor == pRoom){
bool fAltar = FALSE;
/* check if a galtar exists here already */
for (mob = pRoom->pCabal->anchor->people; mob != NULL; mob = mob->next_in_room){
if (!IS_NPC(mob))
continue;
else if (mob->pIndexData->vnum == MOB_VNUM_ALTAR && is_same_cabal(mob->pCabal, pRoom->pCabal)){
fAltar = TRUE;
break;
}
}
/* RESET ALTAR */
if (!fAltar)
reset_altar( pRoom, pRoom->pCabal );
/* RESET GUARD */
if (IS_CABAL(pRoom->pCabal, CABAL_GUARDMOB) && !is_captured( pRoom->pCabal)){
reset_cabal_guard( pRoom, pRoom->pCabal );
}
/* we remove existing guard if there is no guardmob flag */
else if (!IS_CABAL(pRoom->pCabal, CABAL_GUARDMOB)){
remove_cabalguard( pRoom->pCabal );
}
}
/* RESETS */
for ( pReset = pRoom->reset_first; pReset != NULL; pReset = pReset->next )
{
MOB_INDEX_DATA *pMobIndex;
OBJ_INDEX_DATA *pObjIndex, *pObjToIndex;
ROOM_INDEX_DATA *pRoomIndex, *pRoomIndexPrev;
TRAP_INDEX_DATA *pTrapIndex;
TRAP_DATA* pTrapTo;
bool force = FALSE;
int count = 0;
switch ( pReset->command )
{
default:
bug( "Reset_room: bad command %c.", pReset->command );
break;
case 'M':
if ( !( pMobIndex = get_mob_index( pReset->arg1 ) ) )
{
bug( "Reset_room: 'M': bad vnum %d.", pReset->arg1 );
continue;
}
if ( ( pRoomIndex = get_room_index( pReset->arg3 ) ) == NULL )
{
bug( "Reset_area: 'R': bad vnum %d.", pReset->arg3 );
continue;
}
if (loadallmobs && pReset->arg4 == -1)
force = TRUE;
if (!force && pMobIndex->count >= pReset->arg2 )
{
last = FALSE;
break;
}
for (mob = pRoomIndex->people; mob != NULL; mob = mob->next_in_room)
if (mob->pIndexData == pMobIndex)
{
count++;
if (count >= pReset->arg4)
{
last = FALSE;
break;
}
}
if (!force && count >= pReset->arg4)
break;
pMob = create_mobile( pMobIndex );
pMob->homevnum = pRoom->vnum;
if ( room_is_dark( pRoom ) )
SET_BIT(pMob->affected_by, AFF_INFRARED);
pRoomIndexPrev = get_room_index( pRoom->vnum - 1 );
if ( pRoomIndexPrev && IS_SET( pRoomIndexPrev->room_flags, ROOM_PET_SHOP ) )
SET_BIT( pMob->act, ACT_PET);
char_to_room( pMob, pRoom );
LastMob = pMob;
level = URANGE( 0, pMob->level - 2, LEVEL_HERO - 1 );
last = TRUE;
break;
case 'O':
if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
{
bug( "Reset_room: 'O' 1 : bad vnum %d", pReset->arg1 );
bugf ("%d %d %d %d",pReset->arg1, pReset->arg2, pReset->arg3,pReset->arg4 );
continue;
}
if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
{
bug( "Reset_room: 'O' 2 : bad vnum %d.", pReset->arg3 );
bugf ("%d %d %d %d",pReset->arg1, pReset->arg2, pReset->arg3,pReset->arg4 );
continue;
}
//changed to allow obj repop if players present if ( pRoom->area->nplayer > 0 || count_obj_list( pObjIndex, pRoom->contents ) > 0 )
if ( count_obj_list( pObjIndex, pRoom->contents ) > 0 )
{
last = FALSE;
break;
}
if (!can_spawn(pObjIndex))
break;
pObj = create_object( pObjIndex,UMIN(number_fuzzy( level ), LEVEL_HERO -1) );
pObj->homevnum = pRoom->vnum;
obj_to_room( pObj, pRoom );
LastObj = pObj;
last = TRUE;
break;
case 'P':
if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
{
bug( "Reset_area: 'P': bad vnum %d.", pReset->arg1 );
continue;
}
if ( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) )
{
bug( "Reset_area: 'P': bad vnum %d.", pReset->arg3 );
continue;
}
//Viri: allow conainted objects to reset with players ni area if (pRoom->area->nplayer > 0 || ( LastObj = get_obj_type( pObjToIndex ) ) == NULL
if (( LastObj = get_obj_type( pObjToIndex, pRoom ) ) == NULL
|| ( LastObj->in_room == NULL && !last)
|| (count = count_obj_list(pObjIndex,LastObj->contains)) > pReset->arg4 )
{
last = FALSE;
break;
}
while (count < pReset->arg4)
{
if (!can_spawn(pObjIndex))
break;
pObj = create_object( pObjIndex, number_fuzzy( LastObj->level ) );
pObj->homevnum = LastObj->homevnum;
obj_to_obj( pObj, LastObj );
count++;
}
LastObj->value[1] = LastObj->pIndexData->value[1];
last = TRUE;
break;
case 'T':
if ( (pTrapIndex = get_trap_index( pReset->arg1 )) == NULL ){
bug( "Reset_room: 'T' 1 : bad vnum %d", pReset->arg1 );
bugf ("%d %d %d %d",pReset->arg1,
pReset->arg2, pReset->arg3,pReset->arg4 );
continue;
}
if ( (pRoomIndex = get_room_index( pReset->arg3 )) == NULL ){
bug( "Reset_room: 'T' 2 : bad vnum %d.", pReset->arg3 );
bugf ("%d %d %d %d",pReset->arg1,
pReset->arg2, pReset->arg3,pReset->arg4 );
continue;
}
/* check of obj reset requierments */
if (pReset->arg2 == TRAP_ON_OBJ){
if ( !last || pObj == NULL){
continue;
}
else
pTrapTo = pObj->traps;
}
else if (pReset->arg2 == TRAP_ON_EXIT ){
if (pRoomIndex->exit[pReset->arg4] == NULL){
bug( "Reset_room 'T' 4 : no exit found for trap in room %d.",
pRoomIndex->vnum);
bugf ("%d %d %d %d",pReset->arg1,
pReset->arg2, pReset->arg3,pReset->arg4 );
continue;
}
else
pTrapTo = pRoomIndex->exit[pReset->arg4]->traps;
}
else{
bug( "Reset_room 'T' 5 : invalid trap in room %d.",
pRoomIndex->vnum);
bugf ("%d %d %d %d",pReset->arg1,
pReset->arg2, pReset->arg3,pReset->arg4 );
continue;
}
/* make sure we need to create a trap */
if (pTrapTo && pTrapTo->pIndexData == pTrapIndex){
init_trap( pTrapTo, pTrapTo->pIndexData );
continue;
}
else if (pTrapTo){
extract_trap( pRoomIndex->exit[pReset->arg4]->traps );
}
/* create the trap */
if ( (pTrap = create_trap( pTrapIndex, NULL)) == NULL){
bug( "Reset_room 'T' 5 : could not load trap in room %d.",
pRoomIndex->vnum);
bugf ("%d %d %d %d",pReset->arg1,
pReset->arg2, pReset->arg3,pReset->arg4 );
continue;
}
/* attach the trap */
if (pReset->arg2 == TRAP_ON_EXIT){
trap_to_exit( pTrap, pRoomIndex->exit[pReset->arg4] );
}
else if (pReset->arg2 == TRAP_ON_OBJ){
trap_to_obj( pTrap, pObj );
}
break;
case 'G':
case 'E':
if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
{
bug( "Reset_area: 'E' or 'G': bad vnum %d.", pReset->arg1 );
continue;
}
if ( !last )
break;
if ( !LastMob )
{
bug( "Reset_area: 'E' or 'G': null mob for vnum %d.",pReset->arg1 );
last = FALSE;
break;
}
if ( LastMob->pIndexData->pShop )
{
int olevel = 0, i, j;
if (!can_spawn(pObjIndex))
break;
pObj = create_object( pObjIndex,UMIN( number_fuzzy( level ), LEVEL_HERO - 1 ) );
if (!pObjIndex->new_format){
switch ( pObjIndex->item_type )
{
default: olevel = 0;
case ITEM_PILL:
case ITEM_RELIC:
case ITEM_SOCKET:
case ITEM_ARTIFACT:
case ITEM_POTION:
case ITEM_SCROLL:
olevel = 53;
for (i = 1; i < 5; i++)
if (pObjIndex->value[i] > 0)
for (j = 0; j < MAX_CLASS_NOW; j++)
olevel = UMIN(olevel, skill_table[pObjIndex->value[i]].skill_level[j]);
olevel = UMAX(0,(olevel * 3 / 4) - 2);
break;
case ITEM_WAND: olevel = number_range( 10, 20 ); break;
case ITEM_STAFF: olevel = number_range( 15, 25 ); break;
case ITEM_ARMOR: olevel = number_range( 5, 15 ); break;
case ITEM_THROW: olevel = number_range( 5, 15 ); break;
case ITEM_WEAPON: olevel = number_range( 5, 15 ); break;
case ITEM_TREASURE: olevel = number_range( 10, 20 ); break;
case ITEM_RANGED: olevel = number_range( 10, 20 ); break;
case ITEM_INSTRUMENT: olevel = number_range( 5, 15 ); break;
case ITEM_KEY: olevel = number_range( 1, 5 ); break;
case ITEM_PROJECTILE: olevel = number_range( 5, 15 ); break;
}
}
SET_BIT( pObj->extra_flags, ITEM_INVENTORY );
}
else
{
if (!can_spawn(pObjIndex))
break;
pObj = create_object( pObjIndex,UMIN( number_fuzzy( level ), LEVEL_HERO - 1 ) );
}
pObj->homevnum = LastMob->homevnum;
/* hlh pObj->homevnum = LastMob->homevnum = -1; */
if (!can_take(LastMob, pObj)){
char buf[MIL];
sprintf(buf, "Bad reset: %s cannot hold vnum:[%d] (use noalign flag).",
PERS2(LastMob), pObjIndex->vnum);
bug(buf, pObjIndex->vnum);
}
obj_to_ch( pObj, LastMob );
if ( pReset->command == 'E' ){
REMOVE_BIT( pObj->extra_flags, ITEM_INVENTORY );
equip_char( LastMob, pObj, pReset->arg3 );
}
last = TRUE;
break;
case 'D':
break;
case 'R':
if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
{
bug( "Reset_area: 'R': bad vnum %d.", pReset->arg1 );
continue;
}
{
EXIT_DATA *pExit;
int d0, d1;
for ( d0 = 0; d0 < pReset->arg2 - 1; d0++ )
{
d1 = number_range( d0, pReset->arg2-1 );
pExit = pRoomIndex->exit[d0];
pRoomIndex->exit[d0] = pRoomIndex->exit[d1];
pRoomIndex->exit[d1] = pExit;
}
}
break;
}
}
}
/* OLC - Reset one area. */
void reset_area( AREA_DATA *pArea )
{
ROOM_INDEX_DATA *pRoom;
int vnum;
for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++ ){
if ( ( pRoom = get_room_index(vnum) ) != NULL && !IS_SET(pRoom->room_flags2, ROOM_NO_RESET))
reset_room(pRoom);
}
/* reset virtual rooms that belong to this area */
for ( vnum = MAX_ROOM_VNUM; vnum < MAX_ROOM_VNUM + top_vir_room; vnum++ ){
if ( ( pRoom = get_room_index(vnum) ) != NULL && pRoom->area == pArea
&& !IS_SET(pRoom->room_flags2, ROOM_NO_RESET))
reset_room(pRoom);
}
return;
}
CHAR_DATA *create_mobile( MOB_INDEX_DATA *pMobIndex )
{
CHAR_DATA *mob;
int i;
AFFECT_DATA af;
mobile_count++;
if ( pMobIndex == NULL )
{
bug( "Create_mobile: NULL pMobIndex.", 0 );
exit( 1 );
}
mob = new_char();
mob->pIndexData = pMobIndex;
mob->name = str_dup( pMobIndex->player_name );
mob->short_descr = str_dup( pMobIndex->short_descr );
mob->long_descr = str_dup( pMobIndex->long_descr );
mob->description = str_dup( pMobIndex->description );
mob->id = get_mob_id();
mob->spec_fun = pMobIndex->spec_fun;
mob->homevnum = 0;
mob->prompt = NULL;
if (pMobIndex->gold == 0)
mob->gold = 0;
else
mob->gold = number_range(pMobIndex->gold/2, pMobIndex->gold * 3/2);
if (pMobIndex->new_format)
{
mob->group = pMobIndex->group;
if (pMobIndex->pCabal)
mob->pCabal = get_cabal_vnum(pMobIndex->pCabal->vnum);
mob->act = pMobIndex->act;
mob->act2 = pMobIndex->act2;
mob->comm = COMM_NOCHANNELS|COMM_NOYELL|COMM_NOTELL;
mob->affected_by = pMobIndex->affected_by;
mob->affected2_by = pMobIndex->affected2_by;
mob->alignment = pMobIndex->alignment;
mob->level = pMobIndex->level;
mob->hitroll = pMobIndex->hitroll;
mob->damroll = pMobIndex->damage[DICE_BONUS];
mob->max_hit = dice(pMobIndex->hit[DICE_NUMBER],pMobIndex->hit[DICE_TYPE])+pMobIndex->hit[DICE_BONUS];
mob->hit = mob->max_hit;
mob->max_mana = dice(pMobIndex->mana[DICE_NUMBER],pMobIndex->mana[DICE_TYPE])+pMobIndex->mana[DICE_BONUS];
mob->mana = mob->max_mana;
mob->damage[DICE_NUMBER]= pMobIndex->damage[DICE_NUMBER];
mob->damage[DICE_TYPE] = pMobIndex->damage[DICE_TYPE];
mob->dam_type = pMobIndex->dam_type;
if (mob->dam_type == 0)
switch(number_range(1,3))
{
case (1): mob->dam_type = 3; break;
case (2): mob->dam_type = 7; break;
case (3): mob->dam_type = 11; break;
}
for (i = 0; i < 4; i++)
mob->armor[i] = pMobIndex->ac[i];
mob->off_flags = pMobIndex->off_flags;
mob->imm_flags = pMobIndex->imm_flags;
mob->res_flags = pMobIndex->res_flags;
mob->vuln_flags = pMobIndex->vuln_flags;
mob->start_pos = pMobIndex->start_pos;
mob->default_pos = pMobIndex->default_pos;
mob->sex = pMobIndex->sex;
if (mob->sex == 3)
mob->sex = number_range(1,2);
mob->race = pMobIndex->race;
mob->form = pMobIndex->form;
mob->parts = pMobIndex->parts;
mob->size = pMobIndex->size;
mob->extracted = FALSE;
for (i = 0; i < MAX_STATS-1; i ++)
mob->perm_stat[i] = UMIN(25,11 + mob->level/4);
mob->perm_stat[STAT_LUCK] = 16;
if (IS_SET(mob->act,ACT_WARRIOR))
{
mob->perm_stat[STAT_STR] += 3;
mob->perm_stat[STAT_INT] -= 1;
mob->perm_stat[STAT_CON] += 2;
}
if (IS_SET(mob->act,ACT_THIEF))
{
mob->perm_stat[STAT_DEX] += 3;
mob->perm_stat[STAT_INT] += 1;
mob->perm_stat[STAT_WIS] -= 1;
}
if (IS_SET(mob->act,ACT_CLERIC))
{
mob->perm_stat[STAT_WIS] += 3;
mob->perm_stat[STAT_DEX] -= 1;
mob->perm_stat[STAT_STR] += 1;
}
if (IS_SET(mob->act,ACT_MAGE))
{
mob->perm_stat[STAT_INT] += 3;
mob->perm_stat[STAT_STR] -= 1;
mob->perm_stat[STAT_DEX] += 1;
}
if (IS_SET(mob->off_flags,OFF_FAST))
mob->perm_stat[STAT_DEX] += 2;
mob->perm_stat[STAT_STR] += mob->size - SIZE_MEDIUM;
mob->perm_stat[STAT_CON] += (mob->size - SIZE_MEDIUM) / 2;
if (IS_AFFECTED(mob,AFF_SANCTUARY))
{
af.where = TO_AFFECTS;
af.type = skill_lookup("sanctuary");
af.level = mob->level;
af.duration = -1;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_SANCTUARY;
affect_to_char( mob, &af );
}
if (IS_AFFECTED(mob,AFF_HASTE))
{
af.where = TO_AFFECTS;
af.type = skill_lookup("haste");
af.level = mob->level;
af.duration = -1;
af.location = APPLY_DEX;
af.modifier = 1 + (mob->level >= 18) + (mob->level >= 25) + (mob->level >= 32);
af.bitvector = AFF_HASTE;
affect_to_char( mob, &af );
}
if (IS_AFFECTED(mob,AFF_PROTECT_EVIL))
{
af.where = TO_AFFECTS;
af.type = skill_lookup("protection evil");
af.level = mob->level;
af.duration = -1;
af.location = APPLY_SAVING_SPELL;
af.modifier = -1;
af.bitvector = AFF_PROTECT_EVIL;
affect_to_char(mob,&af);
}
if (IS_AFFECTED(mob,AFF_PROTECT_GOOD))
{
af.where = TO_AFFECTS;
af.type = skill_lookup("protection good");
af.level = mob->level;
af.duration = -1;
af.location = APPLY_SAVING_SPELL;
af.modifier = -1;
af.bitvector = AFF_PROTECT_GOOD;
affect_to_char(mob,&af);
}
}
else
{
mob->act = pMobIndex->act;
mob->act2 = pMobIndex->act2;
mob->affected_by = pMobIndex->affected_by;
mob->alignment = pMobIndex->alignment;
mob->level = pMobIndex->level;
mob->hitroll = pMobIndex->hitroll;
mob->damroll = 0;
mob->max_hit = mob->level * 8 + number_range(mob->level * mob->level/4,mob->level * mob->level);
mob->max_hit *= .9;
mob->hit = mob->max_hit;
mob->max_mana = 100 + dice(mob->level,10);
mob->mana = mob->max_mana;
switch(number_range(1,3))
{
case (1): mob->dam_type = 3; break;
case (2): mob->dam_type = 7; break;
case (3): mob->dam_type = 11; break;
}
for (i = 0; i < 3; i++)
mob->armor[i] = interpolate(mob->level,100,-100);
mob->armor[3] = interpolate(mob->level,100,0);
mob->race = pMobIndex->race;
mob->off_flags = pMobIndex->off_flags;
mob->imm_flags = pMobIndex->imm_flags;
mob->res_flags = pMobIndex->res_flags;
mob->vuln_flags = pMobIndex->vuln_flags;
mob->start_pos = pMobIndex->start_pos;
mob->default_pos = pMobIndex->default_pos;
mob->sex = pMobIndex->sex;
mob->form = pMobIndex->form;
mob->parts = pMobIndex->parts;
mob->size = SIZE_MEDIUM;
mob->extracted = FALSE;
for (i = 0; i < MAX_STATS-1; i ++)
mob->perm_stat[i] = 11 + mob->level/4;
mob->perm_stat[STAT_LUCK] = 16;
}
mob->position = mob->start_pos;
mob->next = char_list;
char_list = mob;
pMobIndex->count++;
return mob;
}
/* refreshes list of resets with a new room number */
void fix_resets( RESET_DATA* pReset, int room_vnum ){
for (; pReset; pReset = pReset->next ){
switch ( pReset->command ){
case 'M':
case 'O':
case 'T':
pReset->arg3 = room_vnum; break;
case 'R':
case 'D':
pReset->arg1 = room_vnum; break;
}
}
}
void clone_room( ROOM_INDEX_DATA* src, ROOM_INDEX_DATA* dest, bool fFull ){
EXTRA_DESCR_DATA *pExtra, *ed;
RESET_DATA *pReset, *pr, *pr_last = NULL;
Double_List *watch, *tmp_list;
/* cabal */
dest->pCabal = src->pCabal;
/* name etc. */
free_string( dest->name );
free_string( dest->description );
free_string( dest->description2 );
dest->name = str_dup( src->name );
dest->description = str_dup( src->description );
dest->description2 = str_dup( src->description2 );
/* numeric data */
dest->sector_type = src->sector_type;
dest->room_flags = src->room_flags;
dest->room_flags2 = src->room_flags2;
dest->heal_rate = src->heal_rate;
dest->mana_rate = src->mana_rate;
dest->temp = src->temp;
/* extra desc. data */
while ( (pExtra = dest->extra_descr) != NULL){
dest->extra_descr = pExtra->next;
free_extra_descr( pExtra );
}
for ( pExtra = src->extra_descr; pExtra; pExtra = pExtra->next ){
ed = new_extra_descr();
ed->keyword = str_dup( pExtra->keyword );
ed->description = str_dup( pExtra->description );
ed->next = dest->extra_descr;
dest->extra_descr = ed;
}
/* rest of data is only copied on full copy */
if (!fFull)
return;
/* resets, we have to copy them in such way as to preserve their current order */
while ( (pReset = dest->reset_first)){
dest->reset_first = pReset->next;
free_reset_data( pReset );
}
for ( pReset = src->reset_first; pReset; pReset = pReset->next ){
pr = new_reset_data();
pr->command = pReset->command;
pr->arg1 = pReset->arg1;
pr->arg2 = pReset->arg2;
pr->arg3 = pReset->arg3;
pr->arg4 = pReset->arg4;
if (dest->reset_first == NULL){
dest->reset_first = pr;
pr->next = NULL;
pr_last = pr;
}
else{
pr_last->next = pr;
pr->next = NULL;
pr_last = pr;
}
}
/* we now refresh the resets with proper room number */
fix_resets( dest->reset_first, dest->vnum );
/* watch vnums */
while ( dest->watch_vnums ){
Double_List * tmp_list = dest->watch_vnums;
dest->watch_vnums = tmp_list->next_node;
free (tmp_list);
}
for (watch = src->watch_vnums; watch; watch = watch->next_node){
tmp_list = (Double_List *) malloc (sizeof (Double_List));
tmp_list->cur_entry = watch->cur_entry;
if (dest->watch_vnums == NULL){
tmp_list->next_node = NULL;
tmp_list->prev_node = NULL;
dest->watch_vnums = tmp_list;
}
else{
tmp_list->next_node = dest->watch_vnums;
tmp_list->prev_node = NULL;
dest->watch_vnums->prev_node = tmp_list;
dest->watch_vnums = tmp_list;
}
}
}
void clone_mobile(CHAR_DATA *parent, CHAR_DATA *clone)
{
int i;
AFFECT_DATA *paf, *paf_next;
if ( parent == NULL || clone == NULL || !IS_NPC(parent))
return;
for (paf = clone->affected; paf != NULL; paf = paf_next)
{
paf_next = paf->next;
affect_remove(clone, paf);
}
clone->homevnum = parent->homevnum;
clone->name = str_dup(parent->name);
clone->short_descr = str_dup(parent->short_descr);
clone->long_descr = str_dup(parent->long_descr);
clone->description = str_dup(parent->description);
clone->group = parent->group;
clone->sex = parent->sex;
clone->class = parent->class;
clone->race = parent->race;
clone->level = parent->level;
clone->trust = 0;
clone->timer = parent->timer;
clone->wait = parent->wait;
clone->hit = parent->hit;
clone->max_hit = parent->max_hit;
clone->mana = parent->mana;
clone->max_mana = parent->max_mana;
clone->move = parent->move;
clone->max_move = parent->max_move;
clone->gold = parent->gold;
clone->exp = parent->exp;
clone->act = parent->act;
clone->act2 = parent->act2;
clone->comm = parent->comm;
clone->imm_flags = parent->imm_flags;
clone->res_flags = parent->res_flags;
clone->vuln_flags = parent->vuln_flags;
clone->invis_level = parent->invis_level;
clone->affected_by = parent->affected_by;
clone->affected2_by = parent->affected2_by;
clone->position = parent->position;
clone->practice = parent->practice;
clone->train = parent->train;
clone->savingaffl = parent->savingaffl;
clone->savingmaled = parent->savingmaled;
clone->savingmental = parent->savingmental;
clone->savingbreath = parent->savingbreath;
clone->savingspell = parent->savingspell;
clone->alignment = parent->alignment;
clone->hitroll = parent->hitroll;
clone->damroll = parent->damroll;
clone->wimpy = parent->wimpy;
clone->form = parent->form;
clone->parts = parent->parts;
clone->size = parent->size;
clone->extracted = parent->extracted;
clone->off_flags = parent->off_flags;
clone->dam_type = parent->dam_type;
clone->start_pos = parent->start_pos;
clone->default_pos = parent->default_pos;
clone->spec_fun = parent->spec_fun;
for (i = 0; i < 4; i++)
clone->armor[i] = parent->armor[i];
for (i = 0; i < MAX_STATS; i++)
{
clone->perm_stat[i] = parent->perm_stat[i];
clone->mod_stat[i] = parent->mod_stat[i];
}
for (i = 0; i < 3; i++)
clone->damage[i] = parent->damage[i];
for (paf = parent->affected; paf != NULL; paf = paf_next)
{
paf_next = paf->next;
affect_to_char(clone, paf);
}
}
/* creates a trap, attatches to global list, and zeros the values */
TRAP_DATA* create_trap(TRAP_INDEX_DATA* pTrapIndex, CHAR_DATA* owner){
TRAP_DATA* tr = new_trap();
tr->pIndexData = pTrapIndex;
init_trap( tr, pTrapIndex);
if (owner != NULL)
trap_to_char( tr, owner );
else
tr->owner = owner;
tr->on_obj = NULL;
tr->on_exit = NULL;
/* attatch to global list */
if (trap_list == NULL)
trap_list = tr;
else{
tr->next = trap_list;
trap_list = tr;
}
return tr;
}
OBJ_DATA *create_object( OBJ_INDEX_DATA *pObjIndex, int level)
{
AFFECT_DATA *paf;
OBJ_DATA *obj;
if ( pObjIndex == NULL )
{
bug( "Create_object: NULL pObjIndex.", 0 );
exit( 1 );
}
obj = new_obj();
obj->pIndexData = pObjIndex;
obj->in_room = NULL;
obj->next_bidobj = NULL;
obj->enchanted = FALSE;
obj->eldritched = FALSE;
if (pObjIndex->new_format)
obj->level = pObjIndex->level;
else
obj->level = UMAX(0,level);
if (pObjIndex->pCabal)
obj->pCabal = get_cabal_vnum(pObjIndex->pCabal->vnum);
obj->race = pObjIndex->race;
obj->class = pObjIndex->class;
obj->vnum = pObjIndex->vnum;
obj->wear_loc = -1;
obj->name = str_dup( pObjIndex->name );
obj->short_descr = str_dup( pObjIndex->short_descr );
obj->description = str_dup( pObjIndex->description );
obj->material = str_dup(pObjIndex->material);
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->weight = pObjIndex->weight;
obj->cost = pObjIndex->cost;
obj->condition = pObjIndex->condition;
obj->homevnum = 0;
obj->idle = 0;
obj->extracted = FALSE;
obj->owner = 0;
obj->traps = NULL;
switch ( obj->item_type )
{
default:
bug( "Read_object: vnum %d bad type.", pObjIndex->vnum );
break;
case ITEM_CABAL:
break;
case ITEM_LIGHT:
if (obj->value[2] == 999)
obj->value[2] = -1;
break;
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_CONTAINER:
case ITEM_DRINK_CON:
case ITEM_KEY:
case ITEM_BOAT:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_FOUNTAIN:
case ITEM_MAP:
case ITEM_CLOTHING:
case ITEM_TREASURE:
case ITEM_INSTRUMENT:
case ITEM_GEM:
case ITEM_RANGED:
case ITEM_PROJECTILE:
case ITEM_JEWELRY:
break;
case ITEM_FOOD:
if (obj->value[4] == 0)
obj->value[4] = 168;
obj->timer = obj->value[4];
break;
case ITEM_HERB:
obj->timer = number_range( 500, 1000);
case ITEM_RELIC:
case ITEM_SOCKET:
case ITEM_ARTIFACT:
case ITEM_SCROLL:
if (level != -1 && !pObjIndex->new_format)
obj->value[0] = number_fuzzy( obj->value[0] );
break;
case ITEM_WAND:
case ITEM_STAFF:
if (level != -1 && !pObjIndex->new_format)
{
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_THROW:
case ITEM_WEAPON:
if (level != -1 && !pObjIndex->new_format)
{
obj->value[1] = number_fuzzy( number_fuzzy( 1 * level / 4 + 2 ) );
obj->value[2] = number_fuzzy( number_fuzzy( 3 * level / 4 + 6 ) );
}
break;
case ITEM_ARMOR:
if (level != -1 && !pObjIndex->new_format)
{
obj->value[0] = number_fuzzy( level / 5 + 3 );
obj->value[1] = number_fuzzy( level / 5 + 3 );
obj->value[2] = number_fuzzy( level / 5 + 3 );
}
break;
case ITEM_POTION:
case ITEM_PILL:
if (level != -1 && !pObjIndex->new_format)
obj->value[0] = number_fuzzy( number_fuzzy( obj->value[0] ) );
break;
case ITEM_MONEY:
if (!pObjIndex->new_format)
obj->value[0] = obj->cost;
break;
}
for (paf = pObjIndex->affected; paf != NULL; paf = paf->next)
if ( paf->location == APPLY_SPELL_AFFECT )
affect_to_obj(obj,paf);
obj->next = object_list;
object_list = obj;
pObjIndex->count++;
return obj;
}
void clone_object(OBJ_DATA *parent, OBJ_DATA *clone)
{
int i;
AFFECT_DATA *paf;
EXTRA_DESCR_DATA *ed,*ed_new;
if (parent == NULL || clone == NULL)
return;
clone->name = str_dup(parent->name);
clone->short_descr = str_dup(parent->short_descr);
clone->description = str_dup(parent->description);
clone->item_type = parent->item_type;
clone->extra_flags = parent->extra_flags;
clone->wear_flags = parent->wear_flags;
clone->weight = parent->weight;
clone->cost = parent->cost;
clone->pCabal = parent->pCabal;
clone->race = parent->race;
clone->class = parent->class;
clone->vnum = parent->vnum;
clone->level = parent->level;
clone->condition = parent->condition;
if (!IS_NULLSTR(clone->material))
free_string(clone->material);
clone->material = str_dup(parent->material);
clone->timer = parent->timer;
clone->extracted = parent->extracted;
for (i = 0; i < 5; i ++)
clone->value[i] = parent->value[i];
clone->enchanted = parent->enchanted;
for (paf = parent->affected; paf != NULL; paf = paf->next)
affect_to_obj(clone,paf);
for (ed = parent->extra_descr; ed != NULL; ed = ed->next)
{
ed_new = new_extra_descr();
ed_new->keyword = str_dup( ed->keyword);
ed_new->description = str_dup( ed->description );
ed_new->next = clone->extra_descr;
clone->extra_descr = ed_new;
}
}
void clear_char( CHAR_DATA *ch )
{
static CHAR_DATA ch_zero;
int i;
*ch = ch_zero;
ch->name = &str_empty[0];
ch->short_descr = &str_empty[0];
ch->long_descr = &str_empty[0];
ch->description = &str_empty[0];
ch->prompt = &str_empty[0];
ch->logon = mud_data.current_time;
ch->lines = PAGELEN;
for (i = 0; i < 4; i++)
ch->armor[i] = 100;
ch->position = POS_STANDING;
if (!IS_NPC(ch))
{
ch->hit = pc_race_table[ch->race].hit;
ch->mana = pc_race_table[ch->race].mana;
}
else
{
ch->hit = 20;
ch->mana = 100;
}
ch->max_hit = ch->hit;
ch->max_mana = ch->mana;
ch->move = 100;
ch->max_move = ch->move;
for (i = 0; i < MAX_STATS; i ++)
{
ch->perm_stat[i] = 13;
ch->mod_stat[i] = 0;
}
ch->perm_stat[STAT_LUCK] = 16;
}
char *get_extra_descr( const char *name, EXTRA_DESCR_DATA *ed )
{
for ( ; ed != NULL; ed = ed->next )
if ( is_name( (char *) name, ed->keyword ) )
return ed->description;
return NULL;
}
char *get_auto_extra_descr( const char *name, EXTRA_DESCR_DATA *ed, bool fAuto)
{
for ( ; ed != NULL; ed = ed->next )
if ( (fAuto && is_auto_name( (char *) name, ed->keyword ) )
|| is_name( (char *) name, ed->keyword ) )
return ed->description;
return NULL;
}
/* Translates mob virtual number to its mob index struct. *
* Hash table lookup. */
MOB_INDEX_DATA *get_mob_index( int vnum )
{
MOB_INDEX_DATA *pMobIndex;
for ( pMobIndex = mob_index_hash[vnum % MAX_KEY_HASH]; pMobIndex != NULL; pMobIndex = pMobIndex->next )
if ( pMobIndex->vnum == vnum )
return pMobIndex;
if ( fBootDb )
{
bug( "Get_mob_index: bad vnum %d.", vnum );
exit( 1 );
}
return NULL;
}
/* Translates mob virtual number to its obj index struct. *
* Hash table lookup. */
OBJ_INDEX_DATA *get_obj_index( int vnum )
{
OBJ_INDEX_DATA *pObjIndex;
for ( pObjIndex = obj_index_hash[vnum % MAX_KEY_HASH]; pObjIndex != NULL; pObjIndex = pObjIndex->next )
if ( pObjIndex->vnum == vnum )
return pObjIndex;
if ( fBootDb )
{
bug( "Get_obj_index: bad vnum %d.", vnum );
exit( 1 );
}
return NULL;
}
/* Translates mob virtual number to its room index struct. *
* Hash table lookup. */
ROOM_INDEX_DATA *get_room_index( int vnum )
{
ROOM_INDEX_DATA *pRoomIndex;
if (vnum <= 0)
return NULL;
for ( pRoomIndex = room_index_hash[vnum % MAX_KEY_HASH]; pRoomIndex != NULL; pRoomIndex = pRoomIndex->next )
if ( pRoomIndex->vnum == vnum )
return pRoomIndex;
if ( fBootDb )
{
bug( "Get_room_index: bad vnum %d.", vnum );
exit( 1 );
}
return NULL;
}
/* Read a letter from a file. */
char fread_letter( FILE *fp )
{
char c = '\0';
do
c = getc( fp );
while ( isspace(c) );
return c;
}
/* Read a number from a file. */
int fread_number( FILE *fp )
{
int number = 0;
bool sign;
char c;
if (!fp){
bug("fread_number: null file passed", 0);
return 0;
}
do
c = getc( fp );
while ( isspace(c) );
number = 0;
sign = FALSE;
if ( c == '+' )
c = getc( fp );
else if ( c == '-' )
{
sign = TRUE;
c = getc( fp );
}
if ( !isdigit(c) )
{
bug( "Fread_number: bad format.", 0 );
// exit( 1 );
}
while ( isdigit(c) )
{
number = number * 10 + c - '0';
c = getc( fp );
}
if ( sign )
number = 0 - number;
if ( c == '|' )
number += fread_number( fp );
else if ( c != ' ' )
ungetc( c, fp );
return number;
}
unsigned long fread_unsigned_long( FILE *fp )
{
unsigned long int number = 0;
bool sign;
char c;
if (!fp){
bug("fread_number: null file passed", 0);
return 0;
}
do
c = getc( fp );
while ( isspace(c) );
number = 0;
sign = FALSE;
if ( c == '+' )
c = getc( fp );
else if ( c == '-' )
{
sign = TRUE;
c = getc( fp );
}
if ( !isdigit(c) )
{
bug( "Fread_number: bad format.", 0 );
// exit( 1 );
}
while ( isdigit(c) )
{
number = number * 10 + c - '0';
c = getc( fp );
}
if ( sign )
number = 0 - number;
if ( c == '|' )
number += fread_number( fp );
else if ( c != ' ' )
ungetc( c, fp );
return number;
}
/* read a regular long */
long fread_long( FILE *fp )
{
long number = 0;
bool sign;
char c;
if (!fp){
bug("fread_number: null file passed", 0);
return 0;
}
do
c = getc( fp );
while ( isspace(c) );
number = 0;
sign = FALSE;
if ( c == '+' )
c = getc( fp );
else if ( c == '-' )
{
sign = TRUE;
c = getc( fp );
}
if ( !isdigit(c) )
{
bug( "Fread_number: bad format.", 0 );
// exit( 1 );
}
while ( isdigit(c) )
{
number = number * 10 + c - '0';
c = getc( fp );
}
if ( sign )
number = 0 - number;
if ( c == '|' )
number += fread_number( fp );
else if ( c != ' ' )
ungetc( c, fp );
return number;
}
long fread_flag( FILE *fp)
{
int number;
char c;
bool negative = FALSE;
do
c = getc(fp);
while ( isspace(c));
if (c == '-')
{
negative = TRUE;
c = getc(fp);
}
number = 0;
if (!isdigit(c))
while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
{
number += flag_convert(c);
c = getc(fp);
}
while (isdigit(c))
{
number = number * 10 + c - '0';
c = getc(fp);
}
if (c == '|')
number += fread_flag(fp);
else if ( c != ' ')
ungetc(c,fp);
if (negative)
return -1 * number;
return number;
}
long flag_convert(char letter )
{
long bitsum = 0;
char i;
if ('A' <= letter && letter <= 'Z')
{
bitsum = 1;
for (i = letter; i > 'A'; i--)
bitsum *= 2;
}
else if ('a' <= letter && letter <= 'z')
{
bitsum = 67108864;
for (i = letter; i > 'a'; i --)
bitsum *= 2;
}
return bitsum;
}
/* Read to end of line (for comments). */
void fread_to_eol( FILE *fp )
{
char c;
do
c = getc( fp );
while ( c != '\n' && c != '\r' );
do
c = getc( fp );
while ( c == '\n' || c == '\r' );
ungetc( c, fp );
return;
}
/* Read one word (into static buffer). */
char *fread_word_noquote( FILE *fp )
{
static char word[MIL];
char *pword;
char cEnd;
do
cEnd = getc( fp );
while ( isspace( cEnd ) && (cEnd != '\r'));
if ( cEnd == '\'' || cEnd == '"' )
pword = word;
else
{
word[0] = cEnd;
pword = word+1;
cEnd = ' ';
}
for ( ; pword < word + MIL; pword++ )
{
*pword = getc( fp );
if ( cEnd == ' ' ? isspace(*pword) : *pword == cEnd )
{
if ( cEnd == ' ' )
ungetc( *pword, fp );
*pword = '\0';
return word;
}
}
bug( "Fread_word: word too long", 0);
// exit( 1 );
return NULL;
}
/* Read one word (into static buffer). */
char *fread_word( FILE *fp )
{
static char word[MIL];
char *pword;
char cEnd;
do
cEnd = getc( fp );
while ( isspace( cEnd ) );
if ( cEnd == '\'' || cEnd == '"' )
pword = word;
else
{
word[0] = cEnd;
pword = word+1;
cEnd = ' ';
}
for ( ; pword < word + MIL; pword++ )
{
*pword = getc( fp );
if ( cEnd == ' ' ? isspace(*pword) : *pword == cEnd )
{
if ( cEnd == ' ' )
ungetc( *pword, fp );
*pword = '\0';
return word;
}
}
bug( "Fread_word: word too long", 0);
return NULL;
}
/* Allocate some ordinary memory, *
* with the expectation of freeing it someday. */
void *alloc_mem( int sMem )
{
void *pMem;
int *magic;
int iList;
sMem += sizeof(*magic);
for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
if ( sMem <= rgSizeList[iList] )
break;
if ( iList == MAX_MEM_LIST )
{
bug( "Alloc_mem: size %d too large.", sMem );
exit( 1 );
}
if ( rgFreeList[iList] == NULL )
pMem = alloc_perm( rgSizeList[iList] );
else
{
pMem = rgFreeList[iList];
rgFreeList[iList] = * ((void **) rgFreeList[iList]);
}
magic = (int *) pMem;
*magic = MAGIC_NUM;
pMem += sizeof(*magic);
return pMem;
}
/* Free some memory. *
* Recycle it back onto the free list for blocks of that size. */
void free_mem( void *pMem, int sMem )
{
int iList;
int *magic;
pMem -= sizeof(*magic);
magic = (int *) pMem;
if (*magic != MAGIC_NUM)
{
bug("Attempt to recyle invalid memory of size %d.",sMem);
bug((char*) pMem + sizeof(*magic),0);
return;
}
*magic = 0;
sMem += sizeof(*magic);
for ( iList = 0; iList < MAX_MEM_LIST; iList++ )
if ( sMem <= rgSizeList[iList] )
break;
if ( iList == MAX_MEM_LIST )
{
bug( "Free_mem: size %d too large.", sMem );
exit( 1 );
}
* ((void **) pMem) = rgFreeList[iList];
rgFreeList[iList] = pMem;
}
/* Allocate some permanent memory. *
* Permanent memory is never freed, *
* pointers into it may be copied safely. */
void *alloc_perm( int sMem )
{
static char *pMemPerm;
static int iMemPerm;
void *pMem = NULL;
while ( sMem % sizeof(long) != 0 ) {
sMem++;
}
if ( sMem > MAX_PERM_BLOCK ) {
bug( "Alloc_perm: %d too large.", sMem );
exit( 1 );
}
if ( pMemPerm == NULL || iMemPerm + sMem > MAX_PERM_BLOCK ) {
iMemPerm = 0;
init_malloc("calloc alloc_perm");
if ( ( pMemPerm = calloc( 1, MAX_PERM_BLOCK ) ) == NULL ) {
perror( "Alloc_perm" );
exit( 1 );
}
end_malloc("calloc alloc_perm");
}
pMem = pMemPerm + iMemPerm;
iMemPerm += sMem;
nAllocPerm += 1;
sAllocPerm += sMem;
return pMem;
}
void do_areas( CHAR_DATA *ch, char *argument )
{
AREA_DATA *pArea1 = area_first, *pArea2 = area_first;
int iArea, iAreaHalf = (top_area + 1) / 2;
BUFFER *buffer;
char buf[MSL];
if (argument[0] != '\0')
{
send_to_char("No argument is used with this command.\n\r",ch);
return;
}
buffer = new_buf();
for ( iArea = 0; iArea < iAreaHalf; iArea++ )
pArea2 = pArea2->next;
for ( iArea = 0; iArea < iAreaHalf; iArea++ )
{
sprintf( buf, "%-39s%-39s\n\r", pArea1->credits, (pArea2 != NULL) ? pArea2->credits : "" );
add_buf(buffer,buf);
pArea1 = pArea1->next;
if ( pArea2 != NULL )
pArea2 = pArea2->next;
}
page_to_char(buf_string(buffer),ch);
free_buf(buffer);
}
extern int numFree;
void do_memory( CHAR_DATA *ch, char *argument )
{
sendf( ch, "Affects: %5d\n\r", top_affect );
sendf( ch, "Areas: %5d (%d bastions)\n\r", top_area, mud_data.tot_bastion );
sendf( ch, "ExDes: %5d\n\r", top_ed );
sendf( ch, "Exits: %5d\n\r", top_exit );
sendf( ch, "Helps: %5d\n\r", top_help );
sendf( ch, "Socials: %5d\n\r", social_count );
sendf( ch, "Mobs: %5d %7d new format %7d in use\n\r", top_mob_index,newmobs,mobile_count);
sendf( ch, "Mob progs: %5d %7d files\n\r",mprog_count,mprogf_count );
sendf( ch, "Objs: %5d %7d new format\n\r", top_obj_index,newobjs );
sendf( ch, "Traps: %5d\n\r", top_trap_index);
sendf( ch, "Cabals: %5d\n\r", top_cabal_index);
sendf( ch, "Resets: %5d\n\r", top_reset );
sendf( ch, "Rooms: %5d\n\r", top_room );
sendf( ch, "VirRooms: %5d\n\r", top_vir_room );
sendf( ch, "Night Descrips: %5d\n\r", night_count );
sendf( ch, "Shops: %5d\n\r", top_shop );
sendf( ch, "Share Strings: %5d strings of %7d bytes %7d bytes is reboot\n\r",
nAllocString, sAllocString, 4*MAX_STRING/5 );
sendf( ch, "Overflow Strings: %5d strings of %7d bytes\n\r",nOverFlowString, sOverFlowString );
sendf( ch, "Perm Strings: %5d blocks of %7d bytes %7d blocks is reboot\n\r",
nAllocPerm, sAllocPerm, MAX_PERM_BLOCK * 4 / 5 );
sendf(ch, "Reboot counter: %d, FreeString %d/%d", reboot_tick_counter, numFree, MAX_FREE);
if( Full )
sendf( ch, "Shared String Heap is full, increase MAX_STRING.\n\r" );
}
void do_dump( CHAR_DATA *ch, char *argument )
{
int count = 0, count2 = 0, num_pcs = 0, aff_count = 0, vnum, nMatch = 0;
CHAR_DATA *fch;
MOB_INDEX_DATA *pMobIndex;
PC_DATA *pc;
OBJ_DATA *obj;
OBJ_INDEX_DATA *pObjIndex;
ROOM_INDEX_DATA *room;
EXIT_DATA *exit;
DESCRIPTOR_DATA *d;
AFFECT_DATA *af;
FILE *fp;
if (argument[0] == '\0')
{
send_to_char("memory dump: enter anything as an argument to dump the memory.\n\r", ch);
return;
}
fclose(fpReserve);
fp = fopen("mem.dmp","w");
fprintf(fp,"MobProt %4d (%8d bytes)\n", top_mob_index, top_mob_index * (sizeof(*pMobIndex)));
for (fch = char_list; fch != NULL; fch = fch->next)
{
count++;
if (fch->pcdata != NULL)
num_pcs++;
for (af = fch->affected; af != NULL; af = af->next)
aff_count++;
}
for (fch = char_free; fch != NULL; fch = fch->next)
count2++;
fprintf(fp,"Mobs %4d (%8d bytes), %2d free (%d bytes)\n",
count, count * (sizeof(*fch)), count2, count2 * (sizeof(*fch)));
count = 0;
for (pc = pcdata_free; pc != NULL; pc = pc->next)
count++;
fprintf(fp,"Pcdata %4d (%8d bytes), %2d free (%d bytes)\n",
num_pcs, num_pcs * (sizeof(*pc)), count, count * (sizeof(*pc)));
count = 0; count2 = 0;
for (d = descriptor_list; d != NULL; d = d->next)
count++;
for (d= descriptor_free; d != NULL; d = d->next)
count2++;
fprintf(fp, "Descs %4d (%8d bytes), %2d free (%d bytes)\n",
count, count * (sizeof(*d)), count2, count2 * (sizeof(*d)));
for ( vnum = 0; nMatch < top_obj_index; vnum++ )
if ( ( pObjIndex = get_obj_index( vnum ) ) != NULL )
{
for (af = pObjIndex->affected; af != NULL; af = af->next)
aff_count++;
nMatch++;
}
fprintf(fp,"ObjProt %4d (%8d bytes)\n",top_obj_index, top_obj_index * (sizeof(*pObjIndex)));
count = 0; count2 = 0;
for (obj = object_list; obj != NULL; obj = obj->next)
{
count++;
for (af = obj->affected; af != NULL; af = af->next)
aff_count++;
}
for (obj = obj_free; obj != NULL; obj = obj->next)
count2++;
fprintf(fp,"Objs %4d (%8d bytes), %2d free (%d bytes)\n",
count, count * (sizeof(*obj)), count2, count2 * (sizeof(*obj)));
count = 0;
for (af = affect_free; af != NULL; af = af->next)
count++;
fprintf(fp,"Affects %4d (%8d bytes), %2d free (%d bytes)\n",
aff_count, aff_count * (sizeof(*af)), count, count * (sizeof(*af)));
fprintf(fp,"Rooms %4d (%8d bytes)\n", top_room, top_room * (sizeof(*room)));
fprintf(fp,"Exits %4d (%8d bytes)\n", top_exit, top_exit * (sizeof(*exit)));
fclose(fp);
fp = fopen("mob.dmp","w");
fprintf(fp,"\nMobile Analysis\n");
fprintf(fp, "---------------\n");
nMatch = 0;
for (vnum = 0; nMatch < top_mob_index; vnum++)
if ((pMobIndex = get_mob_index(vnum)) != NULL)
{
nMatch++;
fprintf(fp,"#%-4d %3d active %3d killed %s\n",
pMobIndex->vnum,pMobIndex->count, pMobIndex->killed,pMobIndex->short_descr);
}
fclose(fp);
fp = fopen("obj.dmp","w");
fprintf(fp,"\nObject Analysis\n");
fprintf(fp, "---------------\n");
nMatch = 0;
for (vnum = 0; nMatch < top_obj_index; vnum++)
if ((pObjIndex = get_obj_index(vnum)) != NULL)
{
nMatch++;
fprintf(fp,"#%-4d %3d active %3d reset %s\n",
pObjIndex->vnum,pObjIndex->count, pObjIndex->reset_num,pObjIndex->short_descr);
}
fclose(fp);
fpReserve = fopen( NULL_FILE, "r" );
}
/* Stick a little fuzz on a number. */
int number_fuzzy( int number )
{
switch ( number_bits( 2 ) )
{
case 0: number -= 1; break;
case 3: number += 1; break;
}
return UMAX( 1, number );
}
int temp_adjust( int number )
{
int hour, month, week;
if (mud_data.time_info.month <= 8)
month = mud_data.time_info.month - 4;
else
month = 4 - (mud_data.time_info.month - 8);
week = mud_data.time_info.day / 7 - 2;
if (mud_data.time_info.hour <= 12)
hour = mud_data.time_info.hour - 6;
else
hour = 6 - (mud_data.time_info.hour - 12);
return number + (month * 5) + week + hour;
}
/* Generate a random number. */
int number_range( int from, int to )
{
int power, number;
if (from == 0 && to == 0)
return 0;
if ( ( to = to - from + 1 ) <= 1 )
return from;
for ( power = 2; power < to; power <<= 1 );
while ( ( number = number_mm() & (power -1 ) ) >= to );
return from + number;
}
/* Generate a percentile roll. */
int number_percent( void )
{
int percent;
while ( (percent = number_mm() & (128-1) ) > 99 );
return 1 + percent;
}
/* Generate a random door. */
int number_door( void )
{
int door;
while ( ( door = number_mm() & (8-1) ) > 5);
return door;
}
/* Generate a random door from the room. */
/* -1 on no valid doors */
int random_door( CHAR_DATA* ch, ROOM_INDEX_DATA* room )
{
int doors[MAX_DOOR];
int i = 0;
int max_door = 0;
for (i = 0; i < MAX_DOOR; i++){
if (room->exit[i] != NULL
&& room->exit[i]->to_room
&& can_see_room(ch, room->exit[i]->to_room))
doors[max_door++] = i;
}
return max_door == 0 ? -1 : doors[number_range(0, max_door - 1)];
}
int number_bits( int width )
{
return number_mm( ) & ( ( 1 << width ) - 1 );
}
/* I've gotten too many bad reports on OS-supplied random number generators. *
* This is the Mitchell-Moore algorithm from Knuth Volume II. *
* Best to leave the constants alone unless you've read Knuth. */
/* I noticed streaking with this random number generator, so I switched *
* back to the system srandom call. If this doesn't work for you, *
* define OLD_RAND to use the old system. */
#if defined (OLD_RAND)
static int rgiState[2+55];
#endif
void init_mm( )
{
#if defined (OLD_RAND)
int *piState;
int iState;
piState = &rgiState[2];
piState[-2] = 55 - 55;
piState[-1] = 55 - 24;
piState[0] = ((int) mud_data.current_time) & ((1 << 30) - 1);
piState[1] = 1;
for ( iState = 2; iState < 55; iState++ )
{
piState[iState] = (piState[iState-1] + piState[iState-2]) & ((1 << 30) - 1);
}
#else
srandom(time(NULL)^getpid());
#endif
}
long number_mm( void )
{
#if defined (OLD_RAND)
int *piState;
int iState1, iState2, iRand;
piState = &rgiState[2];
iState1 = piState[-2];
iState2 = piState[-1];
iRand = (piState[iState1] + piState[iState2]) & ((1 << 30) - 1);
piState[iState1] = iRand;
if ( ++iState1 == 55 )
iState1 = 0;
if ( ++iState2 == 55 )
iState2 = 0;
piState[-2] = iState1;
piState[-1] = iState2;
return iRand >> 6;
#else
return random() >> 6;
#endif
}
/* Roll some dice. */
int dice( int number, int size )
{
int idice, sum;
switch ( size )
{
case 0: return 0;
case 1: return number;
}
for ( idice = 0, sum = 0; idice < number; idice++ )
sum += number_range( 1, size );
return sum;
}
/* Simple linear interpolation. */
int interpolate( int level, int value_00, int value_32 )
{
return value_00 + level * (value_32 - value_00) / 32;
}
/* Removes the tildes from a string. *
* Used for player-entered strings that go into disk files. */
void smash_tilde( char *str )
{
for ( ; *str != '\0'; str++ )
if ( *str == '~' )
*str = '-';
}
void smash_tilde2( char *str )
{
for ( ; *str != '\0'; str++ )
if ( *str == '~' )
*str = '\0';
}
/* Finds a string and replaces it with another */
void str_replace(char *buf, const char *s, const char *repl)
{
char out_buf[MSL];
char *pc, *out;
int len = strlen(s);
bool found = FALSE;
for (pc = buf, out = out_buf; *pc && (out-out_buf) < (MSL-len-4); )
{
if (!strncasecmp(pc, s, len))
{
out += sprintf(out, repl);
pc += len;
found = TRUE;
}
else
*out++ = *pc++;
}
if (found) /* don't bother copying if we did not change anything */
{
*out = '\0';
strcpy(buf, out_buf);
}
}
/* Compare strings, case insensitive. *
* Return TRUE if different *
* (compatibility with historical functions). */
bool str_cmp( const char *astr, const char *bstr )
{
if ( astr == NULL )
{
if (bstr == NULL)
bug( "Str_cmp %d: null astr.", 1 );
else
bugf( "Str_cmp: null astr, bstr = %s.", bstr );
return TRUE;
}
if ( bstr == NULL )
{
bug( "Str_cmp: null bstr.", 0 );
return TRUE;
}
for ( ; *astr || *bstr; astr++, bstr++ )
if ( LOWER(*astr) != LOWER(*bstr) )
return TRUE;
return FALSE;
}
/* Compare strings, case sensitive. *
* Return TRUE if different *
* (compatibility with historical functions). */
bool str_cmp_2( const char *astr, const char *bstr )
{
if ( astr == NULL )
{
bug( "Str_cmp 2: null astr.", 0 );
return TRUE;
}
if ( bstr == NULL )
{
bug( "Str_cmp: null bstr.", 0 );
return TRUE;
}
for ( ; *astr || *bstr; astr++, bstr++ )
if ((*astr) != (*bstr) )
return TRUE;
return FALSE;
}
/* Compare strings, case insensitive, for prefix matching. *
* Return TRUE if astr not a prefix of bstr *
* (compatibility with historical functions). */
bool str_prefix( const char *astr, const char *bstr )
{
if ( astr == NULL )
{
bug( "Strn_cmp: null astr.", 0 );
return TRUE;
}
if ( bstr == NULL )
{
bug( "Strn_cmp: null bstr.", 0 );
return TRUE;
}
for ( ; *astr; astr++, bstr++ )
if ( LOWER(*astr) != LOWER(*bstr) )
return TRUE;
return FALSE;
}
/* Compare strings, case insensitive, for match anywhere. *
* Returns TRUE is astr not part of bstr. *
* (compatibility with historical functions). */
bool str_infix( const char *astr, const char *bstr )
{
int sstr1, sstr2, ichar;
char c0;
if ( ( c0 = LOWER(astr[0]) ) == '\0' )
return FALSE;
sstr1 = strlen(astr);
sstr2 = strlen(bstr);
for ( ichar = 0; ichar <= sstr2 - sstr1; ichar++ )
if ( c0 == LOWER(bstr[ichar]) && !str_prefix( astr, bstr + ichar ) )
return FALSE;
return TRUE;
}
/* Compare strings, case insensitive, for suffix matching. *
* Return TRUE if astr not a suffix of bstr *
* (compatibility with historical functions). */
bool str_suffix( const char *astr, const char *bstr )
{
int sstr1 = strlen(astr), sstr2 = strlen(bstr);
if ( sstr1 <= sstr2 && !str_cmp( astr, bstr + sstr2 - sstr1 ) )
return FALSE;
else
return TRUE;
}
/* Returns an initial-capped string. */
char *capitalize( const char *str )
{
static char strcap[MSL];
int i;
for ( i = 0; str[i] != '\0'; i++ )
strcap[i] = LOWER(str[i]);
strcap[i] = '\0';
strcap[0] = UPPER(strcap[0]);
return strcap;
}
/* Append a string to a file. */
void append_file( CHAR_DATA *ch, char *file, char *str )
{
FILE *fp;
// change back for IS_NPC(ch)
if ( str[0] == '\0' )
return;
fclose( fpReserve );
if ( ( fp = fopen( file, "a" ) ) == NULL )
{
perror( file );
send_to_char( "Could not open the file!\n\r", ch );
}
else
fprintf( fp, "[%5d] %s: %s\n", ch->in_room ? ch->in_room->vnum : 0, ch->name, str );
fclose( fp );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
/* Append a string to a file. */
void append_string( char *file, char *str )
{
FILE *fp;
if ( str[0] == '\0' )
return;
fclose( fpReserve );
if ( ( fp = fopen( file, "a" ) ) == NULL )
perror( file );
else
fprintf( fp, str );
fclose( fp );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
/* Reports a bug. */
void bug( const char *str, int param )
{
char buf[MSL];
FILE *fp;
if ( fpArea != NULL )
{
int iLine, 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 );
}
nlogf( "[*****] FILE: %s LINE: %d", strArea, iLine );
if ( ( fp = fopen( "shutdown.txt", "a" ) ) != NULL )
fprintf( fp, "[*****] %s\n", buf );
else
fp = fopen( NULL_FILE, "r" );
fclose( fp );
}
strcpy( buf, "[*****] BUG: " );
sprintf( buf + strlen(buf), str, param );
log_string( buf );
}
/* Writes a string into Event log */
void log_event(CHAR_DATA* ch, char* str)
{append_file(ch, EVENT_FILE, str );}
/* Writes a string to the log. */
void log_string( const char *str )
{
char *strtime = ctime( &mud_data.current_time );
strtime[strlen(strtime)-1] = '\0';
fprintf( stderr, "%s :: %s\n", strtime, str );
}
/* This function is here to aid in debugging. *
* If the last expression in a function is another function call, *
* gcc likes to generate a JMP instead of a CALL. *
* This is called "tail chaining." *
* It hoses the debugger call stack for that call. *
* So I make this the last call in certain critical functions, *
* where I really need the call stack to be right for debugging! *
* If you don't understand this, then LEAVE IT ALONE. *
* Don't remove any calls to tail_chain anywhere. */
void tail_chain( void )
{
return;
}
/* returns help index */
HELP_DATA *get_help_index( int vnum ){
HELP_DATA* pHelp;
for(pHelp = help_first ; pHelp; pHelp = pHelp->next ){
if ( pHelp->vnum == vnum )
return( pHelp );
}
return NULL;
}
/* returns cabal index */
CABAL_INDEX_DATA *get_cabal_index( int vnum ){
CABAL_INDEX_DATA* pCab;
for(pCab = cabal_index_list ; pCab; pCab = pCab->next ){
if ( pCab->vnum == vnum )
return( pCab );
}
return NULL;
}
/* returns cabal index */
CABAL_INDEX_DATA *get_cabal_index_str( char* name ){
CABAL_INDEX_DATA* pCab;
for(pCab = cabal_index_list ; pCab; pCab = pCab->next ){
if (LOWER(name[0]) == LOWER(pCab->name[0]) && !str_cmp(name, pCab->name))
return( pCab );
}
return NULL;
}
/* returns trap index */
TRAP_INDEX_DATA *get_trap_index( int vnum ){
TRAP_INDEX_DATA* pTrap;
for(pTrap = trap_index_list ; pTrap; pTrap = pTrap->next ){
if ( pTrap->vnum == vnum )
return( pTrap );
}
return NULL;
}
/* MOB Programs */
/* Returns the index of the prog list */
PROG_CODE *get_prog_index( int vnum, int type )
{
PROG_CODE *prg;
switch ( type )
{
case PRG_MPROG:
prg = mprog_list;
break;
case PRG_OPROG:
prg = oprog_list;
break;
case PRG_RPROG:
prg = rprog_list;
break;
default:
return NULL;
}
for( ; prg; prg = prg->next )
{
if ( prg->vnum == vnum )
return( prg );
}
return NULL;
}
/* This routine transfers between alpha and numeric forms of the *
* mob_prog bitvector types. This allows the use of the words in the *
* mob/script files. */
int mprog_name_to_type ( char *name )
{
if ( !str_cmp( name, "in_file_prog" ) ) return IN_FILE_PROG;
if ( !str_cmp( name, "act_prog" ) ) return ACT_PROG;
if ( !str_cmp( name, "speech_prog" ) ) return SPEECH_PROG;
if ( !str_cmp( name, "rand_prog" ) ) return RAND_PROG;
if ( !str_cmp( name, "fight_prog" ) ) return FIGHT_PROG;
if ( !str_cmp( name, "hitprcnt_prog" ) ) return HITPRCNT_PROG;
if ( !str_cmp( name, "death_prog" ) ) return DEATH_PROG;
if ( !str_cmp( name, "entry_prog" ) ) return ENTRY_PROG;
if ( !str_cmp( name, "greet_prog" ) ) return GREET_PROG;
if ( !str_cmp( name, "all_greet_prog" ) ) return ALL_GREET_PROG;
if ( !str_cmp( name, "give_prog" ) ) return GIVE_PROG;
if ( !str_cmp( name, "bribe_prog" ) ) return BRIBE_PROG;
if ( !str_cmp( name, "time_prog" ) ) return TIME_PROG;
if ( !str_cmp( name, "get_prog" ) ) return GET_PROG;
if ( !str_cmp( name, "drop_prog" ) ) return DROP_PROG;
if ( !str_cmp( name, "guild_prog" ) ) return GUILD_PROG;
if ( !str_cmp( name, "bloody_prog" ) ) return BLOODY_PROG;
if ( !str_cmp( name, "justice_prog" ) ) return JUSTICE_PROG;
return( ERROR_PROG );
}
/* This routine reads in scripts of MOBprograms from a file */
MPROG_DATA* mprog_file_read( char *f, MPROG_DATA *mprg, MOB_INDEX_DATA *pMobIndex )
{
char MOBProgfile[MIL];
char letter;
MPROG_DATA *mprg2;
FILE *progfile;
bool done = FALSE;
sprintf( MOBProgfile, "%s%s", MOB_DIR, f);
progfile = fopen( MOBProgfile, "r" );
if ( !progfile )
{
bug( "Mob: %d couldnt open mobprog file", pMobIndex->vnum );
printf ("File: %s\n", MOBProgfile);
fclose (progfile);
exit( 1 );
}
mprg2 = mprg;
switch ( letter = fread_letter( progfile ) )
{
case '>':
mprog_count++;
break;
case '|':
bug( "empty mobprog file.", 0 );
exit( 1 );
break;
default:
bug( "in mobprog file syntax error.", 0 );
printf ("File: %s\n", MOBProgfile);
exit( 1 );
break;
}
while ( !done )
{
mprg2->type = mprog_name_to_type( fread_word( progfile ) );
switch ( mprg2->type )
{
case ERROR_PROG:
bug( "mobprog file type error", 0 );
exit( 1 );
break;
case IN_FILE_PROG:
bug( "mprog file contains a call to file.", 0 );
exit( 1 );
break;
default:
pMobIndex->progtypes = pMobIndex->progtypes | mprg2->type;
mprg2->arglist = fread_string( progfile );
mprg2->comlist = fread_string( progfile );
switch ( letter = fread_letter( progfile ) )
{
case '>':
mprog_count++;
mprg2->next = (MPROG_DATA *)alloc_perm( sizeof( MPROG_DATA ) );
mprg2 = mprg2->next;
mprg2->next = NULL;
break;
case '|':
done = TRUE;
break;
default:
bug( "in mobprog file syntax error.", 0 );
exit( 1 );
break;
}
break;
}
}
fclose( progfile );
return mprg2;
}
/* Snarf a MOBprogram section from the area file. */
/* This handles both the old and new format of mobprogs */
void load_mobprogs( FILE *fp )
{
MOB_INDEX_DATA *iMob;
MPROG_DATA *original, *working;
PROG_CODE *pMprog;
TRIGFILE_DATA *originalt, *workingt;
char letter;
char *file;
int value;
if ( area_last == NULL )
{
bug( "Load_new_mprogs: no #AREA seen yet.", 0 );
exit( 1 );
}
/* This function distinguishes between oldmobs and new progs */
for ( ; ; ){
sh_int vnum = 0;
switch ( letter = fread_letter( fp ) )
{
default:
bug( "Load_mobprogs: bad command '%c'.",letter);
exit(1);
break;
/* New progs are always written before S */
case 'S':
case 's':
fread_to_eol( fp );
return;
case '*':
fread_to_eol( fp );
break;
/* OLD PROG */
case 'M':
case 'm':
value = fread_number( fp );
mprogf_count++;
if ( ( iMob = get_mob_index( value ) ) == NULL )
{
bug( "Load_mobprogs: vnum %d doesnt exist", value );
exit( 1 );
}
if ( ( original = iMob->mobprogs ) )
for ( ; original->next != NULL; original = original->next );
working = (MPROG_DATA *)alloc_perm( sizeof( MPROG_DATA ) );
if ( original )
original->next = working;
else
iMob->mobprogs = working;
working->dowhen = fread_number(fp);
file = fread_word( fp );
if ( ( originalt = iMob->trigfile ) )
for ( ; originalt->next != NULL; originalt = originalt->next );
workingt = (TRIGFILE_DATA *)alloc_perm( sizeof( TRIGFILE_DATA ) );
if ( originalt )
originalt->next = workingt;
else
iMob->trigfile = workingt;
workingt->name = str_dup( file );
workingt->dowhen = working->dowhen;
working = mprog_file_read( file , working, iMob );
workingt->next= NULL;
working->next = NULL;
fread_to_eol( fp );
break;
/* NEW PROG */
case '#':
vnum = fread_number( fp );
if ( vnum == 0 )
continue; /* skip read, old progs follow */
fBootDb = FALSE;
if ( get_prog_index( vnum, PRG_MPROG ) != NULL )
{
bug( "Load_new_mprogs: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pMprog = alloc_perm( sizeof(*pMprog) );
pMprog->vnum = vnum;
pMprog->code = fread_string( fp );
if ( mprog_list == NULL )
mprog_list = pMprog;
else
{
pMprog->next = mprog_list;
mprog_list = pMprog;
}
top_mprog_index++;
}
}
}
/* This procedure is responsible for reading any in_file MOBprograms. */
void mprog_read_programs( FILE *fp, MOB_INDEX_DATA *pMobIndex)
{
MPROG_DATA *mprg;
char letter;
bool done = FALSE;
if ( ( letter = fread_letter( fp ) ) != '>' )
{
bug( "Load_mobiles: vnum %d MOBPROG char", pMobIndex->vnum );
exit( 1 );
}
pMobIndex->mobprogs = (MPROG_DATA *)alloc_perm( sizeof( MPROG_DATA ) );
mprg = pMobIndex->mobprogs;
while ( !done )
{
mprg->type = mprog_name_to_type( fread_word( fp ) );
switch ( mprg->type )
{
case ERROR_PROG:
bug( "Load_mobiles: vnum %d MOBPROG type.", pMobIndex->vnum );
exit( 1 );
break;
case IN_FILE_PROG:
mprg = mprog_file_read( fread_string( fp ), mprg,pMobIndex );
fread_to_eol( fp );
switch ( letter = fread_letter( fp ) )
{
case '>':
mprg->next = (MPROG_DATA *)alloc_perm( sizeof( MPROG_DATA ) );
mprg = mprg->next;
mprg->next = NULL;
break;
case '|':
mprg->next = NULL;
fread_to_eol( fp );
done = TRUE;
break;
default:
bug( "Load_mobiles: vnum %d bad MOBPROG.", pMobIndex->vnum );
exit( 1 );
break;
}
break;
default:
pMobIndex->progtypes = pMobIndex->progtypes | mprg->type;
mprg->arglist = fread_string( fp );
fread_to_eol( fp );
mprg->comlist = fread_string( fp );
fread_to_eol( fp );
switch ( letter = fread_letter( fp ) )
{
case '>':
mprg->next = (MPROG_DATA *)alloc_perm( sizeof( MPROG_DATA ) );
mprg = mprg->next;
mprg->next = NULL;
break;
case '|':
mprg->next = NULL;
fread_to_eol( fp );
done = TRUE;
break;
default:
bug( "Load_mobiles: vnum %d bad MOBPROG.", pMobIndex->vnum );
exit( 1 );
break;
}
break;
}
}
}
void do_repop( CHAR_DATA *ch, char *argument )
{
AREA_DATA *pArea;
if ( argument[0] == 0)
{
reset_area(ch->in_room->area);
send_to_char("Area repop!\n\r",ch);
}
if (!strcmp(argument, "room"))
{
reset_room(ch->in_room);
send_to_char("room repop!\n\r",ch);
}
if (!strcmp(argument, "all"))
{
for (pArea = area_first; pArea; pArea = pArea->next)
reset_area(pArea);
send_to_char("World has been repopped!\n\r",ch);
}
}
/* To have VLIST show more than vnum 0 - 9900, change the number below: */
#define MAX_SHOW_VNUM 327
#define NUL '\0'
#define COLUMNS 5
#define MAX_ROW ((MAX_SHOW_VNUM / COLUMNS)+1)
extern ROOM_INDEX_DATA * room_index_hash [MAX_KEY_HASH];
const sh_int opposite_dir [6] = { DIR_SOUTH, DIR_WEST, DIR_NORTH, DIR_EAST, DIR_DOWN, DIR_UP };
typedef enum {exit_from, exit_to, exit_both} exit_status;
/* get the 'short' name of an area (e.g. MIDGAARD, MIRROR etc. *
* assumes that the filename saved in the AREA_DATA struct *
* is something like midgaard.are */
char * area_name (AREA_DATA *pArea)
{
static char buffer[64];
char *period;
assert (pArea != NULL);
strncpy (buffer, pArea->file_name, 64);
period = strchr (buffer, '.');
if (period)
*period = '\0';
return buffer;
}
void room_pair (ROOM_INDEX_DATA* left, ROOM_INDEX_DATA* right, exit_status ex, char *buffer)
{
char *sExit;
switch (ex)
{
default:
sExit = "??"; break;
case exit_from:
sExit = "< "; break;
case exit_to:
sExit = " >"; break;
case exit_both:
sExit = "<>"; break;
}
sprintf (buffer, "%5d %-26.26s %s%5d %-26.26s(%-8.8s)\n\r",
left->vnum, left->name, sExit, right->vnum, right->name, area_name(right->area));
}
void checkexits (ROOM_INDEX_DATA *room, AREA_DATA *pArea, char* buffer)
{
char buf[MSL];
int i;
EXIT_DATA *exit;
ROOM_INDEX_DATA *to_room;
strcpy (buffer, "");
for (i = 0; i < 6; i++)
{
exit = room->exit[i];
if (!exit)
continue;
else
to_room = exit->to_room;
if (to_room)
{
if ( (room->area == pArea) && (to_room->area != pArea) )
{
if ( to_room->exit[opposite_dir[i]] && to_room->exit[opposite_dir[i]]->to_room == room )
room_pair (room,to_room,exit_both,buf);
else
room_pair (room,to_room,exit_to,buf);
strcat (buffer, buf);
}
else if ( (room->area != pArea) && (exit->to_room->area == pArea) )
if (!(to_room->exit[opposite_dir[i]] && to_room->exit[opposite_dir[i]]->to_room == room ))
{
room_pair (to_room,room,exit_from,buf);
strcat (buffer, buf);
}
}
}
}
void do_exlist (CHAR_DATA *ch, char * argument)
{
AREA_DATA* pArea;
ROOM_INDEX_DATA* room;
int i;
char buffer[MSL];
pArea = ch->in_room->area;
for (i = 0; i < MAX_KEY_HASH; i++)
for (room = room_index_hash[i]; room != NULL; room = room->next)
{
checkexits (room, pArea, buffer);
send_to_char (buffer, ch);
}
}
void do_vlist (CHAR_DATA *ch, char *argument)
{
int i, j, vnum;
ROOM_INDEX_DATA *room;
char buf2 [100];
BUFFER *buffer;
buffer = new_buf();
for (i = 0; i < MAX_ROW; i++)
{
add_buf(buffer,"\n\r");
for (j = 0; j < COLUMNS; j++)
{
vnum = (i*COLUMNS + j);
if (vnum < MAX_SHOW_VNUM)
{
room = get_room_index (vnum * 100 + 1);
if (!room)
room = get_room_index (vnum * 100 + 5);
if (!room)
room = get_room_index (vnum * 100 + 11);
sprintf (buf2, "%3d %-8.8s ", vnum, room ? area_name(room->area) : "-" );
add_buf (buffer,buf2);
}
}
}
page_to_char(buf_string(buffer),ch);
free_buf(buffer);
}
void load_socials( FILE *fp)
{
for ( ; ; )
{
struct social_type social;
char *temp;
social.char_no_arg = NULL;
social.others_no_arg = NULL;
social.char_found = NULL;
social.others_found = NULL;
social.vict_found = NULL;
social.char_not_found = NULL;
social.char_auto = NULL;
social.others_auto = NULL;
temp = fread_word(fp);
if (!strcmp(temp,"#0"))
return;
#if defined(social_debug)
else
fprintf(stderr,"%s\n\r",temp);
#endif
strcpy(social.name,temp);
fread_to_eol(fp);
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.char_no_arg = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.char_no_arg = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.others_no_arg = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.others_no_arg = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.char_found = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.char_found = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.others_found = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.others_found = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.vict_found = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.vict_found = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.char_not_found = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.char_not_found = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.char_auto = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.char_auto = temp;
temp = fread_string_eol(fp);
if (!strcmp(temp,"$"))
social.others_auto = NULL;
else if (!strcmp(temp,"#"))
{
social_table[social_count] = social;
social_count++;
continue;
}
else
social.others_auto = temp;
social_table[social_count] = social;
social_count++;
}
}
void load_army_indexes( FILE *fp ){
if ( !area_last ){
bug( "Load_army_indexes: no #AREA seen yet.", 0 );
exit( 1 );
}
fread_army_indexes( fp, area_last );
}
void load_cabal_indexes( FILE *fp ){
if ( !area_last ){
bug( "Load_cabal_indexes: no #AREA seen yet.", 0 );
exit( 1 );
}
fread_cabal_indexes( fp, area_last );
}
void load_mobiles( FILE *fp )
{
MOB_INDEX_DATA *pMobIndex;
if ( !area_last )
{
bug( "Load_mobiles: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; )
{
sh_int vnum;
char letter;
int iHash;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_mobiles: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_mob_index( vnum ) != NULL )
{
bug( "Load_mobiles: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pMobIndex = alloc_perm( sizeof(*pMobIndex) );
pMobIndex->vnum = vnum;
pMobIndex->area = area_last;
pMobIndex->new_format = TRUE;
newmobs++;
pMobIndex->player_name = fread_string( fp );
pMobIndex->short_descr = fread_string( fp );
pMobIndex->long_descr = fread_string( fp );
pMobIndex->description = fread_string( fp );
pMobIndex->race = race_lookup(fread_string( fp ));
pMobIndex->long_descr[0] = UPPER(pMobIndex->long_descr[0]);
pMobIndex->description[0] = UPPER(pMobIndex->description[0]);
pMobIndex->act = fread_flag( fp ) | ACT_IS_NPC | race_table[pMobIndex->race].act;
pMobIndex->act2 = fread_flag( fp ) | ACT_IS_NPC | race_table[pMobIndex->race].act2;
pMobIndex->affected_by = fread_flag( fp ) | race_table[pMobIndex->race].aff;
pMobIndex->affected2_by = fread_flag( fp );
pMobIndex->pShop = NULL;
pMobIndex->alignment = fread_number( fp );
pMobIndex->group = fread_number( fp );
pMobIndex->level = fread_number( fp );
pMobIndex->hitroll = fread_number( fp );
pMobIndex->hit[DICE_NUMBER] = fread_number( fp );
/* 'd' */ fread_letter( fp );
pMobIndex->hit[DICE_TYPE] = fread_number( fp );
/* '+' */ fread_letter( fp );
pMobIndex->hit[DICE_BONUS] = fread_number( fp );
pMobIndex->mana[DICE_NUMBER] = fread_number( fp );
fread_letter( fp );
pMobIndex->mana[DICE_TYPE] = fread_number( fp );
fread_letter( fp );
pMobIndex->mana[DICE_BONUS] = fread_number( fp );
pMobIndex->damage[DICE_NUMBER] = fread_number( fp );
fread_letter( fp );
pMobIndex->damage[DICE_TYPE] = fread_number( fp );
fread_letter( fp );
pMobIndex->damage[DICE_BONUS] = fread_number( fp );
pMobIndex->dam_type = attack_lookup(fread_word(fp));
pMobIndex->ac[AC_PIERCE] = fread_number( fp ) * 10;
pMobIndex->ac[AC_BASH] = fread_number( fp ) * 10;
pMobIndex->ac[AC_SLASH] = fread_number( fp ) * 10;
pMobIndex->ac[AC_EXOTIC] = fread_number( fp ) * 10;
pMobIndex->off_flags = fread_flag( fp ) | race_table[pMobIndex->race].off;
pMobIndex->imm_flags = fread_flag( fp ) | race_table[pMobIndex->race].imm;
pMobIndex->res_flags = fread_flag( fp ) | race_table[pMobIndex->race].res;
pMobIndex->vuln_flags = fread_flag( fp ) | race_table[pMobIndex->race].vuln;
pMobIndex->start_pos = position_lookup(fread_word(fp));
pMobIndex->default_pos = position_lookup(fread_word(fp));
pMobIndex->sex = sex_lookup(fread_word(fp));
pMobIndex->pCabal = get_cabal_index_str( fread_string( fp ) );
if (pMobIndex->start_pos < POS_SLEEPING)
pMobIndex->start_pos = POS_STANDING;
if (pMobIndex->default_pos < POS_SLEEPING)
pMobIndex->default_pos = POS_STANDING;
if (pMobIndex->start_pos > POS_STANDING)
pMobIndex->start_pos = POS_STANDING;
if (pMobIndex->default_pos > POS_STANDING)
pMobIndex->default_pos = POS_STANDING;
if (pMobIndex->sex > 3)
pMobIndex->sex = 0;
pMobIndex->gold = fread_number( fp );
if (!str_cmp(race_table[pMobIndex->race].name, "unique"))
{
pMobIndex->form = fread_flag( fp ) | race_table[pMobIndex->race].form;
pMobIndex->parts = fread_flag( fp ) | race_table[pMobIndex->race].parts;
}
else
{
fread_flag( fp );
fread_flag( fp );
pMobIndex->form = race_table[pMobIndex->race].form;
pMobIndex->parts = race_table[pMobIndex->race].parts;
}
if (IS_SET(pMobIndex->form, FORM_SNAKE))
SET_BIT(pMobIndex->form, FORM_REPTILE);
if (IS_SET(pMobIndex->form, FORM_REPTILE))
SET_BIT(pMobIndex->form, FORM_COLD_BLOOD);
if (IS_SET(pMobIndex->form, FORM_AMPHIBIAN))
SET_BIT(pMobIndex->form, FORM_COLD_BLOOD);
if (IS_SET(pMobIndex->form, FORM_FISH))
SET_BIT(pMobIndex->form, FORM_COLD_BLOOD);
pMobIndex->size = size_lookup(fread_word(fp));
fread_word(fp);
for ( ; ; )
{
letter = fread_letter( fp );
if (letter == 'F')
{
char *word;
long vector;
word = fread_word(fp);
vector = fread_flag(fp);
if (!str_prefix(word,"act"))
REMOVE_BIT(pMobIndex->act,vector);
else if (!str_prefix(word,"aff"))
REMOVE_BIT(pMobIndex->affected_by,vector);
else if (!str_prefix(word,"off"))
REMOVE_BIT(pMobIndex->off_flags,vector);
else if (!str_prefix(word,"imm"))
REMOVE_BIT(pMobIndex->imm_flags,vector);
else if (!str_prefix(word,"res"))
REMOVE_BIT(pMobIndex->res_flags,vector);
else if (!str_prefix(word,"vul"))
REMOVE_BIT(pMobIndex->vuln_flags,vector);
else if (!str_prefix(word,"for"))
REMOVE_BIT(pMobIndex->form,vector);
else if (!str_prefix(word,"par"))
REMOVE_BIT(pMobIndex->parts,vector);
else
{
bug("Flag remove: flag not found.",0);
exit(1);
}
}
else if ( letter == '>' )
{
ungetc(letter,fp);
mprog_read_programs( fp, pMobIndex );
break;
}
else if ( letter == 'P' )
{
PROG_LIST *pMprog;
char *word;
int trigger = 0;
pMprog = alloc_perm(sizeof(*pMprog));
word = fread_word( fp );
if ( !(trigger = flag_lookup( word, mprog_flags )) )
{
bug( "MOBprogs: invalid trigger.",0);
exit(1);
}
SET_BIT( pMobIndex->mprog_flags, trigger );
pMprog->trig_type = trigger;
pMprog->vnum = fread_number( fp );
pMprog->trig_phrase = fread_string( fp );
pMprog->next = pMobIndex->mprogs;
pMobIndex->mprogs = pMprog;
}
else
{
ungetc(letter,fp);
break;
}
}
iHash = vnum % MAX_KEY_HASH;
pMobIndex->next = mob_index_hash[iHash];
mob_index_hash[iHash] = pMobIndex;
top_mob_index++;
top_vnum_mob = top_vnum_mob < vnum ? vnum : top_vnum_mob;
assign_area_vnum( vnum );
kill_table[URANGE(0, pMobIndex->level, MAX_LEVEL-1)].number++;
}
}
void load_objects( FILE *fp )
{
sh_int vnum = 0;
OBJ_INDEX_DATA *pObjIndex;
if ( !area_last )
{
bug( "Load_objects: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; )
{
int iHash;
char letter = '\0';
vnum = 0;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_objects: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 ) {
break;
}
fBootDb = FALSE;
if ( get_obj_index( vnum ) != NULL )
{
bug( "Load_objects: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pObjIndex = alloc_perm( sizeof(*pObjIndex) );
pObjIndex->vnum = vnum;
pObjIndex->area = area_last;
pObjIndex->new_format = TRUE;
pObjIndex->pCabal = NULL;
pObjIndex->race = 0;
pObjIndex->class = -1;
pObjIndex->reset_num = 0;
newobjs++;
pObjIndex->name = fread_string( fp );
pObjIndex->short_descr = fread_string( fp );
pObjIndex->description = fread_string( fp );
pObjIndex->material = fread_string( fp );
pObjIndex->item_type = item_lookup(fread_word( fp ));
pObjIndex->extra_flags = fread_flag( fp );
pObjIndex->wear_flags = fread_flag( fp );
if (pObjIndex->item_type == ITEM_POTION && !CAN_WEAR(pObjIndex, ITEM_HOLD))
SET_BIT(pObjIndex->wear_flags,ITEM_HOLD);
switch(pObjIndex->item_type)
{
case ITEM_WEAPON:
pObjIndex->value[0] = weapon_type(fread_word(fp));
pObjIndex->value[1] = fread_number(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = attack_lookup(fread_word(fp));
pObjIndex->value[4] = fread_flag(fp);
break;
case ITEM_THROW:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = fread_number(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = attack_lookup(fread_word(fp));
pObjIndex->value[4] = fread_flag(fp);
break;
case ITEM_CONTAINER:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = fread_flag(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = fread_number(fp);
pObjIndex->value[4] = fread_number(fp);
break;
case ITEM_DRINK_CON:
case ITEM_FOUNTAIN:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = fread_number(fp);
pObjIndex->value[2] = liq_lookup(fread_word(fp));
if (pObjIndex->value[2] == -1)
{
pObjIndex->value[2] = 0;
bug("Unknown liquid type",0);
}
pObjIndex->value[3] = fread_number(fp);
pObjIndex->value[4] = fread_number(fp);
break;
case ITEM_WAND:
case ITEM_STAFF:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = fread_number(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = skill_lookup(fread_word(fp));
pObjIndex->value[4] = fread_number(fp);
break;
case ITEM_POTION:
case ITEM_RELIC:
case ITEM_ARTIFACT:
case ITEM_PILL:
case ITEM_SCROLL:
case ITEM_HERB:
pObjIndex->value[0] = fread_number(fp);
pObjIndex->value[1] = skill_lookup(fread_word(fp));
pObjIndex->value[2] = skill_lookup(fread_word(fp));
pObjIndex->value[3] = skill_lookup(fread_word(fp));
pObjIndex->value[4] = skill_lookup(fread_word(fp));
break;
case ITEM_SOCKET:
pObjIndex->value[0] = fread_flag(fp);
pObjIndex->value[1] = fread_flag(fp);
pObjIndex->value[2] = fread_flag(fp);
pObjIndex->value[3] = fread_flag(fp);
pObjIndex->value[4] = fread_flag(fp);
break;
case ITEM_RANGED:
pObjIndex->value[0] = fread_flag(fp);
pObjIndex->value[1] = fread_number(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = fread_number(fp);
pObjIndex->value[4] = fread_flag(fp);
break;
case ITEM_PROJECTILE:
pObjIndex->value[0] = fread_flag(fp);
pObjIndex->value[1] = fread_number(fp);
pObjIndex->value[2] = fread_number(fp);
pObjIndex->value[3] = attack_lookup(fread_word(fp));
pObjIndex->value[4] = fread_flag(fp);
break;
default:
pObjIndex->value[0] = fread_flag( fp );
pObjIndex->value[1] = fread_flag( fp );
pObjIndex->value[2] = fread_flag( fp );
pObjIndex->value[3] = fread_flag( fp );
pObjIndex->value[4] = fread_flag( fp );
break;
}
pObjIndex->level = fread_number( fp );
pObjIndex->weight = fread_number( fp );
pObjIndex->cost = fread_number( fp );
letter = fread_letter( fp );
switch (letter)
{
case ('P') : pObjIndex->condition = 100; break;
case ('G') : pObjIndex->condition = 90; break;
case ('A') : pObjIndex->condition = 75; break;
case ('W') : pObjIndex->condition = 50; break;
case ('D') : pObjIndex->condition = 25; break;
case ('B') : pObjIndex->condition = 10; break;
case ('R') : pObjIndex->condition = 0; break;
default: pObjIndex->condition = 100; break;
}
for ( ; ; )
{
char letter;
letter = fread_letter( fp );
if ( letter == 'E' )
{
EXTRA_DESCR_DATA *ed;
ed = alloc_perm( sizeof(*ed) );
ed->keyword = fread_string( fp );
ed->description = fread_string( fp );
ed->next = pObjIndex->extra_descr;
pObjIndex->extra_descr = ed;
top_ed++;
}
else if ( letter == 'A' )
{
AFFECT_DATA *paf;
paf = alloc_perm( sizeof(*paf) );
paf->where = TO_OBJECT;
paf->type = -1;
paf->level = pObjIndex->level;
paf->duration = -1;
paf->location = fread_number( fp );
paf->modifier = fread_number( fp );
paf->bitvector = 0;
paf->next = pObjIndex->affected;
pObjIndex->affected = paf;
top_affect++;
}
else if ( letter == 'C')
pObjIndex->pCabal = get_cabal_index_str( fread_string( fp ) );
else if (letter == 'F')
{
AFFECT_DATA *paf;
paf = alloc_perm( sizeof(*paf) );
letter = fread_letter(fp);
switch (letter)
{
case 'A': paf->where = TO_AFFECTS; break;
case 'I': paf->where = TO_IMMUNE; break;
case 'R': paf->where = TO_RESIST; break;
case 'S': paf->where = TO_SKILL; break;
case 'V': paf->where = TO_VULN; break;
default: bug( "Load_objects: Bad where on flag set.", 0 ); exit( 1 );
}
paf->type = -1;
paf->level = pObjIndex->level;
paf->duration = -1;
paf->location = fread_number(fp);
paf->modifier = fread_number(fp);
paf->bitvector = fread_flag(fp);
paf->next = pObjIndex->affected;
pObjIndex->affected = paf;
top_affect++;
}
else if ( letter == 'L')
pObjIndex->class = fread_number (fp );
else if ( letter == 'M' )
{
OBJ_MESSAGE_DATA *new_message;
new_message = alloc_perm( sizeof( *new_message ) );
new_message->onself = fread_string( fp );
new_message->onother = fread_string( fp );
new_message->offself = fread_string( fp );
new_message->offother = fread_string( fp );
pObjIndex->message = new_message;
}
else if ( letter == 'P' )
{
PROG_LIST *pOprog;
char *word;
int trigger = 0;
pOprog = alloc_perm(sizeof(*pOprog));
word = fread_word( fp );
if ( !(trigger = flag_lookup( word, oprog_flags )) )
{
bug( "OBJprogs: invalid trigger.",0);
exit(1);
}
SET_BIT( pObjIndex->oprog_flags, trigger );
pOprog->trig_type = trigger;
pOprog->vnum = fread_number( fp );
pOprog->trig_phrase = fread_string( fp );
pOprog->next = pObjIndex->oprogs;
pObjIndex->oprogs = pOprog;
}
else if ( letter == 'R')
pObjIndex->race = fread_number (fp );
else if( letter == 'T' )
{
OBJ_SPELL_DATA *new_spell;
new_spell = alloc_perm( sizeof( *new_spell ) );
new_spell->spell = fread_number( fp );
new_spell->target = fread_number( fp );
new_spell->percent = fread_number( fp );
new_spell->message = fread_string( fp );
new_spell->message2 = fread_string( fp );
new_spell->next = pObjIndex->spell;
pObjIndex->spell = new_spell;
}
else
{
ungetc( letter, fp );
break;
}
}
iHash = vnum % MAX_KEY_HASH;
pObjIndex->next = obj_index_hash[iHash];
obj_index_hash[iHash] = pObjIndex;
top_obj_index++;
top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj;
assign_area_vnum( vnum );
}
}
/* Converts all old format objects to new format. *
* Called by boot_db (db.c). *
* Loops over all resets to find the level of the mob *
* loaded before the object to determine the level of *
* the object. */
void convert_objects( void )
{
int vnum;
AREA_DATA *pArea;
RESET_DATA *pReset;
MOB_INDEX_DATA *pMob = NULL;
OBJ_INDEX_DATA *pObj;
ROOM_INDEX_DATA *pRoom;
if ( newobjs == top_obj_index )
return;
for ( pArea = area_first; pArea; pArea = pArea->next )
{
for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++ )
{
if ( !( pRoom = get_room_index( vnum ) ) )
continue;
for ( pReset = pRoom->reset_first; pReset; pReset = pReset->next )
{
switch ( pReset->command )
{
case 'M':
if ( !( pMob = get_mob_index( pReset->arg1 ) ) )
bug( "Convert_objects: 'M': bad vnum %d.", pReset->arg1 );
break;
case 'O':
if ( !( pObj = get_obj_index( pReset->arg1 ) ) )
{
bug( "Convert_objects: 'O': bad vnum %d.", pReset->arg1 );
break;
}
if ( pObj->new_format )
continue;
if ( !pMob )
{
bug( "Convert_objects: 'O': No mob reset yet.", 0 );
break;
}
pObj->level = pObj->level < 1 ? pMob->level - 2 : UMIN(pObj->level, pMob->level - 2);
break;
case 'P':
{
OBJ_INDEX_DATA *pObj, *pObjTo;
if ( !( pObj = get_obj_index( pReset->arg1 ) ) )
{
bug( "Convert_objects: 'P': bad vnum %d.", pReset->arg1 );
break;
}
if ( pObj->new_format )
continue;
if ( !( pObjTo = get_obj_index( pReset->arg3 ) ) )
{
bug( "Convert_objects: 'P': bad vnum %d.", pReset->arg3 );
break;
}
pObj->level = pObj->level < 1 ? pObjTo->level : UMIN(pObj->level, pObjTo->level);
}
break;
case 'G':
case 'E':
if ( !( pObj = get_obj_index( pReset->arg1 ) ) )
{
bug( "Convert_objects: 'E' or 'G': bad vnum %d.", pReset->arg1 );
break;
}
if ( !pMob )
{
bug( "Convert_objects: 'E' or 'G': null mob for vnum %d.",pReset->arg1 );
break;
}
if ( pObj->new_format )
continue;
if ( pMob->pShop )
{
switch ( pObj->item_type )
{
default: pObj->level = UMAX(0, pObj->level); break;
case ITEM_PILL:
case ITEM_RELIC:
case ITEM_SOCKET:
case ITEM_ARTIFACT:
case ITEM_POTION: pObj->level = UMAX(5, pObj->level); break;
case ITEM_SCROLL:
case ITEM_ARMOR:
case ITEM_THROW:
case ITEM_WEAPON: pObj->level = UMAX(10, pObj->level); break;
case ITEM_WAND:
case ITEM_TREASURE: pObj->level = UMAX(15, pObj->level); break;
case ITEM_RANGED: pObj->level = UMAX(15, pObj->level); break;
case ITEM_PROJECTILE: pObj->level = UMAX(15,pObj->level); break;
case ITEM_INSTRUMENT:pObj->level= UMAX(10, pObj->level); break;
case ITEM_STAFF: pObj->level = UMAX(20, pObj->level); break;
}
}
else
pObj->level = pObj->level < 1 ? pMob->level : UMIN( pObj->level, pMob->level );
break;
}
}
}
}
for ( pArea = area_first; pArea ; pArea = pArea->next )
for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++ )
if ( (pObj = get_obj_index( vnum )) )
if ( !pObj->new_format )
convert_object( pObj );
}
/* Converts an old_format obj to new_format. *
* Called by convert_objects (db2.c). *
* Dug out of create_obj (db.c) */
void convert_object( OBJ_INDEX_DATA *pObjIndex )
{
int level, number, type;
if ( !pObjIndex || pObjIndex->new_format )
return;
level = pObjIndex->level;
pObjIndex->level = UMAX( 0, pObjIndex->level );
pObjIndex->cost = 10*level;
switch ( pObjIndex->item_type )
{
default:
bug( "Obj_convert: vnum %d bad type.", pObjIndex->item_type );
break;
case ITEM_LIGHT:
case ITEM_TREASURE:
case ITEM_RANGED:
case ITEM_INSTRUMENT:
case ITEM_FURNITURE:
case ITEM_TRASH:
case ITEM_CONTAINER:
case ITEM_DRINK_CON:
case ITEM_KEY:
case ITEM_FOOD:
case ITEM_HERB:
case ITEM_BOAT:
case ITEM_CORPSE_NPC:
case ITEM_CORPSE_PC:
case ITEM_FOUNTAIN:
case ITEM_MAP:
case ITEM_CLOTHING:
case ITEM_SCROLL:
break;
case ITEM_WAND:
case ITEM_STAFF:
pObjIndex->value[2] = pObjIndex->value[1];
break;
case ITEM_THROW:
case ITEM_WEAPON:
/* The conversion below is based on the values generated *
* in one_hit() (fight.c). Since I don't want a lvl 50 *
* weapon to do 15d3 damage, the min value will be below *
* the one in one_hit, and to make up for it, I've made *
* the max value higher. *
* (I don't want 15d2 because this will hardly ever roll *
* 15 or 30, it will only roll damage close to 23. *
* I can't do 4d8+11, because one_hit there is no dice- *
* bounus value to set...) *
* The conversion below gives: *
* level: dice min max mean *
* 1: 1d8 1( 2) 8( 7) 5( 5) *
* 2: 2d5 2( 3) 10( 8) 6( 6) 8
* 3: 2d5 2( 3) 10( 8) 6( 6) 8
* 5: 2d6 2( 3) 12(10) 7( 7) *
* 10: 4d5 4( 5) 20(14) 12(10) *
* 20: 5d5 5( 7) 25(21) 15(14) *
* 30: 5d7 5(10) 35(29) 20(20) *
* 50: 5d11 5(15) 55(44) 30(30) */
number = UMIN(level/4 + 1, 5);
type = (level + 7)/number;
pObjIndex->value[1] = number;
pObjIndex->value[2] = type;
break;
case ITEM_ARMOR:
pObjIndex->value[0] = level / 5 + 3;
pObjIndex->value[1] = pObjIndex->value[0];
pObjIndex->value[2] = pObjIndex->value[0];
break;
case ITEM_POTION:
case ITEM_RELIC:
case ITEM_SOCKET:
case ITEM_ARTIFACT:
case ITEM_PILL:
break;
case ITEM_MONEY:
pObjIndex->value[0] = pObjIndex->cost;
break;
}
pObjIndex->new_format = TRUE;
++newobjs;
}
/* Converts an old_format mob into new_format. *
* Called by load_old_mob (db.c). *
* Dug out of create_mobile (db.c) */
void convert_mobile( MOB_INDEX_DATA *pMobIndex )
{
int i, type, number, bonus, level;
if ( !pMobIndex || pMobIndex->new_format )
return;
level = pMobIndex->level;
pMobIndex->act |= ACT_WARRIOR;
pMobIndex->act2 = 0;
/* Calculate hit dice. Gives close to the hitpoints *
* of old format mobs created with create_mobile() (db.c) *
* A high number of dice makes for less variance in mobiles *
* hitpoints. *
* (might be a good idea to reduce the max number of dice) *
* The conversion below gives: *
* *
* level: dice min max diff mean *
* 1: 1d2+6 7( 7) 8( 8) 1( 1) 8( 8) *
* 2: 1d3+15 16( 15) 18( 18) 2( 3) 17( 17) *
* 3: 1d6+24 25( 24) 30( 30) 5( 6) 27( 27) *
* 5: 1d17+42 43( 42) 59( 59) 16( 17) 51( 51) *
* 10: 3d22+96 99( 95) 162( 162) 63( 67) 131( ) *
* 15: 5d30+161 166(159) 311( 311) 145( 150) 239( ) *
* 30: 10d61+416 426(419) 1026(1026) 600( 607) 726( ) *
* 50: 10d169+920 930(923) 2610(2610) 1680(1688) 1770( ) *
* *
* The values in parenthesis give the values generated in create_mobile. *
* Diff = max - min. Mean is the arithmetic mean. *
* (hmm.. must be some roundoff error in my calculations.. smurfette got *
* 1d6+23 hp at level 3 ? -- anyway.. the values above should be *
* approximately right..) */
type = level*level*27/40;
number = UMIN(type/40 + 1, 10);
type = UMAX(2, type/number);
bonus = UMAX(0, level*(8 + level)*.9 - number*type);
pMobIndex->hit[DICE_NUMBER] = number;
pMobIndex->hit[DICE_TYPE] = type;
pMobIndex->hit[DICE_BONUS] = bonus;
pMobIndex->mana[DICE_NUMBER] = level;
pMobIndex->mana[DICE_TYPE] = 10;
pMobIndex->mana[DICE_BONUS] = 100;
/* Calculate dam dice. Gives close to the damage *
* of old format mobs in damage() (fight.c) */
type = level*7/4;
number = UMIN(type/8 + 1, 5);
type = UMAX(2, type/number);
bonus = UMAX(0, level*9/4 - number*type);
pMobIndex->damage[DICE_NUMBER] = number;
pMobIndex->damage[DICE_TYPE] = type;
pMobIndex->damage[DICE_BONUS] = bonus;
switch ( number_range( 1, 3 ) )
{
case (1): pMobIndex->dam_type = 3; break;
case (2): pMobIndex->dam_type = 7; break;
case (3): pMobIndex->dam_type = 11; break;
}
for (i = 0; i < 3; i++)
pMobIndex->ac[i] = interpolate( level, 100, -100);
pMobIndex->ac[3] = interpolate( level, 100, 0);
pMobIndex->gold /= 100;
pMobIndex->size = SIZE_MEDIUM;
pMobIndex->new_format = TRUE;
++newmobs;
}
void do_hotreboot (CHAR_DATA *ch, char * argument)
{
FILE *fp;
DESCRIPTOR_DATA *d, *d_next;
OBJ_DATA *obj, *obj_next;
char buf [100], buf2[100];
extern int control;
char arg[MIL];
bool fSave = FALSE; //if arg == 0 then safe, otherwise its due to a signal
argument = one_argument(argument,arg);
fp = fopen (HOTREBOOT_FILE, "w");
if (!fp)
{
sprintf(buf,"`&Mud Control`8: ``Hot Reboot file not writeable, aborted.\n\r");
do_echo(NULL,buf);
log_string ("Could not write to hot reboot file.");
perror ("do_hotreboot:fopen");
fclose (fp);
return;
}
/* Consider changing all saved areas here, if you use OLC */
if (atoi(arg)==1)
sprintf (buf, "\n\r *** SIGBUS detected: Mud Crash is imminent - Trying to Hot Reboot ***\n\r");
else if (atoi(arg)==2)
sprintf (buf, "\n\r *** SIGTERM detected: Mud Crash is imminent - Trying to Hot Reboot ***\n\r");
else if (atoi(arg)==3)
sprintf (buf, "\n\r *** SIGABRT detected: Mud Crash is imminent - Trying to Hot Reboot ***\n\r");
else if (atoi(arg)==4)
sprintf (buf, "\n\r *** Planetary anomaly detected! World destruction is imminent! Trying to world shift... ***\n\r");
else{
fSave = TRUE;
if (ch != NULL){
sprintf (buf, "\n\r *** %s has initiated a world shift - please wait! *** \n\r", PERS2(ch));
}
else{
sprintf (buf, "\n\r *** The world is shifting - please wait! *** \n\r");
}
}
if (fSave){
/* SAVE MUD STATUS */
save_mud();
/* SAVE CABAL DATA */
save_cabals(TRUE, NULL );
/* SAVE ARMIES */
save_armies();
/* SAVE CLANS */
SaveClans();
}
/* Check for Maintance */
if (reboot_buffer[0] != '\0')
strcat(buf," *** Extended world shift, this may take some time. *** \n\r");
/* For each playing descriptor, save its state */
for (d = descriptor_list; d ; d = d_next)
{
CHAR_DATA * och = CH (d);
d_next = d->next; /* We delete from the list , so need to save this */
if (!d->character || d->connected != CON_PLAYING ) /* drop those logging on */
{
write_to_descriptor (d->descriptor, "\n\rSorry, we are rebooting. Come back in a few seconds.\n\r", 0);
close_socket (d); /* throw'em out */
}
else
{
/* clean off blanket of darkness between reboots */
affect_strip(och, gsn_blanket);
/* force revert */
do_revert(och, "" );
/* same for charm person */
if (!IS_AFFECTED(och, AFF_CHARM))
affect_strip(och, gsn_charm_person);
fprintf (fp, "%d %s %s %s %ld\n", d->descriptor, och->name, d->ident, d->host, och->logon );
if (fSave)
save_char_obj (och);
write_to_descriptor (d->descriptor, buf, 0);
if (d->character->level > 51 && atoi(arg)>=1 && atoi(arg)<=4)
{
write_to_descriptor (d->descriptor, last_malloc, 0);
write_to_descriptor (d->descriptor, "\n\r", 0);
write_to_descriptor (d->descriptor, last_loop, 0);
write_to_descriptor (d->descriptor, "\n\r", 0);
write_to_descriptor (d->descriptor, last_command, 0);
write_to_descriptor (d->descriptor, "\n\r", 0);
write_to_descriptor (d->descriptor, last_mprog, 0);
write_to_descriptor (d->descriptor, "\n\r", 0);
}
extract_char(och, TRUE);
}
}
fprintf (fp, "-1\n");
fprintf (fp, "%d\n", mud_data.max_on);
fprintf (fp, "%d\n", mud_data.deaths);
fprintf (fp, "%ld\n", mud_data.crash_time);
fclose (fp);
fp = fopen (OBJSAVE_FILE, "w");
if (fSave){
for (obj = object_list; obj != NULL; obj = obj_next )
{
obj_next = obj->next;
if (IS_OBJ_STAT(obj,ITEM_MELT_DROP))
continue;
if (obj->in_room != NULL
&& obj->in_room->vnum != ROOM_VNUM_BOUNTY //objects in bounty room are saved/loaded with bounties
&& obj->carried_by == NULL
&& !IS_VIRROOM(obj->in_room)
&& (IS_LIMITED(obj)
|| obj->homevnum != obj->in_room->vnum
|| obj->contains != NULL
|| CAN_WEAR(obj, ITEM_HAS_OWNER)) )
fwrite_obj(NULL, obj, fp, 0, 0, FALSE);
else if (obj->item_type == ITEM_CABAL && obj->carried_by && obj->carried_by->in_room)
fwrite_obj(NULL, obj, fp, 9999, 0, TRUE);
}
}
fprintf (fp, "#END\n");
fclose (fp);
/* Close reserve and other always-open files and release other resources */
fclose (fpReserve);
/* exec - descriptors are inherited */
sprintf (buf, "%d", mud_data.mudport);
sprintf (buf2, "%d", control);
execl ("../src/clands", "MUD", buf, "Forsaken_Lands", buf2, reboot_buffer, (char *) NULL);
/* Failed - sucessful exec will not return */
perror ("do_hotreboot: execl");
sprintf(buf,"[`&The Voice of God`7]`8 - World shift FAILED!``");
do_echo(NULL,buf);
/* Here you might want to reopen fpReserve */
fpReserve = fopen (NULL_FILE, "r");
}
/* Recover from a Hot Reboot - load players */
void hotreboot_recover ()
{
DESCRIPTOR_DATA *d;
CHAR_DATA *ch, *ch_next;
FILE *fp;
char name [100], ident[MSL], host[MSL];
time_t logont, temp;
int tempmax, tempdeaths, desc;
bool fOld;
int i = 0;
log_string ("World shift recovery initiated");
fp = fopen (HOTREBOOT_FILE, "r");
if (!fp) /* there are some descriptors open which will hang forever then ? */
{
perror ("hotreboot_recover:fopen");
log_string ("World shift file not found. Exiting.");
fclose (fp);
exit (1);
}
unlink (HOTREBOOT_FILE); /* In case something crashes - doesn't prevent reading */
for (i = 0; i < 1000; i++)
{
fscanf (fp, "%d ", &desc);
if (desc == -1)
{
fscanf (fp, "\n%d\n", &tempmax);
fscanf (fp, "\n%d\n", &tempdeaths);
fscanf (fp, "%ld\n", &temp);
mud_data.max_on = tempmax;
mud_data.deaths = tempdeaths;
mud_data.crash_time = temp;
break;
}
fscanf (fp, "%s %s %s %ld\n", name, ident, host, &logont);
/* Write something, and check if it goes error-free */
if (!write_to_descriptor (desc, "\n\rRestoring from world shift...\n\r",0))
{
close (desc); /* nope */
continue;
}
d = new_descriptor();
d->descriptor = desc;
d->ident = str_dup (ident);
d->host = str_dup (host);
d->next = descriptor_list;
descriptor_list = d;
d->connected = CON_HOTREBOOT_RECOVER; /* -15, so close_socket frees the char */
/* Now, find the pfile */
fOld = load_char (d, name);
d->character->logon = logont;
if (!fOld) /* Player file not found?! */
{
write_to_descriptor (desc, "\n\rSomehow, your character was lost in the Hot Reboot. Sorry.\n\r", 0);
close_socket (d);
}
else /* ok! */
{
write_to_descriptor (desc, "\n\rWorld shifting is complete.\n\r",0);
/* Just In Case */
if (!d->character->in_room)
d->character->in_room = get_room_index (ROOM_VNUM_TEMPLE);
/* Insert in the char_list */
load_obj (d->character);
d->character->next = char_list;
char_list = d->character;
char_to_room (d->character, d->character->in_room);
d->character->next_player = player_list;
player_list = d->character;
reset_char(d->character);
do_look (d->character, "");
act ("$n materializes!", d->character, NULL, NULL, TO_ROOM);
d->connected = CON_PLAYING;
}
}
fclose (fp);
/* This is to get the player's stallions and familiars and other stuff back after reboot */
for ( ch = char_list; ch != NULL; ch = ch_next )
{
ch_next = ch->next;
if (!IS_NPC(ch) || ch->in_room == NULL)
continue;
if ((ch->pIndexData->vnum >= MOB_VNUM_SERVANT_FIRE
&& ch->pIndexData->vnum <= MOB_VNUM_SERVANT_EARTH)
&& ch->summoner != NULL && !IS_NPC(ch->summoner)){
ch->summoner->pcdata->familiar = ch;
}
else if (ch->pIndexData->vnum == MOB_VNUM_MONSTER
&& ch->summoner != NULL
&& !IS_NPC(ch->summoner)){
ch->summoner->pcdata->familiar = ch;
}
/* reset zombies after rebot to originals (Viri: not needed, save in pfiles now
else if (ch->pIndexData->vnum == MOB_VNUM_ZOMBIE){
AFFECT_DATA* paf;
MOB_INDEX_DATA* mob;
if ( (paf = affect_find(ch->affected, skill_lookup("animate corpse"))) != NULL
&& (mob = get_mob_index(paf->modifier)) != NULL){
ch->off_flags = paf->bitvector;
ch->dam_type = mob->dam_type;
ch->act = mob->act;
REMOVE_BIT(mob->act,ACT_SCAVENGER);
REMOVE_BIT(mob->act,ACT_IS_HEALER);
REMOVE_BIT(mob->act,ACT_TRAIN);
REMOVE_BIT(mob->act,ACT_PRACTICE);
REMOVE_BIT(mob->act,ACT_TOO_BIG);
}
}
*/
}
}
/* format_room_name */
/* links in db.c cabal.c */
/* written by viri */
bool format_room_name(ROOM_INDEX_DATA* room, char* room_name)
{
//The following function attaches appropriate
//ascii color string to the room name based on the
//room_color_table in tables.c
//buffer for the name.
char buf[MIL];
//pointers for the string
char* strptr;
char* bufptr;
/*
1)prefix buf with appropriate ascii code.
2)Run through the room_name copying non-ascii char's only.
3)When terminator is hit or MIL is reached stop.
4)attatch end of ascii sequence, termianate string.
*/
if (room == NULL || room_name == NULL)
return FALSE;
strptr = room_name;
bufptr = buf;
//we prefix the buffer.
*bufptr++ = '`';
*bufptr++ = room_color_table[UMIN(MAX_SECT, room->sector_type)].ch;
//First we cleant the name length is MSL - 2(prefix) - 2 (postifx).
while( *strptr != '\0')
{
//we copy the string normaly unless there is asci code.
if ( *strptr != '`')
{
*bufptr++ = *strptr++;
continue;
}
//got a ascii code, we skip the next 2 char.
strptr++;
strptr++;
}//end copy loop;
//we terminate ascii
*bufptr++ = '`';
*bufptr++ = '`';
//terminate string
*bufptr++ = '\0';
//free string
free_string(room->name);
room->name = str_dup(buf);
return TRUE;
}//end room_name_formant
/* color_rooms*/
/* only in db.c */
/* Viri */
void color_rooms()
{
/* We run through ALL the rooms, coloring the names. */
ROOM_INDEX_DATA* room;
int i = 0;
for (i = 0; i < MAX_KEY_HASH; i++)
for (room = room_index_hash[i]; room != NULL; room = room->next)
{
if (room == NULL)
continue;
if (!format_room_name(room, room->name))
{
log_string("ERROR IN ROOM NAME FORMAT");
nlogf("format_room_name returned error on room %d", room->vnum);
}
}
}
void load_objprogs( FILE *fp )
{
PROG_CODE *pOprog;
if ( area_last == NULL )
{
bug( "Load_objprogs: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; )
{
sh_int vnum;
char letter;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_objprogs: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_prog_index( vnum, PRG_OPROG ) != NULL )
{
bug( "Load_objprogs: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pOprog = alloc_perm( sizeof(*pOprog) );
pOprog->vnum = vnum;
pOprog->code = fread_string( fp );
if ( oprog_list == NULL )
oprog_list = pOprog;
else
{
pOprog->next = oprog_list;
oprog_list = pOprog;
}
top_oprog_index++;
}
return;
}
void load_roomprogs( FILE *fp )
{
PROG_CODE *pRprog;
if ( area_last == NULL )
{
bug( "Load_roomprogs: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; )
{
sh_int vnum;
char letter;
letter = fread_letter( fp );
if ( letter != '#' )
{
bug( "Load_roomprogs: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum == 0 )
break;
fBootDb = FALSE;
if ( get_prog_index( vnum, PRG_RPROG ) != NULL )
{
bug( "Load_roomprogs: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pRprog = alloc_perm( sizeof(*pRprog) );
pRprog->vnum = vnum;
pRprog->code = fread_string( fp );
if ( rprog_list == NULL )
rprog_list = pRprog;
else
{
pRprog->next = rprog_list;
rprog_list = pRprog;
}
top_rprog_index++;
}
return;
}
void load_traps( FILE *fp ){
TRAP_INDEX_DATA *pTrap;
char* temp;
if ( area_last == NULL ){
bug( "Load_traps: no #AREA seen yet.", 0 );
exit( 1 );
}
for ( ; ; ){
sh_int vnum;
char letter;
letter = fread_letter( fp );
if ( letter != '#' ){
bug( "Load_traps: # not found.", 0 );
exit( 1 );
}
vnum = fread_number( fp );
if ( vnum <= 0 )
break;
fBootDb = FALSE;
if ( get_trap_index( vnum ) != NULL ){
bug( "Load_traps: vnum %d duplicated.", vnum );
exit( 1 );
}
fBootDb = TRUE;
pTrap = new_trap_index();
pTrap->area = area_last;
pTrap->vnum = vnum;
/* read in commons */
pTrap->name = fread_string( fp );
pTrap->echo = fread_string( fp );
pTrap->oEcho = fread_string( fp );
if ( (pTrap->type = trap_lookup( fread_word( fp ) )) < 1)
bug("load_traps: Unknown trap type for vnum %d.", vnum);
pTrap->level = fread_number( fp );
pTrap->flags = fread_flag( fp );
/* read in type based stuff */
switch (pTrap->type){
default:
case TTYPE_DUMMY:
pTrap->value[0] = fread_number( fp );
pTrap->value[1] = fread_number( fp );
pTrap->value[2] = fread_number( fp );
pTrap->value[3] = fread_number( fp );
pTrap->value[4] = fread_number( fp );
break;
case TTYPE_DAMAGE:
pTrap->value[0] = attack_lookup( fread_word( fp ));
if (pTrap->value[0] < 0){
bug("Load_traps: value[0] of TTYPE_DAMAGE vnum %d was incorrect.", vnum);
pTrap->value[0] = 1;
}
pTrap->value[1] = fread_number( fp );
pTrap->value[2] = fread_number( fp );
pTrap->value[3] = fread_number( fp );
pTrap->value[4] = fread_number( fp );
break;
case TTYPE_XDAMAGE:
temp = fread_string( fp );
pTrap->value[0] = skill_lookup(temp);
free_string( temp );
if (pTrap->value[0] < 0){
bug("Load_traps: value[0] of TTYPE_XDAMAGE vnum %d was incorrect.", vnum);
pTrap->value[0] = 1;
}
pTrap->value[1] = fread_number( fp );
pTrap->value[2] = fread_number( fp );
pTrap->value[3] = fread_number( fp );
pTrap->value[4] = fread_number( fp );
break;
case TTYPE_SPELL:
temp = fread_string( fp );
pTrap->value[0] = skill_lookup(temp);
if (pTrap->value[0] < 0){
bug("Load_traps: value[0] of TTYPE_SPELL vnum %d was incorrect.", vnum);
pTrap->value[0] = 1;
}
pTrap->value[1] = fread_number( fp );
temp = fread_string( fp );
pTrap->value[2] = skill_lookup(temp);
free_string( temp );
if (pTrap->value[2] < 0){
bug("Load_traps: value[2] of TTYPE_SPELL vnum %d was incorrect.", vnum);
pTrap->value[2] = 1;
}
pTrap->value[3] = fread_number( fp );
pTrap->value[4] = fread_number( fp );
break;
case TTYPE_MOB:
pTrap->value[0] = fread_number( fp );
pTrap->value[1] = fread_number( fp );
pTrap->value[2] = fread_number( fp );
pTrap->value[3] = fread_number( fp );
pTrap->value[4] = fread_number( fp );
break;
}
if ( trap_index_list == NULL )
trap_index_list = pTrap;
else{
pTrap->next = trap_index_list;
trap_index_list = pTrap;
}
}
return;
}
void fix_mobprogs( void )
{
MOB_INDEX_DATA *pMobIndex;
PROG_LIST *list;
PROG_CODE *prog;
int iHash;
for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
{
for ( pMobIndex = mob_index_hash[iHash];
pMobIndex != NULL;
pMobIndex = pMobIndex->next )
{
for( list = pMobIndex->mprogs; list != NULL; list = list->next )
{
if ( ( prog = get_prog_index( list->vnum, PRG_MPROG ) ) != NULL )
list->code = prog->code;
else
{
bug( "Fix_mobprogs: code vnum %d not found.", list->vnum );
exit( 1 );
}
}
}
}
}
void fix_objprogs( void )
{
OBJ_INDEX_DATA *pObjIndex;
PROG_LIST *list;
PROG_CODE *prog;
int iHash;
for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
{
for ( pObjIndex = obj_index_hash[iHash];
pObjIndex != NULL;
pObjIndex = pObjIndex->next )
{
for( list = pObjIndex->oprogs; list != NULL; list = list->next )
{
if ( ( prog = get_prog_index( list->vnum, PRG_OPROG ) ) != NULL )
list->code = prog->code;
else
{
bug( "Fix_objprogs: code vnum %d not found.", list->vnum );
exit( 1 );
}
}
}
}
}
void fix_roomprogs( void )
{
ROOM_INDEX_DATA *pRoomIndex;
PROG_LIST *list;
PROG_CODE *prog;
int iHash;
for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ )
{
for ( pRoomIndex = room_index_hash[iHash];
pRoomIndex != NULL;
pRoomIndex = pRoomIndex->next )
{
for( list = pRoomIndex->rprogs; list != NULL; list = list->next )
{
if ( ( prog = get_prog_index( list->vnum, PRG_RPROG ) ) != NULL )
list->code = prog->code;
else
{
bug( "Fix_roomprogs: code vnum %d not found.", list->vnum );
exit( 1 );
}
}
}
}
}
//prints a text entry for an object
void dump_object( FILE* fp, OBJ_INDEX_DATA* obj ){
AFFECT_DATA* paf;
int i;
char buf[MIL];
//vnum rare unique type level material extra_flags weight keywords area name
fprintf(fp, "%d \"%s\" \"%s\" %d %d \"%s\" \"%s\" \"%s\" \"%s\"",
obj->vnum,
IS_SET(obj->wear_flags, ITEM_RARE) ? "R" : IS_SET(obj->wear_flags, ITEM_UNIQUE) ? "U" : "",
item_name(obj->item_type),
obj->level,
obj->weight,
obj->material,
extra_bit_name(obj->extra_flags),
obj->area->name,
obj->short_descr);
//print item dependent info
fprintf(fp, "\"" );
switch ( obj->item_type ){
case ITEM_SOCKET:
if (IS_SOC_STAT(obj, SOCKET_ARMOR)
&& IS_SOC_STAT(obj, SOCKET_WEAPON))
fprintf(fp, "Ar/Wep");
else if (IS_SOC_STAT(obj, SOCKET_ARMOR))
fprintf(fp, "Ar ");
else if (IS_SOC_STAT(obj, SOCKET_WEAPON))
fprintf(fp, " Wep");
else
fprintf(fp, " Wep");
if (obj->value[1]){
sprintf(buf, " Extra: %s",
flag_string( extra_flags, obj->value[1] ) );
fprintf(fp, buf);
}
if (obj->value[4]){
sprintf(buf, " Flags: %s\n",
flag_string( weapon_type2, obj->value[4] ) );
fprintf(fp, buf);
}
break;
case ITEM_SCROLL:
case ITEM_ARTIFACT:
case ITEM_POTION:
case ITEM_PILL:
sprintf( buf, "Level %d: ", obj->value[0] );
for ( i = 1; i <= 4; i++ ){
if ( obj->value[i] >= 0
&& obj->value[i] < MAX_SKILL
&& skill_table[obj->value[i]].name != NULL){
strcat( buf, " '" );
strcat( buf, skill_table[obj->value[i]].name );
strcat( buf, "' " );
}
}
fprintf(fp, buf);
break;
case ITEM_WAND:
case ITEM_STAFF:
if (skill_table[obj->value[3]].name == NULL)
break;
sprintf( buf, "%dx%dLvl ", obj->value[2], obj->value[0] );
if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL ){
strcat( buf, " '" );
strcat( buf, skill_table[obj->value[3]].name );
strcat( buf, "' " );
}
fprintf(fp, buf);
break;
case ITEM_DRINK_CON:
sprintf(buf,"%s %s ",
liq_table[obj->value[2]].liq_color,
liq_table[obj->value[2]].liq_name);
fprintf(fp, buf);
break;
case ITEM_CONTAINER:
sprintf(buf,"%d at %d# ",
obj->value[3], obj->value[0]);
fprintf(fp, buf);
if (obj->value[4] != 100){
sprintf(buf," %d%%", obj->value[4]);
fprintf(fp, buf);
}
break;
case ITEM_WEAPON:
buf[0] = 0;
if (IS_WEAPON_STAT(obj, WEAPON_TWO_HANDS) )
strcat(buf, "2h");
switch (obj->value[0]){
case(WEAPON_EXOTIC) : strcat(buf,"Ex"); break;
case(WEAPON_SWORD) : strcat(buf,"Sw"); break;
case(WEAPON_DAGGER) : strcat(buf,"Da"); break;
case(WEAPON_SPEAR) : strcat(buf,"Sp"); break;
case(WEAPON_MACE) : strcat(buf,"Ma"); break;
case(WEAPON_AXE) : strcat(buf,"Ax"); break;
case(WEAPON_FLAIL) : strcat(buf,"Fl"); break;
case(WEAPON_WHIP) : strcat(buf,"Wh"); break;
case(WEAPON_POLEARM): strcat(buf,"Po"); break;
case(WEAPON_STAFF) : strcat(buf,"St"); break;
default : strcat(buf,"??"); break;
}
fprintf(fp, "%s ", buf);
if (obj->new_format){
sprintf(buf,"%dd%d(%d)", obj->value[1],obj->value[2], (1 + obj->value[2]) * obj->value[1] / 2);
}
else{
sprintf( buf, "%d-%d(%d)", obj->value[1], obj->value[2], ( obj->value[1] + obj->value[2] ) / 2 );
}
fprintf(fp, buf );
fprintf(fp, " [%s] ",
(obj->value[3] > 0 && obj->value[3] < MAX_DAMAGE_MESSAGE) ? attack_table[obj->value[3]].noun : "undefined");
if (obj->value[4])
fprintf(fp, "Flags: %s", weapon_bit_name(obj->value[4]));
break;
case ITEM_ARMOR:
sprintf( buf, "AC %d %d %d %d",
obj->value[0], obj->value[1], obj->value[2], obj->value[3] );
break;
case ITEM_THROW:
if (obj->new_format)
sprintf(buf,"%dd%d (%d)",
obj->value[1],obj->value[2], (1 + obj->value[2]) * obj->value[1] / 2);
else
sprintf( buf, "%d-%d (%d)",
obj->value[1], obj->value[2], ( obj->value[1] + obj->value[2] ) / 2 );
fprintf(fp, buf );
break;
case ITEM_RANGED:
if (obj->value[3] == 0)
sprintf(buf, "%s ",
flag_string(projectile_type, obj->value[0]));
else{
OBJ_INDEX_DATA* ammo = get_obj_index( obj->value[3] );
sprintf(buf, "%s ",
ammo == NULL ? "NOT FOUND" : ammo->short_descr);
}
fprintf(fp, buf);
sprintf(buf, "Ammo %d Rate %d ",
obj->value[1], obj->value[2]);
fprintf(fp, buf);
sprintf(buf, "Flags: %s ",flag_string(ranged_type, obj->value[4]));
fprintf(fp, buf);
break;
case ITEM_PROJECTILE:
sprintf(buf, "%s",
flag_string(projectile_type, obj->value[0]));
fprintf(fp, buf);
if (obj->new_format)
sprintf(buf, "%dd%d (%d) ",
obj->value[1],obj->value[2], (1 + obj->value[2]) * obj->value[1] / 2);
else
sprintf( buf, "%d-%d (%d) ",
obj->value[1], obj->value[2], ( obj->value[1] + obj->value[2] ) / 2 );
fprintf(fp, buf);
}
fprintf(fp, "\" " );
fprintf(fp, "\"" );
//now affects
for ( paf = obj->affected; paf != NULL; paf = paf->next ){
if ( paf->location != APPLY_NONE
&& (paf->location < APPLY_O_COND || paf->where == TO_SKILL)
&& paf->modifier != 0 ){
sprintf( buf, "%s by %d.",
(paf->where == TO_SKILL ? skill_table[paf->location].name : affect_loc_name( paf->location )),
paf->modifier );
fprintf( fp, "%-70.70s", buf );
}
if (paf->bitvector){
switch(paf->where){
case TO_AFFECTS: sprintf(buf,"Adds %s affect.", affect_bit_name(paf->bitvector)); break;
case TO_OBJECT: sprintf(buf,"Adds %s object flag.", extra_bit_name(paf->bitvector)); break;
case TO_WEAPON: sprintf(buf,"Adds %s weapon flags.", weapon_bit_name(paf->bitvector)); break;
case TO_IMMUNE: sprintf(buf,"Adds immunity to %s.", imm_bit_name(paf->bitvector)); break;
case TO_RESIST: sprintf(buf,"Adds resistance to %s.", imm_bit_name(paf->bitvector)); break;
case TO_VULN: sprintf(buf,"Adds vulnerability to %s.", imm_bit_name(paf->bitvector)); break;
case TO_SKILL: /* handled above */ break;
default: sprintf(buf,"Unknown bit %d: %d", paf->where,paf->bitvector); break;
}
fprintf( fp, "%-70.70s", buf );
}
}
fprintf(fp, "\"" );
fprintf(fp, "\n" );
}