Ejemplo n.º 1
0
void
GetChaseTarget(edict_t *ent)
{
	int i;
	edict_t *other;

	if (!ent)
	{
		return;
	}

	for (i = 1; i <= maxclients->value; i++)
	{
		other = g_edicts + i;

		if (other->inuse && !other->client->resp.spectator)
		{
			ent->client->chase_target = other;
			ent->client->update_chase = true;
			UpdateChaseCam(ent);
			return;
		}
	}

	gi.centerprintf(ent, "No other players to chase.");
}
Ejemplo n.º 2
0
/*
void GetChaseTarget(edict_t *ent)
{
	int i;
	edict_t *other;

	for (i = 1; i <= maxclients->value; i++) {
		other = g_edicts + i;
		if (other->inuse && !other->client->resp.spectator) {
			ent->client->chase_target = other;
			ent->client->update_chase = true;
			UpdateChaseCam(ent);
			return;
		}
	}
	gi.centerprintf(ent, "No other players to chase.");
}
*/
void GetChaseTarget (edict_t *ent)//GHz
{
	int		i;
	edict_t *other;

	for (i=1; i<globals.num_edicts; i++) {
		other = &g_edicts[i];
		if (other == ent)
			continue;
		if (!IsValidChaseTarget(other))
			continue;
		ent->client->chase_target = other;
		ent->client->update_chase = true;
		UpdateChaseCam(ent);
		return;
	}
	gi.centerprintf(ent, "Nothing to chase.\n");
}
Ejemplo n.º 3
0
/*
==============
ClientThink

This will be called once for each client frame, which will
usually be a couple times for each server frame.
==============
*/
void ClientThink (edict_t *ent, usercmd_t *ucmd)
{
	gclient_t	*client;
	edict_t	*other;
	int		i, j;
	pmove_t	pm;

	level.current_entity = ent;
	client = ent->client;

	if (level.intermissiontime)
	{
		client->ps.pmove.pm_type = PM_FREEZE;
		// can exit intermission after five seconds
		if (level.time > level.intermissiontime + 5.0 
			&& (ucmd->buttons & BUTTON_ANY) )
			level.exitintermission = true;
		return;
	}

	pm_passent = ent;

	if (ent->client->chase_target) {

		client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]);
		client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]);
		client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]);

	} else {

		// set up for pmove
		memset (&pm, 0, sizeof(pm));

		if (ent->movetype == MOVETYPE_NOCLIP)
			client->ps.pmove.pm_type = PM_SPECTATOR;
		else if (ent->s.modelindex != 255)
			client->ps.pmove.pm_type = PM_GIB;
		else if (ent->deadflag)
			client->ps.pmove.pm_type = PM_DEAD;
		else
			client->ps.pmove.pm_type = PM_NORMAL;

		client->ps.pmove.gravity = sv_gravity->value;
		pm.s = client->ps.pmove;

		for (i=0 ; i<3 ; i++)
		{
			pm.s.origin[i] = ent->s.origin[i]*8;
			pm.s.velocity[i] = ent->velocity[i]*8;
		}

		if (memcmp(&client->old_pmove, &pm.s, sizeof(pm.s)))
		{
			pm.snapinitial = true;
	//		gi.dprintf ("pmove changed!\n");
		}

		pm.cmd = *ucmd;

		pm.trace = PM_trace;	// adds default parms
		pm.pointcontents = gi.pointcontents;

		// perform a pmove
		gi.Pmove (&pm);

		// save results of pmove
		client->ps.pmove = pm.s;
		client->old_pmove = pm.s;

		for (i=0 ; i<3 ; i++)
		{
			ent->s.origin[i] = pm.s.origin[i]*0.125;
			ent->velocity[i] = pm.s.velocity[i]*0.125;
		}

		VectorCopy (pm.mins, ent->mins);
		VectorCopy (pm.maxs, ent->maxs);

		client->resp.cmd_angles[0] = SHORT2ANGLE(ucmd->angles[0]);
		client->resp.cmd_angles[1] = SHORT2ANGLE(ucmd->angles[1]);
		client->resp.cmd_angles[2] = SHORT2ANGLE(ucmd->angles[2]);

		if (ent->groundentity && !pm.groundentity && (pm.cmd.upmove >= 10) && (pm.waterlevel == 0))
		{
			gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
			PlayerNoise(ent, ent->s.origin, PNOISE_SELF);
		}

		ent->viewheight = pm.viewheight;
		ent->waterlevel = pm.waterlevel;
		ent->watertype = pm.watertype;
		ent->groundentity = pm.groundentity;
		if (pm.groundentity)
			ent->groundentity_linkcount = pm.groundentity->linkcount;

		if (ent->deadflag)
		{
			client->ps.viewangles[ROLL] = 40;
			client->ps.viewangles[PITCH] = -15;
			client->ps.viewangles[YAW] = client->killer_yaw;
		}
		else
		{
			VectorCopy (pm.viewangles, client->v_angle);
			VectorCopy (pm.viewangles, client->ps.viewangles);
		}

		gi.linkentity (ent);

		if (ent->movetype != MOVETYPE_NOCLIP)
			G_TouchTriggers (ent);

		// touch other objects
		for (i=0 ; i<pm.numtouch ; i++)
		{
			other = pm.touchents[i];
			for (j=0 ; j<i ; j++)
				if (pm.touchents[j] == other)
					break;
			if (j != i)
				continue;	// duplicated
			if (!other->touch)
				continue;
			other->touch (other, ent, NULL, NULL);
		}

	}

	client->oldbuttons = client->buttons;
	client->buttons = ucmd->buttons;
	client->latched_buttons |= client->buttons & ~client->oldbuttons;

	// save light level the player is standing on for
	// monster sighting AI
	ent->light_level = ucmd->lightlevel;

	// fire weapon from final position if needed
	if (client->latched_buttons & BUTTON_ATTACK)
	{
		if (client->resp.spectator) {

			client->latched_buttons = 0;

			if (client->chase_target) {
				client->chase_target = NULL;
				client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
			} else
				GetChaseTarget(ent);

		} else if (!client->weapon_thunk) {
			client->weapon_thunk = true;
			Think_Weapon (ent);
		}
	}

	if (client->resp.spectator) {
		if (ucmd->upmove >= 10) {
			if (!(client->ps.pmove.pm_flags & PMF_JUMP_HELD)) {
				client->ps.pmove.pm_flags |= PMF_JUMP_HELD;
				if (client->chase_target)
					ChaseNext(ent);
				else
					GetChaseTarget(ent);
			}
		} else
			client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD;
	}

	// update chase cam if being followed
	for (i = 1; i <= maxclients->value; i++) {
		other = g_edicts + i;
		if (other->inuse && other->client->chase_target == ent)
			UpdateChaseCam(other);
	}
}
Ejemplo n.º 4
0
/*
=================
ClientEndServerFrame

Called for each player at the end of the server frame
and right after spawning
=================
*/
void ClientEndServerFrame (edict_t *ent)
{
	float	bobtime;
	int		i;

	current_player = ent;
	current_client = ent->client;

	if (ent->client->chase_target)
		UpdateChaseCam(ent);

	if (kpded2)
	{
		// if eyecam is enabled, set who's eyes we're looking through
		if (ent->client->chase_target && ent->client->chasemode == EYECAM_CHASE)
			ent->client->pov = ent->client->chase_target - g_edicts - 1;
		else
			ent->client->pov = -1;

		// set team info to be shown in server browsers
		ent->client->team = ent->client->pers.team;

		// don't send any entities/players to spectators when spectating is disabled
		if (level.modeset == MATCH && no_spec->value && ent->client->pers.spectator == SPECTATING && !ent->client->pers.admin && !ent->client->pers.rconx[0])
			ent->client->noents = true;
		else
			ent->client->noents = false;
	}

	//
	// If the origin or velocity have changed since ClientThink(),
	// update the pmove values.  This will happen when the client
	// is pushed by a bmodel or kicked by an explosion.
	// 
	// If it wasn't updated here, the view position would lag a frame
	// behind the body position when pushed -- "sinking into plats"
	//
	for (i=0 ; i<3 ; i++)
	{
		current_client->ps.pmove.origin[i] = ent->s.origin[i]*8.0;
		// make sure the velocity can overflow ("trigger_push" may exceed the limit) for back-compatibility (newer GCC may otherwise give 0x8000)
		current_client->ps.pmove.velocity[i] = (int)(ent->velocity[i]*8.0);
	}

	//
	// If the end of unit layout is displayed, don't give
	// the player any normal movement attributes
	//
	if (level.intermissiontime)
	{
		// darken the intermission background
		current_client->ps.blend[0] = 0;
		current_client->ps.blend[1] = 0;
		current_client->ps.blend[2] = 0;
		current_client->ps.blend[3] = 0.5;
		current_client->ps.fov = 90;
		if (level.framenum == level.startframe) return; // delay hud refresh to avoid overflow
		G_SetStats (ent);
		goto updatescore;
	}

	if (ent->client->chase_target && ent->client->chasemode == EYECAM_CHASE)
	{
		G_SetStats (ent);
		goto updatescore;
	}

	if (ent->client->chase_target)
		ent->client->ps.fov = 90;

	AngleVectors (ent->client->v_angle, forward, right, up);

	// burn from lava, etc
	P_WorldEffects ();

	//
	// set model angles from view angles so other things in
	// the world can tell which direction you are looking
	//

	// Ridah, Hovercars, handle angles differently
	if (ent->flags & (FL_HOVERCAR | FL_HOVERCAR_GROUND | FL_BIKE))
	{
		if (current_client->ps.fov < 105)
			current_client->ps.fov = 105;	// fix FOV while in Hovercar

		if (ent->client->v_angle[PITCH] > 180)
			ent->s.angles[PITCH] = (-360 + ent->client->v_angle[PITCH]);
		else
			ent->s.angles[PITCH] = ent->client->v_angle[PITCH];
	}
	else
	// done.
	{
		if (ent->client->v_angle[PITCH] > 180)
			ent->s.angles[PITCH] = (-360 + ent->client->v_angle[PITCH])/3;
		else
			ent->s.angles[PITCH] = ent->client->v_angle[PITCH]/3;

		// Ridah, snap the pitch so that it doesn't change as often (cut network bandwidth)
		ent->s.angles[PITCH] = (int)(((int)ent->s.angles[PITCH]) / 5) * 5;
	}
	ent->s.angles[YAW] = ent->client->v_angle[YAW];
	ent->s.angles[ROLL] = 0;
	ent->s.angles[ROLL] = SV_CalcRoll (ent->s.angles, ent->velocity)*4;
/*
	if (ent->client->anim_end == FRAME_lside_run_07)
		ent->s.angles[YAW] = anglemod(ent->s.angles[YAW] - 90);
	else if (ent->client->anim_end == FRAME_rside_run_07)
		ent->s.angles[YAW] = anglemod(ent->s.angles[YAW] + 90);
*/
	// Ridah, Hovercars
	if (ent->flags & (FL_HOVERCAR | FL_HOVERCAR_GROUND | FL_BIKE))
		ent->s.angles[ROLL] *= 0.5;
	// done.

	//
	// calculate speed and cycle to be used for
	// all cyclic walking effects
	//
	xyspeed = sqrt(ent->velocity[0]*ent->velocity[0] + ent->velocity[1]*ent->velocity[1]);

	if (xyspeed < 5)
	{
		bobmove = 0;
		current_client->bobtime = 0;	// start at beginning of cycle again
	}
	else if (ent->groundentity)
	{	// so bobbing only cycles when on ground
		if (xyspeed > 210)
			bobmove = 0.25;
		else if (xyspeed > 100)
			bobmove = 0.125;
		else
			bobmove = 0.0625;
	}
	else
		bobmove = 0; // stop bobbing when off ground

	bobtime = (current_client->bobtime += bobmove);

	if (current_client->ps.pmove.pm_flags & PMF_DUCKED)
		bobtime *= 4;

	bobcycle = (int)bobtime;
	bobfracsin = fabs(sin(bobtime*M_PI));

	// detect hitting the floor
// Ridah, Hovercars, no falling damage
if (!(ent->flags & (FL_HOVERCAR | FL_HOVERCAR_GROUND | FL_BIKE)))
// done.
	P_FallingDamage (ent);

	// apply all the damage taken this frame
// Ridah, doesn't work with new palette?
	P_DamageFeedback (ent);

	// determine the view offsets
// Ridah, Hovercars, no view offsets
if (ent->flags & (FL_HOVERCAR | FL_HOVERCAR_GROUND | FL_BIKE))
	ent->client->ps.viewoffset[2] = ent->viewheight;
else
// done.
	SV_CalcViewOffset (ent);


	// determine the gun offsets
// Ridah, Hovercars, no gun offsets
if (ent->flags & (FL_HOVERCAR | FL_HOVERCAR_GROUND | FL_BIKE))
// done.
	SV_CalcGunOffset (ent);

	// Ridah, fade out kicks, which are used for mono's
	if (ent->flags & (FL_BIKE))
	{
		if (ent->client->kick_angles[PITCH] > 0)
		{
			ent->client->kick_angles[PITCH] -= 5 * FRAMETIME;
			if (ent->client->kick_angles[PITCH] < 0)
				ent->client->kick_angles[PITCH] = 0;
		}
		else if (ent->client->kick_angles[PITCH] < 0)
		{
			ent->client->kick_angles[PITCH] += 5 * FRAMETIME;
			if (ent->client->kick_angles[PITCH] > 0)
				ent->client->kick_angles[PITCH] = 0;
		}

		VectorCopy( ent->client->kick_angles, ent->client->ps.kick_angles );
	}

	// determine the full screen color blend
	// must be after viewoffset, so eye contents can be
	// accurately determined
	// FIXME: with client prediction, the contents
	// should be determined by the client
	SV_CalcBlend (ent);

	G_SetStats (ent);

	G_SetClientEvent (ent);

	G_SetClientEffects (ent);

	G_SetClientSound (ent);

	G_SetClientFrame (ent);

	VectorCopy (ent->velocity, ent->client->oldvelocity);
	VectorCopy (ent->client->ps.viewangles, ent->client->oldviewangles);

	// clear weapon kicks
	VectorClear (ent->client->kick_origin);

	// Ridah, fade out kicks, which are used for mono's
	if (!(ent->flags & FL_BIKE))
	{
		VectorClear (ent->client->kick_angles);
	}

	// store the client's position for backward reconciliation later
	if (antilag->value && ent->solid != SOLID_NOT)
		G_StoreHistory(ent);

updatescore:
	if (ent->client->resp.enterframe == level.framenum) return;

	if (ent->client->showscores == SCORE_MOTD && (level.framenum == (ent->client->resp.enterframe + 150)
		|| (level.modeset == ENDGAMEVOTE && level.framenum == (ent->client->resp.enterframe + 100))))
	{
		if (level.modeset == ENDGAMEVOTE)
			ent->client->showscores = SCORE_MAP_VOTE;
		else
			ent->client->showscores = SCOREBOARD;
		ent->client->resp.scoreboard_frame = 0;
	}
	if (level.modeset == ENDGAMEVOTE && ent->client->showscores == SCOREBOARD && level.framenum == (level.startframe + 150) && !ent->client->resp.vote)
	{
		ent->client->showscores = SCORE_MAP_VOTE;
		ent->client->resp.scoreboard_frame = 0;
	}
	// if the scoreboard is due for an update, update it
	if ((!ent->client->resp.scoreboard_frame || (ent->client->showscores && !ent->client->resp.textbuf[0] && level.framenum >= (ent->client->resp.scoreboard_frame + 30)))
		&& level.framenum >= (ent->client->resp.enterframe + 5))
	{
		DeathmatchScoreboard(ent);
		return;
	}

	if (ent->client->resp.textbuf[0])
	{
		char *b = ent->client->resp.textbuf;
		int j = strlen(b);
		if (j > 300)
		{
			for (i = 300; i < j-20; i++)
				if (b[i] == '\n')
				{
					b[i] = 0;
					gi.cprintf(ent, PRINT_HIGH, "%s\n", b);
					memmove(b, b + i + 1, j - i);
					goto donetext;
				}
		}
		gi.cprintf(ent, PRINT_HIGH, "%s", b);
		b[0] = 0;
	}
donetext:
	if (level.intermissiontime) return;

	if (level.framenum > ent->client->resp.checkdelta)
	{
		ent->client->resp.checkdelta = level.framenum + 70 + (rand()&7);
		gi.WriteByte(svc_stufftext);
		gi.WriteString("cl_nodelta 0\n");
		gi.unicast(ent, false);
	}
	else if (level.framenum > ent->client->resp.checktex)
	{
		ent->client->resp.checktex = level.framenum + 80 + (rand()&7);
		gi.WriteByte(svc_stufftext);
		gi.WriteString(va("cmd %sA $gl_picmip $gl_maxtexsize $gl_polyblend\n", cmd_check));
		gi.unicast(ent, false);
	}
	else if (level.framenum > ent->client->resp.checkpvs)
	{
		ent->client->resp.checkpvs = level.framenum + 80 + (rand()&7);
		gi.WriteByte(svc_stufftext);
		gi.WriteString(va("cmd %sB $gl_clear $r_drawworld\n", cmd_check)); /* $gl_ztrick */
		gi.unicast(ent, false);
	}
	else if (ent->solid != SOLID_NOT && !ent->deadflag)
	{
		if (level.framenum > ent->client->resp.checkmouse)
		{
			ent->client->resp.checkmouse = level.framenum + 30 + (rand()&3);
			gi.WriteByte(svc_stufftext);
			if (antilag->value)
				gi.WriteString(va("cmd %sC $m_pitch $antilag\n", cmd_check)); // piggy-back the mouse check
			else
				gi.WriteString(va("cmd %sC $m_pitch\n", cmd_check));
			gi.unicast(ent, true);
		}
	}
}