#include <ctype.h> #include <stdio.h> #include <string.h> #include "mud.h" /* * Increment with every major format change. */ #define SAVEVERSION 3 /* * Array to keep track of equipment temporarily. -Thoric */ OBJ_DATA *save_equipment[MAX_WEAR][8]; CHAR_DATA *quitting_char = NULL, *loading_char = NULL, *saving_char = NULL; int file_ver = 0; extern FILE *fpArea; extern char strArea[MAX_INPUT_LENGTH]; /* * Array of containers read for proper re-nesting of objects. */ static OBJ_DATA *rgObjNest[MAX_NEST]; /* * Local functions. */ void fwrite_char( const CHAR_DATA * ch, FILE * fp ); void fread_char( CHAR_DATA * ch, FILE * fp, bool preload ); void write_corpses( const CHAR_DATA * ch, const char *name ); static void fread_corpse( const char *name ); extern int falling; void save_home( const CHAR_DATA * ch ) { if( ch->plr_home ) { FILE *fp = NULL; char filename[256]; sprintf( filename, "%s%c/%s.home", PLAYER_DIR, tolower( ( int ) ch->name[0] ), capitalize( ch->name ) ); if( ( fp = fopen( filename, "w" ) ) == NULL ) { } else { OBJ_DATA *contents = ch->plr_home->last_content; if( contents ) fwrite_obj( ch, contents, fp, 0, OS_CARRY ); fprintf( fp, "#END\n" ); fclose( fp ); } } } void load_home( CHAR_DATA * ch ) { char filename[256]; FILE *fph = 0; ROOM_INDEX_DATA *storeroom = ch->plr_home; sprintf( filename, "%s%c/%s.home", PLAYER_DIR, tolower( ( int ) ch->name[0] ), capitalize( ch->name ) ); if( ( fph = fopen( filename, "r" ) ) ) { int iNest = 0; OBJ_DATA *tobj = 0; OBJ_DATA *tobj_next = 0; rset_supermob( storeroom ); for( iNest = 0; iNest < MAX_NEST; ++iNest ) { rgObjNest[iNest] = NULL; } for( ;; ) { char letter = fread_letter( fph ); const char *word = NULL; if( letter == '*' ) { fread_to_eol( fph ); continue; } if( letter != '#' ) { bug( "Load_plr_home: # not found." ); bug( ch->name ); break; } word = fread_word( fph ); if( !str_cmp( word, "OBJECT" ) ) { fread_obj( supermob, fph, OS_CARRY ); } else if( !str_cmp( word, "END" ) ) { break; } else { bug( "Load_plr_home: bad section." ); bug( ch->name ); break; } } fclose( fph ); for( tobj = supermob->first_carrying; tobj; tobj = tobj_next ) { tobj_next = tobj->next_content; obj_from_char( tobj ); obj_to_room( tobj, storeroom ); } release_supermob(); } } /* * 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 = NULL; int x = 0, y = 0; 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], x ); 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 ) || NOT_AUTHED( ch ) ) return; saving_char = ch; /* save pc's clan's data while we're at it to keep the data in sync */ if( !IS_NPC( ch ) && ch->pcdata->clan ) save_clan( ch->pcdata->clan ); 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( ( int ) ch->name[0] ), capitalize( ch->name ) ); /* * Auto-backup pfile (can cause lag with high disk access situtations */ if( IS_SET( sysdata.save_flags, SV_BACKUP ) ) { sprintf( strback, "%s%c/%s", BACKUP_DIR, tolower( ( int ) ch->name[0] ), capitalize( ch->name ) ); 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 ); fprintf( fp, "#END\n" ); fclose( fp ); } re_equip_char( ch ); write_corpses( ch, NULL ); quitting_char = NULL; saving_char = NULL; return; } void save_clone( 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 ) || NOT_AUTHED( ch ) ) return; if( ch->desc && ch->desc->original ) ch = ch->desc->original; de_equip_char( ch ); ch->save_time = current_time; sprintf( strsave, "%s%c/%s.clone", PLAYER_DIR, tolower( ( int ) ch->name[0] ), capitalize( ch->name ) ); /* * Auto-backup pfile (can cause lag with high disk access situtations */ if( IS_SET( sysdata.save_flags, SV_BACKUP ) ) { sprintf( strback, "%s%c/%s", BACKUP_DIR, tolower( ( int ) ch->name[0] ), capitalize( ch->name ) ); rename( strsave, strback ); } if( ( fp = fopen( strsave, "w" ) ) == NULL ) { bug( "Save_char_obj: fopen", 0 ); perror( strsave ); } else { fwrite_char( ch, fp ); fprintf( fp, "#END\n" ); fclose( fp ); } re_equip_char( ch ); write_corpses( ch, NULL ); quitting_char = NULL; saving_char = NULL; return; } /* * Write the char. */ void fwrite_char( const CHAR_DATA * ch, FILE * fp ) { AFFECT_DATA *paf = NULL; int sn = 0, track = 0; SKILLTYPE *skill = NULL; fprintf( fp, "#%s\n", IS_NPC( ch ) ? "MOB" : "PLAYER" ); fprintf( fp, "Version %d\n", SAVEVERSION ); fprintf( fp, "Name %s~\n", ch->name ); if( ch->short_descr && ch->short_descr[0] != '\0' ) fprintf( fp, "ShortDescr %s~\n", ch->short_descr ); if( ch->long_descr && ch->long_descr[0] != '\0' ) fprintf( fp, "LongDescr %s~\n", ch->long_descr ); if( ch->description && ch->description[0] != '\0' ) fprintf( fp, "Description %s~\n", ch->description ); fprintf( fp, "Sex %d\n", ch->sex ); fprintf( fp, "Toplevel %d\n", ch->top_level ); if( ch->trust ) fprintf( fp, "Trust %d\n", ch->trust ); fprintf( fp, "Played %d\n", ch->played + ( int ) ( current_time - ch->logon ) ); fprintf( fp, "Room %ld\n", ( ch->in_room == get_room_index( ROOM_VNUM_LIMBO ) && ch->was_in_room ) ? ch->was_in_room->vnum : ch->in_room->vnum ); if( ch->plr_home != NULL ) fprintf( fp, "PlrHome %ld\n", ch->plr_home->vnum ); fprintf( fp, "HpManaMove %d %d 0 0 %d %d\n", ch->hit, ch->max_hit, ch->move, ch->max_move ); fprintf( fp, "Force %d %d %d %d\n", ch->perm_frc, ch->mod_frc, ch->mana, ch->max_mana ); fprintf( fp, "Gold %d\n", ch->gold ); fprintf( fp, "Bank %ld\n", ch->pcdata->bank ); if( ch->act ) fprintf( fp, "Act %d\n", ch->act ); if( ch->affected_by ) fprintf( fp, "AffectedBy %d\n", ch->affected_by ); fprintf( fp, "Position %d\n", ch->position == POS_FIGHTING ? (short)POS_STANDING : ch->position ); 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, "Alignment %d\n", ch->alignment ); 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->deaf ) fprintf( fp, "Deaf %d\n", ch->deaf ); if( ch->resistant ) fprintf( fp, "Resistant %d\n", ch->resistant ); if( ch->immune ) fprintf( fp, "Immune %d\n", ch->immune ); if( ch->susceptible ) fprintf( fp, "Susceptible %d\n", ch->susceptible ); if( ch->pcdata && ch->pcdata->outcast_time ) fprintf( fp, "Outcast_time %ld\n", (long) ch->pcdata->outcast_time ); if( ch->pcdata && ch->pcdata->restore_time ) fprintf( fp, "Restore_time %ld\n", (long) ch->pcdata->restore_time ); if( ch->mental_state != -10 ) fprintf( fp, "Mentalstate %d\n", ch->mental_state ); if( IS_NPC( ch ) ) { fprintf( fp, "Vnum %ld\n", ch->pIndexData->vnum ); fprintf( fp, "Mobinvis %d\n", ch->mobinvis ); } else { fprintf( fp, "Password %s~\n", ch->pcdata->pwd ); fprintf( fp, "Lastplayed %d\n", ( int ) current_time ); if( ch->pcdata->bamfin && ch->pcdata->bamfin[0] != '\0' ) fprintf( fp, "Bamfin %s~\n", ch->pcdata->bamfin ); if( ch->pcdata->email && ch->pcdata->email[0] != '\0' ) fprintf( fp, "Email %s~\n", ch->pcdata->email ); if( ch->pcdata->bamfout && ch->pcdata->bamfout[0] != '\0' ) fprintf( fp, "Bamfout %s~\n", ch->pcdata->bamfout ); if( ch->pcdata->rank && ch->pcdata->rank[0] != '\0' ) fprintf( fp, "Rank %s~\n", ch->pcdata->rank ); if( ch->pcdata->bestowments && ch->pcdata->bestowments[0] != '\0' ) fprintf( fp, "Bestowments %s~\n", ch->pcdata->bestowments ); 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->authed_by && ch->pcdata->authed_by[0] != '\0' ) fprintf( fp, "AuthedBy %s~\n", ch->pcdata->authed_by ); if( ch->pcdata->min_snoop ) fprintf( fp, "Minsnoop %d\n", ch->pcdata->min_snoop ); if( ch->pcdata->prompt && *ch->pcdata->prompt ) fprintf( fp, "Prompt %s~\n", ch->pcdata->prompt ); if( ch->pcdata->pagerlen != 24 ) fprintf( fp, "Pagerlen %d\n", ch->pcdata->pagerlen ); if( IS_IMMORTAL( ch ) || ch->pcdata->area ) { fprintf( fp, "WizInvis %d\n", ch->pcdata->wizinvis ); } if( ch->pcdata->clan ) { fprintf( fp, "Clan %s~\n", ch->pcdata->clan->name ); if( ch->pcdata->clan_permissions[0] != '\0' ) fprintf( fp, "ClanPerms %s~\n", ch->pcdata->clan_permissions ); } 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 ); if( ch->pcdata->pkills ) fprintf( fp, "PKills %d\n", ch->pcdata->pkills ); if( ch->pcdata->pdeaths ) fprintf( fp, "PDeaths %d\n", ch->pcdata->pdeaths ); if( get_timer( ch, TIMER_PKILLED ) && ( get_timer( ch, TIMER_PKILLED ) > 0 ) ) fprintf( fp, "PTimer %d\n", get_timer( ch, TIMER_PKILLED ) ); 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, "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" ); for( sn = 1; sn < top_sn; sn++ ) { if( skill_table[sn]->name && character_skill_level( ch, sn ) > 0 ) switch ( skill_table[sn]->type ) { default: fprintf( fp, "Skill %d '%s'\n", character_skill_level( ch, sn ), skill_table[sn]->name ); break; case SKILL_SPELL: fprintf( fp, "Spell %d '%s'\n", character_skill_level( ch, sn ), skill_table[sn]->name ); break; case SKILL_WEAPON: fprintf( fp, "Weapon %d '%s'\n", character_skill_level( ch, 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_PERSONAL ) fprintf( fp, "AffectData '%s' %3d %3d %3d %10d\n", skill->name, paf->duration, paf->modifier, paf->location, paf->bitvector ); else fprintf( fp, "Affect %3d %3d %3d %3d %10d\n", paf->type, paf->duration, paf->modifier, paf->location, paf->bitvector ); } track = MAX_KILLTRACK; for( sn = 0; sn < track; sn++ ) { if( ch->pcdata->killed[sn].vnum == 0 ) break; fprintf( fp, "Killed %ld %d\n", ch->pcdata->killed[sn].vnum, ch->pcdata->killed[sn].count ); } #ifdef SWR2_USE_IMC imc_savechar( ch, fp ); #endif fprintf( fp, "End\n\n" ); return; } /* * Write an object and its contents. */ void fwrite_obj( const CHAR_DATA * ch, const OBJ_DATA * obj, FILE * fp, int iNest, short os_type ) { EXTRA_DESCR_DATA *ed = NULL; AFFECT_DATA *paf = NULL; short wear = 0, wear_loc = 0, x = 0; 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_CORPSE ) fwrite_obj( ch, obj->prev_content, fp, iNest, OS_CARRY ); /* * Catch deleted objects -Thoric */ if( obj_extracted( obj ) ) return; /* * Do NOT save prototype items! -Thoric */ if( IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) ) return; /* Corpse saving. -- Altrag */ fprintf( fp, ( os_type == OS_CORPSE ? "#CORPSE\n" : "#OBJECT\n" ) ); if( iNest ) fprintf( fp, "Nest %d\n", iNest ); if( obj->count > 1 ) fprintf( fp, "Count %d\n", obj->count ); if( obj->name && ( !obj->pIndexData->name || str_cmp( obj->name, obj->pIndexData->name ) ) ) fprintf( fp, "Name %s~\n", obj->name ); if( obj->short_descr && ( !obj->pIndexData->short_descr || str_cmp( obj->short_descr, obj->pIndexData->short_descr ) ) ) fprintf( fp, "ShortDescr %s~\n", obj->short_descr ); if( obj->description && ( !obj->pIndexData->description || str_cmp( obj->description, obj->pIndexData->description ) ) ) fprintf( fp, "Description %s~\n", obj->description ); if( obj->action_desc && ( !obj->pIndexData->action_desc || str_cmp( obj->action_desc, obj->pIndexData->action_desc ) ) ) fprintf( fp, "ActionDesc %s~\n", obj->action_desc ); fprintf( fp, "Vnum %ld\n", obj->pIndexData->vnum ); if( os_type == OS_CORPSE && obj->in_room ) fprintf( fp, "Room %ld\n", obj->in_room->vnum ); if( obj->extra_flags != obj->pIndexData->extra_flags ) fprintf( fp, "ExtraFlags %d\n", obj->extra_flags ); if( obj->wear_flags != obj->pIndexData->wear_flags ) fprintf( fp, "WearFlags %d\n", obj->wear_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 ); 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] ) fprintf( fp, "Values %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] ); switch ( obj->item_type ) { case ITEM_DEVICE: if( IS_VALID_SN( obj->value[3] ) ) fprintf( fp, "Spell 3 '%s'\n", skill_table[obj->value[3]]->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 %d\n", paf->type, paf->duration, ( ( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN ) && IS_VALID_SN( paf->modifier ) ) ? skill_table[paf->modifier]->slot : paf->modifier, paf->location, paf->bitvector ); } else { fprintf( fp, "AffectData '%s' %d %d %d %d\n", skill_table[paf->type]->name, paf->duration, ( ( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL || paf->location == APPLY_STRIPSN ) && IS_VALID_SN( paf->modifier ) ) ? skill_table[paf->modifier]->slot : paf->modifier, paf->location, 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( obj->first_content ) fwrite_obj( ch, obj->last_content, fp, iNest + 1, OS_CARRY ); } /* * Load a char and inventory into a new ch structure. */ bool load_char_obj( DESCRIPTOR_DATA * d, const char *name, bool preload ) { char strsave[MAX_INPUT_LENGTH]; CHAR_DATA *ch; FILE *fp; bool found; struct stat fst; int i, x; 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->name = STRALLOC( name ); ch->act = PLR_BLANK | PLR_COMBINE | PLR_PROMPT; ch->top_level = 0; ch->perm_str = 10; ch->perm_int = 10; ch->perm_wis = 10; ch->perm_dex = 10; ch->perm_con = 10; ch->perm_cha = 10; ch->perm_lck = 10; ch->pcdata->condition[COND_THIRST] = 48; ch->pcdata->condition[COND_FULL] = 48; ch->pcdata->condition[COND_BLOODTHIRST] = 10; ch->pcdata->wizinvis = 0; ch->mental_state = -10; ch->mobinvis = 0; for( i = 0; i < MAX_SKILL; i++ ) set_skill_level( ch, 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; ch->mob_clan = NULL; ch->guard_data = NULL; ch->was_sentinel = NULL; ch->plr_home = NULL; #ifdef SWR2_USE_IMC imc_initchar( ch ); #endif found = FALSE; sprintf( strsave, "%s%c/%s", PLAYER_DIR, tolower( ( int ) name[0] ), capitalize( name ) ); #if !defined(AMIGA) && !defined(__MORPHOS__) if( stat( strsave, &fst ) != -1 ) { if( fst.st_size == 0 ) { sprintf( strsave, "%s%c/%s", BACKUP_DIR, tolower( ( int ) name[0] ), capitalize( name ) ); send_to_char( "Restoring your backup player file...", ch ); } else { sprintf( buf, "%s player data for: %s (%dK)", preload ? "Preloading" : "Loading", ch->name, ( int ) fst.st_size / 1024 ); log_string_plus( buf, LOG_COMM ); } } #endif /* else no player file */ if( ( fp = fopen( strsave, "r" ) ) != NULL ) { 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 ); break; } word = fread_word( fp ); if( !str_cmp( word, "PLAYER" ) ) { fread_char( ch, fp, preload ); if( preload ) break; } else if( !str_cmp( word, "OBJECT" ) ) /* Objects */ fread_obj( ch, fp, OS_CARRY ); else if( !str_cmp( 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->short_descr = STRALLOC( "" ); ch->long_descr = STRALLOC( "" ); ch->description = STRALLOC( "" ); ch->editor = NULL; ch->pcdata->clan_permissions = str_dup( "" ); ch->pcdata->clan = NULL; ch->pcdata->pwd = str_dup( "" ); ch->pcdata->email = str_dup( "" ); ch->pcdata->bamfin = str_dup( "" ); ch->pcdata->bamfout = str_dup( "" ); ch->pcdata->rank = str_dup( "" ); ch->pcdata->bestowments = str_dup( "" ); ch->pcdata->title = STRALLOC( "" ); ch->pcdata->homepage = str_dup( "" ); ch->pcdata->bio = STRALLOC( "" ); ch->pcdata->authed_by = STRALLOC( "" ); ch->pcdata->prompt = STRALLOC( "" ); ch->pcdata->wizinvis = 0; ch->pcdata->num_skills = 0; ch->pcdata->adept_skills = 0; } else { int sn; int num_skills = 0; int adept_skills = 0; if( !ch->pcdata->bio ) ch->pcdata->bio = STRALLOC( "" ); if( !ch->pcdata->authed_by ) ch->pcdata->authed_by = STRALLOC( "" ); if( !IS_NPC( ch ) && IS_IMMORTAL( ch ) ) { if( ch->pcdata->wizinvis < 2 ) ch->pcdata->wizinvis = ch->top_level; } 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], i ); save_equipment[i][x] = NULL; } else { break; } } } } for( sn = 0; sn < top_sn; sn++ ) if( character_skill_level( ch, sn ) > 0 ) { num_skills++; if( character_skill_level( ch, sn ) >= 100 ) adept_skills++; } ch->pcdata->num_skills = num_skills; ch->pcdata->adept_skills = adept_skills; } loading_char = NULL; return found; } /* * Read in a char. */ void fread_char( CHAR_DATA * ch, FILE * fp, bool preload ) { char buf[MAX_STRING_LENGTH]; const char *line = NULL; const char *word = NULL; int x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0, x7 = 0; short killcnt = 0; bool fMatch = FALSE; time_t lastplayed = 0; int extra = 0; file_ver = 0; for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); if( word[0] == '\0' ) { bug( "%s: EOF encountered reading file!", __FUNCTION__ ); word = "End"; } fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': KEY( "Act", ch->act, fread_number( fp ) ); KEY( "AffectedBy", ch->affected_by, fread_number( fp ) ); KEY( "Alignment", ch->alignment, fread_number( fp ) ); KEY( "Armor", ch->armor, fread_number( fp ) ); if( !str_cmp( word, "Affect" ) || !str_cmp( word, "AffectData" ) ) { AFFECT_DATA *paf; if( preload ) { fMatch = TRUE; fread_to_eol( fp ); break; } CREATE( paf, AFFECT_DATA, 1 ); if( !str_cmp( word, "Affect" ) ) { paf->type = fread_number( fp ); } else { int sn; char *sname = fread_word( fp ); if( ( sn = skill_lookup( sname ) ) < 0 ) { bug( "Fread_char: unknown skill.", 0 ); } paf->type = sn; } paf->duration = fread_number( fp ); paf->modifier = fread_number( fp ); paf->location = fread_number( fp ); paf->bitvector = fread_number( fp ); LINK( paf, ch->first_affect, ch->last_affect, next, prev ); fMatch = TRUE; break; } if( !str_cmp( 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; if( !x7 ) ch->mod_lck = 0; fMatch = TRUE; break; } if( !str_cmp( 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; if( !x7 || x7 == 0 ) ch->perm_lck = 13; fMatch = TRUE; break; } KEY( "AuthedBy", ch->pcdata->authed_by, fread_string( fp ) ); break; case 'B': KEY( "Bamfin", ch->pcdata->bamfin, fread_string_nohash( fp ) ); KEY( "Bamfout", ch->pcdata->bamfout, fread_string_nohash( fp ) ); KEY( "Bestowments", ch->pcdata->bestowments, fread_string_nohash( fp ) ); KEY( "Bio", ch->pcdata->bio, fread_string( fp ) ); KEY( "Bank", ch->pcdata->bank, fread_number( fp ) ); break; case 'C': KEY( "ClanPerms", ch->pcdata->clan_permissions, fread_string_nohash( fp ) ); if( !str_cmp( word, "Clan" ) ) { char *clan_name = fread_string( fp ); if( !preload && clan_name[0] != '\0' && ( ch->pcdata->clan = get_clan( clan_name ) ) == NULL ) { sprintf( buf, "Warning: the organization %s no longer exists, and therefore you no longer\r\nbelong to that organization.\r\n", clan_name ); send_to_char( buf, ch ); } STRFREE( clan_name ); fMatch = TRUE; break; } if( !str_cmp( 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( "Deaf", ch->deaf, fread_number( fp ) ); KEY( "Description", ch->description, fread_string( fp ) ); break; /* 'E' was moved to after 'S' */ case 'F': KEY( "Flags", ch->pcdata->flags, fread_number( fp ) ); if( !str_cmp( word, "Force" ) ) { line = fread_line( fp ); x1 = x2 = x3 = x4 = x5 = x6 = 0; sscanf( line, "%d %d %d %d", &x1, &x2, &x3, &x4 ); ch->perm_frc = x1; ch->mod_frc = x2; ch->mana = x3; ch->max_mana = x4; fMatch = TRUE; break; } break; case 'G': KEY( "Gold", ch->gold, fread_number( fp ) ); break; case 'H': if( !str_cmp( 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( !str_cmp( word, "HpManaMove" ) ) { line = fread_line( fp ); x1 = x2 = x3 = x4 = x5 = x6 = 0; sscanf( line, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 ); ch->hit = x1; ch->max_hit = x2; ch->move = x5; ch->max_move = x6; if( x4 >= 100 ) { ch->perm_frc = number_range( 1, 20 ); ch->max_mana = x4; ch->mana = x4; } else if( x4 >= 10 ) { ch->perm_frc = 1; ch->max_mana = x4; } fMatch = TRUE; break; } break; case 'I': KEY( "Immune", ch->immune, fread_number( fp ) ); #ifdef SWR2_USE_IMC if( ( fMatch = imc_loadchar( ch, fp, word ) ) ) break; #endif break; case 'K': if( !str_cmp( word, "Killed" ) ) { fMatch = TRUE; if( killcnt >= MAX_KILLTRACK ) bug( "fread_char: killcnt (%d) >= MAX_KILLTRACK", killcnt ); else { ch->pcdata->killed[killcnt].vnum = fread_number( fp ); ch->pcdata->killed[killcnt++].count = fread_number( fp ); } } break; case 'L': if( !str_cmp( word, "Lastplayed" ) ) { lastplayed = fread_number( fp ); fMatch = TRUE; break; } KEY( "LongDescr", ch->long_descr, fread_string( fp ) ); break; case 'M': KEY( "Mentalstate", ch->mental_state, fread_number( fp ) ); KEY( "Minsnoop", ch->pcdata->min_snoop, fread_number( fp ) ); KEY( "Mobinvis", ch->mobinvis, fread_number( fp ) ); break; case 'N': if( !str_cmp( word, "Name" ) ) { /* * Name already set externally. */ fread_to_eol( fp ); fMatch = TRUE; break; } break; case 'O': KEY( "Outcast_time", ch->pcdata->outcast_time, fread_number( fp ) ); break; case 'P': KEY( "Pagerlen", ch->pcdata->pagerlen, fread_number( fp ) ); 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( "Played", ch->played, fread_number( fp ) ); KEY( "Position", ch->position, fread_number( fp ) ); KEY( "Practice", extra, fread_number( fp ) ); KEY( "Prompt", ch->pcdata->prompt, fread_string( fp ) ); if( !str_cmp( word, "PTimer" ) ) { add_timer( ch, TIMER_PKILLED, fread_number( fp ), NULL, 0 ); fMatch = TRUE; break; } if( !str_cmp( word, "PlrHome" ) ) { ch->plr_home = get_room_index( fread_number( fp ) ); if( !ch->plr_home ) ch->plr_home = NULL; fMatch = TRUE; break; } break; case 'R': 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 ) ); if( !str_cmp( word, "Room" ) ) { ch->in_room = get_room_index( fread_number( fp ) ); if( !ch->in_room ) ch->in_room = get_room_index( wherehome( ch ) ); fMatch = TRUE; break; } break; case 'S': KEY( "Sex", ch->sex, fread_number( fp ) ); KEY( "ShortDescr", ch->short_descr, fread_string( fp ) ); KEY( "Susceptible", ch->susceptible, fread_number( fp ) ); if( !str_cmp( 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( !str_cmp( 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( !str_cmp( word, "Site" ) ) { if( !preload ) { sprintf( buf, "Last connected from: %s\r\n", fread_word( fp ) ); send_to_char( buf, ch ); } else fread_to_eol( fp ); fMatch = TRUE; if( preload ) word = "End"; else break; } if( !str_cmp( word, "Skill" ) ) { int value; if( preload ) word = "End"; else { int sn = 0; 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_first_weapon - 1 ); if( sn < 0 ) bug( "Fread_char: unknown skill.", 0 ); else { set_skill_level( ch, sn, value ); } fMatch = TRUE; break; } } if( !str_cmp( 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 { set_skill_level( ch, sn, value ); } fMatch = TRUE; break; } } if( str_cmp( word, "End" ) ) break; case 'E': if( !str_cmp( word, "End" ) ) { if( !ch->short_descr ) ch->short_descr = STRALLOC( "" ); if( !ch->long_descr ) ch->long_descr = STRALLOC( "" ); if( !ch->description ) ch->description = STRALLOC( "" ); if( !ch->pcdata->pwd ) ch->pcdata->pwd = str_dup( "" ); if( !ch->pcdata->email ) ch->pcdata->email = str_dup( "" ); if( !ch->pcdata->bamfin ) ch->pcdata->bamfin = str_dup( "" ); if( !ch->pcdata->bamfout ) ch->pcdata->bamfout = str_dup( "" ); if( !ch->pcdata->bio ) ch->pcdata->bio = STRALLOC( "" ); if( !ch->pcdata->rank ) ch->pcdata->rank = str_dup( "" ); if( !ch->pcdata->bestowments ) ch->pcdata->bestowments = str_dup( "" ); if( !ch->pcdata->title ) ch->pcdata->title = STRALLOC( "" ); if( !ch->pcdata->homepage ) ch->pcdata->homepage = str_dup( "" ); if( !ch->pcdata->authed_by ) ch->pcdata->authed_by = STRALLOC( "" ); if( !ch->pcdata->prompt ) ch->pcdata->prompt = STRALLOC( "" ); if( !ch->pcdata->clan_permissions ) ch->pcdata->clan_permissions = str_dup( "" ); ch->editor = NULL; killcnt = MAX_KILLTRACK; if( killcnt < MAX_KILLTRACK ) ch->pcdata->killed[killcnt].vnum = 0; if( !ch->pcdata->prompt ) ch->pcdata->prompt = STRALLOC( "" ); if( lastplayed != 0 ) { int hitgain; hitgain = ( ( int ) ( current_time - lastplayed ) / 60 ); ch->hit = URANGE( 1, ch->hit + hitgain, ch->max_hit ); ch->move = URANGE( 1, ch->move + hitgain, ch->max_move ); ch->mana = URANGE( 0, ch->mana + hitgain, ch->max_mana ); better_mental_state( ch, hitgain ); } return; } KEY( "Email", ch->pcdata->email, fread_string_nohash( fp ) ); break; case 'T': KEY( "Toplevel", ch->top_level, fread_number( fp ) ); KEY( "Trust", ch->trust, fread_number( fp ) ); /* Let no character be trusted higher than one below maxlevel -- Narn */ ch->trust = UMIN( ch->trust, MAX_LEVEL - 1 ); if( !str_cmp( word, "Title" ) ) { ch->pcdata->title = fread_string( fp ); if( isalpha( ( int ) ch->pcdata->title[0] ) || isdigit( ( int ) 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': KEY( "Version", file_ver, fread_number( fp ) ); break; case 'W': if( !str_cmp( word, "Weapon" ) ) { int sn; int value; if( preload ) word = "End"; else { value = fread_number( fp ); sn = bsearch_skill_exact( fread_word( fp ), gsn_first_weapon, gsn_top_sn - 1 ); if( sn < 0 ) bug( "Fread_char: unknown weapon.", 0 ); else { set_skill_level( ch, sn, value ); } fMatch = TRUE; } break; } KEY( "Wimpy", ch->wimpy, fread_number( fp ) ); KEY( "WizInvis", ch->pcdata->wizinvis, fread_number( fp ) ); break; } if( !fMatch ) { sprintf( buf, "Fread_char: no match: %s", word ); bug( buf, 0 ); } } } void fread_obj( CHAR_DATA * ch, FILE * fp, short os_type ) { OBJ_DATA *obj = NULL; const char *word = NULL; int iNest = 0; bool fMatch = FALSE; bool fNest = FALSE; bool fVnum = FALSE; ROOM_INDEX_DATA *room = NULL; CREATE( obj, OBJ_DATA, 1 ); obj->count = 1; obj->wear_loc = -1; obj->weight = 1; fNest = TRUE; /* Requiring a Nest 0 is a waste */ fVnum = TRUE; iNest = 0; for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); if( word[0] == '\0' ) { bug( "%s: EOF encountered reading file!", __FUNCTION__ ); word = "End"; } fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': if( !str_cmp( word, "Affect" ) || !str_cmp( word, "AffectData" ) ) { AFFECT_DATA *paf = NULL; int pafmod = 0; CREATE( paf, AFFECT_DATA, 1 ); if( !str_cmp( word, "Affect" ) ) { paf->type = fread_number( fp ); } else { int 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_number( fp ); if( paf->location == APPLY_WEAPONSPELL || paf->location == APPLY_WEARSPELL || paf->location == APPLY_REMOVESPELL ) paf->modifier = slot_lookup( pafmod ); else paf->modifier = pafmod; LINK( paf, obj->first_affect, obj->last_affect, next, prev ); fMatch = TRUE; break; } KEY( "Actiondesc", obj->action_desc, fread_string( fp ) ); break; case 'C': KEY( "Cost", obj->cost, fread_number( fp ) ); KEY( "Count", obj->count, fread_number( fp ) ); break; case 'D': KEY( "Description", obj->description, fread_string( fp ) ); break; case 'E': KEY( "ExtraFlags", obj->extra_flags, fread_number( fp ) ); if( !str_cmp( 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( !str_cmp( word, "End" ) ) { if( !fNest || !fVnum ) { bug( "Fread_obj: incomplete object.", 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 { short 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; /* Corpse saving. -- Altrag */ if( os_type == OS_CORPSE ) { if( !room ) { bug( "Fread_obj: Corpse without room", 0 ); room = get_room_index( ROOM_VNUM_LIMBO ); } obj = obj_to_room( obj, room ); } else if( iNest == 0 || rgObjNest[iNest] == NULL ) { int slot = 0; bool reslot = FALSE; if( file_ver > 1 && wear_loc > -1 && wear_loc < MAX_WEAR ) { int x = 0; 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 ) save_equipment[wear_loc][slot] = obj; } else { if( rgObjNest[iNest - 1] ) { separate_obj( rgObjNest[iNest - 1] ); obj = obj_to_obj( 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 'N': KEY( "Name", obj->name, fread_string( fp ) ); if( !str_cmp( 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 'R': KEY( "Room", room, get_room_index( fread_number( fp ) ) ); case 'S': KEY( "ShortDescr", obj->short_descr, fread_string( fp ) ); if( !str_cmp( word, "Spell" ) ) { int iValue = fread_number( fp ); int 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; } break; case 'T': KEY( "Timer", obj->timer, fread_number( fp ) ); break; case 'V': if( !str_cmp( word, "Values" ) ) { int x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0; char *ln = fread_line( fp ); sscanf( ln, "%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6 ); /* clean up some garbage */ if( file_ver < 3 ) x5 = x6 = 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; fMatch = TRUE; break; } if( !str_cmp( word, "Vnum" ) ) { int vnum = fread_number( fp ); if( ( obj->pIndexData = get_obj_index( vnum ) ) == NULL ) { fVnum = FALSE; bug( "Fread_obj: bad vnum %d.", vnum ); } else { fVnum = TRUE; obj->cost = obj->pIndexData->cost; obj->weight = obj->pIndexData->weight; obj->item_type = obj->pIndexData->item_type; obj->wear_flags = obj->pIndexData->wear_flags; obj->extra_flags = obj->pIndexData->extra_flags; } fMatch = TRUE; break; } break; case 'W': KEY( "WearFlags", obj->wear_flags, fread_number( fp ) ); KEY( "WearLoc", obj->wear_loc, fread_number( fp ) ); KEY( "Weight", obj->weight, fread_number( fp ) ); break; } if( !fMatch ) { EXTRA_DESCR_DATA *ed = NULL; AFFECT_DATA *paf = NULL; 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 set_alarm( long seconds ) { #if !defined(AMIGA) && !defined(__MORPHOS__) && !defined( _WIN32 ) 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>\r\n", ch ); return; } strcpy( name, capitalize( arg ) ); sprintf( buf, "%s%c/%s", PLAYER_DIR, tolower( ( int ) arg[0] ), name ); if( stat( buf, &fst ) != -1 ) sprintf( buf, "%s was last on: %s\r\n", name, ctime( &fst.st_mtime ) ); else sprintf( buf, "%s was not found.\r\n", name ); send_to_char( buf, ch ); } void write_corpses( const CHAR_DATA * ch, const char *name ) { OBJ_DATA *corpse = NULL; 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 ) ) { 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; } } fwrite_obj( ch, corpse, fp, 0, OS_CORPSE ); } if( fp ) { fprintf( fp, "#END\n\n" ); fclose( fp ); } else { char buf[127]; sprintf( buf, "%s%s", CORPSE_DIR, capitalize( name ) ); remove( buf ); } return; } /* Directory scanning with Amiga and MorphOS */ #if defined(AMIGA) || defined(__MORPHOS__) void load_corpses( void ) { BPTR sourcelock = NULL; struct ExAllControl *excontrol = NULL; struct ExAllData buffer, *ead = NULL; BOOL exmore = TRUE; memset( &buffer, 0, sizeof( buffer ) ); sourcelock = Lock( (CONST_STRPTR) CORPSE_DIR, SHARED_LOCK ); excontrol = (struct ExAllControl*) AllocDosObject( DOS_EXALLCONTROL, NULL ); excontrol->eac_LastKey = 0; do { exmore = ExAll( sourcelock, &buffer, sizeof( buffer ), ED_NAME, excontrol ); if( !exmore && IoErr() != ERROR_NO_MORE_ENTRIES ) continue; ead = &buffer; do { if( ead->ed_Name[0] != '.' ) { fread_corpse( (const char*) ead->ed_Name ); } ead = ead->ed_Next; } while( ead ); } while( exmore ); FreeDosObject( DOS_EXALLCONTROL, excontrol ); UnLock( sourcelock ); } /* Directory scanning with Windows */ #elif defined(_WIN32) void load_corpses( void ) { char buf[256]; WIN32_FIND_DATA info; HANDLE h; sprintf( buf, "%s*.*", CORPSE_DIR ); h = FindFirstFile( buf, &info ); if( h != INVALID_HANDLE_VALUE ) { do { if( info.cFileName[0] != '.' ) { fread_corpse( info.cFileName ); } } while( FindNextFile( h, &info ) ); FindClose( h ); } } /* Directory scanning with POSIX */ #else void load_corpses( void ) { DIR *dp = NULL; struct dirent *de = NULL; if( !( dp = opendir( CORPSE_DIR ) ) ) { bug( "Load_corpses: can't open CORPSE_DIR", 0 ); perror( CORPSE_DIR ); return; } while( ( de = readdir( dp ) ) != NULL ) { if( de->d_name[0] != '.' ) { fread_corpse( de->d_name ); } } } #endif void fread_corpse( const char *name ) { falling = 1; sprintf( strArea, "%s%s", CORPSE_DIR, name ); fprintf( out_stream, "Corpse -> %s\n", strArea ); if( !( fpArea = fopen( strArea, "r" ) ) ) { perror( strArea ); return; } for( ;; ) { const char *word; char letter = fread_letter( fpArea ); if( letter == '*' ) { fread_to_eol( fpArea ); continue; } if( letter != '#' ) { bug( "Load_corpses: # not found." ); break; } word = fread_word( fpArea ); if( !str_cmp( word, "CORPSE" ) ) { fread_obj( NULL, fpArea, OS_CORPSE ); } else if( !str_cmp( word, "OBJECT" ) ) { fread_obj( NULL, fpArea, OS_CARRY ); } else if( !str_cmp( word, "END" ) ) { break; } else { bug( "Load_corpses: bad section." ); break; } } fclose( fpArea ); fpArea = NULL; sprintf( strArea, "$" ); falling = 0; }