Multiplayer and setangles incompadible?

Discuss anything not covered by any of the other categories.
Post Reply
Wazat
Posts: 771
Joined: Fri Oct 15, 2004 9:50 pm
Location: Middle 'o the desert, USA

Multiplayer and setangles incompadible?

Post by Wazat »

In the mod I'm making for Q-Expo, I have the player hovering in the air invisible acting as the camera. He follows the character through the level. The player is testing his own movements to see what directional keys the user is pressing, and moves the "puppet" (as I call the character on the field) around accordingly.

It all works fine in single player, and I can even turn on deathmatch with no problem. A problem does, however, rear its ugly head when I run Darkplaces with the command -listen to start a real multiplayer game. Now all of a sudden when the camera changes angles (either with the left/right strafe keys or with impulses) it's very choppy, where in single player it was very smooth. Moving forward, backward, and strafing left & right is still perfectly smooth, only angles experience a problem.

Are net messages (such as setangle) sent to the client too infrequently in multiplayer to to give a smooth ride? Or is there something I could do differently?
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
FrikaC
Site Admin
Posts: 1026
Joined: Fri Oct 08, 2004 11:19 pm

Post by FrikaC »

DP lowers the effective ticrate of the server in multiplayer. Because of this, the server is not running at your client's framerate anymore. You'll experience something akin to a mild lag, but it prevents the server from flooding the holy hell out of other networked clients.

I'm guessing that's the problem here......
Wazat
Posts: 771
Joined: Fri Oct 15, 2004 9:50 pm
Location: Middle 'o the desert, USA

Post by Wazat »

Okay, that makes sense. Is there anything I can do to make it look better without bogging down the network?
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

smooth camera

Post by r00k »

you can try stuffing

stuffcmd(self, "cl_nolerp 1\n");

when you are in camera view...

also old quake protocol used 256-byte variable as angle not float
in the engine. Unless you are using a modified client you should
try
angle_x = 360.0 / 256.0 * rint(self.movetarget.v_angle_x * 256.0 / 360.0);
angle_y = 360.0 / 256.0 * rint(self.movetarget.v_angle_y * 256.0 / 360.0);
angle_z = 0;

.movetarget points to the "puppet"

hope this is of some use...
Error
InsideQC Staff
Posts: 865
Joined: Fri Nov 05, 2004 5:15 am
Location: VA, USA
Contact:

Post by Error »

I like stuffing. tastes good :wink:

I'm gonna stop making random comments in coding posts and start coding again :D
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Post by r00k »

Better yet,
goto www.runequake.com and download runequake...

ok look in his poq source and u will find a file called
camera.qc
this file does exactly what you are trying to do!
and it works flawless, i have tried it online and its great!

Credit to slotzero!
Tei
Posts: 193
Joined: Mon Oct 25, 2004 12:22 pm

Post by Tei »

good work r00k
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Post by r00k »

ok i tinkered with slot's code a bit and heres what i came up with
(sorry its long)

Code: Select all

void () W_SetCurrentAmmo;
void () Keep_cam_chasing_owner;

// Resets weapon model after changing view
// called by chase cam or player entities
void (entity player_ent)
Chase_cam_setweapon =
{
	local entity e;

	e = self;
	self = player_ent;
	W_SetCurrentAmmo ();
	self = e;
};

// called either by player or chase cam entities (to restart)
void (entity cam_owner)
Start_chase_cam =
{
	local entity chase_cam;
	//look to see if we already have cam ent
	chase_cam = find (world,classname, "chase_cam");
	while ((chase_cam != world) && (chase_cam.owner != cam_owner))
	{
		chase_cam = find (chase_cam,classname, "chase_cam");
	}
	if (chase_cam == world)
	{	
		chase_cam = spawn ();
	}
	
	chase_cam.owner			= cam_owner;
	chase_cam.owner.chase_active 	= TRUE;
	chase_cam.solid 		= SOLID_NOT;
	chase_cam.movetype 		= MOVETYPE_FLYMISSILE;
	chase_cam.angles 		= chase_cam.owner.angles;
	setmodel (chase_cam, "progs/eyes.mdl");
	setsize (chase_cam, VEC_ORIGIN, VEC_ORIGIN);
	setorigin (chase_cam, chase_cam.owner.origin);
	chase_cam.classname 		= "chase_cam";
	chase_cam.nextthink 		= time + sys_ticrate;
	chase_cam.think 		= Keep_cam_chasing_owner;

	msg_entity = chase_cam.owner;			// target of message
	WriteByte (MSG_ONE, SVC_SETVIEWPORT);
	WriteEntity (MSG_ONE, chase_cam);		// view port

	cam_owner.weaponmodel = "";
};

// secondary think for cam entities
void ()Reable_chase_cam =
{
	local entity boss;
	
	self.nextthink = time + sys_ticrate;
	if (self.owner.health <= 0)
	{
		remove (self);
		return;
	}

	if (self.owner.waterlevel > 0)
	return;
	//refresh after water
	boss = self.owner;		
	remove (self);
	Start_chase_cam (boss);
};

// called only by chase cam entities
// opt values
// TRUE = remove completely
// FALSE = remove view but keep alive with Reable_chase_cam();
void (float opt)Remove_chase_cam =
{
	// makes entity appear gone even if going into keep alive state
	setmodel (self, "");
	self.velocity = VEC_ORIGIN;

	// set view-point back to normal
	msg_entity = self.owner;      // target of message
	WriteByte (MSG_ONE, SVC_SETVIEWPORT);
	WriteEntity (MSG_ONE, self.owner);           // view port	
	Chase_cam_setweapon (self.owner);

	if (!opt)
	{
		self.nextthink = time + sys_ticrate;
		self.think = Reable_chase_cam;
	}
	else
	{
		remove (self);
	}
	
};

/*
###########
main think function for cam entities
self.ammo_shells = distance clipping
self.ammo_nails = hang-up flag
self.ammo_cells = view offset direction
0 = up
1 = left
2 = right
###########
*/
void () Keep_cam_chasing_owner =
{
	local vector pos;
	local vector desired_angle;
	local vector angle;	
	local vector dir;
	local float dist, cap;


	self.nextthink = time + sys_ticrate;

	// check if player turned off
	// or in water
	if (self.owner.chase_active == FALSE)
	{
		Remove_chase_cam (TRUE);
		return;
	}
	if (self.owner.waterlevel > 0)
	{
		if (self.owner.health > 0)
		{
			Remove_chase_cam (FALSE);
			return;
		}
	}

	desired_angle = self.owner.v_angle;

	angle_x = ((self.oldangle_x * (1 - 0.6)) + (desired_angle_x * 0.6));
	angle_y = angles_pick_angle (self.oldangle_y, desired_angle_y, 0.6);
	angle_z = 0;

	angle_x = (angle_x * 1);
	angle_y = (angle_y * 1);

	makevectors (angle);
	
	pos = self.owner.origin;

	traceline (pos, (pos + (32 * v_up)), TRUE, self.owner);
	pos = (pos + ((trace_fraction * 22) * v_up));

	traceline (pos, (pos - (120 * v_forward)), TRUE, self.owner);
	pos = (pos - ((trace_fraction * 100) * v_forward));

	traceline (pos, pos + '0 0 32', FALSE, self.owner);
	if (trace_fraction < 1)
	{
		dir = trace_endpos - '0 0 32';

		traceline (pos, pos - '0 0 32', FALSE, self.owner);
		if (trace_fraction == 1)
		pos = dir;
	}

	dir = normalize (pos - self.origin);
	dist = vlen (pos - self.origin);
	
	traceline (self.origin, pos, FALSE, self.owner);

	if (trace_fraction == 1)
	{
		self.angles = self.owner.angles;

		cap = dist * 0.2;

		if (cap > 5.2)
		self.velocity = dir * dist * 5.2;
		else if (cap > 1)
		self.velocity = dir * dist * cap;
		else
		self.velocity = dir * dist;
	}

	setorigin (self, pos);

	angles_fixangle (angle);
	self.owner.weaponmodel = "";
};

// called by player only
void ()
Toggle_chase_cam =
{
	if ((self.chase_active == TRUE))
	{
		// will be noticed by next think
		// of player's chase cam entity
		self.chase_active = FALSE;
	}
	else
	{
		Start_chase_cam (self);
	}
};

void ()
Chase_cam_lvlstart_think =
{
	if ((self.owner.chase_active == TRUE))
		Start_chase_cam (self.owner);
	remove (self);
};

// called in CLIENT.QC by PutClientInServer
// player.chase_active is set and saved between levels using parm16
// in CLIENT.QC
void ()
Chase_cam_level_start =
{
	local entity e;

	e = spawn ();
	e.owner = self;

	e.movetype = MOVETYPE_NONE;
	e.solid = SOLID_NOT;

	setmodel (e, "");
	setsize (e, VEC_ORIGIN, VEC_ORIGIN);
	setorigin (e, e.owner.origin);

	e.nextthink = time + 0.2;
	e.think = Chase_cam_lvlstart_think;
};
Wazat
Posts: 771
Joined: Fri Oct 15, 2004 9:50 pm
Location: Middle 'o the desert, USA

Post by Wazat »

Thanks, r00k.

Looking at that code, I notice a few things it's doing that I'm not. First of all, the camera isn't the player; instead, it's a separate entity that watches the player. My situation is comparable but different. I was using the player as a camera to watch another entity. I think I need to spawn another entity to act as the camera, and use the player only for motion capturing.

Another thing is the camera here uses velocity to move into position, rather than simply setorigins. I had some trouble with that because I'm using the same entity (the player) to capture the player's movement key presses to tell where he wants to go. I think if I use a separate camera entity, and have it do velocity, maybe it will be a bit smoother. However, moving forward and backward in my mod works fine - it is only turning that is choppy. So maybe that's not it.

I'll have to explore a little more. The choppiness could very well be because it's the player that I'm setting origin on and such.

Thanks again, r00k!
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
MauveBib
Posts: 634
Joined: Thu Nov 04, 2004 1:22 am

Post by MauveBib »

are you capturing the player angles and using them? I tried doing that when I was working on the mouse cursor for cannon fodder quake, and I found that quake is very bitty when capturing angles. I found it to me far more accurate when capturing strafing. Perhaps you could have +strafe set, then capture the strafe direction and convert it to an angle change? I dunno how your mod works, so I dunno if that'll work
Apathy Now!
Wazat
Posts: 771
Joined: Fri Oct 15, 2004 9:50 pm
Location: Middle 'o the desert, USA

Post by Wazat »

Actually it will work -- that's what I'm doing.
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Post Reply