/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( * * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~* * Tricops and Fireblade | * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Character saving and loading module * ****************************************************************************/ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <string.h> #include <time.h> #include <sys/stat.h> #ifndef WIN32 #include <dirent.h> #endif #include "mud.h" /* * Increment with every major format change. */ #define SAVEVERSION 4 /* * Array to keep track of equipment temporarily. -Thoric */ OBJ_DATA *save_equipment[MAX_WEAR][8]; CHAR_DATA *quitting_char, *loading_char, *saving_char; int file_ver; /* handler.c */ MATERIAL_DATA *material_lookup( int number ); extern NATION_DATA *find_nation( char *name ); /* * Array of containers read for proper re-nesting of objects. */ static OBJ_DATA * rgObjNest [MAX_NEST]; /* * Local functions. */ void fwrite_char args( ( CHAR_DATA *ch, FILE *fp ) ); void fread_char args( ( CHAR_DATA *ch, FILE *fp, bool preload) ); void write_corpses args( ( CHAR_DATA *ch, char *name, OBJ_DATA *objrem ) ); void fwrite_alias args( ( CHAR_DATA *ch, ALIAS_DATA *first_alias, FILE *fp ) ); void fread_alias args( ( CHAR_DATA *ch, FILE *fp ) ); void save_world( CHAR_DATA *ch); int get_obj_room_vnum_recursive(OBJ_DATA *obj); #ifdef WIN32 /* NJG */ UINT timer_code = 0; /* needed to kill the timer */ /* Note: need to include: WINMM.LIB to link to timer functions */ void caught_alarm(); void CALLBACK alarm_handler( UINT IDEvent, /* identifies timer event */ UINT uReserved, /* not used */ DWORD dwUser, /* application-defined instance data */ DWORD dwReserved1, /* not used */ DWORD dwReserved2) /* not used */ { caught_alarm(); } void kill_timer() { if (timer_code) timeKillEvent(timer_code); timer_code = 0; } #endif /* * Un-equip character before saving to ensure proper -Thoric * stats are saved in case of changes to or removal of EQ */ void de_equip_char( CHAR_DATA *ch ) { char buf[MAX_STRING_LENGTH]; OBJ_DATA *obj; int x,y; for ( x = 0; x < MAX_WEAR; x++ ) for ( y = 0; y < MAX_LAYERS; y++ ) save_equipment[x][y] = NULL; for ( obj = ch->first_carrying; obj; obj = obj->next_content ) if ( obj->wear_loc > -1 && obj->wear_loc < MAX_WEAR ) { for ( x = 0; x < MAX_LAYERS; x++ ) if ( !save_equipment[obj->wear_loc][x] ) { save_equipment[obj->wear_loc][x] = obj; break; } if ( x == MAX_LAYERS ) { sprintf( buf, "%s had on more than %d layers of clothing in one location (%d): %s", ch->name, MAX_LAYERS, obj->wear_loc, obj->name ); bug( buf, 0 ); } unequip_char(ch, obj); } } /* * Re-equip character -Thoric */ void re_equip_char( CHAR_DATA *ch ) { int x,y; for ( x = 0; x < MAX_WEAR; x++ ) for ( y = 0; y < MAX_LAYERS; y++ ) if ( save_equipment[x][y] != NULL ) { if ( quitting_char != ch ) equip_char(ch, save_equipment[x][y]); save_equipment[x][y] = NULL; } else break; } /* * Save a character and inventory. * Would be cool to save NPC's too for quest purposes, * some of the infrastructure is provided. */ void save_char_obj( CHAR_DATA *ch ) { char strsave[MAX_INPUT_LENGTH]; char strback[MAX_INPUT_LENGTH]; FILE *fp; if ( !ch ) { bug( "Save_char_obj: null ch!", 0 ); return; } if ( IS_NPC(ch) ) return; saving_char = ch; if ( ch->desc && ch->desc->original ) ch = ch->desc->original; de_equip_char( ch ); ch->save_time = current_time; sprintf( strsave, "%s%c/%s",PLAYER_DIR,tolower(ch->pcdata->filename[0]), capitalize( ch->pcdata->filename ) ); /* * Auto-backup pfile (can cause lag with high disk access situtations). */ /* Backup of each pfile on save as above can cause lag in high disk access situations on big muds like Realms. Quitbackup saves most of that and keeps an adequate backup -- Blodkai, 10/97 */ if ( IS_SET( sysdata.save_flags, SV_BACKUP ) || ( IS_SET( sysdata.save_flags, SV_QUITBACKUP ) && quitting_char == ch )) { sprintf( strback,"%s%c/%s",BACKUP_DIR,tolower(ch->pcdata->filename[0]), capitalize( ch->pcdata->filename ) ); rename( strsave, strback ); } if ( ( fp = fopen( strsave, "w" ) ) == NULL ) { bug( "Save_char_obj: fopen", 0 ); perror( strsave ); } else { fwrite_char( ch, fp ); if ( ch->first_carrying ) fwrite_obj( ch, ch->last_carrying, fp, 0, OS_CARRY ); if ( !IS_NPC( ch ) && ch->pcdata->first_alias ) fwrite_alias( ch, ch->pcdata->first_alias, fp ); if ( sysdata.save_pets && ch->pcdata->pet ) fwrite_mobile( fp, ch->pcdata->pet ); fprintf( fp, "#END\n" ); fclose( fp ); } re_equip_char( ch ); quitting_char = NULL; saving_char = NULL; return; } /* * Write the char. */ void fwrite_char( CHAR_DATA *ch, FILE *fp ) { PART_DATA *part; EXPLORED_AREA *xarea; AFFECT_DATA *paf; int i, sn; sh_int pos; SKILLTYPE *skill = NULL; fprintf( fp, "#PLAYER\n" ); fprintf( fp, "Version %d\n", SAVEVERSION ); fprintf( fp, "Name %s~\n", ch->name ); if ( ch->description ) fprintf( fp, "Description %s~\n", ch->description ); fprintf( fp, "Sex %d\n", ch->sex ); fprintf( fp, "Race %d\n", ch->race ); fprintf( fp, "Permissions %d\n", ch->pcdata->permissions); fprintf( fp, "Points %d\n", ch->pcdata->points ); for (i=0; i < MAX_DEITY; i++) { if (ch->talent[i] > -1) fprintf(fp, "Talent %d %d %d\n", i, ch->talent[i], ch->curr_talent[i]); } fprintf( fp, "Played %d\n", ch->played + (int) (current_time - ch->logon) ); fprintf( fp, "Room %d\n", ( ch->in_room == get_room_index( ROOM_VNUM_LIMBO ) && ch->was_in_room ) ? ch->was_in_room->vnum : ch->in_room->vnum ); fprintf( fp, "Memorized %d %d %d %d %d %d %d %d\n", ch->pcdata->memorize[0], ch->pcdata->memorize[1], ch->pcdata->memorize[2], ch->pcdata->memorize[3], ch->pcdata->memorize[4], ch->pcdata->memorize[5], ch->pcdata->memorize[6], ch->pcdata->memorize[7] ); fprintf( fp, "HpManaMove %d %d %d %d %d %d\n", ch->hit, ch->max_hit, ch->mana, ch->max_mana, ch->move, ch->max_move ); fprintf( fp, "Gold %ld\n", ch->gold ); fprintf( fp, "Bank %ld\n", ch->pcdata->balance); if (xIS_SET(ch->act, PLR_BOUNTY)) fprintf( fp, "Bounty %d\n", ch->pcdata->bounty); fprintf( fp, "Exp %d\n", ch->exp ); fprintf( fp, "Height %d\n", ch->height ); fprintf( fp, "Weight %d\n", ch->weight ); if ( !xIS_EMPTY(ch->act) ) fprintf( fp, "Act %s\n", print_bitvector(&ch->act) ); if ( !xIS_EMPTY(ch->affected_by) ) fprintf( fp, "AffectedBy %s\n", print_bitvector(&ch->affected_by) ); if ( !xIS_EMPTY(ch->no_affected_by) ) fprintf( fp, "NoAffectedBy %s\n", print_bitvector(&ch->no_affected_by) ); if ( !xIS_EMPTY(ch->pcdata->perm_aff) ) fprintf( fp, "PermAffects %s\n",print_bitvector(&ch->pcdata->perm_aff)); /* * Strip off fighting positions & store as * new style (pos>=100 flags new style in character loading) */ pos = ch->position; pos +=100; fprintf( fp, "Position %d\n", pos); fprintf( fp, "SavingThrows %d %d %d %d %d\n", ch->saving_poison_death, ch->saving_wand, ch->saving_para_petri, ch->saving_breath, ch->saving_spell_staff ); fprintf( fp, "Hitroll %d\n", ch->hitroll ); fprintf( fp, "Damroll %d\n", ch->damroll ); fprintf( fp, "Armor %d\n", ch->armor ); if ( ch->wimpy ) fprintf( fp, "Wimpy %d\n", ch->wimpy ); if ( ch->resistant ) fprintf( fp, "Resistant %d\n", ch->resistant ); if ( ch->no_resistant ) fprintf( fp, "NoResistant %d\n", ch->no_resistant ); if ( ch->immune ) fprintf( fp, "Immune %d\n", ch->immune ); if ( ch->no_immune ) fprintf( fp, "NoImmune %d\n", ch->no_immune ); if ( ch->susceptible ) fprintf( fp, "Susceptible %d\n", ch->susceptible ); if ( ch->no_susceptible ) fprintf( fp, "NoSusceptible %d\n",ch->no_susceptible ); if ( ch->mental_state != -10 ) fprintf( fp, "Mentalstate %d\n", ch->mental_state ); fprintf( fp, "Password %s~\n", ch->pcdata->pwd ); if ( ch->pcdata->rank && ch->pcdata->rank[0] != '\0' ) fprintf( fp, "Rank %s~\n", ch->pcdata->rank ); fprintf( fp, "Title %s~\n", ch->pcdata->title ); if ( ch->pcdata->homepage && ch->pcdata->homepage[0] != '\0' ) fprintf( fp, "Homepage %s~\n", ch->pcdata->homepage ); if ( ch->pcdata->bio && ch->pcdata->bio[0] != '\0' ) fprintf( fp, "Bio %s~\n", ch->pcdata->bio ); if ( ch->pcdata && ch->pcdata->restore_time ) fprintf( fp, "Restore_time %ld\n",ch->pcdata->restore_time ); fprintf( fp, "WizInvis %d\n", ch->pcdata->wizinvis ); if ( ch->pcdata->prompt && *ch->pcdata->prompt ) fprintf( fp, "Prompt %s~\n", ch->pcdata->prompt ); if ( ch->pcdata->fprompt && *ch->pcdata->fprompt ) fprintf( fp, "FPrompt %s~\n", ch->pcdata->fprompt ); if ( ch->pcdata->pagerlen != 24 ) fprintf( fp, "Pagerlen %d\n", ch->pcdata->pagerlen ); for ( pos = 0; pos < MAX_ALIAS ; pos++ ) /* alias - shogar */ { if ( !ch->pcdata->alias[pos] || !ch->pcdata->alias_sub[pos] ) break; fprintf( fp, "Alias %s %s~\n", ch->pcdata->alias[pos], ch->pcdata->alias_sub[pos] ); } if (IS_SET(ch->pcdata->permissions, PERMIT_BUILD)) { if ( ch->pcdata->bamfin && ch->pcdata->bamfin[0] != '\0' ) fprintf( fp, "Bamfin %s~\n", ch->pcdata->bamfin ); if ( ch->pcdata->bamfout && ch->pcdata->bamfout[0] != '\0' ) fprintf( fp, "Bamfout %s~\n", ch->pcdata->bamfout ); if ( ch->pcdata->r_range_lo && ch->pcdata->r_range_hi ) fprintf( fp, "RoomRange %d %d\n", ch->pcdata->r_range_lo, ch->pcdata->r_range_hi ); if ( ch->pcdata->o_range_lo && ch->pcdata->o_range_hi ) fprintf( fp, "ObjRange %d %d\n", ch->pcdata->o_range_lo, ch->pcdata->o_range_hi ); if ( ch->pcdata->m_range_lo && ch->pcdata->m_range_hi ) fprintf( fp, "MobRange %d %d\n", ch->pcdata->m_range_lo, ch->pcdata->m_range_hi ); } if ( ch->pcdata->deity_name && ch->pcdata->deity_name[0] != '\0' ) fprintf( fp, "Deity %s~\n", ch->pcdata->deity_name ); fprintf( fp, "Flags %d\n", ch->pcdata->flags ); if ( ch->pcdata->release_date > current_time ) fprintf( fp, "Helled %d %s~\n", (int)ch->pcdata->release_date, ch->pcdata->helled_by ); fprintf( fp, "PKills %d\n", ch->pcdata->pkills ); fprintf( fp, "PDeaths %d\n", ch->pcdata->pdeaths ); fprintf( fp, "RKills %d\n", ch->pcdata->rkills ); fprintf( fp, "RDeaths %d\n", ch->pcdata->rdeaths ); if ( get_timer( ch , TIMER_PKILLED) && ( get_timer( ch , TIMER_PKILLED) > 0 ) ) fprintf( fp, "PTimer %d\n", get_timer(ch, TIMER_PKILLED)); fprintf( fp, "MKills %d\n", ch->pcdata->mkills ); fprintf( fp, "MDeaths %d\n", ch->pcdata->mdeaths ); fprintf( fp, "AttrPerm %d %d %d %d %d %d %d\n", ch->perm_str, ch->perm_int, ch->perm_wis, ch->perm_dex, ch->perm_con, ch->perm_cha, ch->perm_lck ); fprintf( fp, "AttrMod %d %d %d %d %d %d %d\n", ch->mod_str, ch->mod_int, ch->mod_wis, ch->mod_dex, ch->mod_con, ch->mod_cha, ch->mod_lck ); fprintf( fp, "Weapons %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", ch->pcdata->weapon[0], ch->pcdata->weapon[1], ch->pcdata->weapon[2], ch->pcdata->weapon[3], ch->pcdata->weapon[4], ch->pcdata->weapon[5], ch->pcdata->weapon[6], ch->pcdata->weapon[7], ch->pcdata->weapon[8], ch->pcdata->weapon[9], ch->pcdata->weapon[10], ch->pcdata->weapon[11], ch->pcdata->weapon[12], ch->pcdata->weapon[13], ch->pcdata->weapon[14], ch->pcdata->weapon[15], ch->pcdata->weapon[16], ch->pcdata->weapon[17], ch->pcdata->weapon[18], ch->pcdata->weapon[19] ); fprintf( fp, "WeaponExp %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", ch->pcdata->weapon_exp[0], ch->pcdata->weapon_exp[1], ch->pcdata->weapon_exp[2], ch->pcdata->weapon_exp[3], ch->pcdata->weapon_exp[4], ch->pcdata->weapon_exp[5], ch->pcdata->weapon_exp[6], ch->pcdata->weapon_exp[7], ch->pcdata->weapon_exp[8], ch->pcdata->weapon_exp[9], ch->pcdata->weapon_exp[10], ch->pcdata->weapon_exp[11], ch->pcdata->weapon_exp[12], ch->pcdata->weapon_exp[13], ch->pcdata->weapon_exp[14], ch->pcdata->weapon_exp[15], ch->pcdata->weapon_exp[16], ch->pcdata->weapon_exp[17], ch->pcdata->weapon_exp[18], ch->pcdata->weapon_exp[19] ); fprintf( fp, "TalentExp %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", ch->pcdata->talent_exp[0], ch->pcdata->talent_exp[1], ch->pcdata->talent_exp[2], ch->pcdata->talent_exp[3], ch->pcdata->talent_exp[4], ch->pcdata->talent_exp[5], ch->pcdata->talent_exp[6], ch->pcdata->talent_exp[7], ch->pcdata->talent_exp[8], ch->pcdata->talent_exp[9], ch->pcdata->talent_exp[10], ch->pcdata->talent_exp[11], ch->pcdata->talent_exp[12], ch->pcdata->talent_exp[13], ch->pcdata->talent_exp[14], ch->pcdata->talent_exp[15], ch->pcdata->talent_exp[16], ch->pcdata->talent_exp[17], ch->pcdata->talent_exp[18] ); fprintf( fp, "Noncombat %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", ch->pcdata->noncombat[0], ch->pcdata->noncombat[1], ch->pcdata->noncombat[2], ch->pcdata->noncombat[3], ch->pcdata->noncombat[4], ch->pcdata->noncombat[5], ch->pcdata->noncombat[6], ch->pcdata->noncombat[7], ch->pcdata->noncombat[8], ch->pcdata->noncombat[9], ch->pcdata->noncombat[10], ch->pcdata->noncombat[11], ch->pcdata->noncombat[12], ch->pcdata->noncombat[13], ch->pcdata->noncombat[14], ch->pcdata->noncombat[15], ch->pcdata->noncombat[16], ch->pcdata->noncombat[17], ch->pcdata->noncombat[18], ch->pcdata->noncombat[19] ); fprintf( fp, "NoncombatExp %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", ch->pcdata->noncombat_exp[0], ch->pcdata->noncombat_exp[1], ch->pcdata->noncombat_exp[2], ch->pcdata->noncombat_exp[3], ch->pcdata->noncombat_exp[4], ch->pcdata->noncombat_exp[5], ch->pcdata->noncombat_exp[6], ch->pcdata->noncombat_exp[7], ch->pcdata->noncombat_exp[8], ch->pcdata->noncombat_exp[9], ch->pcdata->noncombat_exp[10], ch->pcdata->noncombat_exp[11], ch->pcdata->noncombat_exp[12], ch->pcdata->noncombat_exp[13], ch->pcdata->noncombat_exp[14], ch->pcdata->noncombat_exp[15], ch->pcdata->noncombat_exp[16], ch->pcdata->noncombat_exp[17], ch->pcdata->noncombat_exp[18], ch->pcdata->noncombat_exp[19] ); fprintf( fp, "Condition %d %d %d %d\n", ch->pcdata->condition[0], ch->pcdata->condition[1], ch->pcdata->condition[2], ch->pcdata->condition[3] ); if ( ch->desc && ch->desc->host ) fprintf( fp, "Site %s\n", ch->desc->host ); else fprintf( fp, "Site (Link-Dead)\n" ); xarea = ch->pcdata->first_explored; while (xarea) { fprintf( fp, "Explored %d %s\n", xarea->index, print_bitvector(&xarea->rooms)); xarea = xarea->next; } part = ch->first_part; while (part) { if (part->cond != PART_WELL || part->flags != PART_WELL) fprintf(fp, "Part %d %d %d\n", part->loc, part->cond, part->flags); part = part->next; } for ( sn = 1; sn < top_sn; sn++ ) { if ( skill_table[sn]->name && ch->pcdata->learned[sn] > 0 ) switch( skill_table[sn]->type ) { default: fprintf( fp, "Skill %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name); break; case SKILL_SPELL: fprintf( fp, "Spell %d '%s'\n", ch->pcdata->learned[sn], skill_table[sn]->name); break; } } for ( paf = ch->first_affect; paf; paf = paf->next ) { if ( paf->type >= 0 && (skill=get_skilltype(paf->type)) == NULL ) continue; if ( paf->type >= 0 && paf->type < TYPE_RACIAL ) fprintf( fp, "AffectData '%s' %3d %3d %3d %s\n", skill->name, paf->duration, paf->modifier, paf->location, print_bitvector(&paf->bitvector) ); else fprintf( fp, "Affect %3d %3d %3d %3d %s\n", paf->type, paf->duration, paf->modifier, paf->location, print_bitvector(&paf->bitvector) ); } if (ch->pcdata->first_qbit) { BIT_DATA *bit; for (bit = ch->pcdata->first_qbit; bit; bit = bit->next) fprintf(fp, "Qbit %d %s~\n", bit->number, bit->desc); } if (ch->species) fprintf(fp, "Species %s~\n", ch->species); if (ch->pcdata->type) fprintf(fp, "Type %s~\n", ch->pcdata->type); if (ch->pcdata->parent) fprintf(fp, "Parent %s~\n", ch->pcdata->parent); if (ch->pcdata->family) fprintf(fp, "Family %s~\n", ch->pcdata->family); fprintf(fp, "Generation %d\n", ch->pcdata->gen); fprintf(fp, "Age %d\n", ch->pcdata->age_adjust); fprintf(fp, "Shield %d\n", ch->shield); if (ch->pcdata->spouse) fprintf(fp, "Spouse %s~\n", ch->pcdata->spouse); if (ch->pcdata->maiden_name) fprintf(fp, "Maiden %s~\n", ch->pcdata->maiden_name); if (ch->pcdata->name_disguise) fprintf(fp, "Ndisguise %s~\n", ch->pcdata->name_disguise); if (ch->pcdata->were_race) fprintf(fp, "Wererace %s~\n", ch->pcdata->were_race); if (ch->pcdata->auto_attack) fprintf(fp, "AutoAttack %s~\n", ch->pcdata->auto_attack); fprintf(fp, "Speed %d\n", ch->speed); fprintf(fp, "Inborn %d\n", ch->pcdata->inborn); fprintf(fp, "Channels %s~\n", ch->pcdata->channels); if (ch->pcdata->outputprefix) fprintf(fp, "Outputprefix %s~\n", ch->pcdata->outputprefix); if (ch->pcdata->outputsuffix) fprintf(fp, "Outputsuffix %s~\n", ch->pcdata->outputsuffix); if (ch->pcdata->eyes) fprintf(fp, "Eyes %s~\n", ch->pcdata->eyes); if (ch->pcdata->hair) fprintf(fp, "Hair %s~\n", ch->pcdata->hair); if (ch->pcdata->skin_color) fprintf(fp, "Skin_color %s~\n", ch->pcdata->skin_color); if (ch->pcdata->skin_type) fprintf(fp, "Skin_type %s~\n", ch->pcdata->skin_type); if (ch->pcdata->extra_color) fprintf(fp, "Extra_color %s~\n", ch->pcdata->extra_color); if (ch->pcdata->extra_type) fprintf(fp, "Extra_type %s~\n", ch->pcdata->extra_type); #ifdef I3 i3save_char( ch, fp ); #endif #ifdef IMC imc_savechar( ch, fp ); #endif fprintf( fp, "End\n\n" ); return; } /* * Write an object and its contents. */ void fwrite_obj( CHAR_DATA *ch, OBJ_DATA *obj, FILE *fp, int iNest, sh_int os_type ) { EXTRA_DESCR_DATA *ed; AFFECT_DATA *paf; sh_int wear, wear_loc, x; if ( iNest >= MAX_NEST ) { bug( "fwrite_obj: iNest hit MAX_NEST %d", iNest ); return; } /* * Slick recursion to write lists backwards, * so loading them will load in forwards order. */ if ( obj->prev_content && os_type != OS_GEM ) if (os_type==OS_CARRY) fwrite_obj( ch, obj->prev_content, fp, iNest, OS_CARRY ); /* * Castrate storage characters. * Catch deleted objects -Thoric * Do NOT save prototype items! -Thoric */ if ( obj_extracted(obj) || IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) ) return; /* Gem saving -Keolah */ fprintf( fp, (os_type == OS_GEM ? "#GEM\n" : "#OBJECT\n") ); if ( iNest ) fprintf( fp, "Nest %d\n", iNest ); if ( obj->count > 1 ) fprintf( fp, "Count %d\n", obj->count ); if ( QUICKMATCH( obj->name, obj->pIndexData->name ) == 0 ) fprintf( fp, "Name %s~\n", obj->name ); if ( QUICKMATCH( obj->short_descr, obj->pIndexData->short_descr ) == 0 ) fprintf( fp, "ShortDescr %s~\n", obj->short_descr ); if ( QUICKMATCH( obj->description, obj->pIndexData->description ) == 0 ) fprintf( fp, "Description %s~\n", obj->description ); if (obj->obj_by != NULL) fprintf(fp, "ObjBy %s~\n", obj->obj_by); if ( QUICKMATCH( obj->action_desc, obj->pIndexData->action_desc ) == 0 ) fprintf( fp, "ActionDesc %s~\n", obj->action_desc ); fprintf( fp, "Vnum %d\n", obj->pIndexData->vnum ); if (obj->material != NULL) fprintf( fp, "Material %d\n", obj->material->number ); if (os_type == OS_GROUND && obj->in_room ) fprintf( fp, "Room %d\n", obj->in_room->vnum ); /* else if (((IS_OBJ_STAT(obj, ITEM_ARTIFACT)) || (IS_OBJ_STAT(obj, ITEM_PLRBLD))) && !obj->in_room) fprintf( fp, "Room %d\n", get_obj_room_vnum_recursive(obj)); */ if ( !xSAME_BITS(obj->extra_flags, obj->pIndexData->extra_flags) ) fprintf( fp, "ExtraFlags %s\n", print_bitvector(&obj->extra_flags) ); wear_loc = -1; for ( wear = 0; wear < MAX_WEAR; wear++ ) for ( x = 0; x < MAX_LAYERS; x++ ) if ( obj == save_equipment[wear][x] ) { wear_loc = wear; break; } else if ( !save_equipment[wear][x] ) break; if ( wear_loc != -1 ) fprintf( fp, "WearLoc %d\n", wear_loc ); if ( obj->item_type != obj->pIndexData->item_type ) fprintf( fp, "ItemType %d\n", obj->item_type ); if ( obj->weight != obj->pIndexData->weight ) fprintf( fp, "Weight %d\n", obj->weight ); fprintf( fp, "Condition %d\n", obj->condition ); if (obj->size && !xIS_EMPTY(obj->parts)) fprintf( fp, "Size %d\n", obj->size ); if ( obj->mana ) fprintf( fp, "Mana %d\n", obj->mana); if (obj->raw_mana) fprintf( fp, "RawMana %d\n", obj->raw_mana); if (obj->timer) fprintf( fp, "Timer %d\n", obj->timer ); if ( obj->cost != obj->pIndexData->cost ) fprintf( fp, "Cost %d\n", obj->cost ); if ( obj->value[0] || obj->value[1] || obj->value[2] || obj->value[3] || obj->value[4] || obj->value[5] || obj->value[6] ) fprintf( fp, "Values %d %d %d %d %d %d %d\n", obj->value[0], obj->value[1], obj->value[2], obj->value[3], obj->value[4], obj->value[5], obj->value[6] ); switch ( obj->item_type ) { case ITEM_PILL: /* was down there with staff and wand, wrongly - Scryn */ case ITEM_POTION: case ITEM_SCROLL: if ( IS_VALID_SN(obj->value[1]) ) fprintf( fp, "Spell 1 '%s'\n", skill_table[obj->value[1]]->name ); if ( IS_VALID_SN(obj->value[2]) ) fprintf( fp, "Spell 2 '%s'\n", skill_table[obj->value[2]]->name ); if ( IS_VALID_SN(obj->value[3]) ) fprintf( fp, "Spell 3 '%s'\n", skill_table[obj->value[3]]->name ); break; case ITEM_STAFF: case ITEM_WAND: if ( IS_VALID_SN(obj->value[3]) ) fprintf( fp, "Spell 3 '%s'\n", skill_table[obj->value[3]]->name ); break; case ITEM_SALVE: if ( IS_VALID_SN(obj->value[4]) ) fprintf( fp, "Spell 4 '%s'\n", skill_table[obj->value[4]]->name ); if ( IS_VALID_SN(obj->value[5]) ) fprintf( fp, "Spell 5 '%s'\n", skill_table[obj->value[5]]->name ); break; } for ( paf = obj->first_affect; paf; paf = paf->next ) { /* * Save extra object affects -Thoric */ if ( paf->type < 0 || paf->type >= top_sn ) { fprintf( fp, "Affect %d %d %d %d %s\n", paf->type, paf->duration, ((paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN || paf->location == APPLY_RECURRINGSPELL) && IS_VALID_SN(paf->modifier)) ? skill_table[paf->modifier]->slot : paf->modifier, paf->location, print_bitvector(&paf->bitvector) ); } else fprintf( fp, "AffectData '%s' %d %d %d %s\n", skill_table[paf->type]->name, paf->duration, ((paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN || paf->location == APPLY_RECURRINGSPELL) && IS_VALID_SN(paf->modifier)) ? skill_table[paf->modifier]->slot : paf->modifier, paf->location, print_bitvector(&paf->bitvector) ); } for ( ed = obj->first_extradesc; ed; ed = ed->next ) fprintf( fp, "ExtraDescr %s~ %s~\n", ed->keyword, ed->description ); fprintf( fp, "End\n\n" ); /* If we want multiple gems on an item, * will need to change them to a linked list or * something. One gem is plenty for me though. -keo */ if ( obj->gem && obj->name ) fwrite_obj( ch, obj->gem, fp, iNest+1, OS_GEM ); if ( obj->first_content ) fwrite_obj( ch, obj->last_content, fp, iNest + 1, OS_CARRY ); return; } void fwrite_alias( CHAR_DATA *ch, ALIAS_DATA *first_alias, FILE *fp ) { ALIAS_DATA *alias; for ( alias = first_alias; alias; alias = alias->next ) { fprintf( fp, "#ALIAS\n" ); fprintf( fp, "Name %s~\n", alias->name ); fprintf( fp, "Commands %s~\n", alias->alias ); fprintf( fp, "End\n\n" ); } return; } /* * Load a char and inventory into a new ch structure. */ bool load_char_obj( DESCRIPTOR_DATA *d, char *name, bool preload ) { char strsave[MAX_INPUT_LENGTH]; CHAR_DATA *ch; FILE *fp; bool found; struct stat fst; int i, x; extern FILE *fpArea; extern char strArea[MAX_INPUT_LENGTH]; char buf[MAX_INPUT_LENGTH]; CREATE( ch, CHAR_DATA, 1 ); for ( x = 0; x < MAX_WEAR; x++ ) for ( i = 0; i < MAX_LAYERS; i++ ) save_equipment[x][i] = NULL; clear_char( ch ); loading_char = ch; CREATE( ch->pcdata, PC_DATA, 1 ); d->character = ch; ch->desc = d; ch->pcdata->filename = STRALLOC( name ); ch->name = NULL; ch->act = multimeb(PLR_BLANK, PLR_COMBINE, PLR_PROMPT, -1); ch->perm_str = 100; ch->perm_int = 100; ch->perm_wis = 100; ch->perm_dex = 100; ch->perm_con = 100; ch->perm_cha = 100; ch->perm_lck = 100; ch->base_hit = 0; ch->base_mana = 0; ch->base_move = 0; ch->no_resistant = 0; ch->no_susceptible = 0; ch->no_immune = 0; ch->was_in_room = NULL; xCLEAR_BITS(ch->no_affected_by); xCLEAR_BITS(ch->pcdata->perm_aff); ch->pcdata->condition[COND_THIRST] = 48; ch->pcdata->condition[COND_FULL] = 48; ch->pcdata->wizinvis = 0; ch->pcdata->family = NULL; ch->pcdata->gen = 1; ch->pcdata->auto_attack = NULL; ch->in_obj = NULL; ch->on = NULL; ch->pcdata->spouse = NULL; ch->pcdata->eyes = NULL; ch->pcdata->hair = NULL; ch->pcdata->skin_color = NULL; ch->pcdata->skin_type = NULL; ch->pcdata->extra_color = NULL; ch->pcdata->extra_type = NULL; ch->pcdata->first_mutation = NULL; ch->pcdata->last_mutation = NULL; ch->pcdata->maiden_name = NULL; ch->pcdata->name_disguise = NULL; ch->pcdata->channels = NULL; ch->pcdata->outputprefix = NULL; ch->pcdata->outputsuffix = NULL; ch->pcdata->permissions = 0; ch->pcdata->inborn = -1; ch->pcdata->age_adjust = 0; ch->mental_state = -10; ch->mobinvis = 0; for(i = 0; i < MAX_SKILL; i++) ch->pcdata->learned[i] = 0; ch->pcdata->release_date = 0; ch->pcdata->helled_by = NULL; ch->saving_poison_death = 0; ch->saving_wand = 0; ch->saving_para_petri = 0; ch->saving_breath = 0; ch->saving_spell_staff = 0; ch->pcdata->pagerlen = 24; #ifdef I3 i3init_char( ch ); #endif #ifdef IMC imc_initchar( ch ); #endif found = FALSE; sprintf( strsave, "%s%c/%s", PLAYER_DIR, tolower(name[0]), capitalize( name ) ); if ( stat( strsave, &fst ) != -1 ) { if ( fst.st_size == 0 ) { sprintf( strsave, "%s%c/%s", BACKUP_DIR, tolower(name[0]), capitalize( name ) ); send_to_char( "Restoring your backup player file...", ch ); bug("Restoring backup pfile...", 0); } else { sprintf( buf, "%s player data for: %s (%dK)", preload ? "Preloading" : "Loading", ch->pcdata->filename, (int) fst.st_size/1024 ); log_string_plus( buf, LOG_COMM, 0 ); } } /* else no player file */ if ( ( fp = fopen( strsave, "r" ) ) == NULL ) { return FALSE; } /* if fopen */ else { int iNest; for ( iNest = 0; iNest < MAX_NEST; iNest++ ) rgObjNest[iNest] = NULL; found = TRUE; /* Cheat so that bug will show line #'s -- Altrag */ fpArea = fp; strcpy(strArea, strsave); for ( ; ; ) { char letter; char *word; letter = fread_letter( fp ); if ( letter == '*' ) { fread_to_eol( fp ); continue; } if ( letter != '#' ) { bug( "Load_char_obj: # not found.", 0 ); bug( name, 0 ); return FALSE; } word = fread_word( fp ); if ( !strcmp( word, "PLAYER" ) ) { fread_char ( ch, fp, preload ); if ( preload ) break; } else if ( !strcmp( word, "ALIAS" ) ) /* Aliases */ fread_alias( ch, fp ); else if ( !strcmp( word, "OBJECT" ) ) /* Objects */ fread_obj ( ch, fp, OS_CARRY ); else if ( !strcmp( word, "GEM" ) ) fread_obj (ch, fp, OS_GEM ); else if ( !strcmp( word, "MOBILE") ) { CHAR_DATA *mob; mob = fread_mobile( fp ); if (!mob) bug("Bad pet vnum.", 0); else { ch->pcdata->pet = mob; mob->master = ch; xSET_BIT(mob->affected_by, AFF_CHARM); } } else if ( !strcmp( word, "END" ) ) /* Done */ break; else { bug( "Load_char_obj: bad section.", 0 ); bug( name, 0 ); break; } } fclose( fp ); fpArea = NULL; strcpy(strArea, "$"); } if ( !found ) { ch->name = STRALLOC( name ); ch->short_descr = STRALLOC( "" ); ch->description = STRALLOC( "" ); ch->species = STRALLOC( "human" ); ch->nation = NULL; ch->speed = 100; ch->pcdata->parent = STRALLOC( "" ); ch->encumberance = 0; ch->last_hit = NULL; ch->pcdata->were_race = STRALLOC( "" ); ch->shield = 0; ch->pcdata->consenting = NULL; ch->pcdata->magiclink = NULL; ch->pcdata->mindlink = NULL; ch->editor = NULL; ch->pcdata->deity_name = STRALLOC( "" ); ch->pcdata->deity = NULL; ch->pcdata->pet = NULL; ch->pcdata->pwd = str_dup( "" ); ch->pcdata->bamfin = NULL; ch->pcdata->bamfout = NULL; ch->pcdata->rank = str_dup( "" ); ch->pcdata->title = STRALLOC( "" ); ch->pcdata->homepage = str_dup( "" ); ch->pcdata->bio = STRALLOC( "" ); ch->pcdata->prompt = STRALLOC( "" ); ch->pcdata->fprompt = STRALLOC( "" ); ch->pcdata->r_range_lo = 0; ch->pcdata->r_range_hi = 0; ch->pcdata->m_range_lo = 0; ch->pcdata->m_range_hi = 0; ch->pcdata->o_range_lo = 0; ch->pcdata->o_range_hi = 0; ch->pcdata->rkills = 0; ch->pcdata->rdeaths = 0; ch->pcdata->wizinvis = 0; } else { if ( !ch->name ) ch->name = STRALLOC( name ); if ( !ch->pcdata->deity_name ) { ch->pcdata->deity_name = STRALLOC( "" ); ch->pcdata->deity = NULL; } if ( !ch->pcdata->bio ) ch->pcdata->bio = STRALLOC( "" ); { /* Give 'em a brand new body! -- Scion */ check_bodyparts(ch); } if ( IS_SET(ch->pcdata->permissions, PERMIT_BUILD) ) { assign_area( ch ); } if ( file_ver > 1 ) { for ( i = 0; i < MAX_WEAR; i++ ) { for ( x = 0; x < MAX_LAYERS; x++ ) { if ( save_equipment[i][x] ) { equip_char( ch, save_equipment[i][x]); save_equipment[i][x] = NULL; } else break; } } } } /* Rebuild affected_by and RIS to catch errors - FB */ update_aris(ch); loading_char = NULL; return found; } /* * Read in a char. */ #if defined(KEY) #undef KEY #endif #define KEY( literal, field, value ) \ if ( !strcmp( word, literal ) ) \ { \ field = value; \ fMatch = TRUE; \ break; \ } void fread_char( CHAR_DATA *ch, FILE *fp, bool preload ) { PART_DATA *part; EXPLORED_AREA *xarea; char buf[MAX_STRING_LENGTH]; char *line; char *word; int x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20; sh_int killcnt; bool fMatch; int count=0; file_ver = 0; killcnt = 0; for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER(word[0]) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': KEY( "Act", ch->act, fread_bitvector( fp ) ); KEY( "AffectedBy", ch->affected_by, fread_bitvector( fp ) ); KEY( "AutoAttack", ch->pcdata->auto_attack,fread_string(fp)); KEY( "Age", ch->pcdata->age_adjust, fread_number(fp)); KEY( "Armor", ch->armor, fread_number( fp ) ); /* convert from old system -keo */ if (ch->armor < 0) ch->armor = abs(ch->armor / 10); if ( !strcmp( word, "Affect" ) || !strcmp( word, "AffectData" ) ) { AFFECT_DATA *paf; if ( preload ) { fMatch = TRUE; fread_to_eol( fp ); break; } CREATE( paf, AFFECT_DATA, 1 ); if ( !strcmp( word, "Affect" ) ) { paf->type = fread_number( fp ); } else { int sn; char *sname = fread_word(fp); if ( (sn=skill_lookup(sname)) < 0 ) { if ( (sn=herb_lookup(sname)) < 0 ) bug( "Fread_char: unknown skill.", 0 ); else sn += TYPE_HERB; } paf->type = sn; } paf->duration = fread_number( fp ); paf->modifier = fread_number( fp ); paf->location = fread_number( fp ); if ( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN || paf->location == APPLY_RECURRINGSPELL ) paf->modifier = slot_lookup( paf->modifier ); paf->bitvector = fread_bitvector( fp ); LINK(paf, ch->first_affect, ch->last_affect, next, prev ); fMatch = TRUE; break; } if ( !strcmp( word, "AttrMod" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=13; sscanf( line, "%d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7 ); ch->mod_str = x1; ch->mod_int = x2; ch->mod_wis = x3; ch->mod_dex = x4; ch->mod_con = x5; ch->mod_cha = x6; ch->mod_lck = x7; fMatch = TRUE; break; } if ( !str_cmp( word, "Alias" ) ) { if( count >= MAX_ALIAS ) { fread_to_eol( fp ); fMatch = TRUE; break; } ch->pcdata->alias[count] = str_dup( fread_word( fp ) ); ch->pcdata->alias_sub[count] = fread_string_nohash( fp ); count++; fMatch = TRUE; break; } if ( !strcmp( word, "AttrPerm" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=0; sscanf( line, "%d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7 ); ch->perm_str = x1; ch->perm_int = x2; ch->perm_wis = x3; ch->perm_dex = x4; ch->perm_con = x5; ch->perm_cha = x6; ch->perm_lck = x7; fMatch = TRUE; break; } break; case 'B': KEY( "Bamfin", ch->pcdata->bamfin, fread_string_nohash( fp ) ); KEY( "Bamfout", ch->pcdata->bamfout, fread_string_nohash( fp ) ); KEY( "Bio", ch->pcdata->bio, fread_string( fp ) ); KEY( "Bank", ch->pcdata->balance, fread_number( fp ) ); KEY( "Bounty", ch->pcdata->bounty, fread_number( fp ) ); break; case 'C': KEY( "Channels", ch->pcdata->channels, fread_string(fp)); if ( !strcmp( word, "Condition" ) ) { line = fread_line( fp ); sscanf( line, "%d %d %d %d", &x1, &x2, &x3, &x4 ); ch->pcdata->condition[0] = x1; ch->pcdata->condition[1] = x2; ch->pcdata->condition[2] = x3; ch->pcdata->condition[3] = x4; fMatch = TRUE; break; } break; case 'D': KEY( "Damroll", ch->damroll, fread_number( fp ) ); KEY( "Description", ch->description, fread_string( fp ) ); break; /* 'E' was moved to after 'S' */ case 'F': KEY( "Family", ch->pcdata->family, fread_string(fp)); if ( !strcmp( word, "Filename" ) ) { /* * File Name already set externally. */ fread_to_eol( fp ); fMatch = TRUE; break; } KEY( "Flags", ch->pcdata->flags, fread_number( fp ) ); KEY( "FPrompt", ch->pcdata->fprompt, fread_string( fp ) ); break; case 'G': KEY( "Generation", ch->pcdata->gen, fread_number(fp)); KEY( "Gold", ch->gold, fread_number( fp ) ); break; case 'H': KEY( "Hair", ch->pcdata->hair, fread_string(fp)); KEY( "Height", ch->height, fread_number( fp ) ); if ( !strcmp(word, "Helled") ) { ch->pcdata->release_date = fread_number(fp); ch->pcdata->helled_by = fread_string(fp); if ( ch->pcdata->release_date < current_time ) { STRFREE(ch->pcdata->helled_by); ch->pcdata->helled_by = NULL; ch->pcdata->release_date = 0; } fMatch = TRUE; break; } KEY( "Hitroll", ch->hitroll, fread_number( fp ) ); KEY( "Homepage", ch->pcdata->homepage, fread_string_nohash( fp ) ); if ( !strcmp( word, "HpManaMove" ) ) { ch->hit = fread_number( fp ); ch->max_hit = fread_number( fp ); ch->mana = fread_number( fp ); ch->max_mana = fread_number( fp ); ch->move = fread_number( fp ); ch->max_move = fread_number( fp ); fMatch = TRUE; break; } break; case 'I': KEY ( "Inborn", ch->pcdata->inborn, fread_number( fp ) ); KEY( "Immune", ch->immune, fread_number( fp ) ); #ifdef I3 if( ( fMatch = i3load_char( ch, fp, word ) ) ) break; #endif #ifdef IMC if( ( fMatch = imc_loadchar( ch, fp, word ) ) ) break; #endif break; case 'K': break; case 'L': KEY( "Long", ch->description, fread_string(fp)); break; case 'M': KEY( "Maiden", ch->pcdata->maiden_name, fread_string(fp)); KEY( "MDeaths", ch->pcdata->mdeaths, fread_number( fp ) ); if (!strcmp(word, "Memorized" )) { ch->pcdata->memorize[0] = fread_number( fp ); ch->pcdata->memorize[1] = fread_number( fp ); ch->pcdata->memorize[2] = fread_number( fp ); ch->pcdata->memorize[3] = fread_number( fp ); ch->pcdata->memorize[4] = fread_number( fp ); ch->pcdata->memorize[5] = fread_number( fp ); ch->pcdata->memorize[6] = fread_number( fp ); ch->pcdata->memorize[7] = fread_number( fp ); fMatch = TRUE; } KEY( "Mentalstate", ch->mental_state, fread_number( fp ) ); KEY( "MKills", ch->pcdata->mkills, fread_number( fp ) ); KEY( "Mobinvis", ch->mobinvis, fread_number( fp ) ); if ( !strcmp( word, "MobRange" ) ) { ch->pcdata->m_range_lo = fread_number( fp ); ch->pcdata->m_range_hi = fread_number( fp ); fMatch = TRUE; } break; case 'N': if ( !strcmp( word, "Noncombat" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=x8=x9=x10=x11=x12=x13=x14=x15=x16=x17=x18=x19=x20=1; sscanf( line, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7, &x8, &x9, &x10, &x11, &x12, &x13, &x14, &x15, &x16, &x17, &x18, &x19, &x20 ); ch->pcdata->noncombat[0] = x1; ch->pcdata->noncombat[1] = x2; ch->pcdata->noncombat[2] = x3; ch->pcdata->noncombat[3] = x4; ch->pcdata->noncombat[4] = x5; ch->pcdata->noncombat[5] = x6; ch->pcdata->noncombat[6] = x7; ch->pcdata->noncombat[7] = x8; ch->pcdata->noncombat[8] = x9; ch->pcdata->noncombat[9] = x10; ch->pcdata->noncombat[10] = x11; ch->pcdata->noncombat[11] = x12; ch->pcdata->noncombat[12] = x13; ch->pcdata->noncombat[13] = x14; ch->pcdata->noncombat[14] = x15; ch->pcdata->noncombat[15] = x16; ch->pcdata->noncombat[16] = x17; ch->pcdata->noncombat[17] = x18; ch->pcdata->noncombat[18] = x19; ch->pcdata->noncombat[19] = x20; fMatch = TRUE; break; } if ( !strcmp( word, "NoncombatExp" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=x8=x9=x10=x11=x12=x13=x14=x15=x16=x17=x18=x19=x20=1; sscanf( line, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7, &x8, &x9, &x10, &x11, &x12, &x13, &x14, &x15, &x16, &x17, &x18, &x19, &x20 ); ch->pcdata->noncombat_exp[0] = x1; ch->pcdata->noncombat_exp[1] = x2; ch->pcdata->noncombat_exp[2] = x3; ch->pcdata->noncombat_exp[3] = x4; ch->pcdata->noncombat_exp[4] = x5; ch->pcdata->noncombat_exp[5] = x6; ch->pcdata->noncombat_exp[6] = x7; ch->pcdata->noncombat_exp[7] = x8; ch->pcdata->noncombat_exp[8] = x9; ch->pcdata->noncombat_exp[9] = x10; ch->pcdata->noncombat_exp[10] = x11; ch->pcdata->noncombat_exp[11] = x12; ch->pcdata->noncombat_exp[12] = x13; ch->pcdata->noncombat_exp[13] = x14; ch->pcdata->noncombat_exp[14] = x15; ch->pcdata->noncombat_exp[15] = x16; ch->pcdata->noncombat_exp[16] = x17; ch->pcdata->noncombat_exp[17] = x18; ch->pcdata->noncombat_exp[18] = x19; ch->pcdata->noncombat_exp[19] = x20; fMatch = TRUE; break; } KEY ("Name", ch->name, fread_string( fp ) ); KEY ("Ndisguise", ch->pcdata->name_disguise, fread_string(fp)); KEY ("NoAffectedBy", ch->no_affected_by, fread_bitvector( fp ) ); KEY ("NoImmune", ch->no_immune, fread_number( fp ) ); KEY ("NoResistant", ch->no_resistant, fread_number( fp ) ); KEY ("NoSusceptible", ch->no_susceptible, fread_number( fp ) ); break; case 'O': KEY( "Outputprefix", ch->pcdata->outputprefix, fread_string(fp)); KEY( "Outputsuffix", ch->pcdata->outputsuffix, fread_string(fp)); if ( !strcmp( word, "ObjRange" ) ) { ch->pcdata->o_range_lo = fread_number( fp ); ch->pcdata->o_range_hi = fread_number( fp ); fMatch = TRUE; } break; case 'P': KEY( "Permissions", ch->pcdata->permissions, fread_number(fp)); KEY( "Pagerlen", ch->pcdata->pagerlen, fread_number( fp ) ); KEY( "Parent", ch->pcdata->parent, fread_string( fp ) ); if (!strcmp( word, "Part" )) { if (!ch->first_part) check_bodyparts(ch); if ((part = find_bodypart(ch, fread_number(fp))) != NULL) { part->cond = fread_number(fp); part->flags = fread_number(fp); } fMatch = TRUE; break; } KEY( "Password", ch->pcdata->pwd, fread_string_nohash( fp ) ); KEY( "PDeaths", ch->pcdata->pdeaths, fread_number( fp ) ); KEY( "PKills", ch->pcdata->pkills, fread_number( fp ) ); KEY( "PermAffects", ch->pcdata->perm_aff, fread_bitvector(fp)); KEY( "Played", ch->played, fread_number( fp ) ); KEY( "Points", ch->pcdata->points, fread_number( fp ) ); /* * new positions are stored in the file from 100 up * old positions are from 0 up * if reading an old position, some translation is necessary */ if (!strcmp ( word, "Position" ) ) { ch->position = fread_number( fp ); if(ch->position<100){ switch(ch->position){ default: ; case 0: ; case 1: ; case 2: ; case 3: ; case 4: break; case 5: ch->position=6; break; case 6: ch->position=7; break; case 7: ch->position=9; break; case 8: ch->position=12; break; case 9: ch->position=13; break; case 10: ch->position=14; break; case 11: ch->position=15; break; } fMatch = TRUE; } else { ch->position-=100; fMatch = TRUE; } } KEY( "Prompt", ch->pcdata->prompt, fread_string( fp ) ); if (!strcmp ( word, "PTimer" ) ) { add_timer( ch , TIMER_PKILLED, fread_number(fp), NULL, 0 ); fMatch = TRUE; break; } break; case 'Q': if (!strcmp(word, "Qbit")) { BIT_DATA *bit; BIT_DATA *desc; CREATE(bit, BIT_DATA, 1); bit->number = fread_number(fp); if ((desc = find_qbit(bit->number))==NULL) strcpy(bit->desc, fread_string(fp)); else { strcpy(bit->desc, desc->desc); fread_string(fp); } LINK(bit, ch->pcdata->first_qbit, ch->pcdata->last_qbit, next, prev); fMatch = TRUE; } break; case 'R': KEY( "Race", ch->race, fread_number( fp ) ); KEY( "Rank", ch->pcdata->rank, fread_string_nohash( fp ) ); KEY( "Resistant", ch->resistant, fread_number( fp ) ); KEY( "Restore_time",ch->pcdata->restore_time, fread_number( fp ) ); KEY( "RKills", ch->pcdata->rkills, fread_number( fp ) ); KEY( "RDeaths", ch->pcdata->rdeaths, fread_number( fp )); if ( !strcmp( word, "Room" ) ) { ch->in_room = get_room_index( fread_number( fp ) ); if ( !ch->in_room ) ch->in_room = get_room_index( ROOM_VNUM_LIMBO ); fMatch = TRUE; break; } if ( !strcmp( word, "RoomRange" ) ) { ch->pcdata->r_range_lo = fread_number( fp ); ch->pcdata->r_range_hi = fread_number( fp ); fMatch = TRUE; } break; case 'S': KEY( "Sex", ch->sex, fread_number( fp ) ); KEY( "Shield", ch->shield, fread_number(fp)); KEY( "Speed", ch->speed, fread_number(fp)); KEY( "ShortDescr", ch->short_descr, fread_string( fp ) ); KEY( "Skin_color", ch->pcdata->skin_color, fread_string(fp)); KEY( "Skin_type", ch->pcdata->skin_type, fread_string(fp)); KEY( "Species", ch->species, fread_string( fp ) ); KEY( "Spouse", ch->pcdata->spouse, fread_string(fp)); KEY( "Susceptible", ch->susceptible, fread_number( fp ) ); if (ch->species) { ch->nation=find_nation(ch->species); ch->xflags = ch->nation->parts; } if ( !strcmp( word, "SavingThrow" ) ) { ch->saving_wand = fread_number( fp ); ch->saving_poison_death = ch->saving_wand; ch->saving_para_petri = ch->saving_wand; ch->saving_breath = ch->saving_wand; ch->saving_spell_staff = ch->saving_wand; fMatch = TRUE; break; } if ( !strcmp( word, "SavingThrows" ) ) { ch->saving_poison_death = fread_number( fp ); ch->saving_wand = fread_number( fp ); ch->saving_para_petri = fread_number( fp ); ch->saving_breath = fread_number( fp ); ch->saving_spell_staff = fread_number( fp ); fMatch = TRUE; break; } if ( !strcmp( word, "Site" ) ) { if ( !preload ) { sprintf( buf, "Last connected from: %s\n\r", fread_word( fp ) ); send_to_char( buf, ch ); } else fread_to_eol( fp ); fMatch = TRUE; if ( preload ) word = "End"; else break; } if ( !strcmp( word, "Skill" ) ) { int sn; int value; if ( preload ) word = "End"; else { value = fread_number( fp ); if ( file_ver < 3 ) sn = skill_lookup( fread_word( fp ) ); else sn = bsearch_skill_exact( fread_word( fp ), gsn_first_skill, gsn_top_sn-1 ); if ( sn < 0 ) bug( "Fread_char: unknown skill.", 0 ); else { ch->pcdata->learned[sn] = value; } fMatch = TRUE; break; } } if ( !strcmp( word, "Spell" ) ) { int sn; int value; if ( preload ) word = "End"; else { value = fread_number( fp ); sn = bsearch_skill_exact( fread_word( fp ), gsn_first_spell, gsn_first_skill-1 ); if ( sn < 0 ) bug( "Fread_char: unknown spell.", 0 ); else { ch->pcdata->learned[sn] = value; if ( skill_table[sn]->skill_level[get_best_talent(ch, sn)] >= 1000 ) { ch->pcdata->learned[sn] = 0; } } fMatch = TRUE; break; } } if ( strcmp( word, "End" ) ) break; case 'E': if ( !strcmp( word, "End" ) ) { if (!ch->short_descr) ch->short_descr = STRALLOC( "" ); if (!ch->description) ch->description = STRALLOC( "" ); if (!ch->pcdata->pwd) ch->pcdata->pwd = str_dup( "" ); if (!ch->pcdata->bio) ch->pcdata->bio = STRALLOC( "" ); if (!ch->pcdata->rank) ch->pcdata->rank = str_dup( "" ); if (!ch->pcdata->title) ch->pcdata->title = STRALLOC( "" ); if (!ch->pcdata->homepage) ch->pcdata->homepage = str_dup( "" ); if (!ch->pcdata->prompt ) ch->pcdata->prompt = STRALLOC( "" ); if (!ch->pcdata->fprompt ) ch->pcdata->fprompt = STRALLOC( "" ); ch->editor = NULL; if ( !ch->pcdata->prompt ) ch->pcdata->prompt = STRALLOC(""); return; } KEY( "Exp", ch->exp, fread_number( fp ) ); if (!strcmp( word, "Explored" )) { CREATE(xarea, EXPLORED_AREA, 1); xarea->index = fread_number(fp); xarea->rooms = fread_bitvector(fp); LINK(xarea, ch->pcdata->first_explored, ch->pcdata->last_explored, next, prev); fMatch = TRUE; break; } KEY( "Extra_color", ch->pcdata->extra_color, fread_string(fp)); KEY( "Extra_type", ch->pcdata->extra_type, fread_string(fp)); KEY( "Eyes", ch->pcdata->eyes, fread_string(fp)); break; case 'T': if ( !strcmp( word, "Talent" ) ) { int i; i = fread_number(fp); if (i == -1 || i >= MAX_DEITY) bug("Fread_char: illegal Talent number %d", i); else { ch->talent[i] = fread_number(fp); ch->curr_talent[i] = fread_number(fp); } fMatch = TRUE; break; } if ( !strcmp( word, "TalentExp" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=x8=x9=x10=x11=x12=x13=x14=x15=x16=x17=x18=x19=1; sscanf( line, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7, &x8, &x9, &x10, &x11, &x12, &x13, &x14, &x15, &x16, &x17, &x18, &x19); ch->pcdata->talent_exp[0] = x1; ch->pcdata->talent_exp[1] = x2; ch->pcdata->talent_exp[2] = x3; ch->pcdata->talent_exp[3] = x4; ch->pcdata->talent_exp[4] = x5; ch->pcdata->talent_exp[5] = x6; ch->pcdata->talent_exp[6] = x7; ch->pcdata->talent_exp[7] = x8; ch->pcdata->talent_exp[8] = x9; ch->pcdata->talent_exp[9] = x10; ch->pcdata->talent_exp[10] = x11; ch->pcdata->talent_exp[11] = x12; ch->pcdata->talent_exp[12] = x13; ch->pcdata->talent_exp[13] = x14; ch->pcdata->talent_exp[14] = x15; ch->pcdata->talent_exp[15] = x16; ch->pcdata->talent_exp[16] = x17; ch->pcdata->talent_exp[17] = x18; ch->pcdata->talent_exp[18] = x19; fMatch = TRUE; break; } KEY( "Type", ch->pcdata->type, fread_string(fp)); if ( !strcmp( word, "Title" ) ) { ch->pcdata->title = fread_string( fp ); if ( isalpha(ch->pcdata->title[0]) || isdigit(ch->pcdata->title[0]) ) { sprintf( buf, " %s", ch->pcdata->title ); if ( ch->pcdata->title ) STRFREE( ch->pcdata->title ); ch->pcdata->title = STRALLOC( buf ); } fMatch = TRUE; break; } break; case 'V': if ( !strcmp( word, "Vnum" ) ) { ch->pIndexData = get_mob_index( fread_number( fp ) ); fMatch = TRUE; break; } KEY( "Version", file_ver, fread_number( fp ) ); break; case 'W': if ( !strcmp( word, "Weapons" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=x8=x9=x10=x11=x12=x13=x14=x15=x16=x17=x18=x19=x20=1; sscanf( line, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7, &x8, &x9, &x10, &x11, &x12, &x13, &x14, &x15, &x16, &x17, &x18, &x19, &x20 ); ch->pcdata->weapon[0] = x1; ch->pcdata->weapon[1] = x2; ch->pcdata->weapon[2] = x3; ch->pcdata->weapon[3] = x4; ch->pcdata->weapon[4] = x5; ch->pcdata->weapon[5] = x6; ch->pcdata->weapon[6] = x7; ch->pcdata->weapon[7] = x8; ch->pcdata->weapon[8] = x9; ch->pcdata->weapon[9] = x10; ch->pcdata->weapon[10] = x11; ch->pcdata->weapon[11] = x12; ch->pcdata->weapon[12] = x13; ch->pcdata->weapon[13] = x14; ch->pcdata->weapon[14] = x15; ch->pcdata->weapon[15] = x16; ch->pcdata->weapon[16] = x17; ch->pcdata->weapon[17] = x18; ch->pcdata->weapon[18] = x19; ch->pcdata->weapon[19] = x20; fMatch = TRUE; break; } if ( !strcmp( word, "WeaponExp" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=x8=x9=x10=x11=x12=x13=x14=x15=x16=x17=x18=x19=x20=1; sscanf( line, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7, &x8, &x9, &x10, &x11, &x12, &x13, &x14, &x15, &x16, &x17, &x18, &x19, &x20 ); ch->pcdata->weapon_exp[0] = x1; ch->pcdata->weapon_exp[1] = x2; ch->pcdata->weapon_exp[2] = x3; ch->pcdata->weapon_exp[3] = x4; ch->pcdata->weapon_exp[4] = x5; ch->pcdata->weapon_exp[5] = x6; ch->pcdata->weapon_exp[6] = x7; ch->pcdata->weapon_exp[7] = x8; ch->pcdata->weapon_exp[8] = x9; ch->pcdata->weapon_exp[9] = x10; ch->pcdata->weapon_exp[10] = x11; ch->pcdata->weapon_exp[11] = x12; ch->pcdata->weapon_exp[12] = x13; ch->pcdata->weapon_exp[13] = x14; ch->pcdata->weapon_exp[14] = x15; ch->pcdata->weapon_exp[15] = x16; ch->pcdata->weapon_exp[16] = x17; ch->pcdata->weapon_exp[17] = x18; ch->pcdata->weapon_exp[18] = x19; ch->pcdata->weapon_exp[19] = x20; fMatch = TRUE; break; } KEY( "Weight", ch->weight, fread_number( fp ) ); KEY( "Wererace", ch->pcdata->were_race, fread_string( fp ) ); KEY( "Wimpy", ch->wimpy, fread_number( fp ) ); KEY( "WizInvis", ch->pcdata->wizinvis, fread_number( fp ) ); break; } /* switch */ /* if ( !fMatch ) { sprintf( buf, "Fread_char: no match: %s", word ); bug( buf, 0 ); } */ } /* for (;;) */ if (!ch->speed) ch->speed = 100; } void fread_obj( CHAR_DATA *ch, FILE *fp, sh_int os_type ) { OBJ_DATA *obj; char *word; int iNest; bool fMatch; bool fNest; bool fVnum; ROOM_INDEX_DATA *room = NULL; if ( ch ) room = ch->in_room; CREATE( obj, OBJ_DATA, 1 ); obj->count = 1; obj->wear_loc = -1; obj->weight = 1; obj->condition = 100; obj->size = 0; if ( ch ) obj->size = ch->height; fNest = TRUE; /* Requiring a Nest 0 is a waste */ fVnum = TRUE; iNest = 0; for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER(word[0]) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': KEY( "ActionDesc", obj->action_desc, fread_string( fp ) ); if ( !strcmp( word, "Affect" ) || !strcmp( word, "AffectData" ) ) { AFFECT_DATA *paf; int pafmod; CREATE( paf, AFFECT_DATA, 1 ); if ( !strcmp( word, "Affect" ) ) { paf->type = fread_number( fp ); } else { int sn; sn = skill_lookup( fread_word( fp ) ); if ( sn < 0 ) bug( "Fread_obj: unknown skill.", 0 ); else paf->type = sn; } paf->duration = fread_number( fp ); pafmod = fread_number( fp ); paf->location = fread_number( fp ); paf->bitvector = fread_bitvector( fp ); if ( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_STRIPSN || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_RECURRINGSPELL ) paf->modifier = slot_lookup( pafmod ); else paf->modifier = pafmod; /* convert over old eq -keo */ if (paf->location == APPLY_AC) { if (paf->modifier == -5) { paf->location = APPLY_HITROLL; paf->modifier = 1; } else if (paf->modifier < 0) { paf->modifier = abs(paf->modifier / 10); } else if (paf->modifier == 0) { paf->modifier = 1; } } LINK(paf, obj->first_affect, obj->last_affect, next, prev ); fMatch = TRUE; break; } break; case 'C': KEY( "Cost", obj->cost, fread_number( fp ) ); KEY( "Count", obj->count, fread_number( fp ) ); KEY( "Condition", obj->condition, fread_number(fp) ); break; case 'D': KEY( "Description", obj->description, fread_string( fp ) ); break; case 'E': KEY( "ExtraFlags", obj->extra_flags, fread_bitvector( fp ) ); if ( !strcmp( word, "ExtraDescr" ) ) { EXTRA_DESCR_DATA *ed; CREATE( ed, EXTRA_DESCR_DATA, 1 ); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); LINK(ed, obj->first_extradesc, obj->last_extradesc, next, prev ); fMatch = TRUE; } if ( !strcmp( word, "End" ) ) { if ( !fNest || !fVnum || !obj->pIndexData) { /* if ( obj->name ) sprintf ( buf, "Fread_obj: %s incomplete object.", obj->name ); else sprintf ( buf, "Fread_obj: incomplete object." ); bug( buf, 0 ); */ if ( obj->name ) STRFREE( obj->name ); if ( obj->description ) STRFREE( obj->description ); if ( obj->short_descr ) STRFREE( obj->short_descr ); DISPOSE( obj ); return; } else { sh_int wear_loc = obj->wear_loc; if ( !obj->name ) obj->name = QUICKLINK( obj->pIndexData->name ); if ( !obj->description ) obj->description = QUICKLINK( obj->pIndexData->description ); if ( !obj->short_descr ) obj->short_descr = QUICKLINK( obj->pIndexData->short_descr ); if ( !obj->action_desc ) obj->action_desc = QUICKLINK( obj->pIndexData->action_desc ); LINK(obj, first_object, last_object, next, prev ); obj->pIndexData->count += obj->count; if ( !obj->serial ) { cur_obj_serial = UMAX((cur_obj_serial + 1 ) & (BV30-1), 1); obj->serial = obj->pIndexData->serial = cur_obj_serial; } if ( fNest ) rgObjNest[iNest] = obj; numobjsloaded += obj->count; ++physicalobjects; if ( file_ver > 1 || obj->wear_loc < -1 || obj->wear_loc >= MAX_WEAR ) obj->wear_loc = -1; if (os_type == OS_GROUND && room) { obj_to_room(obj, room); } else if ( iNest == 0 || rgObjNest[iNest] == NULL ) { int slot = -1; bool reslot = FALSE; if ( file_ver > 1 && wear_loc > -1 && wear_loc < MAX_WEAR ) { int x; for ( x = 0; x < MAX_LAYERS; x++ ) if ( !save_equipment[wear_loc][x] ) { save_equipment[wear_loc][x] = obj; slot = x; reslot = TRUE; break; } if ( x == MAX_LAYERS ) bug( "Fread_obj: too many layers %d", wear_loc ); } obj = obj_to_char( obj, ch ); if ( reslot && slot != -1 ) save_equipment[wear_loc][slot] = obj; } else { if ( rgObjNest[iNest-1] ) { separate_obj( rgObjNest[iNest-1] ); if (os_type != OS_GEM) { obj = obj_to_obj( obj, rgObjNest[iNest-1] ); } else { rgObjNest[iNest-1]->gem = obj; obj->in_obj = rgObjNest[iNest-1]; } } else bug( "Fread_obj: nest layer missing %d", iNest-1 ); } if ( fNest ) rgObjNest[iNest] = obj; return; } } break; case 'I': KEY( "ItemType", obj->item_type, fread_number( fp ) ); break; case 'M': KEY("Mana", obj->mana, fread_number(fp)); KEY("Material", obj->material, material_lookup(fread_number(fp))); break; case 'N': KEY( "Name", obj->name, fread_string( fp ) ); if ( !strcmp( word, "Nest" ) ) { iNest = fread_number( fp ); if ( iNest < 0 || iNest >= MAX_NEST ) { bug( "Fread_obj: bad nest %d.", iNest ); iNest = 0; fNest = FALSE; } fMatch = TRUE; } break; case 'O': KEY( "ObjBy", obj->obj_by, fread_string(fp) ); break; case 'P': KEY( "PartFlags", obj->parts, fread_bitvector(fp)); break; case 'R': KEY( "RawMana", obj->raw_mana, fread_number(fp)); KEY( "Room", room, get_room_index(fread_number(fp)) ); break; case 'S': KEY( "ShortDescr", obj->short_descr, fread_string( fp ) ); if ( !strcmp( word, "Spell" ) ) { int iValue; int sn; iValue = fread_number( fp ); sn = skill_lookup( fread_word( fp ) ); if ( iValue < 0 || iValue > 5 ) bug( "Fread_obj: bad iValue %d.", iValue ); else if ( sn < 0 ) bug( "Fread_obj: unknown skill.", 0 ); else obj->value[iValue] = sn; fMatch = TRUE; break; } KEY( "Size", obj->size, fread_number(fp)); break; case 'T': KEY( "Timer", obj->timer, fread_number( fp ) ); break; case 'V': if ( !strcmp( word, "Values" ) ) { int x1,x2,x3,x4,x5,x6,x7; char *ln = fread_line( fp ); x1=x2=x3=x4=x5=x6=0; sscanf( ln, "%d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7 ); /* clean up some garbage */ /* if ( file_ver < 3 ) x5=x6=x7=0; */ obj->value[0] = x1; obj->value[1] = x2; obj->value[2] = x3; obj->value[3] = x4; obj->value[4] = x5; obj->value[5] = x6; obj->value[6] = x7; fMatch = TRUE; break; } if ( !strcmp( word, "Vnum" ) ) { int vnum; vnum = fread_number( fp ); /* bug( "Fread_obj: bad vnum %d.", vnum ); */ if ( ( obj->pIndexData = get_obj_index( vnum ) ) == NULL ) fVnum = FALSE; else { fVnum = TRUE; obj->cost = obj->pIndexData->cost; obj->weight = obj->pIndexData->weight; obj->item_type = obj->pIndexData->item_type; obj->extra_flags = obj->pIndexData->extra_flags; obj->parts = obj->pIndexData->parts; } fMatch = TRUE; break; } break; case 'W': KEY( "WearLoc", obj->wear_loc, fread_number( fp ) ); KEY( "Weight", obj->weight, fread_number( fp ) ); break; } if ( !fMatch ) { EXTRA_DESCR_DATA *ed; AFFECT_DATA *paf; bug( "Fread_obj: no match.", 0 ); bug( word, 0 ); fread_to_eol( fp ); if ( obj->name ) STRFREE( obj->name ); if ( obj->description ) STRFREE( obj->description ); if ( obj->short_descr ) STRFREE( obj->short_descr ); while ( (ed=obj->first_extradesc) != NULL ) { STRFREE( ed->keyword ); STRFREE( ed->description ); UNLINK( ed, obj->first_extradesc, obj->last_extradesc, next, prev ); DISPOSE( ed ); } while ( (paf=obj->first_affect) != NULL ) { UNLINK( paf, obj->first_affect, obj->last_affect, next, prev ); DISPOSE( paf ); } DISPOSE( obj ); return; } } } void fread_alias( CHAR_DATA *ch, FILE *fp ) { ALIAS_DATA *alias; char *word; bool fMatch; CREATE( alias, ALIAS_DATA, 1 ); for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER(word[0]) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': KEY( "Commands", alias->alias, fread_string( fp ) ); break; case 'E': if ( !strcmp( word, "End" ) ) { if ( !alias->name || !alias->alias ) { bug( "fread_alias: %s%s%s", alias->name ? "" : "NULL alias->name", ( !alias->name && !alias->alias ) ? " and " : "NULL alias->alias" ); DISPOSE( alias ); return; } else { /* bug( "Debug: fread_alias: %s %s", alias->name, alias->alias ); */ LINK( alias, ch->pcdata->first_alias, ch->pcdata->last_alias, next, prev ); return; } } break; case 'N': KEY( "Name", alias->name, fread_string( fp ) ); break; } if ( !fMatch ) { bug( "Fread_obj: no match." ); bug( word ); fread_to_eol( fp ); DISPOSE( alias ); return; } } } void set_alarm( long seconds ) { #ifdef WIN32 kill_timer (); /* kill old timer */ timer_code = timeSetEvent(seconds * 1000L, 1000, alarm_handler, 0, TIME_PERIODIC); #else alarm( seconds ); #endif } /* * Based on last time modified, show when a player was last on -Thoric */ void do_last( CHAR_DATA *ch, char *argument ) { char buf [MAX_STRING_LENGTH]; char arg [MAX_INPUT_LENGTH]; char name[MAX_INPUT_LENGTH]; struct stat fst; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "Usage: last <playername>\n\r", ch ); return; } strcpy( name, capitalize(arg) ); sprintf( buf, "%s%c/%s", PLAYER_DIR, tolower(arg[0]), name ); if ( stat( buf, &fst ) != -1 ) sprintf( buf, "%s was last on: %s\r", name, ctime( &fst.st_mtime ) ); else sprintf( buf, "%s was not found.\n\r", name ); send_to_char( buf, ch ); } /* * Added support for removeing so we could take out the write_corpses * so we could take it out of the save_char_obj function. --Shaddai */ void write_corpses( CHAR_DATA *ch, char *name, OBJ_DATA *objrem ) { FILE *fp = NULL; /* Name and ch support so that we dont have to have a char to save their corpses.. (ie: decayed corpses while offline) */ if ( ch && IS_NPC(ch) ) { bug( "Write_corpses: writing NPC corpse.", 0 ); return; } if ( ch ) name = ch->name; /* Go by vnum, less chance of screwups. -- Altrag */ /* for ( corpse = first_object; corpse; corpse = corpse->next ) if ( corpse->pIndexData->vnum == OBJ_VNUM_CORPSE_PC && corpse->in_room != NULL && !str_cmp(corpse->short_descr+14, name) && objrem != corpse ) { if ( !fp ) { char buf[127]; sprintf(buf, "%s%s", CORPSE_DIR, capitalize(name)); if ( !(fp = fopen(buf, "w")) ) { bug( "Write_corpses: Cannot open file.", 0 ); perror(buf); return; } } } */ if ( fp ) { fprintf(fp, "#END\n\n"); fclose(fp); } else { char buf[127]; sprintf(buf, "%s%s", CORPSE_DIR, capitalize(name)); remove(buf); } return; } void load_corpses( void ) { } /* * This will write one mobile structure pointed to be fp --Shaddai */ void fwrite_mobile( FILE *fp, CHAR_DATA *mob ) { if ( !IS_NPC( mob ) || !fp ) return; fprintf( fp, "#MOBILE\n" ); fprintf( fp, "Vnum %d\n", mob->pIndexData->vnum ); if ( mob->in_room ) { if (xIS_SET(mob->act, ACT_SENTINEL)) { /* Sentinel mobs get stamped with a "home room" when they are created by create_mobile(), so we need to save them in their home room regardless of where they are right now, so they will go to their home room when they enter the game from a reboot or copyover -- Scion */ fprintf( fp, "Room %d\n", mob->home_room ); } else { fprintf( fp, "Room %d\n", ( mob->in_room == get_room_index( ROOM_VNUM_LIMBO ) && mob->was_in_room ) ? mob->was_in_room->vnum : mob->in_room->vnum ); } } if ( QUICKMATCH( mob->name, mob->pIndexData->player_name) == 0 ) fprintf( fp, "Name %s~\n", mob->name ); if ( QUICKMATCH( mob->short_descr, mob->pIndexData->short_descr) == 0 ) fprintf( fp, "Short %s~\n", mob->short_descr ); if ( QUICKMATCH( mob->description, mob->pIndexData->description) == 0 ) fprintf( fp, "Description %s~\n", mob->description ); fprintf( fp, "Gold %ld\n", mob->gold ); fprintf( fp, "Flags %s\n", print_bitvector(&mob->act) ); /* This is needed for generic mobs */ fprintf( fp, "AttrPerm %d %d %d %d %d %d %d\n", mob->perm_str, mob->perm_int, mob->perm_wis, mob->perm_dex, mob->perm_con, mob->perm_cha, mob->perm_lck ); fprintf(fp, "Part %d\n", mob->xflags); if ( mob->first_carrying ) fwrite_obj( mob, mob->last_carrying, fp, 0, OS_CARRY ); fprintf( fp, "EndMobile\n\n" ); return; } /* * This will read one mobile structure pointer to by fp --Shaddai */ CHAR_DATA * fread_mobile( FILE *fp ) { CHAR_DATA *mob = NULL; char *word; bool fMatch; int inroom = 0; char *line; ROOM_INDEX_DATA *pRoomIndex = NULL; int x1, x2, x3, x4, x5, x6, x7; word = feof( fp ) ? "EndMobile" : fread_word( fp ); if ( !strcmp(word, "Vnum") ) { int vnum; vnum = fread_number( fp ); mob = create_mobile( get_mob_index(vnum) ); if ( !mob ) { for ( ; ; ) { word = feof( fp ) ? "EndMobile" : fread_word( fp ); /* So we don't get so many bug messages when something messes up * --Shaddai */ if ( !strcmp( word, "EndMobile" ) ) break; } bug("Fread_mobile: No index data for vnum %d", vnum ); return NULL; } } else { for ( ; ; ) { word = feof( fp ) ? "EndMobile" : fread_word( fp ); /* So we don't get so many bug messages when something messes up * --Shaddai */ if ( !strcmp( word, "EndMobile" ) ) break; } extract_char(mob, TRUE); bug("Fread_mobile: Vnum not found", 0 ); return NULL; } for ( ; ;) { word = feof( fp ) ? "EndMobile" : fread_word( fp ); fMatch = FALSE; switch ( UPPER(word[0]) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case '#': if ( !strcmp( word, "#OBJECT" ) ) fread_obj ( mob, fp, OS_CARRY ); else if ( !str_cmp(word, "#GEM" ) ) fread_obj ( mob, fp, OS_GEM ); case 'A': if ( !strcmp( word, "AttrPerm" ) ) { line = fread_line( fp ); x1=x2=x3=x4=x5=x6=x7=0; sscanf( line, "%d %d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6, &x7 ); mob->perm_str = x1; mob->perm_int = x2; mob->perm_wis = x3; mob->perm_dex = x4; mob->perm_con = x5; mob->perm_cha = x6; mob->perm_lck = x7; fMatch = TRUE; break; } break; case 'D': KEY( "Description", mob->description, fread_string(fp)); break; case 'E': if ( !strcmp( word, "EndMobile" ) ) { if ( inroom == 0 ) inroom = ROOM_VNUM_NEXUS; pRoomIndex = get_room_index( inroom ); if ( !pRoomIndex ) pRoomIndex = get_room_index( ROOM_VNUM_NEXUS ); char_to_room(mob, pRoomIndex); return mob; } if (!strcmp( word, "End" ) ) /* End of object, need to ignore this. sometimes they creep in there somehow -- Scion */ fMatch=TRUE; /* Trick the system into thinking it matched something */ break; case 'F': KEY( "Flags", mob->act, fread_bitvector(fp)); break; case 'G': KEY( "Gold", mob->gold, fread_number(fp)); break; case 'N': KEY( "Name", mob->name, fread_string( fp ) ); break; case 'P': KEY( "Position", mob->position, fread_number( fp ) ); KEY( "Part", mob->xflags, fread_number( fp ) ); break; case 'R': KEY( "Room", inroom, fread_number(fp)); break; case 'S': KEY( "Short", mob->short_descr, fread_string(fp)); break; } if ( !fMatch && strcmp(word, "End")) { bug ( "Fread_mobile: no match.", 0 ); bug ( word, 0 ); } } return NULL; } /* * This will write in the saved mobile for a char --Shaddai */ void write_char_mobile( CHAR_DATA *ch , char *argument ) { FILE *fp; CHAR_DATA *mob; char buf[MAX_STRING_LENGTH]; if ( IS_NPC( ch ) || !ch->pcdata->pet ) return; fclose( fpReserve ); if ( (fp = fopen( argument, "w")) == NULL ) { sprintf(buf, "Write_char_mobile: couldn't open %s for writing!\n\r", argument ); bug(buf, 0 ); fpReserve = fopen( NULL_FILE, "r" ); return; } mob = ch->pcdata->pet; xSET_BIT( mob->affected_by, AFF_CHARM ); fwrite_mobile( fp, mob ); fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); return; } /* * This will read in the saved mobile for a char --Shaddai */ void read_char_mobile( char *argument ) { FILE *fp; CHAR_DATA *mob; char buf[MAX_STRING_LENGTH]; fclose( fpReserve ); if ( (fp = fopen( argument, "r")) == NULL ) { sprintf(buf, "Read_char_mobile: couldn't open %s for reading!\n\r", argument ); bug(buf, 0 ); fpReserve = fopen( NULL_FILE, "r" ); return; } mob = fread_mobile( fp ); fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); return; } /* Return the vnum the obj is in, regardless of being carried or inside containers. -- Scion */ int get_obj_room_vnum_recursive(OBJ_DATA *obj) { if (!obj) return ROOM_VNUM_LIMBO; if (obj->in_obj) { return get_obj_room_vnum_recursive(obj->in_obj); } else if (obj->carried_by) { if (obj->carried_by->in_room) { return obj->carried_by->in_room->vnum; } else { bug("get_obj_room_vnum_recursive: Char \"%s\" not in room?!",obj->carried_by->name); return ROOM_VNUM_LIMBO; } } else if (obj->in_room) { return obj->in_room->vnum; } else { bug ("get_obj_room_vnum_recursive: obj isn't carried, inside containers, or inside a room!",0); bug ("putting in limbo...",0); obj_to_room(obj, get_room_index(ROOM_VNUM_LIMBO)); return ROOM_VNUM_LIMBO; } } /* * Save the world's objects and mobs in their current positions -- Scion */ void save_world( CHAR_DATA *ch) { FILE *mobfp; FILE *objfp; int mobfile=0; int objfile=0; char filename[256]; CHAR_DATA *rch; OBJ_DATA *obj; sprintf( filename, "%s%s", SYSTEM_DIR, MOB_FILE); if ( ( mobfp = fopen( filename, "w" ) ) == NULL ) { bug( "save_world: fopen mob file", 0 ); perror( filename ); } else mobfile++; sprintf( filename, "%s%s", SYSTEM_DIR, OBJ_FILE); if ( ( objfp = fopen( filename, "w" ) ) == NULL ) { bug("save_world: fopen obj file", 0 ); perror( filename ); } else objfile++; if (objfile) { for ( obj = first_object; obj; obj = obj->next ) { /* Objects that are in inventories get written in fwrite_mob, or to a player's pfile */ if (IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) || (!obj->in_room) /* Don't keep objs that aren't in rooms */ || (obj->carried_by) /* Carried objs save on the char that's carrying them */ || (obj->in_obj) /* Don't keep objs in other objs.. they save when their container saves */ || IS_SET(obj->in_room->room_flags, ROOM_DONATION)) continue; fwrite_obj(NULL, obj, objfp, 0, OS_GROUND); } fprintf(objfp, "#END"); fclose(objfp); } if (mobfile) { for (rch = first_char; rch; rch = rch->next ) { if (!IS_NPC(rch) || rch==supermob || xIS_SET(rch->act, ACT_PROTOTYPE) || xIS_SET(rch->act, ACT_PET)) continue; else fwrite_mobile(mobfp, rch); } fprintf(mobfp, "#END"); fclose(mobfp); } } void load_world(CHAR_DATA *ch) { FILE *mobfp; FILE *objfp; char filename[256]; char *word; int done = 0; int mobfile = 0; int objfile = 0; sprintf( filename, "%s%s", SYSTEM_DIR, MOB_FILE); if ( ( mobfp = fopen( filename, "r" ) ) == NULL ) { bug( "load_world: fopen mob file", 0 ); perror( filename ); return; } else mobfile++; sprintf( filename, "%s%s", SYSTEM_DIR, OBJ_FILE); if ( ( objfp = fopen( filename, "r" ) ) == NULL ) { bug( "load_world: fopen obj file", 0 ); perror( filename ); return; } else objfile++; if (mobfile) { while(done==0) { if (feof(mobfp)) done++; else { word = fread_word(mobfp); if (str_cmp(word, "#END")) fread_mobile( mobfp ); else done++; } } fclose(mobfp); } done = 0; if (objfile) { while (done==0) { if (feof(objfp)) done++; else { word = fread_word(objfp); if (str_cmp(word, "#END")) fread_obj(NULL, objfp, OS_GROUND); else done++; } } fclose(objfp); } }