コード例 #1
0
ファイル: sv_effect.c プロジェクト: bsmr-games/Hexen2
void SV_UpdateEffects(sizebuf_t *sb)
{
	int index;

	for(index=0;index<MAX_EFFECTS;index++)
		if (sv.Effects[index].type)
			SV_SendEffect(sb,index);
}
コード例 #2
0
ファイル: sv_effect.c プロジェクト: svn2github/uhexen2
void SV_UpdateEffects (sizebuf_t *sb)
{
	int		idx;

	for (idx = 0 ; idx < MAX_EFFECTS ; idx++)
	{
		if (sv.Effects[idx].type)
			SV_SendEffect(sb, idx);
	}
}
コード例 #3
0
ファイル: sv_effect.c プロジェクト: svn2github/uhexen2
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
void SV_ParseEffect (sizebuf_t *sb)
{
	int		idx;
	byte		effect;

	effect = G_FLOAT(OFS_PARM0);

	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;
	}

//	Con_Printf("Effect #%d\n", idx);

	memset(&sv.Effects[idx], 0, sizeof(struct EffectT));

	sv.Effects[idx].type = effect;
	G_FLOAT(OFS_RETURN) = idx;

	switch (effect)
	{
	case CE_RAIN:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Rain.min_org);
		VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Rain.max_org);
		VectorCopy(G_VECTOR(OFS_PARM3), sv.Effects[idx].ef.Rain.e_size);
		VectorCopy(G_VECTOR(OFS_PARM4), sv.Effects[idx].ef.Rain.dir);
		sv.Effects[idx].ef.Rain.color = G_FLOAT(OFS_PARM5);
		sv.Effects[idx].ef.Rain.count = G_FLOAT(OFS_PARM6);
		sv.Effects[idx].ef.Rain.wait = G_FLOAT(OFS_PARM7);

		sv.Effects[idx].ef.Rain.next_time = 0;
		break;

	case CE_SNOW:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Rain.min_org);
		VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Rain.max_org);
		sv.Effects[idx].ef.Rain.flags = G_FLOAT(OFS_PARM3);
		VectorCopy(G_VECTOR(OFS_PARM4), sv.Effects[idx].ef.Rain.dir);
		sv.Effects[idx].ef.Rain.count = G_FLOAT(OFS_PARM5);
		//sv.Effects[idx].Rain.veer = G_FLOAT(OFS_PARM6);
		//sv.Effects[idx].Rain.wait = 0.10;
		sv.Effects[idx].ef.Rain.next_time = 0;
		break;

	case CE_FOUNTAIN:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Fountain.pos);
		VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Fountain.angle);
		VectorCopy(G_VECTOR(OFS_PARM3), sv.Effects[idx].ef.Fountain.movedir);
		sv.Effects[idx].ef.Fountain.color = G_FLOAT(OFS_PARM4);
		sv.Effects[idx].ef.Fountain.cnt = G_FLOAT(OFS_PARM5);
		break;

	case CE_QUAKE:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Quake.origin);
		sv.Effects[idx].ef.Quake.radius = G_FLOAT(OFS_PARM2);
		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:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Smoke.origin);
		VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Smoke.velocity);
		sv.Effects[idx].ef.Smoke.framelength = G_FLOAT(OFS_PARM3);
		sv.Effects[idx].ef.Smoke.frame = 0;
		sv.Effects[idx].expire_time = sv.time + 1;
		break;

	case CE_ACID_MUZZFL:
	case CE_FLAMESTREAM:
	case CE_FLAMEWALL:
	case CE_FLAMEWALL2:
	case CE_ONFIRE:
	/* mission pack */
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Smoke.origin);
		VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Smoke.velocity);
		sv.Effects[idx].ef.Smoke.framelength = 0.05;
		sv.Effects[idx].ef.Smoke.frame = G_FLOAT(OFS_PARM3);
		sv.Effects[idx].expire_time = sv.time + 1;
		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:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Smoke.origin);
		sv.Effects[idx].expire_time = sv.time + 1;
		break;

	case CE_WHITE_FLASH:
	case CE_BLUE_FLASH:
	case CE_SM_BLUE_FLASH:
	case CE_RED_FLASH:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Flash.origin);
		sv.Effects[idx].expire_time = sv.time + 1;
		break;

	case CE_RIDER_DEATH:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.RD.origin);
		break;

	case CE_GRAVITYWELL:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.RD.origin);
		sv.Effects[idx].ef.RD.color = G_FLOAT(OFS_PARM2);
		sv.Effects[idx].ef.RD.lifetime = G_FLOAT(OFS_PARM3);
		break;

	case CE_TELEPORTERPUFFS:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Teleporter.origin);
		sv.Effects[idx].expire_time = sv.time + 1;
		break;

	case CE_TELEPORTERBODY:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Teleporter.origin);
		VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Teleporter.velocity[0]);
		sv.Effects[idx].ef.Teleporter.skinnum = G_FLOAT(OFS_PARM3);
		sv.Effects[idx].expire_time = sv.time + 1;
		break;

	case CE_BONESHARD:
	case CE_BONESHRAPNEL:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Missile.origin);
		VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Missile.velocity);
		VectorCopy(G_VECTOR(OFS_PARM3), sv.Effects[idx].ef.Missile.angle);
		VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Missile.avelocity);
		sv.Effects[idx].expire_time = sv.time + 10;
		break;

	case CE_CHUNK:
		VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Chunk.origin);
		sv.Effects[idx].ef.Chunk.type = G_FLOAT(OFS_PARM2);
		VectorCopy(G_VECTOR(OFS_PARM3), sv.Effects[idx].ef.Chunk.srcVel);
		sv.Effects[idx].ef.Chunk.numChunks = G_FLOAT(OFS_PARM4);
		sv.Effects[idx].expire_time = sv.time + 3;
		break;

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

	SV_SendEffect(sb, idx);
}
コード例 #4
0
ファイル: sv_effect.c プロジェクト: bsmr-games/Hexen2
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
void SV_ParseEffect(sizebuf_t *sb)
{
	int index;
	byte effect;

	effect = G_FLOAT(OFS_PARM0);

	for(index=0;index<MAX_EFFECTS;index++)
		if (!sv.Effects[index].type || 
			(sv.Effects[index].expire_time && sv.Effects[index].expire_time <= sv.time)) 
			break;
		
	if (index >= MAX_EFFECTS)
	{
		PR_RunError ("MAX_EFFECTS reached");
		return;
	}

//	Con_Printf("Effect #%d\n",index);

	memset(&sv.Effects[index],0,sizeof(struct EffectT));

	sv.Effects[index].type = effect;
	G_FLOAT(OFS_RETURN) = index;

	switch(effect)
	{
		case CE_RAIN:
			VectorCopy(G_VECTOR(OFS_PARM1),sv.Effects[index].Rain.min_org);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Rain.max_org);
			VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Rain.e_size);
			VectorCopy(G_VECTOR(OFS_PARM4),sv.Effects[index].Rain.dir);
			sv.Effects[index].Rain.color = G_FLOAT(OFS_PARM5);
			sv.Effects[index].Rain.count = G_FLOAT(OFS_PARM6);
			sv.Effects[index].Rain.wait = G_FLOAT(OFS_PARM7);

			sv.Effects[index].Rain.next_time = 0;
			break;

		case CE_FOUNTAIN:
			VectorCopy(G_VECTOR(OFS_PARM1),sv.Effects[index].Fountain.pos);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Fountain.angle);
			VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Fountain.movedir);
			sv.Effects[index].Fountain.color = G_FLOAT(OFS_PARM4);
			sv.Effects[index].Fountain.cnt = G_FLOAT(OFS_PARM5);
			break;

		case CE_QUAKE:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Quake.origin);
			sv.Effects[index].Quake.radius = G_FLOAT(OFS_PARM2);
			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_RIPPLE:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin);
			VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Smoke.velocity);
			sv.Effects[index].Smoke.framelength = G_FLOAT(OFS_PARM3);

			sv.Effects[index].expire_time = sv.time + 1;
			break;

		case CE_ACID_MUZZFL:
		case CE_FLAMESTREAM:
		case CE_FLAMEWALL:
		case CE_FLAMEWALL2:
		case CE_ONFIRE:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin);
			VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Smoke.velocity);
			sv.Effects[index].Smoke.framelength = 0.05;
			sv.Effects[index].Smoke.frame = G_FLOAT(OFS_PARM3);
			sv.Effects[index].expire_time = sv.time + 1;
			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:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin);
			sv.Effects[index].expire_time = sv.time + 1;
			break;

		case CE_WHITE_FLASH:
		case CE_BLUE_FLASH:
		case CE_SM_BLUE_FLASH:
		case CE_HWSPLITFLASH:
		case CE_RED_FLASH:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Flash.origin);
			sv.Effects[index].expire_time = sv.time + 1;
			break;

		case CE_RIDER_DEATH:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].RD.origin);
			break;

		case CE_TELEPORTERPUFFS:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Teleporter.origin);
			sv.Effects[index].expire_time = sv.time + 1;
			break;

		case CE_TELEPORTERBODY:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Teleporter.origin);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Teleporter.velocity[0]);
			sv.Effects[index].Teleporter.skinnum = G_FLOAT(OFS_PARM3);
			sv.Effects[index].expire_time = sv.time + 1;
			break;

		case CE_BONESHRAPNEL:
		case CE_HWBONEBALL:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Missile.origin);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.velocity);
			VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Missile.angle);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.avelocity);

			sv.Effects[index].expire_time = sv.time + 10;
			break;
		case CE_BONESHARD:
		case CE_HWRAVENSTAFF:
		case CE_HWMISSILESTAR:
		case CE_HWEIDOLONSTAR:
		case CE_HWRAVENPOWER:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Missile.origin);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.velocity);
			sv.Effects[index].expire_time = sv.time + 10;
			break;
		case CE_DEATHBUBBLES:
			VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Bubble.offset);
			sv.Effects[index].Bubble.owner = G_EDICTNUM(OFS_PARM1);
			sv.Effects[index].Bubble.count = G_FLOAT(OFS_PARM3);
			sv.Effects[index].expire_time = sv.time + 30;
			break;
		case CE_HWDRILLA:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Missile.origin);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.angle);
			sv.Effects[index].Missile.speed = G_FLOAT(OFS_PARM3);
			sv.Effects[index].expire_time = sv.time + 10;
			break;
		case CE_TRIPMINESTILL:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Chain.origin);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Chain.velocity);
			sv.Effects[index].expire_time = sv.time + 70;
			break;
		case CE_TRIPMINE:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Chain.origin);
			VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Chain.velocity);
			sv.Effects[index].expire_time = sv.time + 10;
			break;
		case CE_SCARABCHAIN:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Chain.origin);
			sv.Effects[index].Chain.owner = G_EDICTNUM(OFS_PARM2);
			sv.Effects[index].Chain.material = G_INT(OFS_PARM3);
			sv.Effects[index].Chain.tag = G_INT(OFS_PARM4);
			sv.Effects[index].Chain.state = 0;
			sv.Effects[index].expire_time = sv.time + 15;
			break;
		case CE_HWSHEEPINATOR:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[0]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[1]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[2]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[3]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[4]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[5]);
			VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Xbow.angle);
			sv.Effects[index].Xbow.bolts = 5;
			sv.Effects[index].Xbow.activebolts = 31;
			sv.Effects[index].Xbow.randseed = 0;
			sv.Effects[index].Xbow.turnedbolts = 0;
			sv.Effects[index].expire_time = sv.time + 7;
			break;
		case CE_HWXBOWSHOOT:
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[0]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[1]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[2]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[3]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[4]);
			VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[5]);
			VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Xbow.angle);
			sv.Effects[index].Xbow.bolts = G_FLOAT(OFS_PARM3);
			sv.Effects[index].Xbow.randseed = G_FLOAT(OFS_PARM4);
			sv.Effects[index].Xbow.turnedbolts = 0;
			if (sv.Effects[index].Xbow.bolts == 3)
			{
				sv.Effects[index].Xbow.activebolts = 7;
			}
			else
			{
				sv.Effects[index].Xbow.activebolts = 31;
			}
			sv.Effects[index].expire_time = sv.time + 15;
			break;
		default:
//			Sys_Error ("SV_ParseEffect: bad type");
			PR_RunError ("SV_SendEffect: bad type");
	}

	SV_SendEffect(sb,index);
}
コード例 #5
0
/*
===================
SV_ExecuteClientMessage

The current net_message is parsed for the given client
===================
*/
void SV_ExecuteClientMessage (client_t *cl)
{
	int		c;
	const char	*s;
	usercmd_t	oldest, oldcmd, newcmd;
	client_frame_t	*frame;
	vec3_t	o;

	// calc ping time
	frame = &cl->frames[cl->netchan.incoming_acknowledged & UPDATE_MASK];
	frame->ping_time = realtime - frame->senttime;

	// make sure the reply sequence number matches the incoming
	// sequence number
	if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
		cl->netchan.outgoing_sequence = cl->netchan.incoming_sequence;
	else
		cl->send_message = false;	// don't reply, sequences have slipped

	// save time for ping calculations
	cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].senttime = realtime;
	cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;

	host_client = cl;
	sv_player = host_client->edict;

	// mark time so clients will know how much to predict
	// other players
	cl->localtime = sv.time;
	cl->delta_sequence = -1;	// no delta unless requested
	while (1)
	{
		if (msg_badread)
		{
			Con_Printf ("%s: badread\n", __thisfunc__);
			SV_DropClient (cl);
			return;
		}

		c = MSG_ReadByte ();
		if (c == -1)
			break;

		switch (c)
		{
		default:
			Con_Printf ("%s: unknown command char\n", __thisfunc__);
			SV_DropClient (cl);
			return;

		case clc_nop:
			break;

		case clc_delta:
			cl->delta_sequence = MSG_ReadByte ();
			break;

		case clc_move:
			MSG_ReadUsercmd (&oldest, false);
			MSG_ReadUsercmd (&oldcmd, false);
			MSG_ReadUsercmd (&newcmd, true);

			if ( cl->state != cs_spawned )
				break;

			SV_PreRunCmd();

			if (net_drop < 20)
			{
				while (net_drop > 2)
				{
					SV_RunCmd (&cl->lastcmd);
					net_drop--;
				}
				if (net_drop > 1)
					SV_RunCmd (&oldest);
				if (net_drop > 0)
					SV_RunCmd (&oldcmd);
			}
			SV_RunCmd (&newcmd);

			SV_PostRunCmd();

			cl->lastcmd = newcmd;
			cl->lastcmd.buttons = 0; // avoid multiple fires on lag
			break;

		case clc_stringcmd:
			s = MSG_ReadString ();
			SV_ExecuteUserCommand (s);
			break;

		case clc_tmove:
			o[0] = MSG_ReadCoord();
			o[1] = MSG_ReadCoord();
			o[2] = MSG_ReadCoord();
			// only allowed by spectators
			if (host_client->spectator)
			{
				VectorCopy(o, sv_player->v.origin);
				SV_LinkEdict(sv_player, false);
			}
			break;

		case clc_inv_select:
			cl->edict->v.inventory = MSG_ReadByte();
			break;

		case clc_get_effect:
			c = MSG_ReadByte();
			if (sv.Effects[c].type)
			{
				Con_Printf("Getting effect %d\n",(int)c);
				SV_SendEffect(&host_client->netchan.message, c);
			}
			break;
		}
	}
}