Пример #1
0
/*
==================
SV_StartParticle

Make sure the event gets sent to all clients
==================
*/
void SV_StartParticle(vec3_t org, vec3_t dir, int color, int count)
{
	int		i, v;

	if (sv.datagram.cursize > MAX_DATAGRAM-16)
	{
		return;
	}
	MSG_WriteByte(&sv.datagram, svc_particle);
	MSG_WriteCoord(&sv.datagram, org[0]);
	MSG_WriteCoord(&sv.datagram, org[1]);
	MSG_WriteCoord(&sv.datagram, org[2]);
	for (i=0 ; i<3 ; i++)
	{
		v = dir[i]*16;
		if (v > 127)
		{
			v = 127;
		}
		else if (v < -128)
		{
			v = -128;
		}
		MSG_WriteChar(&sv.datagram, v);
	}
	MSG_WriteByte(&sv.datagram, count);
	MSG_WriteByte(&sv.datagram, color);
}
Пример #2
0
void ClientReliableWrite_Coord(client_t *cl, float f)
{
	if (cl->num_backbuf) {
		MSG_WriteCoord(&cl->backbuf, f);
		ClientReliable_FinishWrite(cl);
	} else
		MSG_WriteCoord(&cl->netchan.message, f);
}
Пример #3
0
// 2000-05-02 NVS SVC by Maddes
void NVS_WriteCoord (int dest, float f, sizebuf_t *sb)
{
	int	i;

	switch (dest)
	{
	case MSG_INIT:
		if (sv.nvs_msgsignon->conversion_tab[sv.nvs_msgserver->numwrites-sv.nvs_msgwrites])
		{
			if (sb)				// special signon
			{
				MSG_WriteCoord(sb, f);
			}
			else
			{
				MSG_WriteCoord (&sv.signon, f);
			}
		}
		break;

	case MSG_ONE:
	case MSG_ALL:
	case MSG_BROADCAST:
		for (i=0 ; i<svs.maxclients ; i++)
		{
			if (NVS_CheckClient(&svs.clients[i]))
			{
				if (dest == MSG_BROADCAST)	// unreliable
				{
					MSG_WriteCoord (&svs.clients[i].datagram, f);
				}
				else if (dest == MSG_ONE && sb)	// special reliable MSG_ONE
				{
					MSG_WriteCoord (sb, f);
				}
				else				// reliable MSG_ONE, MSG_ALL
				{
					MSG_WriteCoord (&svs.clients[i].message, f);
				}
			}
		}
		break;

	default:
		Host_Error ("NVS_WriteCoord: bad destination");
		break;
	}

	NVS_CheckCounter();
}
Пример #4
0
void Game_AmbientSound(MathVectorf_t *vPosition,const char *cPath,int iVolume,int iAttenuation)
{
	char		**cCheck;
	int			i,iSoundNumber;
	bool		bLarge = false;

	for(iSoundNumber = 0,cCheck = sv.sound_precache; *cCheck; cCheck++,iSoundNumber++)
		if(!strcmp(*cCheck,cPath))
			break;

	if(!*cCheck)
		Console_ErrorMessage(false,(char*)cPath,"Sound was not registered.");

	if(iSoundNumber > 255)
		bLarge = true;

	if(bLarge)
		MSG_WriteByte(&sv.signon,svc_spawnstaticsound2);
	else
		MSG_WriteByte(&sv.signon,svc_spawnstaticsound);

	for(i = 0; i < 3; i++)
		MSG_WriteCoord(&sv.signon,vPosition[i]);

	if(bLarge)
		MSG_WriteShort(&sv.signon,iSoundNumber);
	else
		MSG_WriteByte(&sv.signon,iSoundNumber);

	MSG_WriteByte(&sv.signon,iVolume);
	MSG_WriteByte(&sv.signon,iAttenuation*64);
}
Пример #5
0
/*
================
SV_CreateBaseline

Entity baselines are used to compress the update messages
to the clients -- only the fields that differ from the
baseline will be transmitted
================
*/
void SV_CreateBaseline (void)
{
	int			i;
	edict_t			*svent;
	int				entnum;	
		
	for (entnum = 0; entnum < sv.num_edicts ; entnum++)
	{
		svent = EDICT_NUM(entnum);
		if (svent->free)
			continue;
		// create baselines for all player slots,
		// and any other edict that has a visible model
		if (entnum > MAX_CLIENTS && !svent->v.modelindex)
			continue;

		//
		// create entity baseline
		//
		VectorCopy (svent->v.origin, svent->baseline.origin);
		VectorCopy (svent->v.angles, svent->baseline.angles);
		svent->baseline.frame = svent->v.frame;
		svent->baseline.skinnum = svent->v.skin;
		if (entnum > 0 && entnum <= MAX_CLIENTS)
		{
			svent->baseline.colormap = entnum;
			svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl");
		}
		else
		{
			svent->baseline.colormap = 0;
			svent->baseline.modelindex =
				SV_ModelIndex(PR_GetString(svent->v.model));
		}

		CRITICAL_MESSAGE(sv_signon_lock, SV_SIGNON_LOCK, 0, {
			//
			// flush the signon message out to a seperate buffer if
			// nearly full
			//
			SV_FlushSignon ();

			//
			// add to the message
			//
			MSG_WriteByte (&sv.signon,svc_spawnbaseline);		
			MSG_WriteShort (&sv.signon,entnum);

			MSG_WriteByte (&sv.signon, svent->baseline.modelindex);
			MSG_WriteByte (&sv.signon, svent->baseline.frame);
			MSG_WriteByte (&sv.signon, svent->baseline.colormap);
			MSG_WriteByte (&sv.signon, svent->baseline.skinnum);
			for (i=0 ; i<3 ; i++)
			{
				MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]);
				MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]);
			}
		});
Пример #6
0
void Cam_Pos_Set(float x, float y, float z)
{
	extern qbool clpred_newpos;

	cl.simorg[0] = x;
	cl.simorg[1] = y;
	cl.simorg[2] = z;
	clpred_newpos = true;
	
	VectorCopy (cl.simorg, cl.frames[cl.validsequence & UPDATE_MASK].playerstate[cl.playernum].origin);
	
	if (cls.state >= ca_active && !cls.demoplayback) {
		MSG_WriteByte (&cls.netchan.message, clc_tmove);
		MSG_WriteCoord (&cls.netchan.message, cl.simorg[0]);
		MSG_WriteCoord (&cls.netchan.message, cl.simorg[1]);
		MSG_WriteCoord (&cls.netchan.message, cl.simorg[2]);
	}
}
Пример #7
0
/*  
==================
SV_StartSound

Each entity can have eight independant sound sources, like voice,
weapon, feet, etc.

Channel 0 is an auto-allocate channel, the others override anything
allready running on that entity/channel pair.

An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off.  (max 4 attenuation)

==================
*/  
void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
    float attenuation)
{       
    int         sound_num;
    int field_mask;
    int			i;
	int			ent;
	
	if (volume < 0 || volume > 255)
		Sys_Error ("SV_StartSound: volume = %i", volume);

	if (attenuation < 0 || attenuation > 4)
		Sys_Error ("SV_StartSound: attenuation = %f", attenuation);

	if (channel < 0 || channel > 7)
		Sys_Error ("SV_StartSound: channel = %i", channel);

	if (sv.datagram.cursize > MAX_DATAGRAM-16)
		return;	

// find precache number for sound
    for (sound_num=1 ; sound_num<MAX_SOUNDS
        && sv.sound_precache[sound_num] ; sound_num++)
        if (!strcmp(sample, sv.sound_precache[sound_num]))
            break;
    
    if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
    {
        Con_Printf ("SV_StartSound: %s not precacheed\n", sample);
        return;
    }
    
	ent = NUM_FOR_EDICT(entity);

	channel = (ent<<3) | channel;

	field_mask = 0;
	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
		field_mask |= SND_VOLUME;
	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
		field_mask |= SND_ATTENUATION;

// directed messages go only to the entity the are targeted on
	MSG_WriteByte (&sv.datagram, svc_sound);
	MSG_WriteByte (&sv.datagram, field_mask);
	if (field_mask & SND_VOLUME)
		MSG_WriteByte (&sv.datagram, volume);
	if (field_mask & SND_ATTENUATION)
		MSG_WriteByte (&sv.datagram, attenuation*64);
	MSG_WriteShort (&sv.datagram, channel);
	MSG_WriteByte (&sv.datagram, sound_num);
	for (i=0 ; i<3 ; i++)
		MSG_WriteCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
}           
Пример #8
0
static void Cam_Pos_f (void)
{
	extern qbool clpred_newpos;

	if (Cmd_Argc() == 1)
	{
		Com_Printf ("\"%s %s %s\"\n", myftos(cl.simorg[0]), myftos(cl.simorg[1]), myftos(cl.simorg[2]));
		return;
	}

	if (Cmd_Argc() == 2) {
		// cam_pos "x y z"  -->  cam_pos x y z
		Cmd_TokenizeString (va("cam_pos %s", Cmd_Argv(1)));
	}

	if (Cmd_Argc() != 4) {
		Com_Printf("usage:\n"
			"cam_pos - show current coordinates\n"
			"cam pos x y z - set new coordinates\n");
		return;
	}

	if (!cls.demoplayback && !cl.spectator)
		return;
		
	cl.simorg[0] = Q_atof(Cmd_Argv(1));
	cl.simorg[1] = Q_atof(Cmd_Argv(2));
	cl.simorg[2] = Q_atof(Cmd_Argv(3));
	clpred_newpos = true;
	
	VectorCopy (cl.simorg, cl.frames[cl.validsequence & UPDATE_MASK].playerstate[cl.playernum].origin);
	
	if (cls.state >= ca_active && !cls.demoplayback) {
		MSG_WriteByte (&cls.netchan.message, clc_tmove);
		MSG_WriteCoord (&cls.netchan.message, cl.simorg[0]);
		MSG_WriteCoord (&cls.netchan.message, cl.simorg[1]);
		MSG_WriteCoord (&cls.netchan.message, cl.simorg[2]);
	}
}
Пример #9
0
void Server_MakeStatic(ServerEntity_t *ent)
{
	int	i,bits=0;

	if(ent->alpha == ENTALPHA_ZERO)
	{
		ED_Free(ent);
		return;
	}

	if(SV_ModelIndex(ent->v.model) & 0xFF00)
		bits |= B_LARGEMODEL;
	if((int)(ent->v.frame) & 0xFF00)
		bits |= B_LARGEFRAME;
	if(ent->alpha != ENTALPHA_DEFAULT)
		bits |= B_ALPHA;

	if(bits)
	{
		MSG_WriteByte(&sv.signon, SVC_SPAWNSTATIC2);
		MSG_WriteByte(&sv.signon, bits);
	}
	else
		MSG_WriteByte(&sv.signon, svc_spawnstatic);

	if(bits & B_LARGEMODEL)
		MSG_WriteShort(&sv.signon, SV_ModelIndex(ent->v.model));
	else
		MSG_WriteByte(&sv.signon, SV_ModelIndex(ent->v.model));

	if(bits & B_LARGEFRAME)
		MSG_WriteShort(&sv.signon,ent->v.frame);
	else
		MSG_WriteByte(&sv.signon,ent->v.frame);

	MSG_WriteByte(&sv.signon,ent->Model.fScale);
	MSG_WriteByte(&sv.signon,ent->v.colormap);
	MSG_WriteByte(&sv.signon,ent->Model.iSkin);
	for (i=0 ; i<3 ; i++)
	{
		MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
		MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
	}

	if (bits & B_ALPHA)
		MSG_WriteByte (&sv.signon, ent->alpha);

	ED_Free (ent);
}
Пример #10
0
/*  
==================
SV_StartParticle

Make sure the event gets sent to all clients
==================
*/
void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count)
{
	int		i, v;

// drop silently if there is no room 
	if (sv.datagram.cursize > ((sv.protocol == PROTOCOL_NETQUAKE) ? 1024 : MAX_DATAGRAM) - 16)
		return;

	MSG_WriteByte (&sv.datagram, svc_particle);
	MSG_WriteCoord (&sv.datagram, org[0], sv.protocolflags);
	MSG_WriteCoord (&sv.datagram, org[1], sv.protocolflags);
	MSG_WriteCoord (&sv.datagram, org[2], sv.protocolflags);
	for (i=0 ; i<3 ; i++)
	{
		v = dir[i]*16;
		if (v > 127)
			v = 127;
		else if (v < -128)
			v = -128;
		MSG_WriteChar (&sv.datagram, v);
	}
	MSG_WriteByte (&sv.datagram, count);
	MSG_WriteByte (&sv.datagram, color);
}           
Пример #11
0
/*
================
SV_CreateBaseline

Entity baselines are used to compress the update messages
to the clients -- only the fields that differ from the
baseline will be transmitted
================
*/
void SV_CreateBaseline (void)
{
	int i, entnum, max_edicts;	
	edict_t *svent;

	// because baselines for entnum >= 512 don't make sense
	// FIXME, translate baselines nums as well as packet entity nums?
	max_edicts = min (sv.num_edicts, 512);

	for (entnum = 0; entnum < max_edicts ; entnum++) {
		svent = EDICT_NUM(entnum);
		if (svent->free)
			continue;
		// create baselines for all player slots, and any other edict that has a visible model
		if (entnum > MAX_CLIENTS && !svent->v.modelindex)
			continue;

		// create entity baseline
		VectorCopy (svent->v.origin, svent->baseline.origin);
		VectorCopy (svent->v.angles, svent->baseline.angles);
		svent->baseline.frame = svent->v.frame;
		svent->baseline.skinnum = svent->v.skin;
		if (entnum > 0 && entnum <= MAX_CLIENTS) {
			svent->baseline.colormap = entnum;
			svent->baseline.modelindex = SV_ModelIndex("progs/player.mdl");
		} else {
			svent->baseline.colormap = 0;
			svent->baseline.modelindex = SV_ModelIndex(PR_GetString(svent->v.model));
		}

		// flush the signon message out to a separate buffer if
		// nearly full
		SV_FlushSignon ();

		// add to the message
		MSG_WriteByte (&sv.signon,svc_spawnbaseline);		
		MSG_WriteShort (&sv.signon,entnum);

		MSG_WriteByte (&sv.signon, svent->baseline.modelindex);
		MSG_WriteByte (&sv.signon, svent->baseline.frame);
		MSG_WriteByte (&sv.signon, svent->baseline.colormap);
		MSG_WriteByte (&sv.signon, svent->baseline.skinnum);
		for (i = 0; i < 3; i++) {
			MSG_WriteCoord(&sv.signon, svent->baseline.origin[i]);
			MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]);
		}
	}
}
Пример #12
0
void Particle(MathVector3f_t org, MathVector3f_t dir,float scale,char *texture,int count)
{
	int	i,v;

	if(sv.datagram.cursize > MAX_DATAGRAM-16)
		return;

	MSG_WriteByte(&sv.datagram,SVC_PARTICLE);

	for(i = 0; i < 3; i++)
		MSG_WriteCoord(&sv.datagram,org[i]);

	for(i=0 ; i<3 ; i++)
	{
		v = dir[i]*16;
		if (v > 127)
			v = 127;
		else if (v < -128)
			v = -128;

		MSG_WriteChar(&sv.datagram,v);
	}

	MSG_WriteFloat(&sv.datagram,scale);

	for(i = 0; i < MAX_EFFECTS; i++)
		if(gEffectTexture[i])
		{
			if(!strcmp(texture,gEffectTexture[i]->name))
			{
				MSG_WriteByte(&sv.datagram,i);
				break;
			}
		}
		else
		{
			// Otherwise give the texture the initial slot (this points to the notexture).
			MSG_WriteByte(&sv.datagram,0);
			break;
		}

	MSG_WriteByte(&sv.datagram,count);
}
Пример #13
0
void SV_ParseMultiEffect (sizebuf_t *sb)
{
	int	idx, count;
	byte	effect;
	vec3_t	orig, vel;

	MultiEffectIdCount = 0;
	effect = G_FLOAT(OFS_PARM0);
	switch (effect)
	{
	case CE_HWRAVENPOWER:
		// need to set aside 3 effect ids
		MSG_WriteByte (sb, svc_multieffect);
		MSG_WriteByte (sb, effect);

		VectorCopy(G_VECTOR(OFS_PARM1), orig);
		MSG_WriteCoord(sb, orig[0]);
		MSG_WriteCoord(sb, orig[1]);
		MSG_WriteCoord(sb, orig[2]);
		VectorCopy(G_VECTOR(OFS_PARM2), vel);
		MSG_WriteCoord(sb, vel[0]);
		MSG_WriteCoord(sb, vel[1]);
		MSG_WriteCoord(sb, vel[2]);
		for (count = 0 ; count < 3 ; count++)
		{
			for (idx = 0 ; idx < MAX_EFFECTS ; idx++)
			{
				if (!sv.Effects[idx].type || 
						(sv.Effects[idx].expire_time && sv.Effects[idx].expire_time <= sv.time))
					break;
			}
			if (idx >= MAX_EFFECTS)
			{
				PR_RunError ("MAX_EFFECTS reached");
				return;
			}
			MSG_WriteByte(sb, idx);
			sv.Effects[idx].type = CE_HWRAVENPOWER;
			VectorCopy(orig, sv.Effects[idx].ef.Missile.origin);
			VectorCopy(vel, sv.Effects[idx].ef.Missile.velocity);
			sv.Effects[idx].expire_time = sv.time + 10;
			MultiEffectIds[count] = idx;
		}
		break;

	default:
		PR_RunError ("%s: bad type", __thisfunc__);
	}
}
Пример #14
0
static void VM_M_WriteCoord (prvm_prog_t *prog)
{
	VM_SAFEPARMCOUNT(1, VM_M_WriteCoord);
	MSG_WriteCoord (VM_M_WriteDest(prog), PRVM_G_FLOAT(OFS_PARM0), sv.protocol);
}
Пример #15
0
// Take over the user controls and track a player.
// We find a nice position to watch the player and move there
void Cam_Track(usercmd_t *cmd) 
{
	player_state_t *player, *self;
	frame_t *frame;
	vec3_t vec;

	if (!cl.spectator)
	{
		return;
	}

	// hack: save +movedown command
	cmddown = cmd->upmove < 0;

	// cl_hightrack 
	if (cl_hightrack.value && !locked)
	{
		Cam_CheckHighTarget(); 
	}
	
	if (!autocam || cls.state != ca_active)
	{
		return;
	}

	if (locked && (!cl.players[spec_track].name[0] || cl.players[spec_track].spectator)) 
	{
		locked = false;

		// cl_hightrack 
		if (cl_hightrack.value)
		{
			Cam_CheckHighTarget();
		}
		else 
		{
			Cam_Unlock();
		}
		return;
	}

	frame = &cl.frames[cl.validsequence & UPDATE_MASK];

	if (autocam && cls.mvdplayback)	
	{
		if (ideal_track != spec_track && cls.realtime - last_lock > 0.1 && 
			frame->playerstate[ideal_track].messagenum == cl.parsecount)
		{
			Cam_Lock(ideal_track);
		}

		if (frame->playerstate[spec_track].messagenum != cl.parsecount)	
		{
			int i;

			for (i = 0; i < MAX_CLIENTS; i++) 
			{
				if (frame->playerstate[i].messagenum == cl.parsecount)
					break;
			}

			if (i < MAX_CLIENTS)
			{
				Cam_Lock(i);
			}
		}
	}

	player = frame->playerstate + spec_track;
	self = frame->playerstate + cl.playernum;

	if (!locked || !Cam_IsVisible(player, desired_position))
	{
		if (!locked || cls.realtime - cam_lastviewtime > 0.1) 
		{
			if (!InitFlyby(self, player, true))
				InitFlyby(self, player, false);
			cam_lastviewtime = cls.realtime;
		}
	} 
	else 
	{
		cam_lastviewtime = cls.realtime;
	}
	
	// couldn't track for some reason
	if (!locked || !autocam)
		return;

	if (cl_chasecam.value) 
	{
		cmd->forwardmove = cmd->sidemove = cmd->upmove = 0;

		#ifdef JSS_CAM
		if (!Cvar_Value ("cam_thirdperson"))
		#endif
		{
			VectorCopy(player->viewangles, cl.viewangles);
		}
		VectorCopy(player->origin, desired_position);
		if (memcmp(&desired_position, &self->origin, sizeof(desired_position)) != 0) {
			MSG_WriteByte (&cls.netchan.message, clc_tmove);
			MSG_WriteCoord (&cls.netchan.message, desired_position[0]);
			MSG_WriteCoord (&cls.netchan.message, desired_position[1]);
			MSG_WriteCoord (&cls.netchan.message, desired_position[2]);
			// move there locally immediately
			VectorCopy(desired_position, self->origin);
		}
	} 
	else 
	{
		// Ok, move to our desired position and set our angles to view
		// the player
		VectorSubtract(desired_position, self->origin, vec);
		cmd->forwardmove = cmd->sidemove = cmd->upmove = 0;
		if (VectorLength(vec) > 16) 
		{ 
			// close enough?
			MSG_WriteByte (&cls.netchan.message, clc_tmove);
			MSG_WriteCoord (&cls.netchan.message, desired_position[0]);
			MSG_WriteCoord (&cls.netchan.message, desired_position[1]);
			MSG_WriteCoord (&cls.netchan.message, desired_position[2]);
		}

		// move there locally immediately
		VectorCopy(desired_position, self->origin);
										 
		VectorSubtract(player->origin, desired_position, vec);
		vectoangles(vec, cl.viewangles);
		cl.viewangles[0] = -cl.viewangles[0];
	}
}
Пример #16
0
// ZOID
//
// Take over the user controls and track a player.
// We find a nice position to watch the player and move there
void Cam_Track(usercmd_t *cmd)
{
	player_state_t *player, *self;
	frame_t *frame;
	vec3_t vec;
	float len;

	if (!cl.spectator)
		return;
	
	if (cl_hightrack.value && !locked)
		Cam_CheckHighTarget();

	if (!autocam || cls.state != ca_active)
		return;

	if (locked && (!cl.players[spec_track].name[0] || cl.players[spec_track].spectator)) {
		locked = false;
		if (cl_hightrack.value)
			Cam_CheckHighTarget();
		else
			Cam_Unlock();
		return;
	}

	frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
	player = frame->playerstate + spec_track;
	self = frame->playerstate + cl.playernum;

	if (!locked || !Cam_IsVisible(player, desired_position)) {
		if (!locked || realtime - cam_lastviewtime > 0.1) {
			if (!InitFlyby(self, player, true))
				InitFlyby(self, player, false);
			cam_lastviewtime = realtime;
		}
	} else
		cam_lastviewtime = realtime;
	
	// couldn't track for some reason
	if (!locked || !autocam)
		return;

	if (cl_chasecam.value) {
		cmd->forwardmove = cmd->sidemove = cmd->upmove = 0;

		VectorCopy(player->viewangles, cl.viewangles);
		VectorCopy(player->origin, desired_position);
		if (memcmp(&desired_position, &self->origin, sizeof(desired_position)) != 0) {
			MSG_WriteByte (&cls.netchan.message, clc_tmove);
			MSG_WriteCoord (&cls.netchan.message, desired_position[0]);
			MSG_WriteCoord (&cls.netchan.message, desired_position[1]);
			MSG_WriteCoord (&cls.netchan.message, desired_position[2]);
			// move there locally immediately
			VectorCopy(desired_position, self->origin);
		}
		self->weaponframe = player->weaponframe;

	} else {
		// Ok, move to our desired position and set our angles to view
		// the player
		VectorSubtract(desired_position, self->origin, vec);
		len = vlen(vec);
		cmd->forwardmove = cmd->sidemove = cmd->upmove = 0;
		if (len > 16) { // close enough?
			MSG_WriteByte (&cls.netchan.message, clc_tmove);
			MSG_WriteCoord (&cls.netchan.message, desired_position[0]);
			MSG_WriteCoord (&cls.netchan.message, desired_position[1]);
			MSG_WriteCoord (&cls.netchan.message, desired_position[2]);
		}

		// move there locally immediately
		VectorCopy(desired_position, self->origin);
										 
		VectorSubtract(player->origin, desired_position, vec);
		vectoangles(vec, cl.viewangles);
		cl.viewangles[0] = -cl.viewangles[0];
	}
}
Пример #17
0
/*  
==================
SV_StartSound

Each entity can have eight independant sound sources, like voice,
weapon, feet, etc.

Channel 0 is an auto-allocate channel, the others override anything
already running on that entity/channel pair.

An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off.  (max 4 attenuation)

==================
*/  
void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation)
{       
	int         sound_num;
	int			field_mask;
	int			i;
	int			ent;
	static float lastmsg = 0;

	if (volume < 0 || volume > 255)
	{
		Con_Warning ("SV_StartSound: volume = %d, max = %d\n", volume, 255);
		volume = CLAMP(0, volume, 255);
	}
	if (attenuation < 0 || attenuation > 4)
	{
		Con_Warning ("SV_StartSound: attenuation = %f, max = %d\n", attenuation, 4);
		attenuation = CLAMP(0, attenuation, 4);
	}
	if (channel < 0 || channel > 7)
	{
		Con_Warning ("SV_StartSound: channel = %i, max = %d\n", channel, 7);
		channel = CLAMP(0, channel, 7);
	}

// drop silently if there is no room
	if (sv.datagram.cursize > ((sv.protocol == PROTOCOL_NETQUAKE) ? 1024 : MAX_DATAGRAM) - 16)
		return;	

// find precache number for sound
	for (sound_num=1 ; sound_num<MAX_SOUNDS && sv.sound_precache[sound_num] ; sound_num++)
		if (!strcmp(sample, sv.sound_precache[sound_num]))
			break;

	if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
	{
		if (IsTimeout (&lastmsg, 2))
		{
			// let's not upset and annoy the user
			Con_DPrintf ("SV_StartSound: %s not precacheed\n", sample);
		}
		return;
	}

	ent = NUM_FOR_EDICT(entity);

	field_mask = 0;
	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
		field_mask |= SND_VOLUME;
	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
		field_mask |= SND_ATTENUATION;

	//johnfitz -- PROTOCOL_FITZQUAKE
	if (ent >= 8192)
	{
		if (sv.protocol == PROTOCOL_FITZQUAKE || sv.protocol == PROTOCOL_MARKV || sv.protocol == PROTOCOL_RMQ)
			field_mask |= SND_LARGEENTITY;
		else
			return; // don't send any info protocol can't support
	}
	if (sound_num >= 256 || channel >= 8)
	{
		if (sv.protocol == PROTOCOL_FITZQUAKE || sv.protocol == PROTOCOL_MARKV || sv.protocol == PROTOCOL_RMQ)
			field_mask |= SND_LARGESOUND;
		else
			return; // don't send any info protocol can't support
	}
	//johnfitz

// directed messages go only to the entity the are targeted on
	MSG_WriteByte (&sv.datagram, svc_sound);
	MSG_WriteByte (&sv.datagram, field_mask);
	if (field_mask & SND_VOLUME)
		MSG_WriteByte (&sv.datagram, volume);
	if (field_mask & SND_ATTENUATION)
		MSG_WriteByte (&sv.datagram, attenuation*64);
	
	//johnfitz -- PROTOCOL_FITZQUAKE
	if (field_mask & SND_LARGEENTITY)
	{
		MSG_WriteShort (&sv.datagram, ent);
		MSG_WriteByte (&sv.datagram, channel);
	}
	else
		MSG_WriteShort (&sv.datagram, (ent<<3) | channel);

	if (field_mask & SND_LARGESOUND)
		MSG_WriteShort (&sv.datagram, sound_num);
	else
		MSG_WriteByte (&sv.datagram, sound_num);
	//johnfitz

	for (i=0 ; i<3 ; i++)
		MSG_WriteCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]), sv.protocolflags);
}           
Пример #18
0
void Server_Sound(ServerEntity_t *ent, int channel, char *sample, int iVolume, float attenuation)
{
	int sound_num, field_mask, i, e;

	if(!sample)
	{
		Con_Warning("Bad sample name (%s)!\n",ent->v.cClassname);
		return;
	}
	else if(iVolume < 0 || iVolume > 255)
	{
		Con_Warning("Sound: volume = %i\n", iVolume);
		return;
	}
	else if(attenuation < 0 || attenuation > 4)
	{
		Con_Warning("Sound: attenuation = %f\n", attenuation);
		return;
	}
	else if(channel < 0 || channel > 7)
	{
		Con_Warning("Sound: channel = %i\n", channel);
		return;
	}
	else if(sv.datagram.cursize > MAX_DATAGRAM-16)
		return;

	for(sound_num=1 ; sound_num<MAX_SOUNDS && sv.sound_precache[sound_num] ; sound_num++)
		if(!strcmp(sample,sv.sound_precache[sound_num]))
			break;

	if(sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num])
	{
		// [19/8/2012] Just return a simple warning ~hogsy
		Con_Warning("%s was not precached!\n",sample);
		return;
	}

	e = NUM_FOR_EDICT(ent);

	field_mask = 0;
	if(iVolume != DEFAULT_SOUND_PACKET_VOLUME)
		field_mask |= SND_VOLUME;

	if(attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
		field_mask |= SND_ATTENUATION;

	if(e >= 8192)
		field_mask |= SND_LARGEENTITY;

	if(sound_num >= 256 || channel >= 8)
		field_mask |= SND_LARGESOUND;

	MSG_WriteByte(&sv.datagram,svc_sound);
	MSG_WriteByte(&sv.datagram,field_mask);
	if(field_mask & SND_VOLUME)
		MSG_WriteByte(&sv.datagram, iVolume);
	if(field_mask & SND_ATTENUATION)
		MSG_WriteByte(&sv.datagram,attenuation*64);

	if(field_mask & SND_LARGEENTITY)
	{
		MSG_WriteShort(&sv.datagram,e);
		MSG_WriteByte(&sv.datagram,channel);
	}
	else
		MSG_WriteShort(&sv.datagram,(e<<3)|channel);

	if(field_mask & SND_LARGESOUND)
		MSG_WriteShort(&sv.datagram,sound_num);
	else
		MSG_WriteByte(&sv.datagram,sound_num);

	for(i=0 ; i<3 ; i++)
		MSG_WriteCoord(&sv.datagram,ent->v.origin[i]+0.5*(ent->v.mins[i]+ent->v.maxs[i]));
}
Пример #19
0
qbool SV_MVDWritePackets (int num)
{
	demo_frame_t	*frame, *nextframe;
	demo_client_t	*cl, *nextcl = NULL;
	int				i, j, flags;
	qbool			valid;
	double			time1, playertime, nexttime;
	vec3_t			origin, angles;
	sizebuf_t		msg;
	byte			msg_buf[MAX_MSGLEN];
	demoinfo_t		*demoinfo;

	if (!sv.mvdrecording)
		return false;

	SZ_Init(&msg, msg_buf, sizeof(msg_buf));

	if (num > demo.parsecount - demo.lastwritten + 1)
		num = demo.parsecount - demo.lastwritten + 1;

	// 'num' frames to write
	for ( ; num; num--, demo.lastwritten++)
	{
		SZ_Clear(&msg);

		frame = &demo.frames[demo.lastwritten&DEMO_FRAMES_MASK];
		time1 = frame->time;
		nextframe = frame;

		demo.dbuf = &frame->buf;

		// find two frames
		// one before the exact time (time - msec) and one after,
		// then we can interpolte exact position for current frame
		for (i = 0, cl = frame->clients, demoinfo = demo.info; i < MAX_CLIENTS; i++, cl++, demoinfo++)
		{
			if (cl->parsecount != demo.lastwritten)
				continue; // not valid

			nexttime = playertime = time1 - cl->sec;

			valid = false;

			for (j = demo.lastwritten+1; nexttime < time1 && j < demo.parsecount; j++)
			{
				nextframe = &demo.frames[j&DEMO_FRAMES_MASK];
				nextcl = &nextframe->clients[i];

				if (nextcl->parsecount != j)
					break; // disconnected?
				if (nextcl->fixangle)
					break; // respawned, or walked into teleport, do not interpolate!
				if (!(nextcl->flags & DF_DEAD) && (cl->flags & DF_DEAD))
					break; // respawned, do not interpolate

				nexttime = nextframe->time - nextcl->sec;

				if (nexttime >= time1)
				{
					// good, found what we were looking for
					valid = true;
					break;
				}
			}

			if (valid)
			{
				float f = 0;
				float z = nexttime - playertime;

				if ( z )
					f = (time1 - nexttime) / z;

				for (j = 0; j < 3; j++) {
					angles[j] = adjustangle(cl->info.angles[j], nextcl->info.angles[j], 1.0 + f);
					origin[j] = nextcl->info.origin[j] + f * (nextcl->info.origin[j] - cl->info.origin[j]);
				}
			} else {
				VectorCopy(cl->info.origin, origin);
				VectorCopy(cl->info.angles, angles);
			}

			// now write it to buf
			flags = cl->flags;

			for (j=0; j < 3; j++)
				if (origin[j] != demoinfo->origin[i])
					flags |= DF_ORIGIN << j;

			for (j=0; j < 3; j++)
				if (angles[j] != demoinfo->angles[j])
					flags |= DF_ANGLES << j;

			if (cl->info.model != demoinfo->model)
				flags |= DF_MODEL;
			if (cl->info.effects != demoinfo->effects)
				flags |= DF_EFFECTS;
			if (cl->info.skinnum != demoinfo->skinnum)
				flags |= DF_SKINNUM;
			if (cl->info.weaponframe != demoinfo->weaponframe)
				flags |= DF_WEAPONFRAME;

			MSG_WriteByte (&msg, svc_playerinfo);
			MSG_WriteByte (&msg, i);
			MSG_WriteShort (&msg, flags);

			MSG_WriteByte (&msg, cl->frame);

			for (j=0 ; j<3 ; j++)
				if (flags & (DF_ORIGIN << j))
					MSG_WriteCoord (&msg, origin[j]);

			for (j=0 ; j<3 ; j++)
				if (flags & (DF_ANGLES << j))
					MSG_WriteAngle16 (&msg, angles[j]);

			if (flags & DF_MODEL)
				MSG_WriteByte (&msg, cl->info.model);

			if (flags & DF_SKINNUM)
				MSG_WriteByte (&msg, cl->info.skinnum);

			if (flags & DF_EFFECTS)
				MSG_WriteByte (&msg, cl->info.effects);

			if (flags & DF_WEAPONFRAME)
				MSG_WriteByte (&msg, cl->info.weaponframe);

			VectorCopy(cl->info.origin, demoinfo->origin);
			VectorCopy(cl->info.angles, demoinfo->angles);
			demoinfo->skinnum = cl->info.skinnum;
			demoinfo->effects = cl->info.effects;
			demoinfo->weaponframe = cl->info.weaponframe;
			demoinfo->model = cl->info.model;
		}

		SV_MVDWriteToDisk(demo.lasttype,demo.lastto, (float)time1); // this goes first to reduce demo size a bit
		SV_MVDWriteToDisk(0,0, (float)time1); // now goes the rest
		if (msg.cursize)
			SV_WriteMVDMessage(&msg, dem_all, 0, (float)time1);

		if (!sv.mvdrecording)
		{
			Com_DPrintf("SV_MVDWritePackets: error: in sv.mvdrecording\n");
			return false; // ERROR
		}
	}

	if (!sv.mvdrecording)
		return false; // ERROR

	if (demo.lastwritten > demo.parsecount)
		demo.lastwritten = demo.parsecount;

	demo.dbuf = &demo.frames[demo.parsecount&DEMO_FRAMES_MASK].buf;
	demo.dbuf->maxsize = MAXSIZE + demo.dbuf->bufsize;

	return true;
}
Пример #20
0
void ClientReliableWrite_Coord (float f)
{
	assert (backbuf_write_started);
	MSG_WriteCoord (&backbuf, f);
}
Пример #21
0
void EXT_FUNC MSG_WriteCoord_api(sizebuf_t *sb, float f) {
	MSG_WriteCoord(sb, f);
}
Пример #22
0
void Game_WriteCoord(int mode,float f)
{
	MSG_WriteCoord(Game_WriteDest(mode),f);
}
Пример #23
0
/*
==================
SV_StartSound

Each entity can have eight independant sound sources, like voice,
weapon, feet, etc.

Channel 0 is an auto-allocate channel, the others override anything
allready running on that entity/channel pair.

An attenuation of 0 will play full volume everywhere in the level.
Larger attenuations will drop off.  (max 4 attenuation)

==================
*/
void SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, float attenuation)
{
	int			sound_num, ent;
	int			i, field_mask;

	if (volume < 0 || volume > 255)
		Host_Error ("SV_StartSound: volume = %i", volume);

	if (attenuation < 0 || attenuation > 4)
		Host_Error ("SV_StartSound: attenuation = %f", attenuation);

	if (channel < 0 || channel > 7)
		Host_Error ("SV_StartSound: channel = %i", channel);

	if (sv.datagram.cursize > MAX_DATAGRAM-16)
		return;

// find precache number for sound
	for (sound_num = 1; sound_num < MAX_SOUNDS && sv.sound_precache[sound_num]; sound_num++)
	{
		if (!strcmp(sample, sv.sound_precache[sound_num]))
			break;
	}

	if (sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num])
	{
		Con_Printf ("SV_StartSound: %s not precacheed\n", sample);
		return;
	}

	ent = NUM_FOR_EDICT(entity);

	field_mask = 0;
	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
		field_mask |= SND_VOLUME;
	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
		field_mask |= SND_ATTENUATION;

	//johnfitz -- PROTOCOL_FITZQUAKE
	if (ent >= 8192)
	{
		if (sv.protocol == PROTOCOL_NETQUAKE)
			return; //don't send any info protocol can't support
		else
			field_mask |= SND_LARGEENTITY;
	}
	if (sound_num >= 256 || channel >= 8)
	{
		if (sv.protocol == PROTOCOL_NETQUAKE)
			return; //don't send any info protocol can't support
		else
			field_mask |= SND_LARGESOUND;
	}
	//johnfitz

// directed messages go only to the entity the are targeted on
	MSG_WriteByte (&sv.datagram, svc_sound);
	MSG_WriteByte (&sv.datagram, field_mask);
	if (field_mask & SND_VOLUME)
		MSG_WriteByte (&sv.datagram, volume);
	if (field_mask & SND_ATTENUATION)
		MSG_WriteByte (&sv.datagram, attenuation*64);

	//johnfitz -- PROTOCOL_FITZQUAKE
	if (field_mask & SND_LARGEENTITY)
	{
		MSG_WriteShort (&sv.datagram, ent);
		MSG_WriteByte (&sv.datagram, channel);
	}
	else
		MSG_WriteShort (&sv.datagram, (ent<<3) | channel);
	if (field_mask & SND_LARGESOUND)
		MSG_WriteShort (&sv.datagram, sound_num);
	else
		MSG_WriteByte (&sv.datagram, sound_num);
	//johnfitz

	for (i = 0; i < 3; i++)
		MSG_WriteCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]));
}
Пример #24
0
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
static void SV_SendEffect (sizebuf_t *sb, int idx)
{
	qboolean	DoTest;
	vec3_t		TestO1, Diff;
	float		Size, TestDistance;
	int		i, count;

	if (sb == &sv.reliable_datagram && sv_ce_scale.value > 0)
		DoTest = true;
	else
		DoTest = false;

	VectorClear(TestO1);
	TestDistance = 0;

	switch (sv.Effects[idx].type)
	{
	case CE_RAIN:
	case CE_SNOW:
		DoTest = false;
		break;

	case CE_FOUNTAIN:
		DoTest = false;
		break;

	case CE_QUAKE:
		VectorCopy(sv.Effects[idx].ef.Quake.origin, TestO1);
		TestDistance = 700;
		break;

	case CE_WHITE_SMOKE:
	case CE_GREEN_SMOKE:
	case CE_GREY_SMOKE:
	case CE_RED_SMOKE:
	case CE_SLOW_WHITE_SMOKE:
	case CE_TELESMK1:
	case CE_TELESMK2:
	case CE_GHOST:
	case CE_REDCLOUD:
	case CE_FLAMESTREAM:
	case CE_ACID_MUZZFL:
	case CE_FLAMEWALL:
	case CE_FLAMEWALL2:
	case CE_ONFIRE:
		VectorCopy(sv.Effects[idx].ef.Smoke.origin, TestO1);
		TestDistance = 250;
		break;

	case CE_SM_WHITE_FLASH:
	case CE_YELLOWRED_FLASH:
	case CE_BLUESPARK:
	case CE_YELLOWSPARK:
	case CE_SM_CIRCLE_EXP:
	case CE_BG_CIRCLE_EXP:
	case CE_SM_EXPLOSION:
	case CE_LG_EXPLOSION:
	case CE_FLOOR_EXPLOSION:
	case CE_BLUE_EXPLOSION:
	case CE_REDSPARK:
	case CE_GREENSPARK:
	case CE_ICEHIT:
	case CE_MEDUSA_HIT:
	case CE_MEZZO_REFLECT:
	case CE_FLOOR_EXPLOSION2:
	case CE_XBOW_EXPLOSION:
	case CE_NEW_EXPLOSION:
	case CE_MAGIC_MISSILE_EXPLOSION:
	case CE_BONE_EXPLOSION:
	case CE_BLDRN_EXPL:
	case CE_ACID_HIT:
	case CE_LBALL_EXPL:
	case CE_FIREWALL_SMALL:
	case CE_FIREWALL_MEDIUM:
	case CE_FIREWALL_LARGE:
	case CE_ACID_SPLAT:
	case CE_ACID_EXPL:
	case CE_FBOOM:
	case CE_BRN_BOUNCE:
	case CE_LSHOCK:
	case CE_BOMB:
	case CE_FLOOR_EXPLOSION3:
		VectorCopy(sv.Effects[idx].ef.Smoke.origin, TestO1);
		TestDistance = 250;
		break;

	case CE_WHITE_FLASH:
	case CE_BLUE_FLASH:
	case CE_SM_BLUE_FLASH:
	case CE_RED_FLASH:
		VectorCopy(sv.Effects[idx].ef.Smoke.origin, TestO1);
		TestDistance = 250;
		break;

	case CE_RIDER_DEATH:
		DoTest = false;
		break;

	case CE_GRAVITYWELL:
		DoTest = false;
		break;

	case CE_TELEPORTERPUFFS:
		VectorCopy(sv.Effects[idx].ef.Teleporter.origin, TestO1);
		TestDistance = 350;
		break;

	case CE_TELEPORTERBODY:
		VectorCopy(sv.Effects[idx].ef.Teleporter.origin, TestO1);
		TestDistance = 350;
		break;

	case CE_BONESHARD:
	case CE_BONESHRAPNEL:
		VectorCopy(sv.Effects[idx].ef.Missile.origin, TestO1);
		TestDistance = 600;
		break;

	case CE_CHUNK:
		VectorCopy(sv.Effects[idx].ef.Chunk.origin, TestO1);
		TestDistance = 600;
		break;

	default:
		PR_RunError ("%s: bad type", __thisfunc__);
		break;
	}

	if (!DoTest)
		count = 1;
	else
	{
		count = svs.maxclients;
		TestDistance = (float)TestDistance * sv_ce_scale.value;
		TestDistance *= TestDistance;
	}

	for (i = 0 ; i < count ; i++)
	{
		if (DoTest)
		{
			if (svs.clients[i].active)
			{
				sb = &svs.clients[i].datagram;
				VectorSubtract(svs.clients[i].edict->v.origin, TestO1, Diff);
				Size = (Diff[0]*Diff[0]) + (Diff[1]*Diff[1]) + (Diff[2]*Diff[2]);

				if (Size > TestDistance)
					continue;

				if (sv_ce_max_size.value > 0 && sb->cursize > sv_ce_max_size.value)
					continue;
			}
			else
				continue;
		}

		MSG_WriteByte (sb, svc_start_effect);
		MSG_WriteByte (sb, idx);
		MSG_WriteByte (sb, sv.Effects[idx].type);

		switch (sv.Effects[idx].type)
		{
		case CE_RAIN:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.min_org[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.min_org[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.min_org[2]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.max_org[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.max_org[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.max_org[2]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.e_size[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.e_size[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.e_size[2]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.dir[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.dir[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.dir[2]);
			MSG_WriteShort(sb, sv.Effects[idx].ef.Rain.color);
			MSG_WriteShort(sb, sv.Effects[idx].ef.Rain.count);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Rain.wait);
			break;

		case CE_SNOW:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.min_org[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.min_org[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.min_org[2]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.max_org[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.max_org[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.max_org[2]);
			MSG_WriteByte(sb, sv.Effects[idx].ef.Rain.flags);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.dir[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.dir[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Rain.dir[2]);
			MSG_WriteByte(sb, sv.Effects[idx].ef.Rain.count);
			//MSG_WriteShort(sb, sv.Effects[idx].ef.Rain.veer);
			break;

		case CE_FOUNTAIN:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Fountain.pos[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Fountain.pos[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Fountain.pos[2]);
			MSG_WriteAngle(sb, sv.Effects[idx].ef.Fountain.angle[0]);
			MSG_WriteAngle(sb, sv.Effects[idx].ef.Fountain.angle[1]);
			MSG_WriteAngle(sb, sv.Effects[idx].ef.Fountain.angle[2]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Fountain.movedir[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Fountain.movedir[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Fountain.movedir[2]);
			MSG_WriteShort(sb, sv.Effects[idx].ef.Fountain.color);
			MSG_WriteByte(sb, sv.Effects[idx].ef.Fountain.cnt);
			break;

		case CE_QUAKE:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Quake.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Quake.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Quake.origin[2]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Quake.radius);
			break;

		case CE_WHITE_SMOKE:
		case CE_GREEN_SMOKE:
		case CE_GREY_SMOKE:
		case CE_RED_SMOKE:
		case CE_SLOW_WHITE_SMOKE:
		case CE_TELESMK1:
		case CE_TELESMK2:
		case CE_GHOST:
		case CE_REDCLOUD:
		case CE_FLAMESTREAM:
		case CE_ACID_MUZZFL:
		case CE_FLAMEWALL:
		case CE_FLAMEWALL2:
		case CE_ONFIRE:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[2]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Smoke.velocity[0]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Smoke.velocity[1]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Smoke.velocity[2]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Smoke.framelength);
			/* smoke frame is a mission pack thing only. */
			if (sv_protocol > PROTOCOL_RAVEN_111)
				MSG_WriteFloat(sb, sv.Effects[idx].ef.Smoke.frame);
			break;

		case CE_SM_WHITE_FLASH:
		case CE_YELLOWRED_FLASH:
		case CE_BLUESPARK:
		case CE_YELLOWSPARK:
		case CE_SM_CIRCLE_EXP:
		case CE_BG_CIRCLE_EXP:
		case CE_SM_EXPLOSION:
		case CE_LG_EXPLOSION:
		case CE_FLOOR_EXPLOSION:
		case CE_FLOOR_EXPLOSION3:
		case CE_BLUE_EXPLOSION:
		case CE_REDSPARK:
		case CE_GREENSPARK:
		case CE_ICEHIT:
		case CE_MEDUSA_HIT:
		case CE_MEZZO_REFLECT:
		case CE_FLOOR_EXPLOSION2:
		case CE_XBOW_EXPLOSION:
		case CE_NEW_EXPLOSION:
		case CE_MAGIC_MISSILE_EXPLOSION:
		case CE_BONE_EXPLOSION:
		case CE_BLDRN_EXPL:
		case CE_ACID_HIT:
		case CE_ACID_SPLAT:
		case CE_ACID_EXPL:
		case CE_LBALL_EXPL:
		case CE_FIREWALL_SMALL:
		case CE_FIREWALL_MEDIUM:
		case CE_FIREWALL_LARGE:
		case CE_FBOOM:
		case CE_BOMB:
		case CE_BRN_BOUNCE:
		case CE_LSHOCK:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[2]);
			break;

		case CE_WHITE_FLASH:
		case CE_BLUE_FLASH:
		case CE_SM_BLUE_FLASH:
		case CE_RED_FLASH:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Smoke.origin[2]);
			break;

		case CE_RIDER_DEATH:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.RD.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.RD.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.RD.origin[2]);
			break;

		case CE_TELEPORTERPUFFS:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Teleporter.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Teleporter.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Teleporter.origin[2]);
			break;

		case CE_TELEPORTERBODY:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Teleporter.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Teleporter.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Teleporter.origin[2]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Teleporter.velocity[0][0]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Teleporter.velocity[0][1]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Teleporter.velocity[0][2]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Teleporter.skinnum);
			break;

		case CE_BONESHARD:
		case CE_BONESHRAPNEL:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Missile.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Missile.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Missile.origin[2]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.velocity[0]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.velocity[1]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.velocity[2]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.angle[0]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.angle[1]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.angle[2]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.avelocity[0]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.avelocity[1]);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.Missile.avelocity[2]);
			break;

		case CE_GRAVITYWELL:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.RD.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.RD.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.RD.origin[2]);
			MSG_WriteShort(sb, sv.Effects[idx].ef.RD.color);
			MSG_WriteFloat(sb, sv.Effects[idx].ef.RD.lifetime);
			break;

		case CE_CHUNK:
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Chunk.origin[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Chunk.origin[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Chunk.origin[2]);
			MSG_WriteByte (sb, sv.Effects[idx].ef.Chunk.type);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Chunk.srcVel[0]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Chunk.srcVel[1]);
			MSG_WriteCoord(sb, sv.Effects[idx].ef.Chunk.srcVel[2]);
			MSG_WriteByte (sb, sv.Effects[idx].ef.Chunk.numChunks);
		//	Con_Printf ("Adding %d chunks on server...\n", sv.Effects[idx].Chunk.numChunks);
			break;

		default:
			PR_RunError ("%s: bad type", __thisfunc__);
			break;
		}
	}
}
Пример #25
0
// Take over the user controls and track a player.
// We find a nice position to watch the player and move there
void Cam_Track(usercmd_t *cmd) {
	player_state_t *player, *self;
	frame_t *frame;
	vec3_t vec;
	int do_tmove;

	if (!cl.spectator)
		return;
	
	if (!autocam || cls.state != ca_active)
		return;

	if (locked && (!cl.players[spec_track].name[0] || cl.players[spec_track].spectator)) {
		locked = false;
		Cam_Unlock();
		return;
	}

	frame = &cl.frames[cl.validsequence & UPDATE_MASK];


	if (autocam && cls.mvdplayback)	{
		if (ideal_track != spec_track && cls.realtime - last_lock > 0.1 && 
			frame->playerstate[ideal_track].messagenum == cl.parsecount)
			Cam_Lock(ideal_track);

		if (frame->playerstate[spec_track].messagenum != cl.parsecount)	{
			int i;

			for (i = 0; i < MAX_CLIENTS; i++) {
				if (frame->playerstate[i].messagenum == cl.parsecount)
					break;
			}
			if (i < MAX_CLIENTS)
				Cam_Lock(i);
		}
	}


	player = frame->playerstate + spec_track;
	self = frame->playerstate + cl.playernum;

	if (!locked || !Cam_IsVisible(player, desired_position)) {
		if (!locked || cls.realtime - cam_lastviewtime > 0.1) {
			if (!InitFlyby(self, player, true))
				InitFlyby(self, player, false);
			cam_lastviewtime = cls.realtime;
		}
	} else {
		cam_lastviewtime = cls.realtime;
	}
	
	// couldn't track for some reason
	if (!locked || !autocam)
		return;

	do_tmove = 0;

	if (cl_chasecam.value) {
		cmd->forwardmove = cmd->sidemove = cmd->upmove = 0;

		VectorCopy(player->viewangles, cl.viewangles);
		VectorCopy(player->origin, desired_position);
		if (memcmp(&desired_position, &self->origin, sizeof(desired_position)) != 0)
		{
			do_tmove = 1;
			// move there locally immediately
			VectorCopy(desired_position, self->origin);
		}
	} else {
		// Ok, move to our desired position and set our angles to view
		// the player
		VectorSubtract(desired_position, self->origin, vec);
		cmd->forwardmove = cmd->sidemove = cmd->upmove = 0;
		if (VectorLength(vec) > 16)
		{
			// close enough?
			do_tmove = 1;
		}

		// move there locally immediately
		VectorCopy(desired_position, self->origin);
										 
		VectorSubtract(player->origin, desired_position, vec);
		vectoangles(vec, cl.viewangles);
		cl.viewangles[0] = -cl.viewangles[0];
		if (cl.viewangles[0] < 0)
			cl.viewangles[0] += 360;
	}

	Mouse_SetViewAngles(cl.viewangles);

#ifdef NETQW
	if (do_tmove && cls.netqw)
		NetQW_SetTeleport(cls.netqw, desired_position);
#else
	MSG_WriteByte (&cls.netchan.message, clc_tmove);
	MSG_WriteCoord (&cls.netchan.message, desired_position[0]);
	MSG_WriteCoord (&cls.netchan.message, desired_position[1]);
	MSG_WriteCoord (&cls.netchan.message, desired_position[2]);
#endif
}
Пример #26
0
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
void SV_SendEffect(sizebuf_t *sb, int index)
{
	qboolean	DoTest;
	vec3_t		TestO;
	int			TestDistance;
	int			i;

	if (sv_ce_scale.value > 0)
		DoTest = true;
	else
		DoTest = false;

	VectorCopy(vec3_origin, TestO);

	switch(sv.Effects[index].type)
	{
		case CE_HWSHEEPINATOR:
		case CE_HWXBOWSHOOT:
			VectorCopy(sv.Effects[index].Xbow.origin[5], TestO);
			TestDistance = 900;
			break;
		case CE_SCARABCHAIN:
			VectorCopy(sv.Effects[index].Chain.origin, TestO);
			TestDistance = 900;
			break;

		case CE_TRIPMINE:
			VectorCopy(sv.Effects[index].Chain.origin, TestO);
//			DoTest = false;
			break;

			//ACHTUNG!!!!!!! setting DoTest to false here does not insure that effect will be sent to everyone!
		case CE_TRIPMINESTILL:
			TestDistance = 10000;
			DoTest = false;
			break;

		case CE_RAIN:
			TestDistance = 10000;
			DoTest = false;
			break;

		case CE_FOUNTAIN:
			TestDistance = 10000;
			DoTest = false;
			break;

		case CE_QUAKE:
			VectorCopy(sv.Effects[index].Quake.origin, TestO);
			TestDistance = 700;
			break;

		case CE_WHITE_SMOKE:
		case CE_GREEN_SMOKE:
		case CE_GREY_SMOKE:
		case CE_RED_SMOKE:
		case CE_SLOW_WHITE_SMOKE:
		case CE_TELESMK1:
		case CE_TELESMK2:
		case CE_GHOST:
		case CE_REDCLOUD:
		case CE_FLAMESTREAM:
		case CE_ACID_MUZZFL:
		case CE_FLAMEWALL:
		case CE_FLAMEWALL2:
		case CE_ONFIRE:
		case CE_RIPPLE:
			VectorCopy(sv.Effects[index].Smoke.origin, TestO);
			TestDistance = 250;
			break;

		case CE_SM_WHITE_FLASH:
		case CE_YELLOWRED_FLASH:
		case CE_BLUESPARK:
		case CE_YELLOWSPARK:
		case CE_SM_CIRCLE_EXP:
		case CE_BG_CIRCLE_EXP:
		case CE_SM_EXPLOSION:
		case CE_SM_EXPLOSION2:
		case CE_BG_EXPLOSION:
		case CE_FLOOR_EXPLOSION:
		case CE_BLUE_EXPLOSION:
		case CE_REDSPARK:
		case CE_GREENSPARK:
		case CE_ICEHIT:
		case CE_MEDUSA_HIT:
		case CE_MEZZO_REFLECT:
		case CE_FLOOR_EXPLOSION2:
		case CE_XBOW_EXPLOSION:
		case CE_NEW_EXPLOSION:
		case CE_MAGIC_MISSILE_EXPLOSION:
		case CE_BONE_EXPLOSION:
		case CE_BLDRN_EXPL:
		case CE_ACID_HIT:
		case CE_LBALL_EXPL:
		case CE_FIREWALL_SMALL:
		case CE_FIREWALL_MEDIUM:
		case CE_FIREWALL_LARGE:
		case CE_ACID_SPLAT:
		case CE_ACID_EXPL:
		case CE_FBOOM:
		case CE_BRN_BOUNCE:
		case CE_LSHOCK:
		case CE_BOMB:
		case CE_FLOOR_EXPLOSION3:
			VectorCopy(sv.Effects[index].Smoke.origin, TestO);
			TestDistance = 250;
			break;

		case CE_WHITE_FLASH:
		case CE_BLUE_FLASH:
		case CE_SM_BLUE_FLASH:
		case CE_HWSPLITFLASH:
		case CE_RED_FLASH:
			VectorCopy(sv.Effects[index].Smoke.origin, TestO);
			TestDistance = 250;
			break;


		case CE_RIDER_DEATH:
			DoTest = false;
			break;

		case CE_TELEPORTERPUFFS:
			VectorCopy(sv.Effects[index].Teleporter.origin, TestO);
			TestDistance = 350;
			break;

		case CE_TELEPORTERBODY:
			VectorCopy(sv.Effects[index].Teleporter.origin, TestO);
			TestDistance = 350;
			break;

		case CE_DEATHBUBBLES:
			if (sv.Effects[index].Bubble.owner < 0 || sv.Effects[index].Bubble.owner >= sv.num_edicts)
			{
				return;
			}
			VectorCopy(PROG_TO_EDICT(sv.Effects[index].Bubble.owner)->v.origin, TestO);
			TestDistance = 400;
			break;

		case CE_HWDRILLA:
		case CE_BONESHARD:
		case CE_BONESHRAPNEL:
		case CE_HWBONEBALL:
		case CE_HWRAVENSTAFF:
		case CE_HWRAVENPOWER:

			VectorCopy(sv.Effects[index].Missile.origin, TestO);
			TestDistance = 900;
			break;

		case CE_HWMISSILESTAR:
		case CE_HWEIDOLONSTAR:
			VectorCopy(sv.Effects[index].Missile.origin, TestO);
			TestDistance = 600;
			break;
		default:
//			Sys_Error ("SV_SendEffect: bad type");
			PR_RunError ("SV_SendEffect: bad type");
			break;
	}

	MSG_WriteByte (&sv.multicast, svc_start_effect);
	MSG_WriteByte (&sv.multicast, index);
	MSG_WriteByte (&sv.multicast, sv.Effects[index].type);

	switch(sv.Effects[index].type)
	{
		case CE_RAIN:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.min_org[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.min_org[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.min_org[2]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.max_org[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.max_org[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.max_org[2]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.e_size[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.e_size[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.e_size[2]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.dir[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.dir[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Rain.dir[2]);
			MSG_WriteShort(&sv.multicast, sv.Effects[index].Rain.color);
			MSG_WriteShort(&sv.multicast, sv.Effects[index].Rain.count);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Rain.wait);
			break;

		case CE_FOUNTAIN:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Fountain.pos[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Fountain.pos[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Fountain.pos[2]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Fountain.angle[0]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Fountain.angle[1]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Fountain.angle[2]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Fountain.movedir[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Fountain.movedir[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Fountain.movedir[2]);
			MSG_WriteShort(&sv.multicast, sv.Effects[index].Fountain.color);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Fountain.cnt);
			break;

		case CE_QUAKE:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Quake.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Quake.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Quake.origin[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Quake.radius);
			break;

		case CE_WHITE_SMOKE:
		case CE_GREEN_SMOKE:
		case CE_GREY_SMOKE:
		case CE_RED_SMOKE:
		case CE_SLOW_WHITE_SMOKE:
		case CE_TELESMK1:
		case CE_TELESMK2:
		case CE_GHOST:
		case CE_REDCLOUD:
		case CE_FLAMESTREAM:
		case CE_ACID_MUZZFL:
		case CE_FLAMEWALL:
		case CE_FLAMEWALL2:
		case CE_ONFIRE:
		case CE_RIPPLE:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Smoke.velocity[0]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Smoke.velocity[1]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Smoke.velocity[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Smoke.framelength);
			break;

		case CE_SM_WHITE_FLASH:
		case CE_YELLOWRED_FLASH:
		case CE_BLUESPARK:
		case CE_YELLOWSPARK:
		case CE_SM_CIRCLE_EXP:
		case CE_BG_CIRCLE_EXP:
		case CE_SM_EXPLOSION:
		case CE_SM_EXPLOSION2:
		case CE_BG_EXPLOSION:
		case CE_FLOOR_EXPLOSION:
		case CE_BLUE_EXPLOSION:
		case CE_REDSPARK:
		case CE_GREENSPARK:
		case CE_ICEHIT:
		case CE_MEDUSA_HIT:
		case CE_MEZZO_REFLECT:
		case CE_FLOOR_EXPLOSION2:
		case CE_XBOW_EXPLOSION:
		case CE_NEW_EXPLOSION:
		case CE_MAGIC_MISSILE_EXPLOSION:
		case CE_BONE_EXPLOSION:
		case CE_BLDRN_EXPL:
		case CE_ACID_HIT:
		case CE_ACID_SPLAT:
		case CE_ACID_EXPL:
		case CE_LBALL_EXPL:	
		case CE_FIREWALL_SMALL:
		case CE_FIREWALL_MEDIUM:
		case CE_FIREWALL_LARGE:
		case CE_FBOOM:
		case CE_BOMB:
		case CE_BRN_BOUNCE:
		case CE_LSHOCK:

			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[2]);
			break;

		case CE_WHITE_FLASH:
		case CE_BLUE_FLASH:
		case CE_SM_BLUE_FLASH:			
		case CE_HWSPLITFLASH:
		case CE_RED_FLASH:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Smoke.origin[2]);
			break;


		case CE_RIDER_DEATH:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].RD.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].RD.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].RD.origin[2]);
			break;

		case CE_TELEPORTERPUFFS:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Teleporter.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Teleporter.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Teleporter.origin[2]);
			break;

		case CE_TELEPORTERBODY:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Teleporter.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Teleporter.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Teleporter.origin[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Teleporter.velocity[0][0]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Teleporter.velocity[0][1]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Teleporter.velocity[0][2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Teleporter.skinnum);
			break;
		case CE_BONESHRAPNEL:
		case CE_HWBONEBALL:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.velocity[0]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.velocity[1]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.velocity[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.angle[0]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.angle[1]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.angle[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.avelocity[0]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.avelocity[1]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.avelocity[2]);

			break;
		case CE_BONESHARD:
		case CE_HWRAVENSTAFF:
		case CE_HWMISSILESTAR:
		case CE_HWEIDOLONSTAR:
		case CE_HWRAVENPOWER:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.velocity[0]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.velocity[1]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Missile.velocity[2]);
			break;
		case CE_HWDRILLA:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Missile.origin[2]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Missile.angle[0]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Missile.angle[1]);
			MSG_WriteShort(&sv.multicast, sv.Effects[index].Missile.speed);
			break;
		case CE_DEATHBUBBLES:
			MSG_WriteShort(&sv.multicast, sv.Effects[index].Bubble.owner);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Bubble.offset[0]);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Bubble.offset[1]);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Bubble.offset[2]);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Bubble.count);
			break;
		case CE_SCARABCHAIN:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Chain.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Chain.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Chain.origin[2]);
			MSG_WriteShort(&sv.multicast, sv.Effects[index].Chain.owner+sv.Effects[index].Chain.material);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Chain.tag);
			break;
		case CE_TRIPMINESTILL:
		case CE_TRIPMINE:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Chain.origin[0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Chain.origin[1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Chain.origin[2]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Chain.velocity[0]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Chain.velocity[1]);
			MSG_WriteFloat(&sv.multicast, sv.Effects[index].Chain.velocity[2]);
			break;
		case CE_HWSHEEPINATOR:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[5][0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[5][1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[5][2]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Xbow.angle[0]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Xbow.angle[1]);

			//now send the guys that have turned
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Xbow.turnedbolts);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Xbow.activebolts);
			for (i=0;i<5;i++)
			{
				if ((1<<i)&sv.Effects[index].Xbow.turnedbolts)
				{
					MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[i][0]);
					MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[i][1]);
					MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[i][2]);
					MSG_WriteAngle(&sv.multicast, sv.Effects[index].Xbow.vel[i][0]);
					MSG_WriteAngle(&sv.multicast, sv.Effects[index].Xbow.vel[i][1]);
				}
			}
			break;
		case CE_HWXBOWSHOOT:
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[5][0]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[5][1]);
			MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[5][2]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Xbow.angle[0]);
			MSG_WriteAngle(&sv.multicast, sv.Effects[index].Xbow.angle[1]);
//				MSG_WriteFloat(&sv.multicast, sv.Effects[index].Xbow.angle[2]);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Xbow.bolts);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Xbow.randseed);

			//now send the guys that have turned
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Xbow.turnedbolts);
			MSG_WriteByte(&sv.multicast, sv.Effects[index].Xbow.activebolts);
			for (i=0;i<5;i++)
			{
				if ((1<<i)&sv.Effects[index].Xbow.turnedbolts)
				{
					MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[i][0]);
					MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[i][1]);
					MSG_WriteCoord(&sv.multicast, sv.Effects[index].Xbow.origin[i][2]);
					MSG_WriteAngle(&sv.multicast, sv.Effects[index].Xbow.vel[i][0]);
					MSG_WriteAngle(&sv.multicast, sv.Effects[index].Xbow.vel[i][1]);
				}
			}
			break;
		default:
//			Sys_Error ("SV_SendEffect: bad type");
			PR_RunError ("SV_SendEffect: bad type");
			break;
	}

	if (sb)
	{
		SZ_Write (sb, sv.multicast.data, sv.multicast.cursize);
		SZ_Clear (&sv.multicast);
	}
	else
	{
		if (DoTest)
		{
			SV_Multicast (TestO, MULTICAST_PVS_R);
		}
		else
		{
			SV_Multicast (TestO, MULTICAST_ALL_R);
		}
		sv.Effects[index].client_list = clients_multicast;
	}
}
Пример #27
0
/*
====================
CL_Record

Called by CL_Record_f and CL_EasyRecord_f
====================
*/
static void CL_Record (void)
{
	sizebuf_t	buf;
	byte	buf_data[MAX_MSGLEN];
	int n, i, j;
	char *s;
	entity_t *ent;
	entity_state_t *es, blankes;
	player_info_t *player;
	int seq = 1;

#ifdef MVDPLAY
	if (cls.mvdplayback) {
		Com_Printf ("Can't record while playing MVD demo.\n");
		return;
	}
#endif
	cls.demorecording = true;

/*-------------------------------------------------*/

// serverdata
	// send the info about the new client to all connected clients
	SZ_Init (&buf, buf_data, sizeof(buf_data));

// send the serverdata
	MSG_WriteByte (&buf, svc_serverdata);
	MSG_WriteLong (&buf, PROTOCOL_VERSION);
	MSG_WriteLong (&buf, cl.servercount);
	MSG_WriteString (&buf, cls.gamedirfile);

	if (cl.spectator)
		MSG_WriteByte (&buf, cl.playernum | 128);
	else
		MSG_WriteByte (&buf, cl.playernum);

	// send full levelname
	MSG_WriteString (&buf, cl.levelname);

	// send the movevars
	MSG_WriteFloat(&buf, movevars.gravity);
	MSG_WriteFloat(&buf, movevars.stopspeed);
	MSG_WriteFloat(&buf, cl.maxspeed);
	MSG_WriteFloat(&buf, movevars.spectatormaxspeed);
	MSG_WriteFloat(&buf, movevars.accelerate);
	MSG_WriteFloat(&buf, movevars.airaccelerate);
	MSG_WriteFloat(&buf, movevars.wateraccelerate);
	MSG_WriteFloat(&buf, movevars.friction);
	MSG_WriteFloat(&buf, movevars.waterfriction);
	MSG_WriteFloat(&buf, cl.entgravity);

	// send music
	MSG_WriteByte (&buf, svc_cdtrack);
	MSG_WriteByte (&buf, 0); // none in demos

	// send server info string
	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );

	// flush packet
	CL_WriteRecordDemoMessage (&buf, seq++);
	SZ_Clear (&buf); 

// soundlist
	MSG_WriteByte (&buf, svc_soundlist);
	MSG_WriteByte (&buf, 0);

	n = 0;
	s = cl.sound_name[n+1];
	while (*s) {
		MSG_WriteString (&buf, s);
		if (buf.cursize > MAX_MSGLEN/2) {
			MSG_WriteByte (&buf, 0);
			MSG_WriteByte (&buf, n);
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
			MSG_WriteByte (&buf, svc_soundlist);
			MSG_WriteByte (&buf, n + 1);
		}
		n++;
		s = cl.sound_name[n+1];
	}
	if (buf.cursize) {
		MSG_WriteByte (&buf, 0);
		MSG_WriteByte (&buf, 0);
		CL_WriteRecordDemoMessage (&buf, seq++);
		SZ_Clear (&buf); 
	}

#ifdef VWEP_TEST
// vwep modellist
	if ((cl.z_ext & Z_EXT_VWEP) && cl.vw_model_name[0][0]) {
		// send VWep precaches
		// pray we don't overflow
		for (i = 0; i < MAX_VWEP_MODELS; i++) {
			s = cl.vw_model_name[i];
			if (!*s)
				continue;
			MSG_WriteByte (&buf, svc_serverinfo);
			MSG_WriteString (&buf, "#vw");
			MSG_WriteString (&buf, va("%i %s", i, TrimModelName(s)));
		}
		// send end-of-list messsage
		MSG_WriteByte (&buf, svc_serverinfo);
		MSG_WriteString (&buf, "#vw");
		MSG_WriteString (&buf, "");
	}
	// don't bother flushing, the vwep list is not that large (I hope)
#endif

// modellist
	MSG_WriteByte (&buf, svc_modellist);
	MSG_WriteByte (&buf, 0);

	n = 0;
	s = cl.model_name[n+1];
	while (*s) {
		MSG_WriteString (&buf, s);
		if (buf.cursize > MAX_MSGLEN/2) {
			MSG_WriteByte (&buf, 0);
			MSG_WriteByte (&buf, n);
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
			MSG_WriteByte (&buf, svc_modellist);
			MSG_WriteByte (&buf, n + 1);
		}
		n++;
		s = cl.model_name[n+1];
	}
	if (buf.cursize) {
		MSG_WriteByte (&buf, 0);
		MSG_WriteByte (&buf, 0);
		CL_WriteRecordDemoMessage (&buf, seq++);
		SZ_Clear (&buf); 
	}

// spawnstatic

	for (i = 0; i < cl.num_statics; i++) {
		ent = cl_static_entities + i;

		MSG_WriteByte (&buf, svc_spawnstatic);

		for (j = 1; j < MAX_MODELS; j++)
			if (ent->model == cl.model_precache[j])
				break;
		if (j == MAX_MODELS)
			MSG_WriteByte (&buf, 0);
		else
			MSG_WriteByte (&buf, j);

		MSG_WriteByte (&buf, ent->frame);
		MSG_WriteByte (&buf, 0);
		MSG_WriteByte (&buf, ent->skinnum);
		for (j=0 ; j<3 ; j++)
		{
			MSG_WriteCoord (&buf, ent->origin[j]);
			MSG_WriteAngle (&buf, ent->angles[j]);
		}

		if (buf.cursize > MAX_MSGLEN/2) {
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
		}
	}

// spawnstaticsound

	for (i = 0; i < cl.num_static_sounds; i++) {
		static_sound_t *ss = &cl.static_sounds[i];
		MSG_WriteByte (&buf, svc_spawnstaticsound);
		for (j = 0; j < 3; j++)
			MSG_WriteCoord (&buf, ss->org[j]);
		MSG_WriteByte (&buf, ss->sound_num);
		MSG_WriteByte (&buf, ss->vol);
		MSG_WriteByte (&buf, ss->atten);

		if (buf.cursize > MAX_MSGLEN/2) {
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
		}
	}

// baselines

	memset(&blankes, 0, sizeof(blankes));
	for (i = 0; i < MAX_CL_EDICTS; i++) {
		es = &cl_entities[i].baseline;

		if (memcmp(es, &blankes, sizeof(blankes))) {
			MSG_WriteByte (&buf,svc_spawnbaseline);		
			MSG_WriteShort (&buf, i);

			MSG_WriteByte (&buf, es->modelindex);
			MSG_WriteByte (&buf, es->frame);
			MSG_WriteByte (&buf, es->colormap);
			MSG_WriteByte (&buf, es->skinnum);
			for (j=0 ; j<3 ; j++)
			{
				MSG_WriteShort (&buf, es->s_origin[j]);
				MSG_WriteByte (&buf, es->s_angles[j]);
			}

			if (buf.cursize > MAX_MSGLEN/2) {
				CL_WriteRecordDemoMessage (&buf, seq++);
				SZ_Clear (&buf); 
			}
		}
	}

	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, va("cmd spawn %i 0\n", cl.servercount) );

	if (buf.cursize) {
		CL_WriteRecordDemoMessage (&buf, seq++);
		SZ_Clear (&buf); 
	}

// send current status of all other players

	for (i = 0; i < MAX_CLIENTS; i++) {
		player = cl.players + i;

		MSG_WriteByte (&buf, svc_updatefrags);
		MSG_WriteByte (&buf, i);
		MSG_WriteShort (&buf, player->frags);
		
		MSG_WriteByte (&buf, svc_updateping);
		MSG_WriteByte (&buf, i);
		MSG_WriteShort (&buf, player->ping);
		
		MSG_WriteByte (&buf, svc_updatepl);
		MSG_WriteByte (&buf, i);
		MSG_WriteByte (&buf, player->pl);
		
		MSG_WriteByte (&buf, svc_updateentertime);
		MSG_WriteByte (&buf, i);
		MSG_WriteFloat (&buf, cls.realtime - player->entertime);

		MSG_WriteByte (&buf, svc_updateuserinfo);
		MSG_WriteByte (&buf, i);
		MSG_WriteLong (&buf, player->userid);
		MSG_WriteString (&buf, player->userinfo);

		if (buf.cursize > MAX_MSGLEN/2) {
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
		}
	}
	
// send all current light styles
	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
	{
		if (!cl_lightstyle[i].length)
			continue;		// don't send empty lightstyle strings
		MSG_WriteByte (&buf, svc_lightstyle);
		MSG_WriteByte (&buf, (char)i);
		MSG_WriteString (&buf, cl_lightstyle[i].map);
	}

	for (i = 0; i < MAX_CL_STATS; i++) {
		if (!cl.stats[i])
			continue;		// no need to send zero values
		if (cl.stats[i] >= 0 && cl.stats[i] <= 255) {
			MSG_WriteByte (&buf, svc_updatestat);
			MSG_WriteByte (&buf, i);
			MSG_WriteByte (&buf, cl.stats[i]);
		} else {
			MSG_WriteByte (&buf, svc_updatestatlong);
			MSG_WriteByte (&buf, i);
			MSG_WriteLong (&buf, cl.stats[i]);
		}
		if (buf.cursize > MAX_MSGLEN/2) {
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
		}
	}

	// get the client to check and download skins
	// when that is completed, a begin command will be issued
	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, va("skins\n") );

	CL_WriteRecordDemoMessage (&buf, seq++);

	CL_WriteSetDemoMessage();

	// done
}
Пример #28
0
static qbool SV_MVD_Record (mvddest_t *dest)
{
	sizebuf_t	buf;
	byte buf_data[MAX_MSGLEN];
	int n, i;
	char *s, info[MAX_INFO_STRING];
	client_t *player;
	char *gamedir;

	if (!dest)
		return false;

	DestFlush(true);

	if (!sv.mvdrecording)
	{
		memset(&demo, 0, sizeof(demo));
		for (i = 0; i < UPDATE_BACKUP; i++)
		{
			demo.recorder.frames[i] = demo_frames[i];
			demo.recorder.frames[i].entities.entities = demo_entities[i];
		}

		MVDBuffer_Init(&demo.dbuffer, demo.buffer, sizeof(demo.buffer));
		MVDSetMsgBuf(NULL, &demo.frames[0].buf);

		demo.datagram.maxsize = sizeof(demo.datagram_data);
		demo.datagram.data = demo.datagram_data;

		sv.mvdrecording = true;
	}
//	else
//		SV_WriteRecordMVDMessage(&buf);

	demo.pingtime = demo.time = sv.time;

	dest->nextdest = demo.dest;
	demo.dest = dest;

	singledest = dest;

/*-------------------------------------------------*/

// serverdata
	// send the info about the new client to all connected clients
	SZ_Init (&buf, buf_data, sizeof(buf_data));

// send the serverdata

	gamedir = Info_ValueForKey (svs.info, "*gamedir");
	if (!gamedir[0])
		gamedir = "qw";

	MSG_WriteByte (&buf, svc_serverdata);

	MSG_WriteLong (&buf, PROTOCOL_VERSION);
	MSG_WriteLong (&buf, svs.spawncount);
	MSG_WriteString (&buf, gamedir);

	MSG_WriteFloat (&buf, sv.time);

	// send full levelname
	MSG_WriteString (&buf, sv.mapname);

	// send the movevars
	MSG_WriteFloat(&buf, sv.movevars.gravity);
	MSG_WriteFloat(&buf, sv.movevars.stopspeed);
	MSG_WriteFloat(&buf, sv.movevars.maxspeed);
	MSG_WriteFloat(&buf, sv.movevars.spectatormaxspeed);
	MSG_WriteFloat(&buf, sv.movevars.accelerate);
	MSG_WriteFloat(&buf, sv.movevars.airaccelerate);
	MSG_WriteFloat(&buf, sv.movevars.wateraccelerate);
	MSG_WriteFloat(&buf, sv.movevars.friction);
	MSG_WriteFloat(&buf, sv.movevars.waterfriction);
	MSG_WriteFloat(&buf, sv.movevars.entgravity);

	// send music
	MSG_WriteByte (&buf, svc_cdtrack);
	MSG_WriteByte (&buf, 0); // none in demos

	// send server info string
	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", svs.info) );

	// flush packet
	SV_WriteRecordMVDMessage (&buf);
	SZ_Clear (&buf);

// soundlist
	MSG_WriteByte (&buf, svc_soundlist);
	MSG_WriteByte (&buf, 0);

	n = 0;
	s = sv.sound_name[n+1];
	while (s)
	{
		MSG_WriteString (&buf, s);
		if (buf.cursize > MAX_MSGLEN/2)
		{
			MSG_WriteByte (&buf, 0);
			MSG_WriteByte (&buf, n);
			SV_WriteRecordMVDMessage (&buf);
			SZ_Clear (&buf);
			MSG_WriteByte (&buf, svc_soundlist);
			MSG_WriteByte (&buf, n + 1);
		}
		n++;
		s = sv.sound_name[n+1];
	}

	if (buf.cursize)
	{
		MSG_WriteByte (&buf, 0);
		MSG_WriteByte (&buf, 0);
		SV_WriteRecordMVDMessage (&buf);
		SZ_Clear (&buf);
	}

// modellist
	MSG_WriteByte (&buf, svc_modellist);
	MSG_WriteByte (&buf, 0);

	n = 0;
	s = sv.model_name[n+1];
	while (s)
	{
		MSG_WriteString (&buf, s);
		if (buf.cursize > MAX_MSGLEN/2)
		{
			MSG_WriteByte (&buf, 0);
			MSG_WriteByte (&buf, n);
			SV_WriteRecordMVDMessage (&buf);
			SZ_Clear (&buf);
			MSG_WriteByte (&buf, svc_modellist);
			MSG_WriteByte (&buf, n + 1);
		}
		n++;
		s = sv.model_name[n+1];
	}
	if (buf.cursize)
	{
		MSG_WriteByte (&buf, 0);
		MSG_WriteByte (&buf, 0);
		SV_WriteRecordMVDMessage (&buf);
		SZ_Clear (&buf);
	}

// baselines
	{
		entity_state_t from;
		edict_t *ent;
		entity_state_t *state;

		memset(&from, 0, sizeof(from));

		for (n = 0; n < sv.num_edicts; n++)
		{
			ent = EDICT_NUM(n);
			state = &ent->baseline;

			if (!state->number || !state->modelindex)
			{	//ent doesn't have a baseline
				continue;
			}

			if (!ent)
			{
				MSG_WriteByte(&buf, svc_spawnbaseline);

				MSG_WriteShort (&buf, n);

				MSG_WriteByte (&buf, 0);

				MSG_WriteByte (&buf, 0);
				MSG_WriteByte (&buf, 0);
				MSG_WriteByte (&buf, 0);
				for (i=0 ; i<3 ; i++)
				{
					MSG_WriteCoord(&buf, 0);
					MSG_WriteAngle(&buf, 0);
				}
			}
			else
			{
				MSG_WriteByte(&buf, svc_spawnbaseline);

				MSG_WriteShort (&buf, n);

				MSG_WriteByte (&buf, state->modelindex&255);

				MSG_WriteByte (&buf, state->frame);
				MSG_WriteByte (&buf, (int)state->colormap);
				MSG_WriteByte (&buf, (int)state->skinnum);
				for (i=0 ; i<3 ; i++)
				{
					MSG_WriteCoord(&buf, state->s_origin[i]);
					MSG_WriteAngle(&buf, state->s_angles[i]);
				}
			}
			if (buf.cursize > MAX_MSGLEN/2)
			{
				SV_WriteRecordMVDMessage (&buf);
				SZ_Clear (&buf);
			}
		}
	}

	//prespawn

	for (n = 0; n < sv.num_signon_buffers; n++)
	{
		if (buf.cursize+sv.signon_buffer_size[n] > MAX_MSGLEN/2)
		{
			SV_WriteRecordMVDMessage (&buf);
			SZ_Clear (&buf);
		}
		SZ_Write (&buf, sv.signon_buffers[n], sv.signon_buffer_size[n]);
	}

	if (buf.cursize > MAX_MSGLEN/2)
	{
		SV_WriteRecordMVDMessage (&buf);
		SZ_Clear (&buf);
	}

	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, va("cmd spawn %i\n",svs.spawncount) );

	if (buf.cursize)
	{
		SV_WriteRecordMVDMessage (&buf);
		SZ_Clear (&buf);
	}

// send current status of all other players

	for (i = 0; i < MAX_CLIENTS; i++)
	{
		player = svs.clients + i;

		MSG_WriteByte (&buf, svc_updatefrags);
		MSG_WriteByte (&buf, i);
		MSG_WriteShort (&buf, player->old_frags);

		MSG_WriteByte (&buf, svc_updateping);
		MSG_WriteByte (&buf, i);
		MSG_WriteShort (&buf, SV_CalcPing(player));

		MSG_WriteByte (&buf, svc_updatepl);
		MSG_WriteByte (&buf, i);
		MSG_WriteByte (&buf, player->lossage);

		MSG_WriteByte (&buf, svc_updateentertime);
		MSG_WriteByte (&buf, i);
		MSG_WriteFloat (&buf, svs.realtime - player->connection_started);

		Q_strncpyz (info, player->userinfo, MAX_INFO_STRING);
		Info_RemovePrefixedKeys (info, '_');	// server passwords, etc

		MSG_WriteByte (&buf, svc_updateuserinfo);
		MSG_WriteByte (&buf, i);
		MSG_WriteLong (&buf, player->userid);
		MSG_WriteString (&buf, info);

		if (buf.cursize > MAX_MSGLEN/2)
		{
			SV_WriteRecordMVDMessage (&buf);
			SZ_Clear (&buf);
		}
	}

// send all current light styles
	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
	{
		MSG_WriteByte (&buf, svc_lightstyle);
		MSG_WriteByte (&buf, (char)i);
		MSG_WriteString (&buf, sv.lightstyles[i]);
	}

	// get the client to check and download skins
	// when that is completed, a begin command will be issued
	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, "skins\n");

	SV_WriteRecordMVDMessage (&buf);

	SV_WriteSetMVDMessage();

	singledest = NULL;

	// done
	return true;
}
Пример #29
0
/*
====================
CL_Record_f

record <demoname> <server>
====================
*/
void CL_Record_f (void)
{
	int		c;
	char	name[MAX_OSPATH];
	sizebuf_t	buf;
	char	buf_data[MAX_MSGLEN];
	int n, i, j;
	char *s;
	entity_t *ent;
	entity_state_t *es, blankes;
	player_info_t *player;
	extern	char gamedirfile[];
	int seq = 1;

	c = Cmd_Argc();
	if (c != 2)
	{
		Con_Printf ("record <demoname>\n");
		return;
	}

	if (cls.state != ca_active) {
		Con_Printf ("You must be connected to record.\n");
		return;
	}

	if (cls.demorecording)
		CL_Stop_f();
  
	sprintf (name, "%s/%s", com_gamedir, Cmd_Argv(1));

//
// open the demo file
//
	COM_DefaultExtension (name, ".qwd");

	cls.demofile = fopen (name, "wb");
	if (!cls.demofile)
	{
		Con_Printf ("ERROR: couldn't open.\n");
		return;
	}

	Con_Printf ("recording to %s.\n", name);
	cls.demorecording = true;

/*-------------------------------------------------*/

// serverdata
	// send the info about the new client to all connected clients
	memset(&buf, 0, sizeof(buf));
	buf.data = buf_data;
	buf.maxsize = sizeof(buf_data);

// send the serverdata
	MSG_WriteByte (&buf, svc_serverdata);
	MSG_WriteLong (&buf, PROTOCOL_VERSION);
	MSG_WriteLong (&buf, cl.servercount);
	MSG_WriteString (&buf, gamedirfile);

	if (cl.spectator)
		MSG_WriteByte (&buf, cl.playernum | 128);
	else
		MSG_WriteByte (&buf, cl.playernum);

	// send full levelname
	MSG_WriteString (&buf, cl.levelname);

	// send the movevars
	MSG_WriteFloat(&buf, movevars.gravity);
	MSG_WriteFloat(&buf, movevars.stopspeed);
	MSG_WriteFloat(&buf, movevars.maxspeed);
	MSG_WriteFloat(&buf, movevars.spectatormaxspeed);
	MSG_WriteFloat(&buf, movevars.accelerate);
	MSG_WriteFloat(&buf, movevars.airaccelerate);
	MSG_WriteFloat(&buf, movevars.wateraccelerate);
	MSG_WriteFloat(&buf, movevars.friction);
	MSG_WriteFloat(&buf, movevars.waterfriction);
	MSG_WriteFloat(&buf, movevars.entgravity);

	// send music
	MSG_WriteByte (&buf, svc_cdtrack);
	MSG_WriteByte (&buf, 0); // none in demos

	// send server info string
	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );

	// flush packet
	CL_WriteRecordDemoMessage (&buf, seq++);
	SZ_Clear (&buf); 

// soundlist
	MSG_WriteByte (&buf, svc_soundlist);
	MSG_WriteByte (&buf, 0);

	n = 0;
	s = cl.sound_name[n+1];
	while (*s) {
		MSG_WriteString (&buf, s);
		if (buf.cursize > MAX_MSGLEN/2) {
			MSG_WriteByte (&buf, 0);
			MSG_WriteByte (&buf, n);
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
			MSG_WriteByte (&buf, svc_soundlist);
			MSG_WriteByte (&buf, n + 1);
		}
		n++;
		s = cl.sound_name[n+1];
	}
	if (buf.cursize) {
		MSG_WriteByte (&buf, 0);
		MSG_WriteByte (&buf, 0);
		CL_WriteRecordDemoMessage (&buf, seq++);
		SZ_Clear (&buf); 
	}

// modellist
	MSG_WriteByte (&buf, svc_modellist);
	MSG_WriteByte (&buf, 0);

	n = 0;
	s = cl.model_name[n+1];
	while (*s) {
		MSG_WriteString (&buf, s);
		if (buf.cursize > MAX_MSGLEN/2) {
			MSG_WriteByte (&buf, 0);
			MSG_WriteByte (&buf, n);
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
			MSG_WriteByte (&buf, svc_modellist);
			MSG_WriteByte (&buf, n + 1);
		}
		n++;
		s = cl.model_name[n+1];
	}
	if (buf.cursize) {
		MSG_WriteByte (&buf, 0);
		MSG_WriteByte (&buf, 0);
		CL_WriteRecordDemoMessage (&buf, seq++);
		SZ_Clear (&buf); 
	}

// spawnstatic

	for (i = 0; i < cl.num_statics; i++) {
		ent = cl_static_entities + i;

		MSG_WriteByte (&buf, svc_spawnstatic);

		for (j = 1; j < MAX_MODELS; j++)
			if (ent->model == cl.model_precache[j])
				break;
		if (j == MAX_MODELS)
			MSG_WriteByte (&buf, 0);
		else
			MSG_WriteByte (&buf, j);

		MSG_WriteByte (&buf, ent->frame);
		MSG_WriteByte (&buf, 0);
		MSG_WriteByte (&buf, ent->skinnum);
		for (j=0 ; j<3 ; j++)
		{
			MSG_WriteCoord (&buf, ent->origin[j]);
			MSG_WriteAngle (&buf, ent->angles[j]);
		}

		if (buf.cursize > MAX_MSGLEN/2) {
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
		}
	}

// spawnstaticsound
	// static sounds are skipped in demos, life is hard

// baselines

	memset(&blankes, 0, sizeof(blankes));
	for (i = 0; i < MAX_EDICTS; i++) {
		es = cl_baselines + i;

		if (memcmp(es, &blankes, sizeof(blankes))) {
			MSG_WriteByte (&buf,svc_spawnbaseline);		
			MSG_WriteShort (&buf, i);

			MSG_WriteByte (&buf, es->modelindex);
			MSG_WriteByte (&buf, es->frame);
			MSG_WriteByte (&buf, es->colormap);
			MSG_WriteByte (&buf, es->skinnum);
			for (j=0 ; j<3 ; j++)
			{
				MSG_WriteCoord(&buf, es->origin[j]);
				MSG_WriteAngle(&buf, es->angles[j]);
			}

			if (buf.cursize > MAX_MSGLEN/2) {
				CL_WriteRecordDemoMessage (&buf, seq++);
				SZ_Clear (&buf); 
			}
		}
	}

	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, va("cmd spawn %i 0\n", cl.servercount) );

	if (buf.cursize) {
		CL_WriteRecordDemoMessage (&buf, seq++);
		SZ_Clear (&buf); 
	}

// send current status of all other players

	for (i = 0; i < MAX_CLIENTS; i++) {
		player = cl.players + i;

		MSG_WriteByte (&buf, svc_updatefrags);
		MSG_WriteByte (&buf, i);
		MSG_WriteShort (&buf, player->frags);
		
		MSG_WriteByte (&buf, svc_updateping);
		MSG_WriteByte (&buf, i);
		MSG_WriteShort (&buf, player->ping);
		
		MSG_WriteByte (&buf, svc_updatepl);
		MSG_WriteByte (&buf, i);
		MSG_WriteByte (&buf, player->pl);
		
		MSG_WriteByte (&buf, svc_updateentertime);
		MSG_WriteByte (&buf, i);
		MSG_WriteFloat (&buf, player->entertime);

		MSG_WriteByte (&buf, svc_updateuserinfo);
		MSG_WriteByte (&buf, i);
		MSG_WriteLong (&buf, player->userid);
		MSG_WriteString (&buf, player->userinfo);

		if (buf.cursize > MAX_MSGLEN/2) {
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
		}
	}
	
// send all current light styles
	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
	{
		MSG_WriteByte (&buf, svc_lightstyle);
		MSG_WriteByte (&buf, (char)i);
		MSG_WriteString (&buf, cl_lightstyle[i].map);
	}

	for (i = 0; i < MAX_CL_STATS; i++) {
		MSG_WriteByte (&buf, svc_updatestatlong);
		MSG_WriteByte (&buf, i);
		MSG_WriteLong (&buf, cl.stats[i]);
		if (buf.cursize > MAX_MSGLEN/2) {
			CL_WriteRecordDemoMessage (&buf, seq++);
			SZ_Clear (&buf); 
		}
	}

#if 0
	MSG_WriteByte (&buf, svc_updatestatlong);
	MSG_WriteByte (&buf, STAT_TOTALMONSTERS);
	MSG_WriteLong (&buf, cl.stats[STAT_TOTALMONSTERS]);

	MSG_WriteByte (&buf, svc_updatestatlong);
	MSG_WriteByte (&buf, STAT_SECRETS);
	MSG_WriteLong (&buf, cl.stats[STAT_SECRETS]);

	MSG_WriteByte (&buf, svc_updatestatlong);
	MSG_WriteByte (&buf, STAT_MONSTERS);
	MSG_WriteLong (&buf, cl.stats[STAT_MONSTERS]);
#endif

	// get the client to check and download skins
	// when that is completed, a begin command will be issued
	MSG_WriteByte (&buf, svc_stufftext);
	MSG_WriteString (&buf, va("skins\n") );

	CL_WriteRecordDemoMessage (&buf, seq++);

	CL_WriteSetDemoMessage();

	// done
}
Пример #30
0
static void
PF_clientsound (progs_t *pr)
{
	const char *sample;
	int         channel;
	edict_t    *entity;
	int         volume;
	float       attenuation;

	int         sound_num;
	int         i;
	pr_int_t    ent;
	vec3_t      origin;

	entity = P_EDICT (pr, 0);
	channel = P_FLOAT (pr, 1);
	sample = P_GSTRING (pr, 2);
	volume = P_FLOAT (pr, 3) * 255;
	attenuation = P_FLOAT (pr, 4);

	ent = NUM_FOR_EDICT (pr, entity);

	// If not a client go away
	if (ent > MAX_CLIENTS || ent < 1)
		return;

	if (volume < 0 || volume > 255)
		Sys_Error ("SV_StartSound: volume = %i", volume);

	if (attenuation < 0 || attenuation > 4)
		Sys_Error ("SV_StartSound: attenuation = %f", attenuation);

	if (channel < 0 || channel > 15)
		Sys_Error ("SV_StartSound: channel = %i", channel);

// find precache number for sound
	for (sound_num = 1; sound_num < MAX_SOUNDS
		 && sv.sound_precache[sound_num]; sound_num++)
		if (!strcmp (sample, sv.sound_precache[sound_num]))
			break;

	if (sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num]) {
		Sys_Printf ("SV_StartSound: %s not precacheed\n", sample);
		return;
	}

	channel &= 7;

	channel = (ent << 3) | channel;

	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
		channel |= SND_VOLUME;
	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
		channel |= SND_ATTENUATION;

	// use the entity origin
	VectorCopy (SVvector (entity, origin), origin);

	MSG_WriteByte (&svs.clients[ent - 1].netchan.message, svc_sound);
	MSG_WriteShort (&svs.clients[ent - 1].netchan.message, channel);
	if (channel & SND_VOLUME)
		MSG_WriteByte (&svs.clients[ent - 1].netchan.message, volume);
	if (channel & SND_ATTENUATION)
		MSG_WriteByte (&svs.clients[ent - 1].netchan.message, attenuation * 64);
	MSG_WriteByte (&svs.clients[ent - 1].netchan.message, sound_num);
	for (i = 0; i < 3; i++)
		MSG_WriteCoord (&svs.clients[ent - 1].netchan.message, origin[i]);
}