/**
* \file save.c
* Provides services for saving and retrieving game data
*
* The purpose of this module is provide utilities and functionality for
* saveing, writing, reading and loading of game date, including rooms, mobs,
* objects, and players. Some statistics are also calculated here.
*
* Copyright 2005, Mary C. Huston, All rights reserved.
* Copyright (C) 2004, Shadows of Isildur: Traithe
*
* The program(s) may be used and/or copied only with written
* permission or in accordance with the terms and conditions
* stipulated in the license from DIKU GAMMA (0.0) and SOI.
*
* \author Mary Huston
* \author Email: auroness@gmail.com
*
******************************************************************************
*/
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <stdlib.h>
#include "structs.h"
#include "utils.h"
#include "protos.h"
#include "decl.h"
#define POSSESS_UNDEF 0
#define POSSESS_CARRY 1
#define POSSESS_WEAR 2
#define POSSESS_ROOM 3
static int last_wc = POSSESS_UNDEF;
static int last_eqloc;
static int last_eqlev;
static int file_eof_found = 0;
static int save_stop_obj_processing = 0;
int load_char_objects;
extern int fread_number (FILE *fp);
extern char *fread_word (FILE *fp);
void write_char_data ( CHAR_DATA *ch, FILE *fp );
void write_obj_data ( OBJ_DATA *obj,
char *wc,
int pos,
int objstack,
FILE *fp );
int load_player (char *name, CHAR_DATA *ch, int load_type);
void read_obj_list (int cur_wc,
int cur_eqloc,
int cur_eqlev,
CHAR_DATA *ch,
OBJ_DATA *holder,
FILE *fp,
int room_num);
OBJ_DATA *fread_obj (FILE *fp);
void read_aliases (CHAR_DATA *ch, FILE *fp);
char *unspace (char *s)
{
char *result;
char *orig;
if ( !s ) {
((int *) -1) [0] = 1;
}
if ( *s != ' ' )
return s;
orig = s;
result = malloc (strlen (s) + 1);
while (s && *s == ' ')
s++;
strcpy (result, s);
mem_free (orig);
return result;
}
void fwrite_a_obj (OBJ_DATA *obj, FILE *fp)
{
int affect_count = 0;
int modifiers = 1;
AFFECTED_TYPE *af = NULL;
WOUND_DATA *wound;
OBJECT_DAMAGE *damage;
LODGED_OBJECT_INFO *lodged;
OBJ_DATA *proto = NULL;
TRIGGER_DATA *trig = NULL;
proto = vtoo (obj->virtual);
if ( !proto )
return;
for ( af = obj->xaffected; af; af = af->next ) {
if ( af->a.spell.location ) {
affect_count++;
continue;
}
}
if ( obj->omote_str )
modifiers++;
if ( obj->loaded )
modifiers += 1;
for ( wound = obj->wounds; wound; wound = wound->next ) {
modifiers++;
}
for ( damage = obj->damage; damage; damage = damage->next ) {
modifiers++;
}
for ( lodged = obj->lodged; lodged; lodged = lodged->next ) {
modifiers++;
}
if ( obj->size )
modifiers++;
if ( obj->count > 1 )
modifiers++;
if ( obj->obj_flags.extra_flags )
modifiers++;
if ( obj->obj_flags.type_flag == ITEM_DRINKCON )
modifiers++;
if ( obj->obj_timer ) /* obj_flags.timer */
modifiers++;
if (obj->clock && (obj->morphto >= 0) && obj->morphTime)
modifiers +=3;
if ( obj->book_title && obj->title_skill )
modifiers += 4;
if ( obj->var_color && str_cmp (obj->var_color, "none") )
modifiers++;
if ( obj->item_wear )
modifiers++;
if ( obj->obj_flags.type_flag != ITEM_DRINKCON ) {
if(proto->name && obj->name && *obj->name)
if ( strcmp (obj->name, proto->name) )
modifiers++;
if(proto->short_description && obj->short_description && *obj->short_description)
if ( strcmp (obj->short_description, proto->short_description) )
modifiers++;
if(proto->description && obj->description && *obj->description)
if ( strcmp (obj->description, proto->description) )
modifiers++;
if(proto->full_description && obj->full_description && *obj->full_description)
if ( strcmp (obj->full_description, proto->full_description) )
modifiers++;
}
if ( IS_SET(proto->obj_flags.extra_flags, ITEM_MASK) && proto->obj_flags.type_flag == ITEM_ARMOR && obj->desc_keys && strlen(obj->desc_keys) > 1 ) {
if ( !proto->desc_keys && obj->desc_keys )
modifiers++;
else if ( strcmp (obj->desc_keys, proto->desc_keys) )
modifiers++;
}
if ( IS_SET(proto->obj_flags.extra_flags, ITEM_MASK) && proto->obj_flags.type_flag == ITEM_WORN && obj->desc_keys && strlen(obj->desc_keys) > 1 ) {
if ( strcmp (obj->desc_keys, proto->desc_keys) )
modifiers++;
}
if ( obj->coldload_id )
modifiers++;
fprintf (fp, "Id %d %d %d\n", obj->virtual, affect_count, modifiers);
if ( obj->coldload_id )
fprintf (fp, "coldload %d\n", obj->coldload_id);
if ( obj->obj_flags.type_flag != ITEM_DRINKCON ) {
if(proto->name && obj->name && *obj->name)
if ( strcmp (obj->name, proto->name) )
fprintf (fp, "name %s~\n", obj->name);
if(proto->short_description && obj->short_description && *obj->short_description)
if ( strcmp (obj->short_description, proto->short_description) )
fprintf (fp, "short %s~\n", obj->short_description);
if(proto->description && obj->description && *obj->description)
if ( strcmp (obj->description, proto->description) )
fprintf (fp, "long %s~\n", obj->description);
if(proto->full_description && obj->full_description && *obj->full_description )
if ( strcmp (obj->full_description, proto->full_description) )
fprintf (fp, "full %s~\n", obj->full_description);
if ( IS_SET(proto->obj_flags.extra_flags, ITEM_MASK) && (proto->obj_flags.type_flag == ITEM_WORN || proto->obj_flags.type_flag == ITEM_ARMOR) && obj->desc_keys && strlen(obj->desc_keys) > 1 )
if ( strcmp (obj->desc_keys, proto->desc_keys) )
fprintf (fp, "desc_keys %s~\n", obj->desc_keys);
}
if ( obj->book_title && obj->title_skill ) {
fprintf (fp, "book_title %s~\n", obj->book_title);
fprintf (fp, "title_skill %d\n", obj->title_skill);
fprintf (fp, "title_language %d\n", obj->title_language);
fprintf (fp, "title_script %d\n", obj->title_script);
}
if ( obj->loaded )
fprintf (fp, "loaded %d\n", obj->loaded->virtual);
if ( obj->obj_flags.extra_flags )
fprintf (fp, "extraflags %d\n", obj->obj_flags.extra_flags);
if ( obj->item_wear )
fprintf (fp, "itemwear %d\n", obj->item_wear);
fprintf (fp, "values %d %d %d %d %d %d\n", obj->o.od.value [0],
obj->o.od.value [1], obj->o.od.value [2], obj->o.od.value [3],
obj->o.od.value [4], obj->o.od.value [5]);
if ( obj->obj_flags.type_flag == ITEM_DRINKCON )
fprintf (fp, "weight %d\n", obj->obj_flags.weight);
if ( obj->size )
fprintf (fp, "size %d\n", obj->size);
if ( obj->count > 1 )
fprintf (fp, "count %d\n", obj->count);
if ( obj->obj_timer )
fprintf (fp, "timer %d\n", obj->obj_timer);
if(obj->clock && (obj->morphto >= 0) && obj->morphTime) {
fprintf(fp, "clock %d\n", obj->clock);
fprintf(fp, "morphto %d\n", obj->morphto);
fprintf(fp, "morphTime %d\n", obj->morphTime);
}
if ( obj->var_color && str_cmp (obj->var_color, "none") )
fprintf (fp, "VarColor %s~\n", obj->var_color);
if ( obj->omote_str ) {
fprintf(fp, "OmoteStr %s~\n", obj->omote_str);
}
if ( obj->wounds ) {
for ( wound = obj->wounds; wound; wound = wound->next )
fprintf (fp, "Wound %s %s %s %s %d %d %d %d %d %d %d\n",
wound->location, wound->type, wound->severity, wound->name,
wound->damage, wound->bleeding, wound->poison,
wound->infection, wound->healerskill, wound->lasthealed,
wound->lastbled);
}
if ( obj->damage ) {
for ( damage = obj->damage; damage; damage = damage->next ) {
fprintf (fp, "Damage %s %s %s %d\n", damage->type, damage->name, damage->severity, damage->damage);
}
}
if ( obj->lodged ) {
for ( lodged = obj->lodged; lodged; lodged = lodged->next )
fprintf (fp, "Lodged %s %d\n", lodged->location, lodged->vnum);
}
for ( af = obj->xaffected; af; af = af->next ) {
if ( af->a.spell.location ) {
fprintf (fp, "Afflocmod %d %d %d %d %d %d %d\n",
af->a.spell.location,
af->a.spell.modifier,
af->a.spell.duration,
af->a.spell.bitvector,
af->a.spell.t,
af->a.spell.sn,
af->type);
continue;
}
}
/** Lua functions **/
for ( trig = obj->triggers; trig; trig = trig->next ){
if (obj->triggers){
fprintf (fp, "Prog\n%d\n%s:%s\n",
trig->type,
trig->script,
trig->func);
}
}
/** end lua functions **/
return;
}
void write_obj_data (OBJ_DATA *obj, char *wc, int pos, int objstack, FILE *fp)
{
if ( !obj )
return;
if ( !vtoo (obj->virtual) )
return;
if ( obj->virtual == LEANTO_OBJ_VNUM ) /* Leantos. */
return;
fprintf (fp, "%s %d %d\n", wc, pos, objstack);
/* Save object */
fwrite_a_obj (obj, fp);
/* Save everything this object contains */
if ( obj->contains )
write_obj_data (obj->contains, wc, pos, objstack + 1, fp);
/* Save the next object in the list */
if ( (obj->location == -1 && obj->next_content && obj != obj->next_content ) )
write_obj_data (obj->next_content, wc, pos, objstack, fp);
if ( obj->next_content && obj->next_content == obj )
obj->next_content = NULL;
return;
}
OBJ_DATA *fread_obj (FILE *fp)
{
int obj_vnum = 0;
int affect_count = 0;
int modifiers = 0;
int i, page = 0;
int old_money = 0;
char *p = NULL;
OBJ_DATA *obj = NULL;
OBJ_DATA *tobj = NULL;
WRITING_DATA *writing = NULL;
AFFECTED_TYPE *af = NULL;
AFFECTED_TYPE *taf = NULL;
WOUND_DATA *wound = NULL;
OBJECT_DAMAGE *damage = NULL;
LODGED_OBJECT_INFO *lodged = NULL;
TRIGGER_DATA *trig = NULL;
char *temp_arg = NULL;
if ( strcmp (p = fread_word (fp), "Id") ) {
abort();
}
obj_vnum = fread_number (fp);
affect_count = fread_number (fp);
if ( !(obj = load_object (obj_vnum)) ) {
if ( !(obj = load_object (666)) ) {
if ( !obj ) {
return NULL;
}
}
}
/* Remove prototype affects */
while ( (af = obj->xaffected) ) {
obj->xaffected = af->next;
mem_free (af);
}
fscanf (fp, "%d", &modifiers);
for ( ; modifiers; modifiers-- ) {
p = fread_word (fp);
if ( !strcmp (p, "name") ) {
fgetc (fp);
obj->name = fread_string (fp);
}
else if ( !strcmp (p, "short") ) {
fgetc (fp);
obj->short_description = fread_string (fp);
}
else if ( !strcmp (p, "loaded") ) {
obj->loaded = vtoo(fread_number(fp));
}
else if ( !strcmp (p, "coldload") ) {
obj->coldload_id = fread_number(fp);
}
else if ( !strcmp (p, "extraflags") ) {
obj->obj_flags.extra_flags = fread_number(fp);
}
else if ( !strcmp (p, "itemwear") ) {
obj->item_wear = fread_number(fp);
}
else if ( !strcmp (p, "long") ) {
fgetc (fp);
obj->description = fread_string (fp);
}
else if ( !strcmp (p, "full") ) {
fgetc (fp);
obj->full_description = fread_string (fp);
}
else if ( !strcmp (p, "values") ) {
obj->o.od.value [0] = fread_number (fp);
obj->o.od.value [1] = fread_number (fp);
obj->o.od.value [2] = fread_number (fp);
obj->o.od.value [3] = fread_number (fp);
obj->o.od.value [4] = fread_number (fp);
obj->o.od.value [5] = fread_number (fp);
if ( GET_ITEM_TYPE (obj) == ITEM_BOOK || GET_ITEM_TYPE (obj) == ITEM_PARCHMENT )
writing = obj->writing;
}
else if ( !strcmp (p, "weight") )
obj->obj_flags.weight = fread_number (fp);
else if ( !strcmp (p, "size") )
obj->size = fread_number (fp);
else if ( !strcmp (p, "count") )
obj->count = fread_number (fp);
else if ( !str_cmp (p, "timer") )
obj->obj_timer = fread_number(fp);
else if ( !strcmp (p, "clock") )
obj->clock = fread_number (fp);
else if ( !strcmp (p, "morphTime") )
obj->morphTime = fread_number (fp);
else if ( !strcmp (p, "morphto") )
obj->morphto = fread_number (fp);
else if ( !strcmp (p, "VarColor") ){
temp_arg = fread_string(fp);
obj->var_color = unspace(temp_arg);
}
else if ( !strcmp (p, "book_title") ){
temp_arg = fread_string(fp);
obj->book_title = unspace(temp_arg);
}
else if ( !str_cmp (p, "title_skill") )
obj->title_skill = fread_number(fp);
else if ( !str_cmp (p, "title_script") )
obj->title_script = fread_number(fp);
else if ( !str_cmp (p, "title_language") )
obj->title_language = fread_number(fp);
else if ( !strcmp (p, "page:") ) {
if ( GET_ITEM_TYPE (obj) == ITEM_BOOK )
obj->o.od.value[1] = 0;
else
obj->o.od.value[0] = 0;
writing = obj->writing;
page = fread_number (fp);
for ( i = 1; i; i++ ) {
if ( i == page )
break;
else writing = writing->next_page;
}
}
else if ( !strcmp (p, "message:") ) {
if ( GET_ITEM_TYPE (obj) == ITEM_BOOK )
obj->o.od.value[1] = 0;
else
obj->o.od.value[0] = 0;
fgetc (fp);
writing->message = fread_string(fp);
}
else if ( !strcmp (p, "author:") ) {
if ( GET_ITEM_TYPE (obj) == ITEM_BOOK )
obj->o.od.value[1] = 0;
else
obj->o.od.value[0] = 0;
fgetc (fp);
writing->author = fread_string(fp);
}
else if ( !strcmp (p, "date:") ) {
if ( GET_ITEM_TYPE (obj) == ITEM_BOOK )
obj->o.od.value[1] = 0;
else
obj->o.od.value[0] = 0;
fgetc (fp);
writing->date = fread_string(fp);
}
else if ( !strcmp (p, "language:") )
writing->language = fread_number (fp);
else if ( !strcmp (p, "script:") )
writing->script = fread_number (fp);
else if ( !strcmp (p, "ink:") ) {
if ( GET_ITEM_TYPE (obj) == ITEM_BOOK )
obj->o.od.value[1] = 0;
else
obj->o.od.value[0] = 0;
fgetc (fp);
writing->ink = fread_string(fp);
}
else if ( !strcmp (p, "skill:") )
writing->skill = fread_number(fp);
else if ( !strcmp (p, "desc_keys") ) {
fgetc (fp);
obj->desc_keys = fread_string (fp);
}
else if ( !strcmp (p, "OmoteStr") ) {
temp_arg = fread_string(fp);
obj->omote_str = unspace(temp_arg);
}
else if ( !strcmp (p, "Wound") ) {
if ( !obj->wounds ) {
CREATE (obj->wounds, WOUND_DATA, 1);
wound = obj->wounds;
obj->wounds->next = NULL;
}
else {
CREATE (wound->next, WOUND_DATA, 1);
wound = wound->next;
wound->next = NULL;
}
temp_arg = fread_word(fp);
wound->location = add_hash (temp_arg);
temp_arg = fread_word(fp);
wound->type = add_hash(temp_arg);
temp_arg = fread_word(fp);
wound->severity = add_hash (temp_arg);
temp_arg = fread_word(fp);
wound->name = add_hash(temp_arg);
wound->damage = fread_number(fp);
wound->bleeding = fread_number(fp);
wound->poison = fread_number(fp);
wound->infection = fread_number(fp);
wound->healerskill = fread_number(fp);
wound->lasthealed = fread_number(fp);
wound->lastbled = fread_number(fp);
}
else if ( !strcmp (p, "Damage") ) {
if ( !obj->damage ) {
CREATE (obj->damage, OBJECT_DAMAGE, 1);
damage = obj->damage;
damage->next = NULL;
}
else {
CREATE (damage->next, OBJECT_DAMAGE, 1);
damage = damage->next;
damage->next = NULL;
}
temp_arg = fread_word(fp);
damage->type = str_dup (temp_arg);
temp_arg = fread_word(fp);
damage->name = str_dup (temp_arg);
temp_arg = fread_word(fp);
damage->severity = str_dup (temp_arg);
damage->damage = fread_number(fp);
}
else if ( !strcmp (p, "Lodged") ) {
if ( !obj->lodged ) {
CREATE (obj->lodged, LODGED_OBJECT_INFO, 1);
lodged = obj->lodged;
obj->lodged->next = NULL;
}
else {
CREATE (lodged->next, LODGED_OBJECT_INFO, 1);
lodged = lodged->next;
lodged->next = NULL;
}
temp_arg = fread_word(fp);
lodged->location = add_hash(temp_arg);
lodged->vnum = fread_number(fp);
}
}
if ( old_money ) {
obj->count = obj->o.od.value [0];
obj->o.od.value [0] = 0;
}
/* read_object probably created associated some affects with the
new object. Lets erase all those and put in saved affects */
for ( i = 0; obj && i < affect_count; i++ ) {
temp_arg = fread_word (fp);
if ( !strcmp (temp_arg, "Afflocmod") ) {
CREATE (af, AFFECTED_TYPE, 1);
af->next = NULL;
fscanf (fp, "%d %d %d %d %d %d %d\n",
&af->a.spell.location,
&af->a.spell.modifier,
&af->a.spell.duration,
&af->a.spell.bitvector,
&af->a.spell.t,
&af->a.spell.sn,
&af->type);
if ( !obj->xaffected ){
obj->xaffected = af;
}
else {
taf = obj->xaffected;
while ( taf->next )
taf = taf->next;
taf->next = af;
}
}
/**** for lua functions **/
if ( !strcmp (p, "Prog") ) {
if ( !obj->triggers ) {
CREATE (obj->triggers, TRIGGER_DATA, 1);
trig = obj->triggers;
obj->triggers->next = NULL;
}
else {
CREATE (trig->next, TRIGGER_DATA, 1);
trig = trig->next;
trig->next = NULL;
}
trig->type = fread_number(fp);
temp_arg = fread_word(fp);
trig->script = add_hash(temp_arg);
temp_arg = fread_word(fp);
trig->func = add_hash(temp_arg);
}
/** end lua functions **/
}
if ( GET_ITEM_TYPE (obj) == ITEM_DRINKCON ||
GET_ITEM_TYPE (obj) == ITEM_LIGHT ||
GET_ITEM_TYPE (obj) == ITEM_FOUNTAIN )
if ( !(tobj = vtoo (obj->o.drinkcon.liquid)) ||
GET_ITEM_TYPE (tobj) != ITEM_FLUID )
obj->o.drinkcon.liquid = vtoo (obj->virtual)->o.drinkcon.liquid;
if ( !IS_SET (obj->obj_flags.extra_flags, ITEM_NEWSKILLS) )
update_weapon_skills (obj);
/* Record what object previously was */
if ( obj->virtual == 666 )
obj->o.od.value[0] = obj_vnum;
return obj;
}
int fread_look_obj_header (int *wc, int *eqloc, int *eqlev, FILE *fp)
{
char *ptr = NULL;
if ( last_wc != POSSESS_UNDEF ) {
*wc = last_wc;
*eqloc = last_eqloc;
*eqlev = last_eqlev;
return (1);
}
if ( file_eof_found || save_stop_obj_processing )
return (0);
ptr = fread_word (fp);
if ( *ptr == '\0' ) /* Probably the end of file mark */
return (0);
else if ( !strcmp (ptr, "CARRY") )
*wc = POSSESS_CARRY;
else if ( !strcmp (ptr, "WEAR") )
*wc = POSSESS_WEAR;
else if ( !strcmp (ptr, "ROOM") )
*wc = POSSESS_ROOM;
else if ( !strcmp (ptr, "DONE") ) {
save_stop_obj_processing = 1;
return (0);
}
else if ( !strcmp (ptr, "END") ) {
file_eof_found = 1;
return (0);
}
else
return (0);
*eqloc = fread_number (fp);
*eqlev = fread_number (fp);
last_wc = *wc;
last_eqloc = *eqloc;
last_eqlev = *eqlev;
return (1);
}
void read_obj_list (int cur_wc, int cur_eqloc, int cur_eqlev, CHAR_DATA *ch,
OBJ_DATA *holder, FILE *fp, int room_num)
{
int eqloc = 0;
int eqlev = 0;
int wc = 0;
OBJ_DATA *obj = NULL;
while (1) {
if ( !fread_look_obj_header (&wc, &eqloc, &eqlev, fp) )
return;
if ( cur_eqlev > eqlev )
return;
if ( (cur_wc != wc || cur_eqloc != eqloc) && eqloc != -1 && eqloc != WEAR_PRIM && eqloc != WEAR_SEC && eqloc != WEAR_BOTH ) {
return;
}
if ( (cur_eqlev < eqlev) )
read_obj_list (wc, eqloc, eqlev, ch, obj, fp, room_num);
else {
last_wc = POSSESS_UNDEF;
obj = fread_obj (fp);
if ( !obj ) return;
else if ( holder ) {
if ( ch ) /* All non-player-held books handled by load_all_writing(); */
load_writing(obj);
obj_to_obj (obj, holder);
}
else if ( wc == POSSESS_ROOM ) {
if ( !vtor (room_num) )
printf ("Room %d does not exist for object %d.\n",
room_num, obj->virtual);
else
obj_to_room (obj, room_num);
} else if ( cur_eqloc == -1 ) {
obj->in_room = NOWHERE;
if ( ch )
load_writing(obj);
obj_to_char (obj, ch);
if ( eqloc == WEAR_PRIM || eqloc == WEAR_SEC || eqloc == WEAR_BOTH )
equip_char (ch, obj, eqloc);
}
else {
if ( ch )
load_writing(obj);
obj->carried_by = ch;
obj->in_room = NOWHERE;
equip_char (ch, obj, eqloc);
}
} /* cur_eqlev < eqlev */
} /* while (1) */
return;
}
OBJ_DATA *get_equipped (CHAR_DATA *ch, int location)
{
OBJ_DATA *obj = NULL;
for ( obj = ch->equip; obj; obj = obj->next_content )
if ( obj->location == location )
return obj;
return NULL;
}
void write_obj_suppliment (CHAR_DATA *ch, FILE *fp)
{
int i = 0;
OBJ_DATA *temp_obj = NULL;
if ( ch->right_hand ) {
write_obj_data (ch->right_hand, "CARRY", ch->right_hand->location, 0, fp);
}
if ( ch->left_hand ) {
write_obj_data (ch->left_hand, "CARRY", ch->left_hand->location, 0, fp);
}
for ( i = 0; i < MAX_WEAR; i++ ) {
if ( i == WEAR_PRIM || i == WEAR_BOTH || i == WEAR_SEC || i == WEAR_SHIELD )
continue;
temp_obj = get_equipped (ch, i);
write_obj_data (temp_obj, "WEAR", i, 0, fp);
}
fprintf (fp, "END\n");
return;
}
void read_obj_suppliment (CHAR_DATA *ch, FILE *fp)
{
int i = 0;
file_eof_found = 0;
save_stop_obj_processing = 0;
last_wc = POSSESS_UNDEF;
load_char_objects = 1; /* Global variable */
ch->right_hand = NULL;
ch->left_hand = NULL;
ch->equip = NULL;
read_obj_list (POSSESS_CARRY, -1, 0, ch, NULL, fp, 0);
for (i = 0; i < MAX_WEAR; i++) {
if ( i == WEAR_PRIM || i == WEAR_SEC || i == WEAR_BOTH )
continue;
read_obj_list (POSSESS_WEAR, i, 0, ch, NULL, fp, 0);
}
load_char_objects = 0;
return;
}
#define TYPE_STRING 1
#define TYPE_INT 2
#define TYPE_SKILL 3
#define TYPE_END 5
#define TYPE_AFFECT 6
#define TYPE_SHORTINT 7
#define TYPE_DREAM 8
#define TYPE_OBSOLETE 9
#define TYPE_LONG 10
#define TYPE_SUBCRAFT 11
#define TYPE_ALIAS 12
#define TYPE_WOUND 13
#define TYPE_STORED_PC 14
#define TYPE_LODGED 15
#define TYPE_SPELL 16
#define TYPE_CHARM 17
#define TYPE_VOICE 18
#define TYPE_HOODED 19
#define TYPE_NANNY 21
#define TYPE_APPCOST 22
#define TYPE_ROLE 23
#define TYPE_ROLE_SUMMARY 24
#define TYPE_ROLE_BODY 25
#define TYPE_ROLE_DATE 26
#define TYPE_ROLE_POSTER 27
#define TYPE_ROLE_COST 28
#define TYPE_MAIL_MESSAGE 29
#define TYPE_IP 30
#define TYPE_AFFECTEDBY 31
#define TYPE_NEWSLETTER 32
#define TYPE_OWNER 33
#define TYPE_STABLED 34
#define TYPE_HAS_INV 35
#define TYPE_SPAWN 36
#define TYPE_MOUNT 37
#define TYPE_RESET 38
#define TYPE_RESETZ 39
#define TYPE_DONE 40
struct key_data {
char key [14];
int key_type;
void *ptr;
};
CHAR_DATA *load_char (CHAR_DATA *ch, char *name)
{
int i = 0;
int n = 0;
int sn = 0;
int last_key = 0;
int num_keys = 0;
int clan1 = 0;
int clan2 = 0;
char *p = NULL;
char *p2 = NULL;
FILE *fp = NULL;
AFFECTED_TYPE *af = NULL;
DREAM_DATA *dream = NULL;
DREAM_DATA *dream_list = NULL;
CHAR_DATA *tch = NULL;
SUBCRAFT_HEAD_DATA *craft = NULL;
ALIAS_DATA *current_alias = NULL;
ALIAS_DATA *alias = NULL;
LODGED_OBJECT_INFO *lodged = NULL;
LODGED_OBJECT_INFO *tmplodged = NULL;
CHARM_DATA *ench = NULL;
CHARM_DATA *tmpench = NULL;
WOUND_DATA *wound = NULL;
WOUND_DATA *tmpwound = NULL;
char current_alias_name [MAX_STRING_LENGTH] = { '\0' };
char buf [MAX_STRING_LENGTH] = { '\0' };
char buf2 [MAX_STRING_LENGTH] = { '\0' };
char *temp_arg = NULL;
struct key_data key_table [] = {
{ "Keywords", TYPE_STRING, NULL },
{ "Account", TYPE_STRING, NULL },
{ "Description",TYPE_STRING, NULL },
{ "Short", TYPE_STRING, NULL },
{ "Long", TYPE_STRING, NULL },
{ "Msg", TYPE_STRING, NULL },
{ "CreateCom", TYPE_STRING, NULL },
{ "Email", TYPE_STRING, NULL },
{ "CreateState",TYPE_INT, NULL },
{ "Level", TYPE_INT, NULL },
{ "Sex", TYPE_INT, NULL },
{ "Clan", TYPE_INT, NULL },
{ "Deity", TYPE_INT, NULL },
{ "Height", TYPE_INT, NULL },
{ "Frame", TYPE_INT, NULL },
{ "Race", TYPE_INT, NULL },
{ "Room", TYPE_INT, NULL },
{ "Str", TYPE_INT, NULL },
{ "Int", TYPE_INT, NULL },
{ "Wil", TYPE_INT, NULL },
{ "Con", TYPE_INT, NULL },
{ "Dex", TYPE_INT, NULL },
{ "Aur", TYPE_INT, NULL },
{ "Agi", TYPE_INT, NULL },
{ "StartStr", TYPE_INT, NULL },
{ "StartInt", TYPE_INT, NULL },
{ "StartWil", TYPE_INT, NULL },
{ "StartCon", TYPE_INT, NULL },
{ "StartDex", TYPE_INT, NULL },
{ "StartAur", TYPE_INT, NULL },
{ "StartAgi", TYPE_INT, NULL },
{ "Played", TYPE_LONG, NULL },
{ "Birth", TYPE_INT, NULL },
{ "Time", TYPE_INT, NULL },
{ "Cond0", TYPE_INT, NULL },
{ "Cond1", TYPE_INT, NULL },
{ "Cond2", TYPE_INT, NULL },
{ "Offense", TYPE_SHORTINT, NULL },
{ "Clan_2", TYPE_INT, NULL },
{ "PPoints", TYPE_INT, NULL },
{ "Hit", TYPE_INT, NULL },
{ "NatAttType", TYPE_INT, NULL },
{ "Move", TYPE_INT, NULL },
{ "Maxmove", TYPE_INT, NULL },
{ "Circle", TYPE_INT, NULL },
{ "FightMode", TYPE_INT, NULL },
{ "Color", TYPE_INT, NULL },
{ "Speaks", TYPE_INT, NULL },
{ "Nightmare", TYPE_INT, NULL },
{ "Flags", TYPE_INT, NULL },
{ "PlrFlags", TYPE_INT, NULL },
{ "Talents", TYPE_INT, NULL },
{ "BoatVnum", TYPE_INT, NULL },
{ "Speed", TYPE_INT, NULL },
{ "MountSpeed", TYPE_INT, NULL },
{ "Common", TYPE_INT, NULL },
{ "LastPCMsg", TYPE_INT, NULL },
{ "LastStaffM", TYPE_INT, NULL },
{ "SleepNeeded",TYPE_INT, NULL },
{ "LastLogon", TYPE_INT, NULL },
{ "LastLogoff", TYPE_INT, NULL },
{ "LastDis", TYPE_INT, NULL },
{ "LastConnect",TYPE_INT, NULL },
{ "LastDied", TYPE_INT, NULL },
{ "Autotoll", TYPE_INT, NULL },
{ "ColdloadID", TYPE_INT, NULL },
{ "ImmEnter", TYPE_STRING, NULL },
{ "ImmLeave", TYPE_STRING, NULL },
{ "SiteLie", TYPE_STRING, NULL },
{ "Clans", TYPE_STRING, NULL },
{ "Dream", TYPE_DREAM, NULL },
{ "Dreamed", TYPE_DREAM, NULL },
{ "StaffNotes", TYPE_INT, NULL },
{ "Age", TYPE_INT, NULL },
{ "Intoxication", TYPE_INT, NULL },
{ "Hunger", TYPE_INT, NULL },
{ "Thirst", TYPE_INT, NULL },
{ "Totem", TYPE_INT, NULL },
{ "Damage", TYPE_INT, NULL },
{ "LastRegen", TYPE_INT, NULL },
{ "LastRoom", TYPE_INT, NULL },
{ "Harness", TYPE_INT, NULL },
{ "MaxHarness", TYPE_INT, NULL },
{ "Wound", TYPE_WOUND, NULL },
{ "Spell", TYPE_SPELL, NULL },
{ "Charm", TYPE_CHARM, NULL },
{ "VoiceStr", TYPE_VOICE, NULL },
{ "NannyState", TYPE_NANNY, NULL },
{ "AppCost", TYPE_APPCOST, NULL },
{ "Role", TYPE_ROLE, NULL },
{ "RoleSummary", TYPE_ROLE_SUMMARY, NULL },
{ "RoleBody", TYPE_ROLE_BODY, NULL },
{ "RoleDate", TYPE_ROLE_DATE, NULL },
{ "RolePoster", TYPE_ROLE_POSTER, NULL },
{ "RoleCost", TYPE_ROLE_COST, NULL },
{ "Lodged", TYPE_LODGED, NULL },
{ "Skill", TYPE_SKILL, NULL },
{ "Affect", TYPE_AFFECT, NULL },
{ "AffectedBy", TYPE_AFFECTEDBY, NULL },
{ "Subcraft", TYPE_SUBCRAFT, NULL },
{ "IsHooded", TYPE_HOODED, NULL },
{ "Alias", TYPE_ALIAS, NULL },
{ "End", TYPE_END, NULL },
{ "\0", TYPE_INT, NULL }
};
if ( !isalpha (*name) ) {
return NULL;
}
key_table [n++].ptr = &ch->name;
key_table [n++].ptr = &ch->pc->account;
key_table [n++].ptr = &ch->description;
key_table [n++].ptr = &ch->short_descr;
key_table [n++].ptr = &ch->long_descr;
key_table [n++].ptr = &ch->pc->msg;
key_table [n++].ptr = &ch->pc->creation_comment;
key_table [n++].ptr = &ch->pc->email_address;
key_table [n++].ptr = &ch->pc->create_state;
key_table [n++].ptr = &ch->pc->level;
key_table [n++].ptr = &ch->sex;
key_table [n++].ptr = &clan1;
key_table [n++].ptr = &ch->deity;
key_table [n++].ptr = &ch->height;
key_table [n++].ptr = &ch->frame;
key_table [n++].ptr = &ch->race;
key_table [n++].ptr = &ch->in_room;
key_table [n++].ptr = &ch->str;
key_table [n++].ptr = &ch->intel;
key_table [n++].ptr = &ch->wil;
key_table [n++].ptr = &ch->con;
key_table [n++].ptr = &ch->dex;
key_table [n++].ptr = &ch->aur;
key_table [n++].ptr = &ch->agi;
key_table [n++].ptr = &ch->pc->start_str;
key_table [n++].ptr = &ch->pc->start_intel;
key_table [n++].ptr = &ch->pc->start_wil;
key_table [n++].ptr = &ch->pc->start_con;
key_table [n++].ptr = &ch->pc->start_dex;
key_table [n++].ptr = &ch->pc->start_aur;
key_table [n++].ptr = &ch->pc->start_agi;
key_table [n++].ptr = &ch->time.played;
key_table [n++].ptr = &ch->time.birth;
key_table [n++].ptr = &ch->time.logon;
key_table [n++].ptr = &ch->intoxication;
key_table [n++].ptr = &ch->hunger;
key_table [n++].ptr = &ch->thirst;
key_table [n++].ptr = &ch->offense;
key_table [n++].ptr = &clan2;
key_table [n++].ptr = &ch->ppoints;
key_table [n++].ptr = &ch->hit;
key_table [n++].ptr = &ch->nat_attack_type;
key_table [n++].ptr = &ch->move;
key_table [n++].ptr = &ch->max_move;
key_table [n++].ptr = &ch->circle;
key_table [n++].ptr = &ch->fight_mode;
key_table [n++].ptr = &ch->color;
key_table [n++].ptr = &ch->speaks;
key_table [n++].ptr = &ch->nightmare;
key_table [n++].ptr = &ch->flags;
key_table [n++].ptr = &ch->plr_flags;
key_table [n++].ptr = &ch->psionic_talents;
key_table [n++].ptr = &ch->pc->boat_virtual;
key_table [n++].ptr = &ch->speed;
key_table [n++].ptr = &ch->pc->mount_speed;
key_table [n++].ptr = &ch->pc->common;
key_table [n++].ptr = &ch->pc->last_global_pc_msg;
key_table [n++].ptr = &ch->pc->last_global_staff_msg;
key_table [n++].ptr = &ch->pc->sleep_needed;
key_table [n++].ptr = &ch->pc->last_logon;
key_table [n++].ptr = &ch->pc->last_logoff;
key_table [n++].ptr = &ch->pc->last_disconnect;
key_table [n++].ptr = &ch->pc->last_connect;
key_table [n++].ptr = &ch->pc->last_died;
key_table [n++].ptr = &ch->pc->auto_toll;
key_table [n++].ptr = &ch->coldload_id;
key_table [n++].ptr = &ch->pc->imm_enter;
key_table [n++].ptr = &ch->pc->imm_leave;
key_table [n++].ptr = &ch->pc->site_lie;
key_table [n++].ptr = &ch->clans;
key_table [n++].ptr = &ch->pc->dreams;
key_table [n++].ptr = &ch->pc->dreamed;
key_table [n++].ptr = &ch->pc->staff_notes;
key_table [n++].ptr = &ch->age;
key_table [n++].ptr = &ch->intoxication;
key_table [n++].ptr = &ch->hunger;
key_table [n++].ptr = &ch->thirst;
key_table [n++].ptr = &ch->idol;
key_table [n++].ptr = &ch->damage;
key_table [n++].ptr = &ch->lastregen;
key_table [n++].ptr = &ch->was_in_room;
key_table [n++].ptr = &ch->harness;
key_table [n++].ptr = &ch->max_harness;
key_table [n++].ptr = &ch->voice_str;
key_table [n++].ptr = NULL; /* Nanny State */
key_table [n++].ptr = NULL; /* Role Flag */
key_table [n++].ptr = NULL; /* Special Role (Summary)*/
key_table [n++].ptr = NULL; /* Role Body */
key_table [n++].ptr = NULL; /* Role Date */
key_table [n++].ptr = NULL; /* Role Poster */
key_table [n++].ptr = NULL; /* Role Cost */
key_table [n++].ptr = NULL; /* App Cost */
key_table [n++].ptr = NULL; /* Skill */
key_table [n++].ptr = NULL; /* Voice */
key_table [n++].ptr = NULL; /* Spell */
key_table [n++].ptr = NULL; /* Affect */
key_table [n++].ptr = NULL; /* AffectedBy */
key_table [n++].ptr = NULL; /* Subcraft */
key_table [n++].ptr = NULL; /* Wound */
key_table [n++].ptr = NULL; /* CHARM */
key_table [n++].ptr = NULL; /* Lodged */
key_table [n++].ptr = NULL; /* Alias */
key_table [n++].ptr = NULL; /* End */
GET_NAME (ch) = str_dup (name);
snprintf (buf, MAX_STRING_LENGTH, "save/player/%c/%s", tolower (*name), CAP (name));
if ( !(fp = fopen (buf, "r")) ) {
return NULL;
}
ch->pc->msg = NULL;
ch->pc->creation_comment = NULL;
ch->pc->email_address = NULL;
ch->pc->site_lie = NULL;
ch->deleted = 0;
ch->hour_affects = NULL;
ch->wounds = NULL;
ch->lodged = NULL;
ch->subdue = NULL;
ch->tmp_str = 0;
ch->tmp_intel = 0;
ch->tmp_dex = 0;
ch->tmp_wil = 0;
ch->tmp_con = 0;
ch->tmp_aur = 0;
ch->tmp_agi = 0;
ch->str = 0;
ch->intel = 0;
ch->dex = 0;
ch->wil = 0;
ch->con = 0;
ch->aur = 0;
ch->agi = 0;
ch->clans = str_dup ("");
for ( i = 0; i < MAX_SKILLS; i++ ) {
ch->pc->skills [i] = 0;
ch->skills [i] = 0;
}
for ( num_keys = 0; *key_table [num_keys].key; )
num_keys++;
for ( ; !feof (fp); ) {
if ( !(p = fread_word (fp)) ) {
fclose (fp);
free_char (ch);
return NULL;
}
if ( !str_cmp (p, "Defense") ) {
fread_number (fp);
continue;
}
for ( i = last_key;
i < last_key + num_keys &&
str_cmp (key_table [i % num_keys].key, p);)
i++;
i = i % num_keys;
if ( str_cmp (key_table [i].key, p) ) {
continue;
}
if ( key_table [i].key_type == TYPE_SKILL ||
key_table [i].key_type == TYPE_AFFECT ||
key_table [i].key_type == TYPE_WOUND ||
key_table [i].key_type == TYPE_SPELL ||
key_table [i].key_type == TYPE_LODGED ||
key_table [i].key_type == TYPE_VOICE ||
key_table [i].key_type == TYPE_HOODED ||
key_table [i].key_type == TYPE_NANNY ||
key_table [i].key_type == TYPE_ROLE ||
key_table [i].key_type == TYPE_ROLE_SUMMARY ||
key_table [i].key_type == TYPE_ROLE_BODY ||
key_table [i].key_type == TYPE_ROLE_DATE ||
key_table [i].key_type == TYPE_ROLE_POSTER ||
key_table [i].key_type == TYPE_ROLE_COST ||
key_table [i].key_type == TYPE_AFFECTEDBY ||
key_table [i].key_type == TYPE_APPCOST )
last_key = i;
else
last_key = i + 1;
if ( key_table [i].key_type == TYPE_INT )
* (int *) key_table [i].ptr = fread_number (fp);
else if ( key_table [i].key_type == TYPE_SHORTINT )
* (shortint *) key_table [i].ptr = fread_number (fp);
else if ( key_table [i].key_type == TYPE_STRING ){
temp_arg = fread_string (fp);
* (char **) key_table [i].ptr = unspace (temp_arg);
}
else if ( key_table [i].key_type == TYPE_LONG )
* (long *) key_table [i].ptr = fread_number (fp);
else if ( key_table [i].key_type == TYPE_OBSOLETE )
sn = fread_number (fp);
else if ( key_table [i].key_type == TYPE_ROLE_SUMMARY ) {
CREATE (ch->pc->special_role, ROLE_DATA, 1);
temp_arg = fread_string(fp);
ch->pc->special_role->summary = unspace(temp_arg);
}
else if ( key_table [i].key_type == TYPE_ROLE_BODY ) {
temp_arg = fread_string(fp);
ch->pc->special_role->body = unspace(temp_arg);
}
else if ( key_table [i].key_type == TYPE_ROLE_DATE ) {
temp_arg = fread_string(fp);
ch->pc->special_role->date = unspace(temp_arg);
}
else if ( key_table [i].key_type == TYPE_AFFECTEDBY ) {
ch->affected_by = fread_number(fp);
}
else if ( key_table [i].key_type == TYPE_ROLE_POSTER ) {
temp_arg = fread_string(fp);
ch->pc->special_role->poster = unspace(temp_arg);
}
else if ( key_table [i].key_type == TYPE_ROLE_COST ) {
ch->pc->special_role->cost = fread_number(fp);
}
else if ( key_table [i].key_type == TYPE_END ) {
ch->tmp_str = ch->str;
ch->tmp_dex = ch->dex;
ch->tmp_intel = ch->intel;
ch->tmp_wil = ch->wil;
ch->tmp_con = ch->con;
ch->tmp_aur = ch->aur;
ch->tmp_agi = ch->agi;
GET_MAX_MOVE (ch) = calc_lookup (ch, REG_MISC, MISC_MAX_MOVE);
REMOVE_BIT (ch->flags, FLAG_ENTERING);
REMOVE_BIT (ch->flags, FLAG_LEAVING);
ch->max_hit = 50 + GET_CON (ch) * CONSTITUTION_MULTIPLIER;
fclose (fp);
if ( ch->pc->boat_virtual ) {
for ( tch = character_list; tch; tch = tch->next ) {
if ( tch->deleted )
continue;
if ( IS_NPC (tch) &&
tch->mob->virtual == ch->pc->boat_virtual ) {
ch->vehicle = tch;
break;
}
}
if ( !ch->vehicle ) {
ch->pc->boat_virtual = 0;
ch->in_room = BOAT_ROOM;
}
}
if ( get_affect (ch, MAGIC_AFFECT_SLEEP) )
GET_POS (ch) = SLEEP;
if ( !ch->coldload_id )
ch->coldload_id = get_next_coldload_id (1);
fix_offense (ch);
p = ch->clans;
p2 = p;
ch->clans = str_dup ("");
while ( 1 ) {
p = one_argument (p, buf); /* flags */
p = one_argument (p, buf2); /* clan name */
if ( !*buf2 )
break;
add_clan_id (ch, buf2, buf);
}
mem_free (p2);
if ( clan1 ) {
snprintf (buf, MAX_STRING_LENGTH, "%d", clan1);
add_clan_id (ch, buf,
GET_FLAG (ch, FLAG_LEADER_1) ? "leader" : "member");
}
if ( clan2 ) {
snprintf (buf, MAX_STRING_LENGTH, "%d", clan2);
add_clan_id (ch, buf,
GET_FLAG (ch, FLAG_LEADER_2) ? "leader" : "member");
}
REMOVE_BIT (ch->flags, FLAG_LEADER_1);
REMOVE_BIT (ch->flags, FLAG_LEADER_2);
ch->time.logon = time (0);
return ch;
}
else if ( key_table [i].key_type == TYPE_NANNY )
ch->pc->nanny_state = fread_number(fp);
else if ( key_table [i].key_type == TYPE_APPCOST )
ch->pc->app_cost = fread_number(fp);
else if ( key_table [i].key_type == TYPE_ROLE )
ch->pc->role = fread_number(fp);
else if ( key_table [i].key_type == TYPE_SKILL ) {
p = fread_word (fp);
sn = skill_index_lookup (p);
if ( sn == -1 )
sn = skill_index_lookup (p);
else if ( sn > MAX_SKILLS )
printf ("Skill Num # %d (learned %d) out of range.\n",
sn, fread_number (fp));
else {
ch->skills [sn] = fread_number (fp);
ch->pc->skills [sn] = ch->skills [sn];
}
}
else if ( key_table [i].key_type == TYPE_AFFECT ) {
af = (AFFECTED_TYPE *)alloc (sizeof (AFFECTED_TYPE), 13);
fscanf (fp, "%d %d %d %d %d %d %d\n",
&af->type,
&af->a.spell.duration,
&af->a.spell.modifier,
&af->a.spell.location,
&af->a.spell.bitvector,
&af->a.spell.sn,
&af->a.spell.t);
af->next = NULL;
if ( af->a.spell.location <= APPLY_CON )
affect_to_char (ch, af);
else if ( af->a.spell.location >= FIRST_APPLY_SKILL &&
af->a.spell.location <= LAST_APPLY_SKILL )
affect_to_char (ch, af);
else {
af->next = ch->hour_affects;
ch->hour_affects = af;
}
}
else if ( key_table [i].key_type == TYPE_HOODED ) {
SET_BIT (ch->affected_by, AFF_HOODED);
}
else if ( key_table [i].key_type == TYPE_SUBCRAFT ) {
p = fread_word (fp);
for ( craft = crafts;
craft && str_cmp (craft->subcraft_name, p);
craft = craft->next )
;
if ( !craft ) {
continue;
}
for ( i = CRAFT_FIRST; i <= CRAFT_LAST; i++ )
if ( !get_affect (ch, i) )
break;
if ( i > CRAFT_LAST ) {
continue;
}
magic_add_affect (ch, i, -1, 0, 0, 0, 0);
af = get_affect (ch, i);
af->a.craft = (struct affect_craft_type *)alloc (sizeof (struct affect_craft_type), 23);
af->a.craft->subcraft = craft;
}
else if ( key_table [i].key_type == TYPE_VOICE ) {
temp_arg = fread_string(fp);
ch->voice_str = unspace(temp_arg);
}
else if ( key_table [i].key_type == TYPE_SPELL ) {
continue;
}
else if ( key_table [i].key_type == TYPE_CHARM ) {
ench = (CHARM_DATA *)alloc ((int)sizeof (CHARM_DATA), 36);
ench->next = NULL;
ench->name = fread_string(fp);
ench->original_hours = fread_number(fp);
ench->current_hours = fread_number(fp);
ench->power_source = fread_number(fp);
ench->caster_skill = fread_number(fp);
if ( !ch->charms )
ch->charms = ench;
else {
tmpench = ch->charms;
while ( tmpench->next )
tmpench = tmpench->next;
tmpench->next = ench;
}
}
else if ( key_table [i].key_type == TYPE_WOUND ) {
CREATE (wound, WOUND_DATA, 1);
wound->next = NULL;
temp_arg = fread_word(fp);
wound->location = add_hash(temp_arg);
temp_arg = fread_word(fp);
wound->type = add_hash(temp_arg);
temp_arg = fread_word(fp);
wound->severity = add_hash(temp_arg);
temp_arg = fread_word(fp);
wound->name = add_hash(temp_arg);
wound->damage = fread_number(fp);
wound->bleeding = fread_number(fp);
wound->poison = fread_number(fp);
wound->infection = fread_number(fp);
wound->healerskill = fread_number(fp);
wound->lasthealed = fread_number(fp);
wound->lastbled = fread_number(fp);
if ( !ch->wounds )
ch->wounds = wound;
else {
tmpwound = ch->wounds;
while ( tmpwound->next )
tmpwound = tmpwound->next;
tmpwound->next = wound;
}
}
else if ( key_table [i].key_type == TYPE_LODGED ) {
lodged = (LODGED_OBJECT_INFO *)alloc ((int)sizeof (LODGED_OBJECT_INFO), 36);
lodged->next = NULL;
temp_arg = fread_word(fp);
lodged->location = add_hash(temp_arg);
lodged->vnum = fread_number(fp);
if ( !ch->lodged )
ch->lodged = lodged;
else {
tmplodged = ch->lodged;
while ( tmplodged->next )
tmplodged = tmplodged->next;
tmplodged->next = lodged;
}
}
else if ( key_table [i].key_type == TYPE_DREAM ) {
CREATE (dream, DREAM_DATA, 1);
temp_arg = fread_string (fp);
dream->dream = unspace (temp_arg);
dream->next = NULL;
if ( * (DREAM_DATA **) key_table [i].ptr == NULL )
* (DREAM_DATA **) key_table [i].ptr = dream;
else {
dream_list = * (DREAM_DATA **) key_table [i].ptr;
while ( dream_list->next != NULL )
dream_list = dream_list->next;
dream_list->next = dream;
}
}
else if ( key_table [i].key_type == TYPE_ALIAS ) {
temp_arg = fread_word(fp);
strcpy (buf, temp_arg);
if ( !str_cmp (buf, current_alias_name) ) {
for ( alias = current_alias;
alias->next_line;
alias = alias->next_line )
;
alias->next_line = (ALIAS_DATA *)alloc ((int)sizeof (ALIAS_DATA), 28);
alias = alias->next_line;
}
else {
strcpy (current_alias_name, buf);
alias = (ALIAS_DATA *)alloc ((int)sizeof (ALIAS_DATA), 28);
alias->command = str_dup (current_alias_name);
if ( !ch->pc->aliases )
ch->pc->aliases = alias;
else
current_alias->next_alias = alias;
current_alias = alias;
}
p = strcpy (buf, fgets (buf, MAX_STRING_LENGTH, fp));
buf [strlen (buf) - 1] = '\0';
while ( *p == ' ' || *p == '\t' )
p++;
alias->line = str_dup (p);
}
}
fclose (fp);
free_char (ch);
return NULL;
}
int save_char (CHAR_DATA *ch, int save_objs)
{
if ( IS_NPC (ch) || IS_SET (ch->flags, FLAG_GUEST) || !ch->tname || !*ch->tname ) {
return 1;
}
save_char_mysql (ch);
if ( save_objs )
save_char_objs (ch, ch->tname);
if ( ch->room )
save_attached_mobiles (ch, 0);
return 0;
}
void load_online_stats (void)
{
FILE *fp = NULL;
if ( !(fp = fopen("online_stats", "r")) ) {
system_log("Error opening online_stats!", TRUE);
return;
}
fscanf (fp, "%d\n", &count_max_online);
max_online_date = fread_string(fp);
fclose (fp);
return;
}
void load_leantos (void)
{
FILE *fp = NULL;
OBJ_DATA *obj = NULL;
char buf [MAX_STRING_LENGTH] = {'\0'};
int toroom = 0;
int inroom = 0;
struct room_prog *t, *old, *tmp;
if ( !(fp = fopen("../regions/leantos", "r")) )
return;
while ( !feof (fp) ) {
fscanf (fp, "leanto from room %d to room %d\n", &inroom, &toroom);
obj = load_object(LEANTO_OBJ_VNUM);
obj_to_room (obj, inroom);
snprintf (buf, MAX_STRING_LENGTH, "vstr You enter the lean-to.\nostr %%n enters the lean-to.\natecho %d %%n enters the lean-to.\ntrans %d\natlook %d\n", toroom, toroom, toroom);
CREATE (t, struct room_prog,1);
t->next = NULL;
t->command = add_hash ("enter");
t->keys = add_hash ("lean-to leanto");
t->prog = add_hash (buf);
if ( !vtor (inroom)->prg) {
vtor (inroom)->prg = t;
} else {
old = vtor (inroom)->prg;
tmp = old;
while ( tmp ) {
old = tmp;
tmp = tmp->next;
}
old->next = t;
}
}
fclose(fp);
return;
}
void load_mobiles (void)
{
CHAR_DATA *mob = NULL;
WOUND_DATA *wound = NULL;
WOUND_DATA *tmpwound = NULL;
FILE *fp = NULL;
FILE *op = NULL;
char *key = NULL;
char name[MAX_STRING_LENGTH] = {'\0'};
char location[MAX_STRING_LENGTH] = {'\0'};
char severity[MAX_STRING_LENGTH] = {'\0'};
char type[MAX_STRING_LENGTH] = {'\0'};
char buf[MAX_STRING_LENGTH] = {'\0'};
char line[MAX_STRING_LENGTH] = {'\0'};
char *temp_arg = NULL;
char *temp_hold = NULL;
int i = 0;
int num = 0;
int to_room = 0;
int sn = 0;
for ( i = 0; i <= 99; i++ ) {
snprintf (buf, MAX_STRING_LENGTH, "save/mobiles/mobs.%d", i);
if ( !(fp = fopen(buf, "r+")) )
continue;
for ( ; !feof(fp) ; ) {
key = fread_word(fp);
if ( !str_cmp (key, "END") ) {
if ( mob ) {
SET_BIT (mob->act, ACT_STAYPUT);
char_to_room (mob, to_room);
if ( !mob->room ) {
extract_char (mob);
}
mob = NULL;
}
}
else if ( !str_cmp (key, "Keywords") ) {
temp_arg = fread_string(fp);
temp_hold = unspace(temp_arg);
mob->name = temp_hold;
}
else if ( !str_cmp (key, "Owner") ) {
temp_arg = fread_string(fp);
temp_hold = unspace(temp_arg);
mob->mob->owner = temp_hold;
}
else if ( !str_cmp (key, "SDesc") ) {
temp_arg = fread_string(fp);
temp_hold = unspace(temp_arg);
mob->short_descr = temp_hold;
}
else if ( !str_cmp (key, "Skill") ) {
key = fread_word(fp);
sn = skill_index_lookup (key);
if ( sn == -1 )
sn = skill_index_lookup (key);
if ( sn == -1 )
continue;
if ( sn > MAX_SKILLS )
continue;
else mob->skills [sn] = fread_number(fp);
}
else if ( !str_cmp (key, "LDesc") ) {
temp_arg = fread_string(fp);
temp_hold = unspace(temp_arg);
mob->long_descr = temp_hold;
}
else if ( !str_cmp (key, "DatabaseNumber") ) {
num = fread_number(fp);
mob = new_char (0);
mob = load_mobile (num);
}
else if ( !str_cmp (key, "ColdloadID") ) {
num = fread_number(fp);
mob->coldload_id = num;
}
else if ( !str_cmp (key, "CurrentRoom") ) {
num = fread_number(fp);
to_room = num;
}
else if ( !str_cmp (key, "SpawnLocation") ) {
num = fread_number(fp);
mob->mob->spawnpoint = num;
}
else if ( !str_cmp (key, "Wound") ) {
CREATE (wound, WOUND_DATA, 1);
wound->next = NULL;
temp_arg = fread_string(fp);
temp_hold = unspace(temp_arg);
sscanf (line, "Wound %s %s %s %s %d %d %d %d %d %d %d\n",
location, type, severity, name,
&wound->damage, &wound->bleeding, &wound->poison,
&wound->infection, &wound->healerskill, &wound->lasthealed,
&wound->lastbled);
wound->location = add_hash(temp_hold);
wound->type = add_hash(temp_hold);
wound->severity = add_hash(temp_hold);
wound->name = add_hash(temp_hold);
wound->damage = fread_number(fp);
wound->bleeding = fread_number(fp);
wound->poison = fread_number(fp);
wound->infection = fread_number(fp);
wound->healerskill = fread_number(fp);
wound->lasthealed = fread_number(fp);
wound->lastbled = fread_number(fp);
if ( !mob->wounds )
mob->wounds = wound;
else {
tmpwound = mob->wounds;
while ( tmpwound->next )
tmpwound = tmpwound->next;
tmpwound->next = wound;
}
}
else if ( !str_cmp (key, "HasInventory") ) {
op = NULL;
*buf = '\0';
snprintf (buf, MAX_STRING_LENGTH, "save/mobiles/inventory/%d", mob->coldload_id);
if ( !(op = fopen(buf, "r+")) )
continue;
read_obj_suppliment (mob, op);
fclose (op);
}
else if ( !str_cmp (key, "IsHooded") ) {
SET_BIT (mob->affected_by, AFF_HOODED);
}
else if ( !str_cmp (key, "ENDFILE") )
break;
else continue;
}
fclose (fp);
}
return;
}
void save_player_rooms (void)
{
FILE *fp = NULL;
ROOM_DATA *room = NULL;
char buf [MAX_STRING_LENGTH] = {'\0'};
for ( room = full_room_list; room; room = room->lnext ) {
if ( room->psave_loaded && room->contents ) {
snprintf (buf, MAX_STRING_LENGTH, "save/rooms/%d", room->virtual);
fp = fopen (buf, "w");
if ( !fp )
continue;
write_obj_data (room->contents, "ROOM", 0, 0, fp);
fprintf (fp, "DONE\n");
fclose (fp);
}
else if ( room->psave_loaded && !room->contents ) {
snprintf (buf, MAX_STRING_LENGTH, "save/rooms/%d", room->virtual);
unlink (buf);
}
}
return;
}
void do_saverooms (CHAR_DATA *ch, char *argument, int cmd)
{
save_player_rooms ();
send_to_char ("Ok.\n\r", ch);
return;
}
void load_save_rooms (void)
{
int room_num = 0;
int line_no = 1;
int rooms = 0;
int room_obj_count = 0;
OBJ_DATA *obj = NULL;
FILE *rp = NULL;
char buf [MAX_STRING_LENGTH] = {'\0'};
if ( !(rp = fopen ("save_rooms", "r")) ) {
perror ("save_rooms");
return;
}
file_eof_found = 0;
save_stop_obj_processing = 0;
last_wc = POSSESS_UNDEF;
while (1) {
if ( !fgets (buf, 81, rp) ) {
perror ("save_rooms");
fclose (rp);
return;
}
if ( !str_cmp (buf, "\n") )
continue;
line_no++;
if ( *buf == '#' ) {
rooms++;
sscanf (buf, "#%d", &room_num);
save_stop_obj_processing = 0;
read_obj_list (POSSESS_ROOM, 0, 0, NULL, NULL, rp, room_num);
if ( vtor (room_num) ) {
for ( room_obj_count = 0, obj = vtor (room_num)->contents;
obj;
obj = obj->next_content )
room_obj_count++;
}
}
else if ( !str_cmp (buf, "END\n") ) {
snprintf (buf, MAX_STRING_LENGTH, "Save rooms restored: %d", rooms);
break;
}
else
printf ("Unexpected line: %s\n", buf);
}
fclose (rp);
return;
}
void load_save_room (ROOM_DATA *room)
{
FILE *rp = NULL;
char buf [MAX_STRING_LENGTH] = {'\0'};
if ( !room || room->psave_loaded )
return;
room->psave_loaded = 1;
snprintf (buf, MAX_STRING_LENGTH, "save/rooms/%d", room->virtual);
if ( !(rp = fopen (buf, "r")) ) {
return;
}
file_eof_found = 0;
save_stop_obj_processing = 0;
last_wc = POSSESS_UNDEF;
read_obj_list (POSSESS_ROOM, 0, 0, NULL, NULL, rp, room->virtual);
fclose (rp);
return;
}
CHAR_DATA *load_saved_mobiles (CHAR_DATA *ch, char *name)
{
int virtual = 0;
CHAR_DATA *mob = NULL;
CHAR_DATA *last_mob = NULL;
CHAR_DATA *return_mob = NULL;
FILE *fp = NULL;
char buf [MAX_STRING_LENGTH] = {'\0'};
char hookup [MAX_STRING_LENGTH] = {'\0'};
if ( !(fp = fopen (name, "r")) ) {
return NULL;
}
last_mob = ch;
while ( fgets (buf, 256, fp) ) {
if ( *buf == ' ' || *buf == '\n' )
(void)fgets (buf, 255, fp);
if ( sscanf (buf, "%d %s", &virtual, hookup) != 2 ) {
fclose (fp);
return return_mob;
}
mob = load_a_saved_mobile (virtual, fp, TRUE);
if ( !return_mob )
return_mob = mob;
char_to_room (mob, mob->in_room);
if ( last_mob ){
if ( !str_cmp (hookup, "HITCH") ){
hitch_char (last_mob, mob);
}
else if ( !str_cmp (hookup, "RIDE") ) {
last_mob->mount = mob;
mob->mount = last_mob;
}
}
last_mob = mob;
}
fclose (fp);
return return_mob;
}
CHAR_DATA *load_a_saved_mobile (int virtual, FILE *fp, bool stable)
{
int i = 0; /* indices */
int n = 0;
int sn = 0;
int last_key = 0;
int num_keys = 0;
int stabled = 0;
int checks = 0;
struct time_info_data healing_time;
char *p = NULL; /* words */
char *p2 = NULL;
char buf [MAX_STRING_LENGTH] = {'\0'};
char buf2 [MAX_STRING_LENGTH] = {'\0'};
AFFECTED_TYPE *af = NULL;
CHAR_DATA *mob = NULL;
CHAR_DATA *tch = NULL;
WOUND_DATA *wound = NULL;
WOUND_DATA *tmpwound = NULL;
LODGED_OBJECT_INFO *lodged = NULL;
LODGED_OBJECT_INFO *tmplodged = NULL;
char *temp_arg = NULL;
struct key_data key_table [] = {
{ "Room", TYPE_INT, NULL },
{ "SDesc", TYPE_STRING, NULL },
{ "LDesc", TYPE_STRING, NULL },
{ "Keys", TYPE_STRING, NULL },
{ "FightMode", TYPE_INT, NULL },
{ "Clans", TYPE_STRING, NULL },
{ "ColdloadId", TYPE_INT, NULL },
{ "Flags", TYPE_INT, NULL },
{ "Moves", TYPE_INT, NULL },
{ "Hits", TYPE_INT, NULL },
{ "Speaks", TYPE_INT, NULL },
{ "AffectedBy", TYPE_INT, NULL },
{ "Position", TYPE_INT, NULL },
{ "Act", TYPE_INT, NULL },
{ "Cond0", TYPE_INT, NULL },
{ "Cond1", TYPE_INT, NULL },
{ "Cond2", TYPE_INT, NULL },
{ "Sex", TYPE_INT, NULL },
{ "Height", TYPE_INT, NULL },
{ "Frame", TYPE_INT, NULL },
{ "AccessFlags",TYPE_INT, NULL },
{ "SpawnLocation", TYPE_SPAWN, NULL },
{ "Rider", TYPE_MOUNT, NULL },
{ "Mount", TYPE_MOUNT, NULL },
{ "ResetCmd", TYPE_RESET, NULL },
{ "ResetZone", TYPE_RESETZ, NULL },
{ "Skill", TYPE_SKILL, NULL },
{ "Owner", TYPE_OWNER, NULL },
{ "Stabled", TYPE_STABLED, NULL },
{ "Affect", TYPE_AFFECT, NULL },
{ "Wound", TYPE_WOUND, NULL },
{ "Lodged", TYPE_LODGED, NULL },
{ "HasInventory", TYPE_HAS_INV, NULL },
{ "DONE", TYPE_DONE, NULL },
{ "End", TYPE_END, NULL },
{ "\0", TYPE_INT, NULL }
};
if ( !(mob = load_mobile (virtual)) ) {
return NULL;
}
key_table [n++].ptr = &mob->in_room;
key_table [n++].ptr = &mob->short_descr;
key_table [n++].ptr = &mob->long_descr;
key_table [n++].ptr = &mob->name;
key_table [n++].ptr = &mob->fight_mode;
key_table [n++].ptr = &mob->clans;
key_table [n++].ptr = &mob->coldload_id;
key_table [n++].ptr = &mob->flags;
key_table [n++].ptr = &mob->move;
key_table [n++].ptr = &mob->hit;
key_table [n++].ptr = &mob->speaks;
key_table [n++].ptr = &mob->affected_by;
key_table [n++].ptr = &mob->position;
key_table [n++].ptr = &mob->act;
key_table [n++].ptr = &mob->intoxication;
key_table [n++].ptr = &mob->hunger;
key_table [n++].ptr = &mob->thirst;
key_table [n++].ptr = &mob->sex;
key_table [n++].ptr = &mob->height;
key_table [n++].ptr = &mob->frame;
key_table [n++].ptr = &mob->mob->access_flags;
key_table [n++].ptr = NULL;
key_table [n++].ptr = NULL;
key_table [n++].ptr = NULL;
key_table [n++].ptr = NULL;
key_table [n++].ptr = NULL;
key_table [n++].ptr = NULL;
for ( num_keys = 0; *key_table [num_keys].key; )
num_keys++;
for ( ; !feof (fp);) {
if ( !(p = fread_word (fp)) ) {
free_char (mob);
return NULL;
}
for ( i = last_key;
i < last_key + num_keys &&
str_cmp (key_table [i % num_keys].key, p);)
i++;
i = i % num_keys;
if ( str_cmp (key_table [i].key, p) ) {
continue;
}
if ( key_table [i].key_type == TYPE_SKILL ||
key_table [i].key_type == TYPE_AFFECT ||
key_table [i].key_type == TYPE_WOUND ||
key_table [i].key_type == TYPE_LODGED ||
key_table [i].key_type == TYPE_OWNER ||
key_table [i].key_type == TYPE_STABLED ||
key_table [i].key_type == TYPE_HAS_INV ||
key_table [i].key_type == TYPE_SPAWN ||
key_table [i].key_type == TYPE_RESET ||
key_table [i].key_type == TYPE_RESETZ ||
key_table [i].key_type == TYPE_MOUNT )
last_key = i;
else
last_key = i + 1;
if ( key_table [i].key_type == TYPE_INT )
* (int *) key_table [i].ptr = fread_number (fp);
else if ( key_table [i].key_type == TYPE_SHORTINT )
* (shortint *) key_table [i].ptr = fread_number (fp);
else if ( key_table [i].key_type == TYPE_STRING ){
temp_arg = fread_string(fp);
* (char **) key_table [i].ptr = unspace (temp_arg);
}
else if ( key_table [i].key_type == TYPE_LONG )
* (long *) key_table [i].ptr = fread_number (fp);
else if ( key_table [i].key_type == TYPE_OBSOLETE )
sn = fread_number (fp);
else if ( key_table [i].key_type == TYPE_SPAWN )
mob->mob->spawnpoint = fread_number(fp);
else if ( key_table [i].key_type == TYPE_RESET )
mob->mob->reset_cmd = fread_number(fp);
else if ( key_table [i].key_type == TYPE_RESETZ )
mob->mob->reset_zone = fread_number(fp);
else if ( key_table [i].key_type == TYPE_STABLED ) {
stabled = fread_number(fp);
if ( !stable )
continue;
healing_time = real_time_passed (time(0) - stabled, 0);
checks = ( healing_time.day * 12 );
checks += ( healing_time.hour / 2 );
for ( wound = mob->wounds; wound; wound = tmpwound ) {
tmpwound = wound->next;
for ( i = 0; i < checks; i++ )
natural_healing_check(mob, wound);
}
}
else if ( key_table [i].key_type == TYPE_HAS_INV )
read_obj_suppliment (mob, fp);
else if ( key_table [i].key_type == TYPE_SKILL ) {
p = fread_word (fp);
sn = skill_index_lookup (p);
if ( sn == -1 )
sn = skill_index_lookup (p);
if ( sn == -1 ) {
return NULL;
}
if ( sn > MAX_SKILLS )
printf ("Skill Num # %d (learned %d) out of range.\n",
sn, fread_number (fp));
else
mob->skills [sn] = fread_number (fp);
}
else if ( key_table [i].key_type == TYPE_OWNER ) {
temp_arg = fread_string(fp);
mob->mob->owner = unspace(temp_arg);
}
else if ( key_table [i].key_type == TYPE_AFFECT ) {
af = (AFFECTED_TYPE *)alloc (sizeof (AFFECTED_TYPE), 13);
fscanf (fp, "%d %d %d %d %d %d %d\n",
&af->type,
&af->a.spell.duration,
&af->a.spell.modifier,
&af->a.spell.location,
&af->a.spell.bitvector,
&af->a.spell.sn,
&af->a.spell.t);
af->next = NULL;
affect_to_char (mob, af);
}
else if ( key_table [i].key_type == TYPE_MOUNT ) {
if ( !(tch = get_char_id (fread_number(fp))) )
continue;
if ( mob->mount || tch->mount )
continue;
tch->mount = mob;
mob->mount = tch;
}
else if ( key_table [i].key_type == TYPE_WOUND ) {
CREATE (wound, WOUND_DATA, 1);
wound->next = NULL;
temp_arg = fread_word(fp);
wound->location = add_hash(temp_arg);
temp_arg = fread_word(fp);
wound->type = add_hash(temp_arg);
temp_arg = fread_word(fp);
wound->severity = add_hash(temp_arg);
temp_arg = fread_word(fp);
wound->name = add_hash(temp_arg);
wound->damage = fread_number(fp);
wound->bleeding = fread_number(fp);
wound->poison = fread_number(fp);
wound->infection = fread_number(fp);
wound->healerskill = fread_number(fp);
wound->lasthealed = fread_number(fp);
wound->lastbled = fread_number(fp);
if ( !mob->wounds )
mob->wounds = wound;
else {
tmpwound = mob->wounds;
while ( tmpwound->next )
tmpwound = tmpwound->next;
tmpwound->next = wound;
}
}
else if ( key_table [i].key_type == TYPE_LODGED ) {
lodged = (LODGED_OBJECT_INFO *)alloc ((int)sizeof (LODGED_OBJECT_INFO), 36);
lodged->next = NULL;
temp_arg = fread_word(fp);
lodged->location = add_hash(temp_arg);
lodged->vnum = fread_number(fp);
if ( !mob->lodged )
mob->lodged = lodged;
else {
tmplodged = mob->lodged;
while ( tmplodged->next )
tmplodged = tmplodged->next;
tmplodged->next = lodged;
}
}
else if ( key_table [i].key_type == TYPE_DONE ) {
REMOVE_BIT (mob->flags, FLAG_ENTERING);
REMOVE_BIT (mob->flags, FLAG_LEAVING);
fix_offense (mob);
if ( get_affect (mob, MAGIC_AFFECT_SLEEP) )
GET_POS (mob) = SLEEP;
mob->time.logon = time (0);
return mob;
}
else if ( key_table [i].key_type == TYPE_END ) {
p = mob->clans;
p2 = p;
mob->clans = str_dup ("");
while ( 1 ) {
p = one_argument (p, buf); /* flags */
p = one_argument (p, buf2); /* clan name */
if ( !*buf2 )
break;
add_clan_id (mob, buf2, buf);
}
mem_free (p2);
return mob;
}
}
free_char (mob);
return NULL;
}
void save_mobile (CHAR_DATA *mob, FILE *fp, char *save_reason, int extract)
{
AFFECTED_TYPE *af = NULL;
int i = 0;
WOUND_DATA *wound = NULL;
LODGED_OBJECT_INFO *lodged = NULL;
if ( !IS_NPC (mob) )
return;
fprintf (fp, "%d %s\n", mob->mob->virtual, save_reason);
fprintf (fp, "Room %d\n", mob->in_room);
fprintf (fp, "SDesc %s~\n", mob->short_descr);
fprintf (fp, "LDesc %s~\n", mob->long_descr);
fprintf (fp, "Keys %s~\n", mob->name);
fprintf (fp, "Fightmode %d\n", mob->fight_mode);
fprintf (fp, "Clans %s~\n", mob->clans);
fprintf (fp, "ColdloadId %d\n", mob->coldload_id);
fprintf (fp, "Flags %d\n", mob->flags);
fprintf (fp, "Moves %d\n", mob->move);
fprintf (fp, "Hits %d\n", mob->hit);
fprintf (fp, "Speaks %d\n", mob->speaks);
fprintf (fp, "AffectedBy %ld\n", mob->affected_by);
fprintf (fp, "Position %d\n", mob->position);
fprintf (fp, "Act %ld\n", mob->act);
fprintf (fp, "Cond0 %d\n", mob->intoxication);
fprintf (fp, "Cond1 %d\n", mob->hunger);
fprintf (fp, "Cond2 %d\n", mob->thirst);
fprintf (fp, "Sex %d\n", mob->sex);
fprintf (fp, "Height %d\n", mob->height);
fprintf (fp, "Frame %d\n", mob->frame);
fprintf (fp, "AccessFlags %d\n", mob->mob->access_flags);
fprintf (fp, "SpawnLocation %d\n", mob->mob->spawnpoint);
fprintf (fp, "ResetCmd %d\n", mob->mob->reset_cmd);
fprintf (fp, "ResetZone %d\n", mob->mob->reset_zone);
if ( IS_RIDEE (mob) && IS_NPC (mob->mount) )
fprintf (fp, "Rider %d\n", mob->mount->coldload_id);
if ( IS_RIDER (mob) && IS_NPC (mob->mount) )
fprintf (fp, "Mount %d\n", mob->mount->coldload_id);
for ( i = 1; i <= LAST_SKILL; i++ ) {
if ( mob->skills [i] )
fprintf (fp, "Skill %s %d\n", skill_data[i].skill_name, mob->skills[i]);
}
if ( mob->mob->owner )
fprintf (fp, "Owner %s~\n", mob->mob->owner);
for ( af = mob->hour_affects; af; af = af->next )
if ( (af->type < MAGIC_CLAN_MEMBER_BASE ||
af->type > MAGIC_CLAN_OMNI_BASE + MAX_CLANS) &&
af->type != MAGIC_CLAN_NOTIFY &&
af->type != MAGIC_NOTIFY &&
af->type != MAGIC_WATCH1 &&
af->type != MAGIC_WATCH2 &&
af->type != MAGIC_WATCH3 &&
af->type != MAGIC_GUARD )
fprintf (fp, "Affect %d %d %d %d %d %d %d\n",
af->type,
af->a.spell.duration,
af->a.spell.modifier,
af->a.spell.location,
af->a.spell.bitvector,
af->a.spell.sn,
af->a.spell.t);
for ( wound = mob->wounds; wound; wound = wound->next ){
fprintf (fp, "Wound %s %s %s %s %d %d %d %d %d %d %d\n",
wound->location,
wound->type,
wound->severity,
wound->name,
wound->damage,
wound->bleeding,
wound->poison,
wound->infection,
wound->healerskill,
wound->lasthealed,
wound->lastbled);
}
for ( lodged = mob->lodged; lodged; lodged = lodged->next )
fprintf (fp, "Lodged %s %d\n", lodged->location, lodged->vnum);
if ( mob->equip || mob->right_hand || mob->left_hand ) {
fprintf (fp, "HasInventory\n");
write_obj_suppliment (mob, fp);
}
fprintf (fp, "Done\n");
if ( IS_HITCHER (mob) )
save_mobile (mob->hitchee, fp, "HITCH", extract);
else
fprintf (fp, "End\n");
if ( extract )
extract_char (mob);
return;
}
void save_attached_mobiles (CHAR_DATA *ch, int extract)
{
FILE *fp = NULL;
char save_name [MAX_STRING_LENGTH] = {'\0'};
snprintf (save_name, MAX_STRING_LENGTH, "save/player/%c/%s.a", tolower (*ch->tname), ch->tname);
if ( !(fp = fopen (save_name, "w")) ) {
return;
}
if ( !IS_HITCHER (ch) && !IS_RIDER (ch) )
fprintf (fp, "end\n");
if ( IS_HITCHER (ch) )
save_mobile (ch->hitchee, fp, "HITCH", extract);
if ( IS_RIDER (ch) )
save_mobile (ch->mount, fp, "RIDE", extract);
fclose (fp);
return;
}