Exemple #1
0
void SV_LoadGame_f (void) {
	char name[MAX_OSPATH], mapname[MAX_QPATH], str[32 * 1024], *start;
	FILE *f;
	float time, tfloat, spawn_parms[NUM_SPAWN_PARMS];
	edict_t *ent;
	int entnum, version, r;
	unsigned int i;

	if (Cmd_Argc() != 2) {
		Com_Printf ("Usage: %s <savename> : load a game\n", Cmd_Argv(0));
		return;
	}

	snprintf (name, sizeof (name), "%s/save/%s", com_gamedir, Cmd_Argv(1));
	COM_DefaultExtension (name, ".sav");

	Com_Printf ("Loading game from %s...\n", name);
	if (!(f = fopen (name, "rb"))) {
		Com_Printf ("ERROR: couldn't open.\n");
		return;
	}

	fscanf (f, "%i\n", &version);
	if (version != SAVEGAME_VERSION) {
		fclose (f);
		Com_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
		return;
	}

	fscanf (f, "%s\n", str);
	for (i = 0; i < NUM_SPAWN_PARMS; i++)
		fscanf (f, "%f\n", &spawn_parms[i]);

	// this silliness is so we can load 1.06 save files, which have float skill values
	fscanf (f, "%f\n", &tfloat);
	current_skill = (int)(tfloat + 0.1);
	Cvar_Set (&skill, va("%i", current_skill));

	Cvar_SetValue (&deathmatch, 0);
	Cvar_SetValue (&coop, 0);
	Cvar_SetValue (&teamplay, 0);
	Cvar_SetValue (&maxclients, 1);

	fscanf (f, "%s\n", mapname);
	fscanf (f, "%f\n", &time);

	Host_EndGame();

	CL_BeginLocalConnection ();

	SV_SpawnServer (mapname, false);

	if (sv.state != ss_active) {
		Com_Printf ("Couldn't load map\n");
		return;
	}
	Cvar_ForceSet (&sv_paused, "1"); // pause until all clients connect
	sv.loadgame = true;

	// load the light styles
	for (i = 0; i < MAX_LIGHTSTYLES; i++) {
		fscanf (f, "%s\n", str);
		sv.lightstyles[i] = (char *) Hunk_Alloc (strlen(str) + 1);
		strlcpy (sv.lightstyles[i], str, strlen(str) + 1);
	}

	// load the edicts out of the savegame file
	entnum = -1;		// -1 is the globals
	while (!feof(f)) {
		for (i = 0; i < sizeof(str) - 1; i++) {
			r = fgetc (f);
			if (r == EOF || !r)
				break;
			str[i] = r;
			if (r == '}') {
				i++;
				break;
			}
		}
		if (i == sizeof(str)-1)
			Host_Error ("Loadgame buffer overflow");
		str[i] = 0;
		start = str;
		start = COM_Parse(str);
		if (!com_token[0])
			break;		// end of file

		if (strcmp(com_token,"{"))
			Host_Error ("First token isn't a brace");

		if (entnum == -1) {	
			// parse the global vars
			ED_ParseGlobals (start);
		} else {	
			// parse an edict
			ent = EDICT_NUM(entnum);
			memset (&ent->v, 0, progs->entityfields * 4);
			ent->free = false;
			ED_ParseEdict (start, ent);
	
			// link it into the bsp tree
			if (!ent->free)
				SV_LinkEdict (ent, false);
		}
		entnum++;
	}

	sv.num_edicts = entnum;
	sv.time = time;

	fclose (f);

	for (i = 0; i < NUM_SPAWN_PARMS; i++)
		svs.clients->spawn_parms[i] = spawn_parms[i];
}
Exemple #2
0
/*
===============
Host_Loadgame_f
===============
*/
void Host_Loadgame_f (void)
{
	char	name[MAX_OSPATH];
	FILE	*f;
	char	mapname[MAX_QPATH];
	float	time, tfloat;
	char	str[32768];
	const char  *start;
	int	i, r;
	edict_t	*ent;
	int	entnum;
	int	version;
	float	spawn_parms[NUM_SPAWN_PARMS];

	if (cmd_source != src_command)
		return;

	if (Cmd_Argc() != 2)
	{
		Con_Printf ("load <savename> : load a game\n");
		return;
	}

	cls.demonum = -1;		// stop demo loop in case this fails

	q_snprintf (name, sizeof(name), "%s/%s", com_gamedir, Cmd_Argv(1));
	COM_AddExtension (name, ".sav", sizeof(name));

// we can't call SCR_BeginLoadingPlaque, because too much stack space has
// been used.  The menu calls it before stuffing loadgame command
//	SCR_BeginLoadingPlaque ();

	Con_Printf ("Loading game from %s...\n", name);
	f = fopen (name, "r");
	if (!f)
	{
		Con_Printf ("ERROR: couldn't open.\n");
		return;
	}

	fscanf (f, "%i\n", &version);
	if (version != SAVEGAME_VERSION)
	{
		fclose (f);
		Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
		return;
	}
	fscanf (f, "%s\n", str);
	for (i = 0; i < NUM_SPAWN_PARMS; i++)
		fscanf (f, "%f\n", &spawn_parms[i]);
// this silliness is so we can load 1.06 save files, which have float skill values
	fscanf (f, "%f\n", &tfloat);
	current_skill = (int)(tfloat + 0.1);
	Cvar_SetValue ("skill", (float)current_skill);

	fscanf (f, "%s\n",mapname);
	fscanf (f, "%f\n",&time);

	CL_Disconnect_f ();

	SV_SpawnServer (mapname);

	if (!sv.active)
	{
		fclose (f);
		Con_Printf ("Couldn't load map\n");
		return;
	}
	sv.paused = true;		// pause until all clients connect
	sv.loadgame = true;

// load the light styles

	for (i = 0; i < MAX_LIGHTSTYLES; i++)
	{
		fscanf (f, "%s\n", str);
		sv.lightstyles[i] = (const char *)Hunk_Strdup (str, "lightstyles");
	}

// load the edicts out of the savegame file
	entnum = -1;		// -1 is the globals
	while (!feof(f))
	{
		qboolean inside_string = false;
		for (i = 0; i < (int) sizeof(str) - 1; i++)
		{
			r = fgetc (f);
			if (r == EOF || !r)
				break;
			str[i] = r;
			if (r == '"')
			{
				inside_string = !inside_string;
			}
			else if (r == '}' && !inside_string) // only handle } characters outside of quoted strings
			{
				i++;
				break;
			}
		}
		if (i == (int) sizeof(str) - 1)
		{
			fclose (f);
			Sys_Error ("Loadgame buffer overflow");
		}
		str[i] = 0;
		start = str;
		start = COM_Parse(str);
		if (!com_token[0])
			break;		// end of file
		if (strcmp(com_token,"{"))
		{
			fclose (f);
			Sys_Error ("First token isn't a brace");
		}

		if (entnum == -1)
		{	// parse the global vars
			ED_ParseGlobals (start);
		}
		else
		{	// parse an edict

			ent = EDICT_NUM(entnum);
			memset (&ent->v, 0, progs->entityfields * 4);
			ent->free = false;
			ED_ParseEdict (start, ent);

		// link it into the bsp tree
			if (!ent->free)
				SV_LinkEdict (ent, false);
		}

		entnum++;
	}

	sv.num_edicts = entnum;
	sv.time = time;

	fclose (f);

	for (i = 0; i < NUM_SPAWN_PARMS; i++)
		svs.clients->spawn_parms[i] = spawn_parms[i];

	if (cls.state != ca_dedicated)
	{
		CL_EstablishConnection ("local");
		Host_Reconnect_f ();
	}
}
Exemple #3
0
/*
===============
Host_Loadgame_f
===============
*/
void Host_Loadgame_f (void)
{
	char	name[MAX_OSPATH], temp[MAX_OSPATH];
	vfsfile_t	*f;
	char	mapname[MAX_QPATH];
	float	time, tfloat;
	char	str[32768], *start, *c;
	int		i, r, len, n;
	edict_t	*ent;
	int		entnum;
	int		version;
	float			spawn_parms[NUM_SPAWN_PARMS];

	if (cmd_source != src_command)
		return;

	if (Cmd_Argc() != 2)
	{
		Con_Printf ("load <savename> : load a game\n");
		return;
	}

	cls.demonum = -1;		// stop demo loop in case this fails

//	sprintf (name, "%s", Cmd_Argv(1));
	strcpy (name, Cmd_Argv(1));
	COM_DefaultExtension (name, ".sav");
	
// we can't call SCR_BeginLoadingPlaque, because too much stack space has
// been used.  The menu calls it before stuffing loadgame command
//	SCR_BeginLoadingPlaque ();

	Con_Printf ("Loading game from %s...\n", name);
//	f = fopen (name, "r");
	f = FS_OpenVFS(name, "rb", FS_GAMEONLY);
	if (!f)
	{
		Con_Printf ("ERROR: couldn't open.\n");
		return;
	}

//	fscanf (f, "%i\n", &version);
	version = atoi(VFS_GETS(f, name, sizeof(name)));
	if (version != SAVEGAME_VERSION)
	{
//		fclose (f);
		Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
		VFS_CLOSE (f);
		return;
	}
//	fscanf (f, "%s\n", str);
	VFS_GETS(f, str, sizeof(str));
	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
		spawn_parms[i] = atof(VFS_GETS(f, temp, sizeof(temp)));
//		fscanf (f, "%f\n", &spawn_parms[i]);
// this silliness is so we can load 1.06 save files, which have float skill values
//	fscanf (f, "%f\n", &tfloat);
	tfloat = atof(VFS_GETS(f, temp, sizeof(temp))); // temp buf
	current_skill = (int)(tfloat + 0.1);
	Cvar_SetValue ("skill", (float)current_skill);

#ifdef QUAKE2
	Cvar_SetValue ("deathmatch", 0);
	Cvar_SetValue ("coop", 0);
	Cvar_SetValue ("teamplay", 0);
#endif

//	fscanf (f, "%s\n",mapname);
//	fscanf (f, "%f\n",&time);
	VFS_GETS(f, mapname, sizeof(mapname));
	for (c = mapname+strlen(mapname)-1; c>=mapname && (*c == '\n' || *c == '\r'); *c--='\0');
	time = atof(VFS_GETS(f, temp, sizeof(temp)));

	CL_Disconnect_f ();
	
	allowcheats = sv_cheats.value != 0; // sv_cheats

	// if the video isn't initialized already, it needs to be
	Host_InitVideo();

#ifdef QUAKE2
	SV_SpawnServer (mapname, NULL);
#else
	SV_SpawnServer (mapname);
#endif
	if (!sv.active)
	{
		Con_Printf ("Couldn't load map\n");
		VFS_CLOSE (f);
		return;
	}
	sv.paused = true;		// pause until all clients connect
	sv.loadgame = true;

// load the light styles

	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
	{
//		fscanf (f, "%s\n", str);
		VFS_GETS(f, str, sizeof(str));
//		sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1); // this is no longer necessary, changed to straight array
		for (c = str+strlen(str)-1; c>=str && (*c == '\n' || *c == '\r'); *c--='\0');
		strcpy (sv.lightstyles[i], str);
	}

// load the edicts out of the savegame file
	entnum = -1;		// -1 is the globals
	len = VFS_GETLEN(f);
	n = 0;
//	while (!feof(f))
	for(;;)
	{
		for (i=0 ; i<sizeof(str)-1 ; i++)
		{
//			r = fgetc (f);
			r = VFS_GETC(f);
			if (r == -1 || !r)
				break;
			str[i] = r;
			if (r == '}')
			{
				i++;
				break;
			}
		}
		if (r == -1 || !r)
			break;
		if (i == sizeof(str)-1)
			Sys_Error ("Loadgame buffer overflow");
		str[i] = 0;
		start = str;
		start = COM_Parse(str);
		if (!com_token[0])
			break;		// end of file
		if (strcmp(com_token,"{"))
			Sys_Error ("First token isn't a brace");
			
		if (entnum == -1)
		{	// parse the global vars
			ED_ParseGlobals (start);
		}
		else
		{	// parse an edict

			ent = EDICT_NUM(entnum);
			memset (&ent->v, 0, progs->entityfields * 4);
			ent->free = false;
			ED_ParseEdict (start, ent);
	
		// link it into the bsp tree
			if (!ent->free)
				SV_LinkEdict (ent, false);
		}

		entnum++;
		n++;
	}
	
	sv.num_edicts = entnum;
	sv.time = time;

//	fclose (f);
	VFS_CLOSE (f);

	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
		svs.clients->spawn_parms[i] = spawn_parms[i];

	if (cls.state != ca_dedicated)
	{
		CL_EstablishConnection ("local");
		Host_Reconnect_f ();
	}
}
/*
===============
Host_Loadgame_f
===============
*/
void Host_Loadgame_f (void)
{
    char	name[MAX_OSPATH];
    FILE	*f;
    char	mapname[MAX_QPATH];
    float	time, tfloat;
    char	str[32768], *start;
    int	i, r, line; // Current line # in savegame file
    edict_t	*ent;
    int	entnum, numedicts_save;
    int	version;
    float	spawn_parms[NUM_SPAWN_PARMS];
    qboolean Quote;

    if (cmd_source != src_command)
        return;

    if (Cmd_Argc() != 2)
    {
        Con_Printf ("load <savename> : load a game\n");
        return;
    }

    cls.demonum = -1;		// stop demo loop in case this fails

    sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));
    COM_DefaultExtension (name, ".sav");

// we can't call SCR_BeginLoadingPlaque, because too much stack space has
// been used.  The menu calls it before stuffing loadgame command
//	SCR_BeginLoadingPlaque ();

    Con_SafePrintf ("Loading game from %s...\n", name);
    f = fopen (name, "rb"); // Use binary mode to avoid EOF issues in savegame files
    if (!f)
    {
        Con_Printf ("ERROR: couldn't open.\n");
        return;
    }

    fscanf (f, "%i\n", &version);
    if (version != SAVEGAME_VERSION)
    {
        fclose (f);
        Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
        return;
    }

    // Kludge to read saved games with newlines in title
    do
        fscanf (f, "%s\n", str);
    while (!feof(f) && !strstr(str, "kills:"));

    for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
        fscanf (f, "%f\n", &spawn_parms[i]);
// this silliness is so we can load 1.06 save files, which have float skill values
    fscanf (f, "%f\n", &tfloat);
    current_skill = (int)(tfloat + 0.1);
    Cvar_SetValue ("skill", (float)current_skill);

    fscanf (f, "%s\n",mapname);
    fscanf (f, "%f\n",&time);

    CL_Disconnect_f ();

#ifdef QUAKE2
    SV_SpawnServer (mapname, NULL);
#else
    SV_SpawnServer (mapname);
#endif
    if (!sv.active)
    {
        Con_Printf ("Couldn't load map\n");
        return;
    }
    sv.paused = true;		// pause until all clients connect
    sv.loadgame = true;

// load the light styles

    for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
    {
        fscanf (f, "%s\n", str);
        sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
        strcpy (sv.lightstyles[i], str);
    }

// load the edicts out of the savegame file
    entnum = -1;		// -1 is the globals

    // Hack to avoid validation errors while parsing savegame file
    numedicts_save = sv.num_edicts;
    sv.num_edicts = MAX_EDICTS;

    line = 86; // 85 lines before globals in savegame
    while (!feof(f))
    {
        for (i=0, Quote = false ; i<sizeof(str)-1 ; i++)
        {
            r = fgetc (f);
            if (r == EOF || !r)
                break;

            if (r == '\n')
                ++line;

            str[i] = r;

            // Handle multiline quoted strings containing '}'
            if (!Quote)
            {
                if (r == '\"')
                    Quote = true;
                else if (r == '}')
                {
                    i++;
                    break;
                }
            }
            else if (Quote)
            {
                if (r == '\"')
                    Quote = false;
            }
        }
        if (i == sizeof(str)-1)
            Sys_Error ("Loadgame buffer overflow (%d, max = %d) on line %d", i + 1, sizeof(str) - 1, line);
        if (Quote)
            Sys_Error ("Host_Loadgame_f: %s in quoted string on line %d", r == EOF ? "EOF" : "EOS", line);
        str[i] = 0;
        start = str;
        start = COM_Parse(str);
        if (!com_token[0])
            break;		// end of file
        if (strcmp(com_token,"{"))
            Sys_Error ("First token (%s) isn't a brace on line %d", com_token, line);

        if (entnum == -1)
        {   // parse the global vars
            ED_ParseGlobals (start, line);
        }
        else
        {   // parse an edict

            ent = EDICT_NUM("Host_Loadgame_f1", entnum);

            if (!pr_free[entnum])
                ED_Free (ent); // Unlink from world

            memset (&ent->v, 0, progs->entityfields * 4);
            pr_free[entnum] = false;
            ED_ParseEdict (start, ent, line);

            // link it into the bsp tree
            if (!pr_free[entnum])
            {
                int	mindx = ent->v.modelindex;
                model_t *model = sv.models[mindx];
                char	*mname = pr_String ("Host_Loadgame_f1", ent->v.model);
                char	*cname = pr_String ("Host_Loadgame_f2", ent->v.classname);

                // Check for missing/invalid models (except e.g. player/eyes RoS switch)
                if (mindx != 0 && (model == NULL || *mname != 0 && strcmp(model->name, mname) && strcmp(cname, "player")))
                {
                    Con_Printf ("\x02Host_Loadgame_f: ");

                    if (model == NULL)
                        Con_Printf ("missing model");
                    else
                        Con_Printf ("invalid model (%s)", model->name);

                    Con_Printf (" for edict %d (%s)\n", entnum, ED_DbgEdict(&ent->v));
                }

                SV_LinkEdict (ent, false);
            }
        }

        entnum++;
    }

    sv.num_edicts = numedicts_save;

    // Free edicts not present in the savegame, might
    // otherwise cause odd SV_TouchLinks errors
    for (i = entnum; i < sv.num_edicts; ++i)
    {
        if (!pr_free[i])
        {
            ent = EDICT_NUM("Host_Loadgame_f2", i);

            // Don't warn if edict_reuse is disabled
            if (ent->area.prev && edict_reuse.value)
            {
                Con_Printf ("\002Host_Loadgame_f: ");
                Con_Printf ("invalid touched edict (%d, max = %d)\n", i, entnum);
            }

            ED_Free (ent); // Unlink from world
        }
    }

    sv.num_edicts = entnum; // Set new edict amount from savegame

    // Count active edicts
    for (i = sv.active_edicts = 0; i < sv.num_edicts; ++i)
    {
        if (!pr_free[i])
            ++sv.active_edicts;
    }

    ED_ChkEdict (true, false);

    sv.time = time;

    fclose (f);

    for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
        svs.clients->spawn_parms[i] = spawn_parms[i];

    // Chack for different saved game mode
    if (deathmatch.value != pr_global_struct->deathmatch ||
            coop.value != pr_global_struct->coop ||
            teamplay.value != pr_global_struct->teamplay)
    {
        Con_Printf ("\002Host_Loadgame_f: ");
        Con_Printf ("saved game mode different (dm=%g/%g, coop=%g/%g, team=%g/%g)\n",
                    deathmatch.value, pr_global_struct->deathmatch, coop.value, pr_global_struct->coop, teamplay.value, pr_global_struct->teamplay);
    }

    if (cls.state != ca_dedicated)
    {
        CL_EstablishConnection ("local");
        Host_Reconnect_f ();
    }
}
Exemple #5
0
static int LoadGamestate (const char *level, const char *startspot, int ClientsMode)
{
	FILE	*f;
	char		mapname[MAX_QPATH];
	float		playtime, sk;
	char		str[32768];
	const char	*start;
	int		i, r;
	edict_t		*ent;
	int		entnum;
	int		version;
//	float		spawn_parms[NUM_SPAWN_PARMS];
	qboolean	auto_correct = false;

	if (ClientsMode == 1)	/* for RestoreClients() only: map must be active */
	{
		if (!sv.active)
		{
			Con_Printf ("%s: server not active\n", __thisfunc__);
			return -1;
		}
		FS_MakePath_BUF (FS_USERDIR, &r, savename, sizeof(savename), "clients.gip");
		if (r)
		{
			Host_Error("%s: %d: string buffer overflow!", __thisfunc__, __LINE__);
			return -1;
		}
	}
	else
	{
		FS_MakePath_VABUF (FS_USERDIR, &r, savename, sizeof(savename), "%s.gip", level);
		if (r)
		{
			Host_Error("%s: %d: string buffer overflow!", __thisfunc__, __LINE__);
			return -1;
		}

		if (ClientsMode != 2 && ClientsMode != 3)
			Con_Printf ("Loading game from %s...\n", savename);
	}

	f = fopen (savename, "r");
	if (!f)
	{
		if (ClientsMode == 2)
			Con_Printf ("%s: ERROR: couldn't open savefile\n", __thisfunc__);

		return -1;
	}

	fscanf (f, "%i\n", &version);

	if (version != SAVEGAME_VERSION)
	{
		fclose (f);
		Con_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
		return -1;
	}

	if (ClientsMode != 1)
	{
		fscanf (f, "%s\n", str);
	//	for (i = 0; i < NUM_SPAWN_PARMS; i++)
	//		fscanf (f, "%f\n", &spawn_parms[i]);
		fscanf (f, "%f\n", &sk);
		Cvar_SetValue ("skill", sk);

		fscanf (f, "%s\n", mapname);
		fscanf (f, "%f\n", &playtime);

		SV_SpawnServer (mapname, startspot);
		if (!sv.active)
		{
			fclose (f);
			Con_Printf ("Couldn't load map\n");
			return -1;
		}

	// load the light styles
		for (i = 0; i < MAX_LIGHTSTYLES; i++)
		{
			fscanf (f, "%s\n", str);
			sv.lightstyles[i] = (const char *)Hunk_Strdup (str, "lightstyles");
		}
		SV_LoadEffects (f);
	}

// load the edicts out of the savegame file
	while (!feof(f))
	{
		fscanf (f, "%i\n", &entnum);
		for (i = 0; i < (int) sizeof(str) - 1; i++)
		{
			r = fgetc (f);
			if (r == EOF || !r)
				break;
			str[i] = r;
			if (r == '}')
			{
				i++;
				break;
			}
		}
		if (i == (int) sizeof(str) - 1)
		{
			fclose (f);
			Host_Error ("%s: Loadgame buffer overflow", __thisfunc__);
		}
		str[i] = 0;
		start = str;
		start = COM_Parse(str);
		if (!com_token[0])
			break;		// end of file
		if (strcmp(com_token,"{"))
		{
			fclose (f);
			Host_Error ("%s: First token isn't a brace", __thisfunc__);
		}

		// parse an edict
		if (entnum == -1)
		{
			ED_ParseGlobals (start);
			// Need to restore this
			*sv_globals.startspot = PR_SetEngineString(sv.startspot);
		}
		else
		{
			ent = EDICT_NUM(entnum);
			/* default to active edict: ED_ParseEdict() set it
			 * to free if it really is free.  cf. ED_Write()  */
			ent->free = false;
			/* ED_ParseEdict() will always memset ent->v to 0,
			 * because SaveGamestate() doesn't write entnum 0 */
			ED_ParseEdict (start, ent);

			if (ClientsMode == 1 || ClientsMode == 2 || ClientsMode == 3)
				ent->v.stats_restored = true;

			// link it into the bsp tree
			if (!ent->free)
			{
				if (entnum >= sv.num_edicts)
				{
				/* This is necessary to restore "generated" edicts which were
				 * not available during the map parsing by ED_LoadFromFile().
				 * This includes items dropped by monsters, items "dropped" by
				 * an item_spawner such as the "prizes" in the Temple of Mars
				 * (romeric5), a health sphere generated by the Crusader's
				 * Holy Strength ability, or a respawning-candidate killed
				 * monster in the expansion pack's nightmare mode. -- THOMAS */
				/* Moved this into the if (!ent->free) construct: less debug
				 * chatter.  Even if this skips a free edict in between, the
				 * skipped free edict wasn't parsed by ED_LoadFromFile() and
				 * it will remain as a freed edict. (There is no harm because
				 * we are dealing with extra edicts not originally present in
				 * the map.)  -- O.S. */
					Con_DPrintf("%s: entnum %d >= sv.num_edicts (%d)\n",
							__thisfunc__, entnum, sv.num_edicts);
					sv.num_edicts = entnum + 1;
				}

				SV_LinkEdict (ent, false);
				if (ent->v.modelindex && ent->v.model)
				{
					i = SV_ModelIndex(PR_GetString(ent->v.model));
					if (i != ent->v.modelindex)
					{
						ent->v.modelindex = i;
						auto_correct = true;
					}
				}
			}
		}
	}

	fclose (f);

	if (ClientsMode == 0)
	{
		sv.time = playtime;
		sv.paused = true;
		*sv_globals.serverflags = svs.serverflags;
		RestoreClients (0);
	}
	else if (ClientsMode == 2)
	{
		sv.time = playtime;
	}
	else if (ClientsMode == 3)
	{
		sv.time = playtime;
		*sv_globals.serverflags = svs.serverflags;
		RestoreClients (3);
	}

	if (ClientsMode != 1 && auto_correct)
	{
		Con_DPrintf("*** Auto-corrected model indexes!\n");
	}

//	for (i = 0; i < NUM_SPAWN_PARMS; i++)
//		svs.clients->spawn_parms[i] = spawn_parms[i];

	return 0;
}
Exemple #6
0
/*
===============
SV_LoadGame_f
===============
*/
void SV_LoadGame_f (void)
{
	char	name[MAX_OSPATH];
	FILE	*f;
	char	mapname[MAX_QPATH];
	float	time, tfloat;
	char	str[32768], *start;
	int		i, r;
	edict_t	*ent;
	int		entnum;
	int		version;
	float	spawn_parms[NUM_SPAWN_PARMS];
	qbool	save_disabled_for_loading;

	if (Cmd_Argc() != 2) {
		Com_Printf ("load <savename> : load a game\n");
		return;
	}

	sprintf (name, "%s/save/%s", com_gamedir, Cmd_Argv(1));
	COM_DefaultExtension (name, ".sav");
	
// we can't call SCR_BeginLoadingPlaque, because too much stack space has
// been used.  The menu calls it before stuffing loadgame command
//	SCR_BeginLoadingPlaque ();

	Com_Printf ("Loading game from %s...\n", name);
	f = fopen (name, "r");
	if (!f)
	{
		Com_Printf ("ERROR: couldn't open.\n");
		return;
	}

	fscanf (f, "%i\n", &version);
	if (version != SAVEGAME_VERSION)
	{
		fclose (f);
		Com_Printf ("Savegame is version %i, not %i\n", version, SAVEGAME_VERSION);
		return;
	}
	fscanf (f, "%s\n", str);
	for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
		fscanf (f, "%f\n", &spawn_parms[i]);
// this silliness is so we can load 1.06 save files, which have float skill values
	fscanf (f, "%f\n", &tfloat);
	current_skill = (int)(tfloat + 0.1);
	Cvar_Set (&skill, va("%i", current_skill));

	Cvar_SetValue (&deathmatch, 0);
	Cvar_SetValue (&coop, 0);
	Cvar_SetValue (&teamplay, 0);
	Cvar_SetValue (&maxclients, 1);

	fscanf (f, "%s\n",mapname);
	fscanf (f, "%f\n",&time);

	save_disabled_for_loading = scr_disabled_for_loading;

	Host_EndGame ();

	// Host_EndGame disables the loading plaque, restore it
	scr_disabled_for_loading = save_disabled_for_loading;

	CL_BeginLocalConnection ();

	SV_SpawnServer (mapname, false);
	if (sv.state != ss_active)
	{
		Com_Printf ("Couldn't load map\n");
		return;
	}
	Cvar_ForceSet (&sv_paused, "1");	// pause until all clients connect
	sv.loadgame = true;

// load the light styles

	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
	{
		fscanf (f, "%s\n", str);
		sv.lightstyles[i] = Hunk_Alloc (strlen(str)+1);
		strcpy (sv.lightstyles[i], str);
	}

// load the edicts out of the savegame file
	entnum = -1;		// -1 is the globals
	while (!feof(f))
	{
		for (i=0 ; i<sizeof(str)-1 ; i++)
		{
			r = fgetc (f);
			if (r == EOF || !r)
				break;
			str[i] = r;
			if (r == '}')
			{
				i++;
				break;
			}
		}
		if (i == sizeof(str)-1)
			Host_Error ("Loadgame buffer overflow");
		str[i] = 0;
		start = str;
		start = COM_Parse(str);
		if (!com_token[0])
			break;		// end of file
		if (strcmp(com_token,"{"))
			Host_Error ("First token isn't a brace");
			
		if (entnum == -1)
		{	// parse the global vars
			ED_ParseGlobals (start);
		}
		else
		{	// parse an edict
			ent = EDICT_NUM(entnum);
			memset (&ent->v, 0, progs->entityfields * 4);
			ent->inuse = true;
			ED_ParseEdict (start, ent);
	
			// link it into the bsp tree
			if (ent->inuse)
				SV_LinkEdict (ent, false);
		}

		entnum++;
	}
	
	sv.num_edicts = entnum;
	sv.time = time;

	fclose (f);

	// FIXME: this assumes the player is using client slot #0
	for (i = 0; i < NUM_SPAWN_PARMS; i++)
		svs.clients->spawn_parms[i] = spawn_parms[i];
}