#include "g_local.h" void UpdateChaseCam(edict_t *ent) { vec3_t o, ownerv, goal; edict_t *targ; vec3_t forward, right; trace_t trace; int i; vec3_t oldgoal; vec3_t angles; // is our chase target gone? if (!ent->client->chase_target->inuse || ent->client->chase_target->client->resp.spectator) { edict_t *old = ent->client->chase_target; ChaseNext(ent); if (ent->client->chase_target == old) { ent->client->chase_target = NULL; ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION; return; } } targ = ent->client->chase_target; VectorCopy(targ->s.origin, ownerv); VectorCopy(ent->s.origin, oldgoal); ownerv[2] += targ->viewheight; VectorCopy(targ->client->v_angle, angles); if (angles[PITCH] > 56) angles[PITCH] = 56; AngleVectors (angles, forward, right, NULL); VectorNormalize(forward); VectorMA(ownerv, -30, forward, o); if (o[2] < targ->s.origin[2] + 20) o[2] = targ->s.origin[2] + 20; // jump animation lifts if (!targ->groundentity) o[2] += 16; trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID); VectorCopy(trace.endpos, goal); VectorMA(goal, 2, forward, goal); // pad for floors and ceilings VectorCopy(goal, o); o[2] += 6; trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID); if (trace.fraction < 1) { VectorCopy(trace.endpos, goal); goal[2] -= 6; } VectorCopy(goal, o); o[2] -= 6; trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID); if (trace.fraction < 1) { VectorCopy(trace.endpos, goal); goal[2] += 6; } if (targ->deadflag) ent->client->ps.pmove.pm_type = PM_DEAD; else ent->client->ps.pmove.pm_type = PM_FREEZE; VectorCopy(goal, ent->s.origin); for (i=0 ; i<3 ; i++) ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(targ->client->v_angle[i] - ent->client->resp.cmd_angles[i]); if (targ->deadflag) { ent->client->ps.viewangles[ROLL] = 40; ent->client->ps.viewangles[PITCH] = -15; ent->client->ps.viewangles[YAW] = targ->client->killer_yaw; } else { VectorCopy(targ->client->v_angle, ent->client->ps.viewangles); VectorCopy(targ->client->v_angle, ent->client->v_angle); } ent->viewheight = 0; ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; gi.linkentity(ent); } void ChaseNext(edict_t *ent) { int i; edict_t *e; if (!ent->client->chase_target) return; i = ent->client->chase_target - g_edicts; do { i++; if (i > maxclients->value) i = 1; e = g_edicts + i; if (!e->inuse) continue; if (!e->client->resp.spectator) break; } while (e != ent->client->chase_target); ent->client->chase_target = e; ent->client->update_chase = true; } void ChasePrev(edict_t *ent) { int i; edict_t *e; if (!ent->client->chase_target) return; i = ent->client->chase_target - g_edicts; do { i--; if (i < 1) i = maxclients->value; e = g_edicts + i; if (!e->inuse) continue; if (!e->client->resp.spectator) break; } while (e != ent->client->chase_target); ent->client->chase_target = e; ent->client->update_chase = true; } 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."); } /******************************************************** THIS IS FOR CHASE WHEN DEAD BUT NOT SPECTATOR ********************************************************/ void ChaseCamNextMonster(edict_t *ent) { int i; edict_t *e; i = ent->killer - g_edicts; do { i++; if (i > maxentities->value) i = 1; e = g_edicts + i; if (e->svflags & SVF_MONSTER) if (e->health>0) { ent->killer = e; break; } } while (e != ent->killer); } void ChaseCamPrevMonster(edict_t *ent) { int i; edict_t *e; if (!ent->killer) return; i = ent->killer - g_edicts; do { i--; if (i < 1) i = maxentities->value; e = g_edicts + i; if (e->svflags & SVF_MONSTER) if (e->health>0) if (true) { ent->killer = e; break; } } while (e != ent->killer); } void ChaseCamNextClient(edict_t *ent) { int i; edict_t *e; i = ent->killer - g_edicts; do { i++; if (i > maxentities->value) i = 1; e = g_edicts + i; if (e->client) if (e->health>0) { ent->killer = e; break; } } while (e != ent->killer); } void ChaseCamPrevClient(edict_t *ent) { int i; edict_t *e; if (!ent->killer) return; i = ent->killer - g_edicts; do { i--; if (i < 1) i = maxentities->value; e = g_edicts + i; if (e->client) if (e->health>0) { ent->killer = e; break; } } while (e != ent->killer); } void UpdateChaseCamKiller(edict_t *ent) { vec3_t o, ownerv, goal; edict_t *targ; vec3_t forward, right; trace_t trace; int i; vec3_t oldgoal; vec3_t angles; int DistFromTarg, ViewVertOffset; if (abs(ent->Move_side)) { if (!(ent->client->ps.pmove.pm_flags & PMF_SIDE_HELD) ) { if (ent->Move_side<0) ChaseCamPrevClient(ent); if (ent->Move_side>0) ChaseCamNextClient(ent); ent->client->ps.pmove.pm_flags |= PMF_SIDE_HELD; } } else ent->client->ps.pmove.pm_flags &= ~PMF_SIDE_HELD; VectorCopy(ent->client->cl_origin, ent->s.origin); targ = ent->killer; if (!targ) return; if (abs(ent->Move_up)) { if (!(ent->client->ps.pmove.pm_flags & PMF_JUMP_HELD)) { if (ent->Move_up>0 && ent->viewcam_on!=1) { ent->viewcam_on=1; gi.cprintf(ent, PRINT_HIGH, "-= %s =-\n", make_green(" Free View Cam ")); } if (ent->Move_up<0 && ent->viewcam_on!=2) { ent->viewcam_on=2; ent->client->viewcam_dist = 0; gi.cprintf(ent, PRINT_HIGH, "-= %s =-\n", make_green("Locked View Cam")); } ent->client->ps.pmove.pm_flags |= PMF_JUMP_HELD; } } else ent->client->ps.pmove.pm_flags &= ~PMF_JUMP_HELD; if (targ->client) { DistFromTarg = 100; } if (targ->svflags & SVF_MONSTER) { if (!Q_strcasecmp(targ->classname, "monster_berserk")||!Q_strcasecmp(targ->classname, "monster_gladiator") ||!Q_strcasecmp(targ->classname, "monster_gunner")||!Q_strcasecmp(targ->classname, "monster_infantry") ||!Q_strcasecmp(targ->classname, "monster_soldier_light")||!Q_strcasecmp(targ->classname, "monster_soldier") ||!Q_strcasecmp(targ->classname, "monster_soldier_ss")||!Q_strcasecmp(targ->classname, "turret_driver") ||!Q_strcasecmp(targ->classname, "monster_medic")||!Q_strcasecmp(targ->classname, "monster_chick") ||!Q_strcasecmp(targ->classname, "monster_brain")||!Q_strcasecmp(targ->classname, "monster_mutant") ) { DistFromTarg = 100; } else if (!Q_strcasecmp(targ->classname, "monster_flyer")||!Q_strcasecmp(targ->classname, "monster_floater") ||!Q_strcasecmp(targ->classname, "monster_flipper") ||!Q_strcasecmp(targ->classname, "monster_hover") ) { DistFromTarg = 75; } else if (!Q_strcasecmp(targ->classname, "monster_parasite")) { DistFromTarg = 100; } else if (!Q_strcasecmp(targ->classname, "monster_tank") ||!Q_strcasecmp(targ->classname, "monster_tank_commander")) { DistFromTarg = 100; } else if (!Q_strcasecmp(targ->classname, "monster_supertank")||!Q_strcasecmp(targ->classname, "monster_turret_driver")) { DistFromTarg = 150; } else if (!Q_strcasecmp(targ->classname, "monster_boss2")) { DistFromTarg = 150; } else if (!Q_strcasecmp(targ->classname, "monster_boss3_stand")) { DistFromTarg = 200; } else if (!Q_strcasecmp(targ->classname, "monster_jorg")) { DistFromTarg = 200; } } else { DistFromTarg = 100; } if (ent->viewcam_on!=2) if (ent->Move_forward>0) { if (ent->client->viewcam_dist-5>=-(DistFromTarg/2)) ent->client->viewcam_dist-=5; } else if (ent->Move_forward<0) { if (ent->client->viewcam_dist+5<=DistFromTarg) ent->client->viewcam_dist+=5; } DistFromTarg += ent->client->viewcam_dist; VectorCopy(targ->s.origin, ownerv); VectorCopy(ent->s.origin, oldgoal); ownerv[2] += targ->viewheight; if (ent->viewcam_on==2) { VectorCopy(targ->s.angles, angles); if (targ->client) VectorCopy(targ->client->ps.viewangles, angles); if (angles[PITCH] > 56) angles[PITCH] = 56; if (angles[PITCH] < -56) angles[PITCH] = -56; } else VectorCopy(ent->client->v_angle, angles); AngleVectors (angles, forward, right, NULL); VectorNormalize(forward); VectorMA(ownerv, -DistFromTarg, forward, o); if (ent->viewcam_on==2) if (o[2] < targ->s.origin[2] + 20) o[2] = targ->s.origin[2] + 20; trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID|MASK_WATER); VectorCopy(trace.endpos, goal); VectorMA(goal, 2, forward, goal); // pad for floors and ceilings VectorCopy(goal, o); o[2] += 6; trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID|MASK_WATER); if (trace.fraction < 1) { VectorCopy(trace.endpos, goal); goal[2] -= 6; } VectorCopy(goal, o); o[2] -= 6; trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID|MASK_WATER); if (trace.fraction < 1) { VectorCopy(trace.endpos, goal); goal[2] += 6; } if (targ->deadflag) ent->client->ps.pmove.pm_type = PM_DEAD; else ent->client->ps.pmove.pm_type = PM_FREEZE; VectorCopy(goal, ent->s.origin); if (ent->viewcam_on==2) { for (i=0 ; i<3 ; i++) ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(angles[i] - ent->client->resp.cmd_angles[i]); VectorCopy(angles, ent->client->ps.viewangles); VectorCopy(angles, ent->client->v_angle); } else VectorCopy(ent->client->v_angle, ent->s.angles); ent->viewheight = 0; ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION; VectorCopy(ent->s.origin, ent->client->cl_origin); gi.linkentity(ent); }