mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-23 21:12:09 +00:00
game: Add third person view
Based on codes: * Lazarus mod * KMQuake2 codes * Slight Mechanical Destruction mod https://bitbucket.org/Knightmare66/kmquake2_stable/src/master/game/p_chase.c
This commit is contained in:
parent
45767961b0
commit
6b4f197ac0
13 changed files with 842 additions and 73 deletions
1
Makefile
1
Makefile
|
@ -926,6 +926,7 @@ GAME_OBJS_ = \
|
|||
src/game/monster/turret/turret.o \
|
||||
src/game/monster/widow/widow2.o \
|
||||
src/game/monster/widow/widow.o \
|
||||
src/game/player/chase.o \
|
||||
src/game/player/client.o \
|
||||
src/game/player/hud.o \
|
||||
src/game/player/trail.o \
|
||||
|
|
|
@ -46,3 +46,5 @@ original clients (Vanilla Quake II) commands are still in place.
|
|||
* **set** / **seta** / **setu** / **sets**: set cvar valu with different flags.
|
||||
|
||||
* **listlights**: Show lights style and dlights list.
|
||||
|
||||
* **thirdperson**: Third person view.
|
||||
|
|
|
@ -628,6 +628,7 @@ CL_InitLocal(void)
|
|||
Cmd_AddCommand("spawnentity", NULL);
|
||||
Cmd_AddCommand("spawnonstart", NULL);
|
||||
Cmd_AddCommand("cycleweap", NULL);
|
||||
Cmd_AddCommand("thirdperson", NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2255,6 +2255,10 @@ ClientCommand(edict_t *ent)
|
|||
{
|
||||
CTFObserver(ent);
|
||||
}
|
||||
else if (Q_stricmp(cmd, "thirdperson") == 0)
|
||||
{
|
||||
Cmd_Chasecam_Toggle(ent);
|
||||
}
|
||||
else /* anything that doesn't match a command will be a chat */
|
||||
{
|
||||
Cmd_Say_f(ent, false, true);
|
||||
|
|
|
@ -1072,20 +1072,24 @@ SV_Physics_Toss(edict_t *ent)
|
|||
ent->waterlevel = 0;
|
||||
}
|
||||
|
||||
if (!wasinwater && isinwater)
|
||||
/* Don't do the sounds for the camera */
|
||||
if (Q_stricmp(ent->classname,"chasecam"))
|
||||
{
|
||||
/* don't play splash sound for entities already in water on level start */
|
||||
if (level.framenum > 3)
|
||||
if (!wasinwater && isinwater)
|
||||
{
|
||||
gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO,
|
||||
/* don't play splash sound for entities already in water on level start */
|
||||
if (level.framenum > 3)
|
||||
{
|
||||
gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO,
|
||||
gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
|
||||
}
|
||||
}
|
||||
else if (wasinwater && !isinwater)
|
||||
{
|
||||
gi.positioned_sound(ent->s.origin, g_edicts, CHAN_AUTO,
|
||||
gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
|
||||
}
|
||||
}
|
||||
else if (wasinwater && !isinwater)
|
||||
{
|
||||
gi.positioned_sound(ent->s.origin, g_edicts, CHAN_AUTO,
|
||||
gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
|
||||
}
|
||||
|
||||
/* move teamslaves */
|
||||
for (slave = ent->teamchain; slave; slave = slave->teamchain)
|
||||
|
|
|
@ -1143,6 +1143,7 @@ typedef struct
|
|||
int helpchanged;
|
||||
|
||||
qboolean spectator; /* client is a spectator */
|
||||
int chasetoggle; /* Chasetoggle */
|
||||
|
||||
int max_tesla;
|
||||
int max_prox;
|
||||
|
@ -1292,6 +1293,14 @@ struct gclient_s
|
|||
float tracker_pain_framenum;
|
||||
|
||||
edict_t *owned_sphere; /* this points to the player's sphere */
|
||||
|
||||
/* Third person view */
|
||||
int chasetoggle;
|
||||
edict_t *chasecam;
|
||||
edict_t *oldplayer;
|
||||
int use;
|
||||
int zoom;
|
||||
int delayedstart;
|
||||
};
|
||||
|
||||
struct edict_s
|
||||
|
@ -1452,6 +1461,10 @@ struct edict_s
|
|||
edict_t *target_hint_chain;
|
||||
int hint_chain_id;
|
||||
float lastMoveTime;
|
||||
|
||||
/* Third person view */
|
||||
int chasedist1;
|
||||
int chasedist2;
|
||||
};
|
||||
|
||||
#define SPHERE_DEFENDER 0x0001
|
||||
|
@ -1596,6 +1609,7 @@ typedef struct ghost_s
|
|||
} ghost_t;
|
||||
|
||||
extern cvar_t *ctf;
|
||||
extern char *ctf_statusbar;
|
||||
|
||||
#define CTF_TEAM1_SKIN "ctf_r"
|
||||
#define CTF_TEAM2_SKIN "ctf_b"
|
||||
|
@ -1702,11 +1716,11 @@ qboolean CTFCheckRules(void);
|
|||
void SP_misc_ctf_banner(edict_t *ent);
|
||||
void SP_misc_ctf_small_banner(edict_t *ent);
|
||||
|
||||
extern char *ctf_statusbar;
|
||||
|
||||
void UpdateChaseCam(edict_t *ent);
|
||||
void ChaseNext(edict_t *ent);
|
||||
void ChasePrev(edict_t *ent);
|
||||
void Cmd_Chasecam_Toggle(edict_t *ent);
|
||||
void ChasecamStart(edict_t *ent);
|
||||
void ChasecamRemove(edict_t *ent);
|
||||
void CheckChasecam_Viewent(edict_t *ent);
|
||||
void ChasecamTrack(edict_t *ent);
|
||||
|
||||
void CTFObserver(edict_t *ent);
|
||||
|
||||
|
|
346
src/game/player/chase.c
Normal file
346
src/game/player/chase.c
Normal file
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, Inc.
|
||||
* Copyright (c) ZeniMax Media Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Third person view
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#include "../header/local.h"
|
||||
|
||||
/* The ent is the owner of the chasecam */
|
||||
void
|
||||
ChasecamStart(edict_t *ent)
|
||||
{
|
||||
/* This creates a tempory entity we can manipulate within this
|
||||
* function */
|
||||
edict_t *chasecam;
|
||||
/* Don't work on a spectator! */
|
||||
if (ent->client->resp.spectator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't turn back on during intermission! */
|
||||
if (level.intermissiontime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Tell everything that looks at the toggle that our chasecam is on
|
||||
* and working */
|
||||
ent->client->chasetoggle = 1;
|
||||
/* Make our gun model "non-existent" so it's more realistic to the
|
||||
* player using the chasecam */
|
||||
ent->client->ps.gunindex = 0;
|
||||
chasecam = G_Spawn();
|
||||
chasecam->owner = ent;
|
||||
chasecam->solid = SOLID_NOT;
|
||||
chasecam->movetype = MOVETYPE_FLYMISSILE;
|
||||
/* this turns off Quake2's inclination to predict where the camera is going,
|
||||
* making a much smoother ride */
|
||||
ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;
|
||||
/* this line tells Quake2 not to send the unnecessary info about the
|
||||
* camera to other players */
|
||||
ent->svflags |= SVF_NOCLIENT;
|
||||
/* Now, make the angles of the player model, (!NOT THE HUMAN VIEW!) be
|
||||
* copied to the same angle of the chasecam entity */
|
||||
VectorCopy(ent->s.angles, chasecam->s.angles);
|
||||
/* Clear the size of the entity, so it DOES technically have a size,
|
||||
* but that of '0 0 0'-'0 0 0'. (xyz, xyz). mins = Minimum size,
|
||||
* maxs = Maximum size */
|
||||
VectorClear(chasecam->mins);
|
||||
VectorClear(chasecam->maxs);
|
||||
/* Make the chasecam's origin (position) be the same as the player
|
||||
* entity's because as the camera starts, it will force itself out
|
||||
* slowly backwards from the player model */
|
||||
VectorCopy(ent->s.origin, chasecam->s.origin);
|
||||
chasecam->classname = "chasecam";
|
||||
chasecam->prethink = ChasecamTrack;
|
||||
chasecam->think = ChasecamTrack;
|
||||
ent->client->chasecam = chasecam;
|
||||
ent->client->oldplayer = G_Spawn();
|
||||
CheckChasecam_Viewent(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;
|
||||
}
|
||||
// Put camera back
|
||||
ChasecamStart(ent->owner);
|
||||
// Remove this temporary ent
|
||||
G_FreeEdict(ent);
|
||||
}
|
||||
|
||||
/* Here, the "ent" is referring to the client, the player that owns the
|
||||
* chasecam, and the "opt" integer is telling the function whether to
|
||||
* totally get rid of the camera, or to put it into the background while
|
||||
* it checks if the player is out of the water or not. */
|
||||
void
|
||||
ChasecamRemove(edict_t *ent)
|
||||
{
|
||||
/* Stop the chasecam from moving */
|
||||
VectorClear (ent->client->chasecam->velocity);
|
||||
/* Make the weapon model of the player appear on screen for 1st
|
||||
* person reality and aiming */
|
||||
//Don't turn back on during intermission!
|
||||
if (!level.intermissiontime)
|
||||
{
|
||||
ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
|
||||
}
|
||||
|
||||
/* Make our invisible appearance the same model as the display entity
|
||||
* that mimics us while in chasecam mode */
|
||||
ent->s.modelindex = ent->client->oldplayer->s.modelindex;
|
||||
ent->svflags &= ~SVF_NOCLIENT;
|
||||
|
||||
G_FreeEdict (ent->client->oldplayer);
|
||||
ent->client->oldplayer = NULL;
|
||||
ent->client->chasetoggle = 0;
|
||||
G_FreeEdict (ent->client->chasecam);
|
||||
ent->client->chasecam = NULL;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
void
|
||||
Cmd_Chasecam_Toggle(edict_t *ent)
|
||||
{
|
||||
if (!ent->deadflag)
|
||||
{
|
||||
if (ent->client->chasetoggle)
|
||||
{
|
||||
ChasecamRemove(ent);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChasecamStart(ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CheckChasecam_Viewent(edict_t *ent)
|
||||
{
|
||||
vec3_t angles;
|
||||
|
||||
/*
|
||||
Oldplayer is the fake player that everyone else sees.
|
||||
Assign the same client as the ent we're following so the game
|
||||
can read any vars it wants from there
|
||||
*/
|
||||
if (!ent->client->oldplayer->client)
|
||||
{
|
||||
ent->client->oldplayer->client = ent->client;
|
||||
}
|
||||
/* Copy the angle and model from ourselves to the old player.
|
||||
* Even though people can't see us we still have all this stuff */
|
||||
if ((ent->client->chasetoggle == 1) && (ent->client->oldplayer))
|
||||
{
|
||||
if (ent->client->use)
|
||||
{
|
||||
VectorCopy(ent->client->oldplayer->s.angles, angles);
|
||||
}
|
||||
|
||||
/* Copy player related info */
|
||||
ent->client->oldplayer->s = ent->s;
|
||||
|
||||
/* Lazarus: s.numbers shouldn't be the same */
|
||||
ent->client->oldplayer->s.number = ent->client->oldplayer - g_edicts;
|
||||
if (ent->client->use)
|
||||
{
|
||||
VectorCopy(angles, ent->client->oldplayer->s.angles);
|
||||
}
|
||||
|
||||
ent->client->oldplayer->flags = ent->flags;
|
||||
/* end Lazarus */
|
||||
gi.linkentity (ent->client->oldplayer);
|
||||
}
|
||||
}
|
||||
|
|
@ -1044,6 +1044,16 @@ player_die(edict_t *self, edict_t *inflictor, edict_t *attacker,
|
|||
return;
|
||||
}
|
||||
|
||||
if (self->client->chasetoggle)
|
||||
{
|
||||
ChasecamRemove(self);
|
||||
self->client->pers.chasetoggle = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->client->pers.chasetoggle = 0;
|
||||
}
|
||||
|
||||
VectorClear(self->avelocity);
|
||||
|
||||
self->takedamage = DAMAGE_YES;
|
||||
|
@ -1278,6 +1288,9 @@ InitClientPersistant(gclient_t *client)
|
|||
client->pers.max_rounds = 100;
|
||||
|
||||
client->pers.connected = true;
|
||||
|
||||
/* Default chasecam to off */
|
||||
client->pers.chasetoggle = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1326,6 +1339,7 @@ SaveClientData(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
game.clients[i].pers.chasetoggle = ent->client->chasetoggle;
|
||||
game.clients[i].pers.health = ent->health;
|
||||
game.clients[i].pers.max_health = ent->max_health;
|
||||
game.clients[i].pers.savedFlags =
|
||||
|
@ -1910,6 +1924,18 @@ respawn(edict_t *self)
|
|||
return;
|
||||
}
|
||||
|
||||
if (self->client->oldplayer)
|
||||
{
|
||||
G_FreeEdict (self->client->oldplayer);
|
||||
}
|
||||
self->client->oldplayer = NULL;
|
||||
|
||||
if (self->client->chasecam)
|
||||
{
|
||||
G_FreeEdict (self->client->chasecam);
|
||||
}
|
||||
self->client->chasecam = NULL;
|
||||
|
||||
if (deathmatch->value || coop->value)
|
||||
{
|
||||
/* spectator's don't leave bodies */
|
||||
|
@ -1990,6 +2016,17 @@ spectator_respawn(edict_t *ent)
|
|||
gi.unicast(ent, true);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Third person view */
|
||||
if (ent->client->chasetoggle)
|
||||
{
|
||||
ChasecamRemove(ent);
|
||||
ent->client->pers.chasetoggle = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ent->client->pers.chasetoggle = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2057,7 +2094,7 @@ PutClientInServer(edict_t *ent)
|
|||
int index;
|
||||
vec3_t spawn_origin, spawn_angles;
|
||||
gclient_t *client;
|
||||
int i;
|
||||
int i, chasetoggle;
|
||||
client_persistant_t saved;
|
||||
client_respawn_t resp;
|
||||
|
||||
|
@ -2080,6 +2117,7 @@ PutClientInServer(edict_t *ent)
|
|||
|
||||
index = ent - g_edicts - 1;
|
||||
client = ent->client;
|
||||
chasetoggle = client->pers.chasetoggle;
|
||||
|
||||
/* deathmatch wipes most client data every spawn */
|
||||
if (deathmatch->value)
|
||||
|
@ -2120,7 +2158,11 @@ PutClientInServer(edict_t *ent)
|
|||
}
|
||||
else
|
||||
{
|
||||
char userinfo[MAX_INFO_STRING];
|
||||
|
||||
memset(&resp, 0, sizeof(resp));
|
||||
memcpy(userinfo, client->pers.userinfo, sizeof(userinfo));
|
||||
ClientUserinfoChanged (ent, userinfo);
|
||||
}
|
||||
|
||||
/* clear everything but the persistant data */
|
||||
|
@ -2134,6 +2176,7 @@ PutClientInServer(edict_t *ent)
|
|||
}
|
||||
|
||||
client->resp = resp;
|
||||
client->pers.chasetoggle = chasetoggle;
|
||||
|
||||
/* copy some data from the client to the entity */
|
||||
FetchClientEntData(ent);
|
||||
|
@ -2158,6 +2201,10 @@ PutClientInServer(edict_t *ent)
|
|||
ent->watertype = 0;
|
||||
ent->flags &= ~FL_NO_KNOCKBACK;
|
||||
ent->svflags &= ~SVF_DEADMONSTER;
|
||||
/* Third person view */
|
||||
ent->svflags &= ~SVF_NOCLIENT;
|
||||
/* Turn off prediction */
|
||||
ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
|
||||
|
||||
VectorCopy(mins, ent->mins);
|
||||
VectorCopy(maxs, ent->maxs);
|
||||
|
@ -2258,6 +2305,13 @@ PutClientInServer(edict_t *ent)
|
|||
|
||||
gi.linkentity(ent);
|
||||
|
||||
ent->client->chasetoggle = 0;
|
||||
/* If chasetoggle set then turn on (delayed start of 5 frames - 0.5s) */
|
||||
if (ent->client->pers.chasetoggle && !ent->client->chasetoggle)
|
||||
{
|
||||
ent->client->delayedstart = 5;
|
||||
}
|
||||
|
||||
/* my tribute to cash's level-specific hacks. I hope
|
||||
* live up to his trailblazing cheese. */
|
||||
if (Q_stricmp(level.mapname, "rboss") == 0)
|
||||
|
@ -2603,6 +2657,11 @@ ClientDisconnect(edict_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
if(ent->client->chasetoggle)
|
||||
{
|
||||
ChasecamRemove(ent);
|
||||
}
|
||||
|
||||
gi.bprintf(PRINT_HIGH, "%s disconnected\n", ent->client->pers.netname);
|
||||
|
||||
if (ctf->value)
|
||||
|
@ -2728,6 +2787,11 @@ ClientThink(edict_t *ent, usercmd_t *ucmd)
|
|||
|
||||
if (level.intermissiontime)
|
||||
{
|
||||
if (client->chasetoggle)
|
||||
{
|
||||
ChasecamRemove(ent);
|
||||
}
|
||||
|
||||
client->ps.pmove.pm_type = PM_FREEZE;
|
||||
|
||||
/* can exit intermission after five seconds */
|
||||
|
@ -2740,6 +2804,44 @@ ClientThink(edict_t *ent, usercmd_t *ucmd)
|
|||
return;
|
||||
}
|
||||
|
||||
if (client->chasetoggle)
|
||||
{
|
||||
ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
|
||||
}
|
||||
|
||||
/* +use now does the cool look around stuff but only in SP games */
|
||||
if ((ucmd->buttons & BUTTON_USE) && (!deathmatch->value))
|
||||
{
|
||||
client->use = 1;
|
||||
if ((ucmd->forwardmove < 0) && (client->zoom < 60))
|
||||
{
|
||||
client->zoom++;
|
||||
}
|
||||
else if ((ucmd->forwardmove > 0) && (client->zoom > -40))
|
||||
{
|
||||
client->zoom--;
|
||||
}
|
||||
ucmd->forwardmove = 0;
|
||||
ucmd->sidemove = 0;
|
||||
}
|
||||
else if (client->use)
|
||||
{
|
||||
if (client->oldplayer)
|
||||
{
|
||||
// set angles
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(
|
||||
ent->client->oldplayer->s.angles[i] - ent->client->resp.cmd_angles[i]);
|
||||
}
|
||||
}
|
||||
client->use = 0;
|
||||
}
|
||||
|
||||
pm_passent = ent;
|
||||
|
||||
if (ent->client->chase_target)
|
||||
|
@ -2997,6 +3099,16 @@ ClientBeginServerFrame(edict_t *ent)
|
|||
|
||||
client = ent->client;
|
||||
|
||||
if (client->delayedstart > 0)
|
||||
{
|
||||
client->delayedstart--;
|
||||
}
|
||||
|
||||
if (client->delayedstart == 1)
|
||||
{
|
||||
ChasecamStart(ent);
|
||||
}
|
||||
|
||||
if (deathmatch->value &&
|
||||
(client->pers.spectator != client->resp.spectator) &&
|
||||
((level.time - client->respawn_time) >= 5))
|
||||
|
|
|
@ -133,6 +133,9 @@ BeginIntermission(edict_t *targ)
|
|||
{
|
||||
respawn(client);
|
||||
}
|
||||
|
||||
/* Save third person view */
|
||||
client->client->pers.chasetoggle = client->client->chasetoggle;
|
||||
}
|
||||
|
||||
level.intermissiontime = level.time;
|
||||
|
@ -664,7 +667,8 @@ G_SetStats(edict_t *ent)
|
|||
ent->client->ps.stats[STAT_HELPICON] = gi.imageindex("i_help");
|
||||
}
|
||||
else if (((ent->client->pers.hand == CENTER_HANDED) ||
|
||||
(ent->client->ps.fov > 91)) &&
|
||||
(ent->client->ps.fov > 91) ||
|
||||
(ent->client->chasetoggle)) &&
|
||||
ent->client->pers.weapon)
|
||||
{
|
||||
cvar_t *gun;
|
||||
|
|
|
@ -401,31 +401,44 @@ SV_CalcViewOffset(edict_t *ent)
|
|||
/* absolutely bound offsets
|
||||
so the view can never be
|
||||
outside the player box */
|
||||
if (v[0] < -14)
|
||||
if (!ent->client->chasetoggle)
|
||||
{
|
||||
v[0] = -14;
|
||||
}
|
||||
else if (v[0] > 14)
|
||||
{
|
||||
v[0] = 14;
|
||||
}
|
||||
if (v[0] < -14)
|
||||
{
|
||||
v[0] = -14;
|
||||
}
|
||||
else if (v[0] > 14)
|
||||
{
|
||||
v[0] = 14;
|
||||
}
|
||||
|
||||
if (v[1] < -14)
|
||||
{
|
||||
v[1] = -14;
|
||||
}
|
||||
else if (v[1] > 14)
|
||||
{
|
||||
v[1] = 14;
|
||||
}
|
||||
if (v[1] < -14)
|
||||
{
|
||||
v[1] = -14;
|
||||
}
|
||||
else if (v[1] > 14)
|
||||
{
|
||||
v[1] = 14;
|
||||
}
|
||||
|
||||
if (v[2] < -22)
|
||||
{
|
||||
v[2] = -22;
|
||||
if (v[2] < -22)
|
||||
{
|
||||
v[2] = -22;
|
||||
}
|
||||
else if (v[2] > 30)
|
||||
{
|
||||
v[2] = 30;
|
||||
}
|
||||
}
|
||||
else if (v[2] > 30)
|
||||
else
|
||||
{
|
||||
v[2] = 30;
|
||||
VectorSet (v, 0, 0, 0);
|
||||
if (ent->client->chasecam)
|
||||
{
|
||||
ent->client->ps.pmove.origin[0] = ent->client->chasecam->s.origin[0] * 8;
|
||||
ent->client->ps.pmove.origin[1] = ent->client->chasecam->s.origin[1] * 8;
|
||||
ent->client->ps.pmove.origin[2] = ent->client->chasecam->s.origin[2] * 8;
|
||||
}
|
||||
}
|
||||
|
||||
VectorCopy(v, ent->client->ps.viewoffset);
|
||||
|
@ -557,7 +570,16 @@ SV_CalcBlend(edict_t *ent)
|
|||
ent->client->ps.blend[2] = ent->client->ps.blend[3] = 0;
|
||||
|
||||
/* add for contents */
|
||||
VectorAdd(ent->s.origin, ent->client->ps.viewoffset, vieworg);
|
||||
if (ent->client->chasetoggle)
|
||||
{
|
||||
/* if always on then do shading to camera not player */
|
||||
VectorCopy(ent->client->chasecam->s.origin, vieworg);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorAdd(ent->s.origin, ent->client->ps.viewoffset, vieworg);
|
||||
}
|
||||
|
||||
contents = gi.pointcontents(vieworg);
|
||||
|
||||
if (contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER))
|
||||
|
@ -1616,4 +1638,9 @@ ClientEndServerFrame(edict_t *ent)
|
|||
InventoryMessage(ent);
|
||||
gi.unicast(ent, false);
|
||||
}
|
||||
|
||||
if (ent->client->chasetoggle == 1)
|
||||
{
|
||||
CheckChasecam_Viewent(ent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -510,8 +510,16 @@ ChangeWeapon(edict_t *ent)
|
|||
|
||||
ent->client->weaponstate = WEAPON_ACTIVATING;
|
||||
ent->client->ps.gunframe = 0;
|
||||
ent->client->ps.gunindex = gi.modelindex(
|
||||
ent->client->pers.weapon->view_model);
|
||||
/* Don't display weapon if chasetoggle is on */
|
||||
if (ent->client->chasetoggle)
|
||||
{
|
||||
ent->client->ps.gunindex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ent->client->ps.gunindex = gi.modelindex(
|
||||
ent->client->pers.weapon->view_model);
|
||||
}
|
||||
|
||||
ent->client->anim_priority = ANIM_PAIN;
|
||||
|
||||
|
@ -1069,7 +1077,14 @@ weapon_grenade_fire(edict_t *ent, qboolean held)
|
|||
}
|
||||
}
|
||||
|
||||
AngleVectors(ent->client->v_angle, forward, right, up);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, up);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, up);
|
||||
}
|
||||
|
||||
if (ent->client->pers.weapon->tag == AMMO_TESLA)
|
||||
{
|
||||
|
@ -1360,7 +1375,16 @@ weapon_grenadelauncher_fire(edict_t *ent)
|
|||
}
|
||||
|
||||
VectorSet(offset, 8, 8, ent->viewheight - 8);
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
}
|
||||
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
|
@ -1377,9 +1401,26 @@ weapon_grenadelauncher_fire(edict_t *ent)
|
|||
}
|
||||
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
gi.WriteByte(MZ_GRENADE | is_silenced);
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast (ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
|
||||
|
@ -1459,7 +1500,14 @@ Weapon_RocketLauncher_Fire(edict_t *ent)
|
|||
radius_damage *= damage_multiplier;
|
||||
}
|
||||
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
}
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -1;
|
||||
|
@ -1470,9 +1518,26 @@ Weapon_RocketLauncher_Fire(edict_t *ent)
|
|||
|
||||
/* send muzzle flash */
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
gi.WriteByte(MZ_ROCKET | is_silenced);
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast(ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
|
||||
|
@ -1531,7 +1596,15 @@ Blaster_Fire(edict_t *ent, vec3_t g_offset, int damage,
|
|||
damage *= damage_multiplier;
|
||||
}
|
||||
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
}
|
||||
|
||||
VectorSet(offset, 24, 8, ent->viewheight - 8);
|
||||
VectorAdd(offset, g_offset, offset);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
@ -1543,7 +1616,15 @@ Blaster_Fire(edict_t *ent, vec3_t g_offset, int damage,
|
|||
|
||||
/* send muzzle flash */
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
if (hyper)
|
||||
{
|
||||
|
@ -1554,7 +1635,14 @@ Blaster_Fire(edict_t *ent, vec3_t g_offset, int damage,
|
|||
gi.WriteByte(MZ_BLASTER | is_silenced);
|
||||
}
|
||||
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
PlayerNoise(ent, start, PNOISE_WEAPON);
|
||||
}
|
||||
|
@ -1802,7 +1890,15 @@ Machinegun_Fire(edict_t *ent)
|
|||
}
|
||||
|
||||
/* get start / end positions */
|
||||
VectorAdd(ent->client->v_angle, ent->client->kick_angles, angles);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
VectorAdd (ent->client->oldplayer->s.angles, ent->client->kick_angles, angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorAdd(ent->client->v_angle, ent->client->kick_angles, angles);
|
||||
}
|
||||
|
||||
AngleVectors(angles, forward, right, NULL);
|
||||
VectorSet(offset, 0, 8, ent->viewheight - 8);
|
||||
P_ProjectSource(ent, offset, forward, right, start);
|
||||
|
@ -1810,9 +1906,26 @@ Machinegun_Fire(edict_t *ent)
|
|||
DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN);
|
||||
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
gi.WriteByte(MZ_MACHINEGUN | is_silenced);
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
PlayerNoise(ent, start, PNOISE_WEAPON);
|
||||
|
||||
|
@ -1983,7 +2096,15 @@ Chaingun_Fire(edict_t *ent)
|
|||
for (i = 0; i < shots; i++)
|
||||
{
|
||||
/* get start / end positions */
|
||||
AngleVectors(ent->client->v_angle, forward, right, up);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, up);
|
||||
}
|
||||
|
||||
r = 7 + crandom() * 4;
|
||||
u = crandom() * 4;
|
||||
VectorSet(offset, 0, r, u + ent->viewheight - 8);
|
||||
|
@ -1997,9 +2118,26 @@ Chaingun_Fire(edict_t *ent)
|
|||
|
||||
/* send muzzle flash */
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
gi.WriteByte((MZ_CHAINGUN1 + shots - 1) | is_silenced);
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast(ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
PlayerNoise(ent, start, PNOISE_WEAPON);
|
||||
|
||||
|
@ -2057,7 +2195,14 @@ weapon_shotgun_fire(edict_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
}
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -2;
|
||||
|
@ -2086,9 +2231,26 @@ weapon_shotgun_fire(edict_t *ent)
|
|||
|
||||
/* send muzzle flash */
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
gi.WriteByte(MZ_SHOTGUN | is_silenced);
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast(ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
PlayerNoise(ent, start, PNOISE_WEAPON);
|
||||
|
@ -2135,7 +2297,14 @@ weapon_supershotgun_fire(edict_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
}
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -2;
|
||||
|
@ -2149,9 +2318,19 @@ weapon_supershotgun_fire(edict_t *ent)
|
|||
kick *= damage_multiplier;
|
||||
}
|
||||
|
||||
v[PITCH] = ent->client->v_angle[PITCH];
|
||||
v[YAW] = ent->client->v_angle[YAW] - 5;
|
||||
v[ROLL] = ent->client->v_angle[ROLL];
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
v[PITCH] = ent->client->oldplayer->s.angles[PITCH];
|
||||
v[YAW] = ent->client->oldplayer->s.angles[YAW] - 5;
|
||||
v[ROLL] = ent->client->oldplayer->s.angles[ROLL];
|
||||
}
|
||||
else
|
||||
{
|
||||
v[PITCH] = ent->client->v_angle[PITCH];
|
||||
v[YAW] = ent->client->v_angle[YAW] - 5;
|
||||
v[ROLL] = ent->client->v_angle[ROLL];
|
||||
}
|
||||
|
||||
AngleVectors(v, forward, NULL, NULL);
|
||||
|
||||
if (aimfix->value)
|
||||
|
@ -2169,7 +2348,15 @@ weapon_supershotgun_fire(edict_t *ent)
|
|||
DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD,
|
||||
DEFAULT_SSHOTGUN_COUNT / 2, MOD_SSHOTGUN);
|
||||
|
||||
v[YAW] = ent->client->v_angle[YAW] + 5;
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
v[YAW] = ent->client->oldplayer->s.angles[YAW] + 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[YAW] = ent->client->v_angle[YAW] + 5;
|
||||
}
|
||||
|
||||
AngleVectors(v, forward, NULL, NULL);
|
||||
|
||||
if (aimfix->value)
|
||||
|
@ -2189,9 +2376,26 @@ weapon_supershotgun_fire(edict_t *ent)
|
|||
|
||||
/* send muzzle flash */
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
gi.WriteByte(MZ_SSHOTGUN | is_silenced);
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
PlayerNoise(ent, start, PNOISE_WEAPON);
|
||||
|
@ -2263,7 +2467,14 @@ weapon_railgun_fire(edict_t *ent)
|
|||
kick *= damage_multiplier;
|
||||
}
|
||||
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
}
|
||||
|
||||
VectorScale(forward, -3, ent->client->kick_origin);
|
||||
ent->client->kick_angles[0] = -3;
|
||||
|
@ -2274,9 +2485,26 @@ weapon_railgun_fire(edict_t *ent)
|
|||
|
||||
/* send muzzle flash */
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
gi.WriteByte(MZ_RAILGUN | is_silenced);
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast(ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
PlayerNoise(ent, start, PNOISE_WEAPON);
|
||||
|
@ -2342,9 +2570,26 @@ weapon_bfg_fire(edict_t *ent)
|
|||
{
|
||||
/* send muzzle flash */
|
||||
gi.WriteByte(svc_muzzleflash);
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.WriteShort(ent->client->oldplayer - g_edicts);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteShort(ent - g_edicts);
|
||||
}
|
||||
|
||||
gi.WriteByte(MZ_BFG | is_silenced);
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
|
||||
if (ent->client->oldplayer)
|
||||
{
|
||||
gi.multicast(ent->client->oldplayer->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.multicast(ent->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
|
||||
ent->client->ps.gunframe++;
|
||||
|
||||
|
@ -2365,7 +2610,14 @@ weapon_bfg_fire(edict_t *ent)
|
|||
damage *= damage_multiplier;
|
||||
}
|
||||
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
if ((ent->client->use) && (ent->client->oldplayer))
|
||||
{
|
||||
AngleVectors(ent->client->oldplayer->s.angles, forward, right, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AngleVectors(ent->client->v_angle, forward, right, NULL);
|
||||
}
|
||||
|
||||
VectorScale(forward, -2, ent->client->kick_origin);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ extern void VectorScale ( const vec3_t in , vec_t scale , vec3_t out ) ;
|
|||
extern void VectorInverse ( vec3_t v ) ;
|
||||
extern vec_t VectorLength ( const vec3_t v ) ;
|
||||
extern void CrossProduct ( const vec3_t v1 , const vec3_t v2 , vec3_t cross ) ;
|
||||
extern void _VectorCopy ( const vec3_t in , vec3_t out ) ;
|
||||
extern void _VectorCopy( const vec3_t in , vec3_t out ) ;
|
||||
extern void _VectorAdd ( const vec3_t veca , const vec3_t vecb , vec3_t out ) ;
|
||||
extern void _VectorSubtract ( const vec3_t veca , const vec3_t vecb , vec3_t out ) ;
|
||||
extern vec_t _DotProduct ( const vec3_t v1 , const vec3_t v2 ) ;
|
||||
|
@ -93,7 +93,7 @@ extern void R_ConcatRotations ( const float in1 [ 3 ] [ 3 ] , const float in2 [
|
|||
extern void PerpendicularVector ( vec3_t dst , const vec3_t src ) ;
|
||||
extern void ProjectPointOnPlane ( vec3_t dst , const vec3_t p , const vec3_t normal ) ;
|
||||
extern void AngleVectors2 ( const vec3_t value1 , vec3_t angles ) ;
|
||||
extern void AngleVectors ( const vec3_t angles , vec3_t forward , vec3_t right , vec3_t up ) ;
|
||||
extern void AngleVectors( const vec3_t angles , vec3_t forward , vec3_t right , vec3_t up ) ;
|
||||
extern void RotatePointAroundVector ( vec3_t dst , const vec3_t dir , const vec3_t point , float degrees ) ;
|
||||
extern void Weapon_Trap ( edict_t * ent ) ;
|
||||
extern void weapon_trap_fire ( edict_t * ent , qboolean held ) ;
|
||||
|
@ -1769,6 +1769,7 @@ extern void GetChaseTarget ( edict_t * ent ) ;
|
|||
extern void ChasePrev ( edict_t * ent ) ;
|
||||
extern void ChaseNext ( edict_t * ent ) ;
|
||||
extern void UpdateChaseCam ( edict_t * ent ) ;
|
||||
extern void ChasecamTrack(edict_t *ent);
|
||||
extern void ai_run ( edict_t * self , float dist ) ;
|
||||
extern qboolean ai_checkattack ( edict_t * self ) ;
|
||||
extern void ai_run_slide ( edict_t * self , float distance ) ;
|
||||
|
|
|
@ -1768,6 +1768,7 @@
|
|||
{"ChasePrev", (byte *)ChasePrev},
|
||||
{"ChaseNext", (byte *)ChaseNext},
|
||||
{"UpdateChaseCam", (byte *)UpdateChaseCam},
|
||||
{"ChasecamTrack", (byte *)ChasecamTrack},
|
||||
{"ai_run", (byte *)ai_run},
|
||||
{"ai_checkattack", (byte *)ai_checkattack},
|
||||
{"ai_run_slide", (byte *)ai_run_slide},
|
||||
|
|
Loading…
Reference in a new issue