753 lines · 17.2 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <stdio.h>#include "../dat.h"#include "../fns.h" #define Function(f) {#f, f} mmove_t mmove_reloc; field_t fields[] = {	{"classname", FOFS(classname), F_LSTRING},	{"model", FOFS(model), F_LSTRING},	{"spawnflags", FOFS(spawnflags), F_INT},	{"speed", FOFS(speed), F_FLOAT},	{"accel", FOFS(accel), F_FLOAT},	{"decel", FOFS(decel), F_FLOAT},	{"target", FOFS(target), F_LSTRING},	{"targetname", FOFS(targetname), F_LSTRING},	{"pathtarget", FOFS(pathtarget), F_LSTRING},	{"deathtarget", FOFS(deathtarget), F_LSTRING},	{"killtarget", FOFS(killtarget), F_LSTRING},	{"combattarget", FOFS(combattarget), F_LSTRING},	{"message", FOFS(message), F_LSTRING},	{"team", FOFS(team), F_LSTRING},	{"wait", FOFS(wait), F_FLOAT},	{"delay", FOFS(delay), F_FLOAT},	{"random", FOFS(random), F_FLOAT},	{"move_origin", FOFS(move_origin), F_VECTOR},	{"move_angles", FOFS(move_angles), F_VECTOR},	{"style", FOFS(style), F_INT},	{"count", FOFS(count), F_INT},	{"health", FOFS(health), F_INT},	{"sounds", FOFS(sounds), F_INT},	{"light", 0, F_IGNORE},	{"dmg", FOFS(dmg), F_INT},	{"mass", FOFS(mass), F_INT},	{"volume", FOFS(volume), F_FLOAT},	{"attenuation", FOFS(attenuation), F_FLOAT},	{"map", FOFS(map), F_LSTRING},	{"origin", FOFS(s.origin), F_VECTOR},	{"angles", FOFS(s.angles), F_VECTOR},	{"angle", FOFS(s.angles), F_ANGLEHACK}, 	{"goalentity", FOFS(goalentity), F_EDICT, FFL_NOSPAWN},	{"movetarget", FOFS(movetarget), F_EDICT, FFL_NOSPAWN},	{"enemy", FOFS(enemy), F_EDICT, FFL_NOSPAWN},	{"oldenemy", FOFS(oldenemy), F_EDICT, FFL_NOSPAWN},	{"activator", FOFS(activator), F_EDICT, FFL_NOSPAWN},	{"groundentity", FOFS(groundentity), F_EDICT, FFL_NOSPAWN},	{"teamchain", FOFS(teamchain), F_EDICT, FFL_NOSPAWN},	{"teammaster", FOFS(teammaster), F_EDICT, FFL_NOSPAWN},	{"owner", FOFS(owner), F_EDICT, FFL_NOSPAWN},	{"mynoise", FOFS(mynoise), F_EDICT, FFL_NOSPAWN},	{"mynoise2", FOFS(mynoise2), F_EDICT, FFL_NOSPAWN},	{"target_ent", FOFS(target_ent), F_EDICT, FFL_NOSPAWN},	{"chain", FOFS(chain), F_EDICT, FFL_NOSPAWN}, 	{"prethink", FOFS(prethink), F_FUNCTION, FFL_NOSPAWN},	{"think", FOFS(think), F_FUNCTION, FFL_NOSPAWN},	{"blocked", FOFS(blocked), F_FUNCTION, FFL_NOSPAWN},	{"touch", FOFS(touch), F_FUNCTION, FFL_NOSPAWN},	{"use", FOFS(use), F_FUNCTION, FFL_NOSPAWN},	{"pain", FOFS(pain), F_FUNCTION, FFL_NOSPAWN},	{"die", FOFS(die), F_FUNCTION, FFL_NOSPAWN}, 	{"stand", FOFS(monsterinfo.stand), F_FUNCTION, FFL_NOSPAWN},	{"idle", FOFS(monsterinfo.idle), F_FUNCTION, FFL_NOSPAWN},	{"search", FOFS(monsterinfo.search), F_FUNCTION, FFL_NOSPAWN},	{"walk", FOFS(monsterinfo.walk), F_FUNCTION, FFL_NOSPAWN},	{"run", FOFS(monsterinfo.run), F_FUNCTION, FFL_NOSPAWN},	{"dodge", FOFS(monsterinfo.dodge), F_FUNCTION, FFL_NOSPAWN},	{"attack", FOFS(monsterinfo.attack), F_FUNCTION, FFL_NOSPAWN},	{"melee", FOFS(monsterinfo.melee), F_FUNCTION, FFL_NOSPAWN},	{"sight", FOFS(monsterinfo.sight), F_FUNCTION, FFL_NOSPAWN},	{"checkattack", FOFS(monsterinfo.checkattack), F_FUNCTION, FFL_NOSPAWN},	{"currentmove", FOFS(monsterinfo.currentmove), F_MMOVE, FFL_NOSPAWN}, 	{"endfunc", FOFS(moveinfo.endfunc), F_FUNCTION, FFL_NOSPAWN}, 	// temp spawn vars -- only valid when the spawn function is called	{"lip", STOFS(lip), F_INT, FFL_SPAWNTEMP},	{"distance", STOFS(distance), F_INT, FFL_SPAWNTEMP},	{"height", STOFS(height), F_INT, FFL_SPAWNTEMP},	{"noise", STOFS(noise), F_LSTRING, FFL_SPAWNTEMP},	{"pausetime", STOFS(pausetime), F_FLOAT, FFL_SPAWNTEMP},	{"item", STOFS(item), F_LSTRING, FFL_SPAWNTEMP}, //need for item field in edict struct, FFL_SPAWNTEMP item will be skipped on saves	{"item", FOFS(item), F_ITEM}, 	{"gravity", STOFS(gravity), F_LSTRING, FFL_SPAWNTEMP},	{"sky", STOFS(sky), F_LSTRING, FFL_SPAWNTEMP},	{"skyrotate", STOFS(skyrotate), F_FLOAT, FFL_SPAWNTEMP},	{"skyaxis", STOFS(skyaxis), F_VECTOR, FFL_SPAWNTEMP},	{"minyaw", STOFS(minyaw), F_FLOAT, FFL_SPAWNTEMP},	{"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP},	{"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP},	{"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP},	{"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP}, 	{0, 0, 0, 0} }; field_t		levelfields[] ={	{"changemap", LLOFS(changemap), F_LSTRING},                   	{"sight_client", LLOFS(sight_client), F_EDICT},	{"sight_entity", LLOFS(sight_entity), F_EDICT},	{"sound_entity", LLOFS(sound_entity), F_EDICT},	{"sound2_entity", LLOFS(sound2_entity), F_EDICT}, 	{NULL, 0, F_INT}}; field_t		clientfields[] ={	{"pers.weapon", CLOFS(pers.weapon), F_ITEM},	{"pers.lastweapon", CLOFS(pers.lastweapon), F_ITEM},	{"newweapon", CLOFS(newweapon), F_ITEM}, 	{NULL, 0, F_INT}}; /*============InitGame This will be called when the dll is first loaded, whichonly happens when a new game is started or a save gameis loaded.============*/void InitGame (void){	gi.dprintf ("==== InitGame ====\n"); 	gun_x = gi.cvar ("gun_x", "0", 0);	gun_y = gi.cvar ("gun_y", "0", 0);	gun_z = gi.cvar ("gun_z", "0", 0); 	//FIXME: sv_ prefix is wrong for these	sv_rollspeed = gi.cvar ("sv_rollspeed", "200", 0);	sv_rollangle = gi.cvar ("sv_rollangle", "2", 0);	sv_maxvelocity = gi.cvar ("sv_maxvelocity", "2000", 0);	sv_gravity = gi.cvar ("sv_gravity", "800", 0); 	// noset vars	dedicated = gi.cvar ("dedicated", "0", CVAR_NOSET); 	// latched vars	sv_cheats = gi.cvar ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH);	gi.cvar ("gamename", GAMEVERSION , CVAR_SERVERINFO | CVAR_LATCH);	gi.cvar ("gamedate", "Nov 30 1997" , CVAR_SERVERINFO | CVAR_LATCH); 	maxclients = gi.cvar ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);	maxspectators = gi.cvar ("maxspectators", "4", CVAR_SERVERINFO);	deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH);	coop = gi.cvar ("coop", "0", CVAR_LATCH);	skill = gi.cvar ("skill", "1", CVAR_LATCH);	maxentities = gi.cvar ("maxentities", "1024", CVAR_LATCH); 	// change anytime vars	dmflags = gi.cvar ("dmflags", "0", CVAR_SERVERINFO);	fraglimit = gi.cvar ("fraglimit", "0", CVAR_SERVERINFO);	timelimit = gi.cvar ("timelimit", "0", CVAR_SERVERINFO);	password = gi.cvar ("password", "", CVAR_USERINFO);	spectator_password = gi.cvar ("spectator_password", "", CVAR_USERINFO);	filterban = gi.cvar ("filterban", "1", 0); 	g_select_empty = gi.cvar ("g_select_empty", "0", CVAR_ARCHIVE); 	run_pitch = gi.cvar ("run_pitch", "0.002", 0);	run_roll = gi.cvar ("run_roll", "0.005", 0);	bob_up  = gi.cvar ("bob_up", "0.005", 0);	bob_pitch = gi.cvar ("bob_pitch", "0.002", 0);	bob_roll = gi.cvar ("bob_roll", "0.002", 0); 	// flood control	flood_msgs = gi.cvar ("flood_msgs", "4", 0);	flood_persecond = gi.cvar ("flood_persecond", "4", 0);	flood_waitdelay = gi.cvar ("flood_waitdelay", "10", 0); 	// dm map list	sv_maplist = gi.cvar ("sv_maplist", "", 0); 	// items	InitItems (); 	Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), ""); 	Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), ""); 	// initialize all entities for this game	game.maxentities = maxentities->value;	g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);	globals.edicts = g_edicts;	globals.max_edicts = game.maxentities; 	// initialize all clients for this game	game.maxclients = maxclients->value;	game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);	globals.num_edicts = game.maxclients+1;} //========================================================= void WriteField1 (FILE *, field_t *field, byte *base){	void		*p;	int			len;	int			index; 	if (field->flags & FFL_SPAWNTEMP)		return; 	p = (void *)(base + field->ofs);	switch (field->type)	{	case F_INT:	case F_FLOAT:	case F_ANGLEHACK:	case F_VECTOR:	case F_IGNORE:		break; 	case F_LSTRING:	case F_GSTRING:		if ( *(char **)p )			len = strlen(*(char **)p) + 1;		else			len = 0;		*(int *)p = len;		break;	case F_EDICT:		if ( *(edict_t **)p == NULL)			index = -1;		else			index = *(edict_t **)p - g_edicts;		*(int *)p = index;		break;	case F_CLIENT:		if ( *(gclient_t **)p == NULL)			index = -1;		else			index = *(gclient_t **)p - game.clients;		*(int *)p = index;		break;	case F_ITEM:		if ( *(edict_t **)p == NULL)			index = -1;		else			index = *(gitem_t **)p - itemlist;		*(int *)p = index;		break; 	//relative to code segment	case F_FUNCTION:		if (*(byte **)p == NULL)			index = 0;		else			index = *(byte **)p - ((byte *)InitGame);		*(int *)p = index;		break; 	//relative to data segment	case F_MMOVE:		if (*(byte **)p == NULL)			index = 0;		else			index = *(byte **)p - (byte *)&mmove_reloc;		*(int *)p = index;		break; 	default:		gi.error ("WriteEdict: unknown field type");	}}  void WriteField2 (FILE *f, field_t *field, byte *base){	int			len;	void		*p; 	if (field->flags & FFL_SPAWNTEMP)		return; 	p = (void *)(base + field->ofs);	switch (field->type)	{	case F_LSTRING:		if ( *(char **)p )		{			len = strlen(*(char **)p) + 1;			fwrite (*(char **)p, len, 1, f);		}		break;	}} void ReadField (FILE *f, field_t *field, byte *base){	void		*p;	int			len;	int			index; 	if (field->flags & FFL_SPAWNTEMP)		return; 	p = (void *)(base + field->ofs);	switch (field->type)	{	case F_INT:	case F_FLOAT:	case F_ANGLEHACK:	case F_VECTOR:	case F_IGNORE:		break; 	case F_LSTRING:		len = *(int *)p;		if (!len)			*(char **)p = NULL;		else		{			*(char **)p = gi.TagMalloc (len, TAG_LEVEL);			fread (*(char **)p, len, 1, f);		}		break;	case F_EDICT:		index = *(int *)p;		if ( index == -1 )			*(edict_t **)p = NULL;		else			*(edict_t **)p = &g_edicts[index];		break;	case F_CLIENT:		index = *(int *)p;		if ( index == -1 )			*(gclient_t **)p = NULL;		else			*(gclient_t **)p = &game.clients[index];		break;	case F_ITEM:		index = *(int *)p;		if ( index == -1 )			*(gitem_t **)p = NULL;		else			*(gitem_t **)p = &itemlist[index];		break; 	//relative to code segment	case F_FUNCTION:		index = *(int *)p;		if ( index == 0 )			*(byte **)p = NULL;		else			*(byte **)p = ((byte *)InitGame) + index;		break; 	//relative to data segment	case F_MMOVE:		index = *(int *)p;		if (index == 0)			*(byte **)p = NULL;		else			*(byte **)p = (byte *)&mmove_reloc + index;		break; 	default:		gi.error ("ReadEdict: unknown field type");	}} //========================================================= /*==============WriteClient All pointer variables (except function pointers) must be handled specially.==============*/void WriteClient (FILE *f, gclient_t *client){	field_t		*field;	gclient_t	temp;		// all of the ints, floats, and vectors stay as they are	temp = *client; 	// change the pointers to lengths or indexes	for (field=clientfields ; field->name ; field++)	{		WriteField1 (f, field, (byte *)&temp);	} 	// write the block	fwrite (&temp, sizeof(temp), 1, f); 	// now write any allocated data following the edict	for (field=clientfields ; field->name ; field++)	{		WriteField2 (f, field, (byte *)client);	}} /*==============ReadClient All pointer variables (except function pointers) must be handled specially.==============*/void ReadClient (FILE *f, gclient_t *client){	field_t		*field; 	fread (client, sizeof(*client), 1, f); 	for (field=clientfields ; field->name ; field++)	{		ReadField (f, field, (byte *)client);	}} /*============WriteGame This will be called whenever the game goes to a new level,and when the user explicitly saves the game. Game information include cross level data, like multi leveltriggers, help computer info, and all client states. A single player death will automatically restore from thelast save position.============*/void WriteGame (char *filename, qboolean autosave){	FILE	*f;	int		i;	char	str[16]; 	if (!autosave)		SaveClientData (); 	f = fopen (filename, "wb");	if (!f)		gi.error ("Couldn't open %s", filename); 	memset (str, 0, sizeof(str));	strcpy (str, "Nov 30 1997");	fwrite (str, sizeof(str), 1, f); 	game.autosaved = autosave;	fwrite (&game, sizeof(game), 1, f);	game.autosaved = false; 	for (i=0 ; i<game.maxclients ; i++)		WriteClient (f, &game.clients[i]); 	fclose (f);} void ReadGame (char *filename){	FILE	*f;	int		i;	char	str[16]; 	gi.FreeTags (TAG_GAME); 	f = fopen (filename, "rb");	if (!f)		gi.error ("Couldn't open %s", filename); 	fread (str, sizeof(str), 1, f);	if (strcmp (str, "Nov 30 1997"))	{		fclose (f);		gi.error ("Savegame from an older version.\n");	} 	g_edicts =  gi.TagMalloc (game.maxentities * sizeof(g_edicts[0]), TAG_GAME);	globals.edicts = g_edicts; 	fread (&game, sizeof(game), 1, f);	game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);	for (i=0 ; i<game.maxclients ; i++)		ReadClient (f, &game.clients[i]); 	fclose (f);} 

Lines 1–500 of 753.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t