void Cmd_Chasecam_Toggle (edict_t *ent) { // Lazarus: Don't allow thirdperson when using spycam if (!ent->deadflag && !ent->client->spycam) { if (ent->client->chasetoggle) ChasecamRemove (ent, OPTION_OFF); // Knightmare- don't use server chasecam if client chasecam is on else if (!cl_3dcam->value || deathmatch->value || coop->value) ChasecamStart (ent); } }
void Cmd_Chasecam_Toggle (edict_t *ent) { int i; edict_t *e; //////////////////////////////////// // ADDED if(ent->client->resp.spectator == true)// || //(ent->client->resp.team == CTF_NOTEAM && ent->client->resp.player_class == NO_CLASS)) { if (ent->client->chase_target) { //ent->svflags &= ~SVF_NOCLIENT; //added ent->client->chase_target = NULL; } else { for (i = 1; i <= maxclients->value; i++) { e = g_edicts + i; if (e->inuse && e->solid != SOLID_NOT) { ent->client->chase_target = e; ent->client->update_chase = true; ent->svflags |= SVF_NOCLIENT; //added break; } } } } // Lazarus: Don't allow thirdperson when using spycam else if (!ent->deadflag && !ent->client->spycam /*&& ent->client->resp.player_class*/) { // if (ent->client->chasetoggle) if (ent->client->chaseactive) { // gi.cprintf (ent, PRINT_HIGH, "Leaving Third Person mode.\n"); ChasecamRemove (ent); } // Knightmare- don't use server chasecam if client chasecam is on else if (!cl_thirdperson->value || deathmatch->value || coop->value) { // gi.cprintf (ent, PRINT_HIGH, "Starting Third Person mode.\n"); ChasecamStart (ent); } } }
/* ent = chasecam */ void ChasecamRestart (edict_t *ent) { /* Keep thinking this function to check all the time whether the * player is out of the water */ /* If the player is dead, the camera is not wanted... Kill me and stop * the function. (return;) */ if (ent->owner->health <= 0) { G_FreeEdict(ent); return; } /* If the player is still completly underwater, break the routine unless tpp has changed!*/ // if (ent->owner->waterlevel && !tpp->value) // return; //Put camera back ChasecamStart (ent->owner); //Remove this temporary ent G_FreeEdict (ent); }
void ChasecamTrack (edict_t *ent) { /* Create tempory vectors and trace variables */ trace_t tr; vec3_t spot1, spot2, dir; vec3_t forward, right, up; int dist; int cap; ent->nextthink = level.time + 0.100; /* get the CLIENT's angle, and break it down into direction vectors, * of forward, right, and up. VERY useful */ AngleVectors (ent->owner->client->v_angle, forward, right, up); /* go starting at the player's origin, forward, ent->chasedist1 * distance, and save the location in vector spot2 */ VectorMA (ent->owner->s.origin, -ent->chasedist1, forward, spot2); /* make spot2 a bit higher, but adding 20 to the Z coordinate */ spot2[2] += 20.000; /* if the client is looking down, do backwards up into the air, 0.6 * to the ratio of looking down, so the crosshair is still roughly * aiming at where the player is aiming. */ if (ent->owner->client->v_angle[0] < 0.000) VectorMA (spot2, (ent->owner->client->v_angle[0] * 0.2), up, spot2); /* if the client is looking up, do the same, but do DOWN rather than * up, so the camera is behind the player aiming in a similar dir */ else if (ent->owner->client->v_angle[0] > 0.000) VectorMA (spot2, (ent->owner->client->v_angle[0] * 0.2), up, spot2); /* make the tr traceline trace from the player model's position, to spot2, * ignoring the player, with MASK_SHOT. These masks have been fixed * from the previous version. The MASK_SHOT will stop the camera from * getting stuck in walls, sky, etc. */ tr = gi.trace (ent->owner->s.origin, NULL, NULL, spot2, ent->owner, MASK_SHOT); /* subtract the endpoint from the start point for length and * direction manipulation */ VectorSubtract (tr.endpos, ent->owner->s.origin, spot1); /* in this case, length */ ent->chasedist1 = VectorLength (spot1); /* go, starting from the end of the trace, 2 points forward (client * angles) and save the location in spot2 */ VectorMA (tr.endpos, 2, forward, spot2); /* make spot1 the same for tempory vector modification and make spot1 * a bit higher than spot2 */ VectorCopy (spot2, spot1); spot1[2] += 32; /* another trace from spot2 to spot2, ignoring player, no masks */ tr = gi.trace (spot2, NULL, NULL, spot1, ent->owner, MASK_SHOT); /* if we hit something, copy the trace end to spot2 and lower spot2 */ if (tr.fraction < 1.000) { VectorCopy (tr.endpos, spot2); spot2[2] -= 32; } /* subtract endpos spot2 from startpos the camera origin, saving it to * the dir vector, and normalize dir for a direction from the camera * origin, to the spot2 */ VectorSubtract (spot2, ent->s.origin, dir); VectorNormalize (dir); /* subtract the same things, but save it in spot1 for a temporary * length calculation */ VectorSubtract (spot2, ent->s.origin, spot1); dist = VectorLength (spot1); /* another traceline */ tr = gi.trace (ent->s.origin, NULL, NULL, spot2, ent->owner, MASK_SHOT); /* if we DON'T hit anyting, do some freaky stuff <G> */ if (tr.fraction == 1.000) { /* Make the angles of the chasecam, the same as the player, so * we are always behind the player. (angles) */ VectorCopy (ent->owner->s.angles, ent->s.angles); /* calculate the percentages of the distances, and make sure we're * not going too far, or too short, in relation to our panning * speed of the chasecam entity */ cap = (dist * 0.400); /* if we're going too fast, make us top speed */ if (cap > 5.200) { ent->velocity[0] = ((dir[0] * dist) * 5.2); ent->velocity[1] = ((dir[1] * dist) * 5.2); ent->velocity[2] = ((dir[2] * dist) * 5.2); } else { /* if we're NOT going top speed, but we're going faster than * 1, relative to the total, make us as fast as we're going */ if ( (cap > 1.000) ) { ent->velocity[0] = ((dir[0] * dist) * cap); ent->velocity[1] = ((dir[1] * dist) * cap); ent->velocity[2] = ((dir[2] * dist) * cap); } else { /* if we're not going faster than one, don't accelerate our * speed at all, make us go slow to our destination */ ent->velocity[0] = (dir[0] * dist); ent->velocity[1] = (dir[1] * dist); ent->velocity[2] = (dir[2] * dist); } } /* subtract endpos;player position, from chasecam position to get * a length to determine whether we should accelerate faster from * the player or not */ VectorSubtract (ent->owner->s.origin, ent->s.origin, spot1); if (VectorLength(spot1) < 20) { ent->velocity[0] *= 2; ent->velocity[1] *= 2; ent->velocity[2] *= 2; } } /* if we DID hit something in the tr.fraction call ages back, then * make the spot2 we created, the position for the chasecamera. */ else VectorCopy (spot2, ent->s.origin); /* If the distance is less than 90, then we haven't reached the * furthest point. If we HAVEN'T reached the furthest point, keep * going backwards. This was a fix for the "shaking". The camera was * getting forced backwards, only to be brought back, next think */ if (ent->chasedist1 < 90.00) ent->chasedist1 += 1; /* if we're too far away, give us a maximum distance */ else if (ent->chasedist1 > 90.00) ent->chasedist1 = 90; /* if we haven't gone anywhere since the last think routine, and we * are greater than 20 points in the distance calculated, add one to * the second chasedistance variable * The "ent->movedir" is a vector which is not used in this entity, so * we can use this a tempory vector belonging to the chasecam, which * can be carried through think routines. */ if (ent->movedir == ent->s.origin) { if (dist > 20) ent->chasedist2++; } /* if we've buggered up more than 3 times, there must be some mistake, * so restart the camera so we re-create a chasecam, destroy the old one, * slowly go outwards from the player, and keep thinking this routing in * the new camera entity */ if (ent->chasedist2 > 3) { ChasecamStart (ent->owner); G_FreeEdict(ent); return; } /* Copy the position of the chasecam now, and stick it to the movedir * variable, for position checking when we rethink this function */ VectorCopy (ent->s.origin, ent->movedir); }
/* The "ent" is the chasecam */ void ChasecamTrack (edict_t *ent) { /* Create tempory vectors and trace variables */ trace_t tr; vec3_t spot1, spot2, dir; vec3_t forward, right, up,angles; int distance; int tot; ent->nextthink = level.time + 0.100; /* if our owner is under water, run the remove routine to repeatedly * check for emergment from water */ // if (ent->owner->waterlevel && !tpp->value) // { // ChasecamRemove (ent->owner, OPTION_BACKGROUND); // return; // } /* get the CLIENT's angle, and break it down into direction vectors, * of forward, right, and up. VERY useful */ VectorCopy(ent->owner->client->v_angle,angles); if (angles[PITCH] > 56) angles[PITCH] = 56; AngleVectors (angles, forward, right, up); VectorNormalize(forward); /* go starting at the player's origin, forward, ent->chasedist1 * distance, and save the location in vector spot2 */ VectorMA (ent->owner->s.origin, -ent->chasedist1, forward, spot2); /* make spot2 a bit higher, by adding viewheight to the Z coordinate */ spot2[2] += (ent->owner->viewheight + 16); // jump animation lifts if (!ent->owner->groundentity) spot2[2] += 16; /* make the tr traceline trace from the player model's position, to spot2, * ignoring the player, with a mask. */ tr = gi.trace (ent->owner->s.origin, vec3_origin, vec3_origin, spot2, ent->owner, MASK_SOLID); /* subtract the endpoint from the start point for length and * direction manipulation */ VectorSubtract (tr.endpos, ent->owner->s.origin, spot1); /* in this case, length */ ent->chasedist1 = VectorLength (spot1); /* go, starting from the end of the trace, 2 points forward (client * angles) and save the location in spot2 */ VectorMA (tr.endpos, 2, forward, spot2); /* make spot1 the same for tempory vector modification and make spot1 * a bit higher than spot2 */ VectorCopy (spot2, spot1); spot1[2] += 32; /* another trace from spot2 to spot1, ignoring player, no masks */ tr = gi.trace (spot2, vec3_origin, vec3_origin, spot1, ent->owner, MASK_SOLID); /* if we hit something, copy the trace end to spot2 and lower spot2 */ if (tr.fraction < 1.000) { VectorCopy (tr.endpos, spot2); spot2[2] -= 32; } /* subtract endpos spot2 from startpos the camera origin, saving it to * the dir vector, and normalize dir for a direction from the camera * origin, to the spot2 */ VectorSubtract (spot2, ent->s.origin, dir); distance = VectorLength (dir); VectorNormalize (dir); /* another traceline */ tr = gi.trace (ent->s.origin, vec3_origin, vec3_origin, spot2, ent->owner, MASK_SOLID); /* if we DON'T hit anyting, do some freaky stuff */ if (tr.fraction == 1.000) { /* subtract the endpos camera position, from the startpos, the * player, and save in spot1. Normalize spot1 for a direction, and * make that direction the angles of the chasecam for copying to the * clients view angle which is displayed to the client. (human) */ VectorSubtract (ent->s.origin, ent->owner->s.origin, spot1); VectorNormalize (spot1); VectorCopy (spot1, ent->s.angles); /* calculate the percentages of the distances, and make sure we're * not going too far, or too short, in relation to our panning * speed of the chasecam entity */ tot = (distance * 0.400); /* if we're going too fast, make us top speed */ if (tot > 5.200) { ent->velocity[0] = ((dir[0] * distance) * 5.2); ent->velocity[1] = ((dir[1] * distance) * 5.2); ent->velocity[2] = ((dir[2] * distance) * 5.2); } else { /* if we're NOT going top speed, but we're going faster than * 1, relative to the total, make us as fast as we're going */ if (tot > 1.000) { ent->velocity[0] = ((dir[0] * distance) * tot); ent->velocity[1] = ((dir[1] * distance) * tot); ent->velocity[2] = ((dir[2] * distance) * tot); } else { /* if we're not going faster than one, don't accelerate our * speed at all, make us go slow to our destination */ ent->velocity[0] = (dir[0] * distance); ent->velocity[1] = (dir[1] * distance); ent->velocity[2] = (dir[2] * distance); } } /* subtract endpos,player position, from chasecam position to get * a length to determine whether we should accelerate faster from * the player or not */ VectorSubtract (ent->owner->s.origin, ent->s.origin, spot1); if (VectorLength(spot1) < 20) { ent->velocity[0] *= 2; ent->velocity[1] *= 2; ent->velocity[2] *= 2; } } /* if we DID hit something in the tr.fraction call ages back, then * make the spot2 we created, the position for the chasecamera. */ else VectorCopy (spot2, ent->s.origin); /* add to the distance between the player and the camera */ ent->chasedist1 += 2; /* if we're too far away, give us a maximum distance */ if (ent->chasedist1 > (60.00 + ent->owner->client->zoom)) ent->chasedist1 = (60.00 + ent->owner->client->zoom); /* if we haven't gone anywhere since the last think routine, and we * are greater than 20 points in the distance calculated, add one to * the second chasedistance variable * The "ent->movedir" is a vector which is not used in this entity, so * we can use this a tempory vector belonging to the chasecam, which * can be carried through think routines. */ if (VectorCompare(ent->movedir, ent->s.origin)) { if (distance > 20) ent->chasedist2++; } /* if we've buggered up more than 3 times, there must be some mistake, * so restart the camera so we re-create a chasecam, destroy the old one, * slowly go outwards from the player, and keep thinking this routing in * the new camera entity */ if (ent->chasedist2 > 3) { G_FreeEdict (ent->owner->client->oldplayer); ChasecamStart (ent->owner); G_FreeEdict(ent); return; } /* Copy the position of the chasecam now, and stick it to the movedir * variable, for position checking when we rethink this function */ VectorCopy (ent->s.origin, ent->movedir); /* MUST LINK SINCE WE CHANGED THE ORIGIN! */ gi.linkentity (ent); //UpdateFakeCrosshair (ent->owner); }