mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 21:31:37 +00:00
rewrote cam tracking code. should make cl_chasecam 0 more robust and avoid spam about invalid clients to track (and the associated ptrack spam).
smoothed out cl_chasecam 0 angles. server browser no longer counts spectators as players. also sorts players by frags. fix ezhud r_tracking_frame issue, by making it technically 0 height when not tracking. r_showfields is now a separate cvar, instead of being rolled into r_showbboxes. now shows only a single entity. fix qport issue. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4915 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
6853a4fd1e
commit
59cbcfe355
26 changed files with 377 additions and 229 deletions
|
@ -146,7 +146,7 @@ static int CL_FindHighTrack(int seat, char *rule)
|
|||
|
||||
//set a default to the currently tracked player, to reuse the current player we're tracking if someone lower equalises.
|
||||
j = cl.playerview[seat].cam_spec_track;
|
||||
if (j >= 0 && cl.players[j].name[0] && !cl.players[j].spectator)
|
||||
if (j >= 0 && cl.players[j].userid && cl.players[j].name[0] && !cl.players[j].spectator)
|
||||
max = CL_TrackScore(&cl.players[j], rule);
|
||||
else
|
||||
{
|
||||
|
@ -158,7 +158,7 @@ static int CL_FindHighTrack(int seat, char *rule)
|
|||
{
|
||||
s = &cl.players[i];
|
||||
score = CL_TrackScore(s, rule);
|
||||
if (s->name[0] && !s->spectator && score > max)
|
||||
if (s->userid && s->name[0] && !s->spectator && score > max)
|
||||
{
|
||||
if (j == i) //this was our default.
|
||||
continue;
|
||||
|
@ -210,7 +210,7 @@ qboolean Cam_DrawViewModel(playerview_t *pv)
|
|||
{
|
||||
if (cl.spectator)
|
||||
{
|
||||
if (pv->cam_auto && pv->cam_locked && cl_chasecam.ival)
|
||||
if (pv->cam_state == CAM_EYECAM && cl_chasecam.ival)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -224,18 +224,17 @@ qboolean Cam_DrawViewModel(playerview_t *pv)
|
|||
|
||||
int Cam_TrackNum(playerview_t *pv)
|
||||
{
|
||||
if (!pv->cam_auto)
|
||||
return -1;
|
||||
return pv->cam_spec_track;
|
||||
if (pv->cam_state == CAM_EYECAM)
|
||||
return pv->cam_spec_track;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Cam_Unlock(playerview_t *pv)
|
||||
{
|
||||
if (pv->cam_auto)
|
||||
if (pv->cam_state)
|
||||
{
|
||||
CL_SendClientCommand(true, "ptrack");
|
||||
pv->cam_auto = CAM_NONE;
|
||||
pv->cam_locked = false;
|
||||
pv->cam_state = CAM_FREECAM;
|
||||
pv->viewentity = (cls.demoplayback)?0:(pv->playernum+1); //free floating
|
||||
Sbar_Changed();
|
||||
}
|
||||
|
@ -245,12 +244,12 @@ void Cam_Lock(playerview_t *pv, int playernum)
|
|||
{
|
||||
int i;
|
||||
|
||||
pv->cam_lastviewtime = -1000;
|
||||
pv->cam_lastviewtime = -1000; //allow the wallcam to re-snap as soon as it can
|
||||
|
||||
CL_SendClientCommand(true, "ptrack %i", playernum);
|
||||
|
||||
pv->cam_spec_track = playernum;
|
||||
pv->cam_locked = false;
|
||||
pv->cam_state = CAM_PENDING;
|
||||
pv->viewentity = (cls.demoplayback)?0:(pv->playernum+1); //free floating until actually locked
|
||||
|
||||
|
||||
|
@ -259,10 +258,16 @@ void Cam_Lock(playerview_t *pv, int playernum)
|
|||
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
|
||||
{
|
||||
memcpy(&pv->stats, cl.players[playernum].stats, sizeof(pv->stats));
|
||||
pv->cam_locked = true; //instantly lock if the player is valid.
|
||||
// pv->cam_state = CAM_;
|
||||
|
||||
// pv->viewentity = playernum+1;
|
||||
/*
|
||||
pv->cam_state = cl_chasecam.ival?CAM_EYECAM:CAM_PENDING; //instantly lock if the player is valid.
|
||||
pv->viewentity = playernum+1;
|
||||
*/
|
||||
if (cls.z_ext & Z_EXT_VIEWHEIGHT)
|
||||
pv->viewheight = cl.players[playernum].statsf[STAT_VIEWHEIGHT];
|
||||
|
||||
}
|
||||
|
||||
Sbar_Changed();
|
||||
|
@ -389,7 +394,7 @@ static qboolean InitFlyby(playerview_t *pv, vec3_t selforigin, vec3_t playerorig
|
|||
return false;
|
||||
}
|
||||
|
||||
pv->cam_locked = true;
|
||||
pv->cam_state = CAM_WALLCAM;
|
||||
pv->viewentity = pv->playernum+1;//pv->cam_spec_track+1;
|
||||
VectorCopy(vec, pv->cam_desired_position);
|
||||
return true;
|
||||
|
@ -403,19 +408,18 @@ static void Cam_CheckHighTarget(playerview_t *pv)
|
|||
j = CL_AutoTrack_Choose(pv - cl.playerview);
|
||||
if (j >= 0)
|
||||
{
|
||||
if (pv->cam_spec_track != j || !pv->cam_locked)
|
||||
if (pv->cam_spec_track != j || pv->cam_state == CAM_FREECAM)
|
||||
{
|
||||
if (cl.teamplay)
|
||||
Stats_Message("Now tracking:\n%s\n%s", cl.players[j].name, cl.players[j].team);
|
||||
else
|
||||
Stats_Message("Now tracking:\n%s", cl.players[j].name);
|
||||
pv->cam_auto++;
|
||||
Cam_Lock(pv, j);
|
||||
//un-lock any higher seats watching our new target. this keeps things ordered.
|
||||
for (spv = pv+1; spv >= cl.playerview && spv < &cl.playerview[cl.splitclients]; spv++)
|
||||
{
|
||||
if (Cam_TrackNum(spv) == j)
|
||||
spv->cam_locked = false;
|
||||
spv->cam_state = CAM_FREECAM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -445,9 +449,9 @@ void Cam_SelfTrack(playerview_t *pv)
|
|||
}
|
||||
else
|
||||
{ //view from a random wall
|
||||
if (!pv->cam_locked || !Cam_IsVisible(pv->simorg, pv->cam_desired_position))
|
||||
if (pv->cam_state != CAM_WALLCAM || !Cam_IsVisible(pv->simorg, pv->cam_desired_position))
|
||||
{
|
||||
if (!pv->cam_locked || realtime - pv->cam_lastviewtime > 0.1)
|
||||
if (pv->cam_state != CAM_WALLCAM || realtime - pv->cam_lastviewtime > 0.1)
|
||||
{
|
||||
if (!InitFlyby(pv, pv->cam_desired_position, pv->simorg, pv->simangles, true))
|
||||
InitFlyby(pv, pv->cam_desired_position, pv->simorg, pv->simangles, false);
|
||||
|
@ -460,7 +464,7 @@ void Cam_SelfTrack(playerview_t *pv)
|
|||
}
|
||||
|
||||
//tracking failed.
|
||||
if (!pv->cam_locked)
|
||||
if (pv->cam_state != CAM_WALLCAM)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -474,6 +478,23 @@ void Cam_SelfTrack(playerview_t *pv)
|
|||
}
|
||||
}
|
||||
|
||||
//player entity became visible, lock on to them (now that we know where they are etc)
|
||||
void Cam_NowLocked(playerview_t *pv)
|
||||
{
|
||||
pv->cam_lastviewtime = realtime;
|
||||
if (!cl_chasecam.ival)
|
||||
{
|
||||
if (pv->cam_state != CAM_WALLCAM || !Cam_IsVisible(pv->simorg, pv->cam_desired_position))
|
||||
{
|
||||
if (pv->cam_state != CAM_WALLCAM || realtime - pv->cam_lastviewtime > 0.1)
|
||||
{
|
||||
if (!InitFlyby(pv, pv->cam_desired_position, pv->simorg, pv->simangles, true))
|
||||
InitFlyby(pv, pv->cam_desired_position, pv->simorg, pv->simangles, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ZOID
|
||||
//
|
||||
// Take over the user controls and track a player.
|
||||
|
@ -488,15 +509,15 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd)
|
|||
if (!cl.spectator || !cl.worldmodel) //can happen when the server changes level
|
||||
return;
|
||||
|
||||
if (autotrackmode != TM_USER && !pv->cam_locked)
|
||||
if (autotrackmode != TM_USER && pv->cam_state == CAM_FREECAM)
|
||||
Cam_CheckHighTarget(pv);
|
||||
|
||||
if (!pv->cam_auto || cls.state != ca_active || cl.worldmodel->loadstate != MLS_LOADED)
|
||||
if (pv->cam_state == CAM_FREECAM || cls.state != ca_active || cl.worldmodel->loadstate != MLS_LOADED)
|
||||
return;
|
||||
|
||||
if (pv->cam_locked && (!cl.players[pv->cam_spec_track].name[0] || cl.players[pv->cam_spec_track].spectator))
|
||||
if (CAM_ISLOCKED(pv) && (!cl.players[pv->cam_spec_track].name[0] || cl.players[pv->cam_spec_track].spectator))
|
||||
{
|
||||
pv->cam_locked = false;
|
||||
pv->cam_state = CAM_FREECAM;
|
||||
if (autotrackmode != TM_USER)
|
||||
Cam_CheckHighTarget(pv);
|
||||
else
|
||||
|
@ -508,22 +529,24 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd)
|
|||
player = frame->playerstate + pv->cam_spec_track;
|
||||
self = frame->playerstate + pv->playernum;
|
||||
|
||||
if (!cl_chasecam.value && (!pv->cam_locked || !Cam_IsVisible(player->origin, pv->cam_desired_position)))
|
||||
if (!cl_chasecam.value && (pv->cam_state != CAM_WALLCAM || !Cam_IsVisible(player->origin, pv->cam_desired_position)))
|
||||
{
|
||||
if (!pv->cam_locked || realtime - pv->cam_lastviewtime > 0.1)
|
||||
if (pv->cam_state != CAM_WALLCAM || realtime - pv->cam_lastviewtime > 0.1)
|
||||
{
|
||||
if (!InitFlyby(pv, self->origin, player->origin, player->viewangles, true))
|
||||
InitFlyby(pv, self->origin, player->origin, player->viewangles, false);
|
||||
pv->cam_lastviewtime = realtime;
|
||||
}
|
||||
}
|
||||
else if (cl_chasecam.value && pv->cam_state == CAM_WALLCAM)
|
||||
pv->cam_state = CAM_PENDING;
|
||||
else
|
||||
{
|
||||
pv->cam_lastviewtime = realtime;
|
||||
}
|
||||
|
||||
//tracking failed.
|
||||
if (!pv->cam_locked || !pv->cam_auto)
|
||||
if (pv->cam_state == CAM_FREECAM || pv->cam_state == CAM_PENDING)
|
||||
return;
|
||||
|
||||
|
||||
|
@ -574,12 +597,12 @@ void Cam_Track(playerview_t *pv, usercmd_t *cmd)
|
|||
// move there locally immediately
|
||||
VectorCopy(pv->cam_desired_position, self->origin);
|
||||
|
||||
VectorSubtract(player->origin, pv->cam_desired_position, vec);
|
||||
VectorAngles(vec, NULL, pv->viewangles);
|
||||
pv->viewangles[0] = -pv->viewangles[0];
|
||||
// VectorSubtract(player->origin, pv->cam_desired_position, vec);
|
||||
// VectorAngles(vec, NULL, pv->viewangles);
|
||||
// pv->viewangles[0] = -pv->viewangles[0];
|
||||
}
|
||||
|
||||
void Cam_SetAutoTrack(int userid)
|
||||
void Cam_SetModAutoTrack(int userid)
|
||||
{ //this is a hint from the server about who to track
|
||||
int slot;
|
||||
playerview_t *pv = &cl.playerview[0];
|
||||
|
@ -624,7 +647,6 @@ void Cam_TrackCrosshairedPlayer(playerview_t *pv)
|
|||
// Con_Printf("Track %i? %f\n", best, bestdot);
|
||||
if (best != -1) //did we actually get someone?
|
||||
{
|
||||
pv->cam_auto++;
|
||||
Cam_Lock(pv, best);
|
||||
}
|
||||
}
|
||||
|
@ -719,9 +741,8 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
|
|||
if (!(pv->cam_oldbuttons & BUTTON_ATTACK))
|
||||
{
|
||||
pv->cam_oldbuttons |= BUTTON_ATTACK;
|
||||
pv->cam_auto++;
|
||||
|
||||
if (pv->cam_auto > CAM_TRACK)
|
||||
if (pv->cam_state != CAM_FREECAM)
|
||||
{
|
||||
Cam_Unlock(pv);
|
||||
VectorCopy(pv->viewangles, cmd->angles);
|
||||
|
@ -735,7 +756,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
|
|||
else
|
||||
{
|
||||
pv->cam_oldbuttons &= ~BUTTON_ATTACK;
|
||||
if (!pv->cam_auto && autotrackmode == TM_USER)
|
||||
if (pv->cam_state == CAM_FREECAM && autotrackmode == TM_USER)
|
||||
{
|
||||
if ((cmd->buttons & BUTTON_JUMP) && !(pv->cam_oldbuttons & BUTTON_JUMP))
|
||||
Cam_TrackCrosshairedPlayer(pv);
|
||||
|
@ -744,7 +765,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
if (pv->cam_auto && autotrackmode != TM_USER)
|
||||
if (autotrackmode != TM_USER)
|
||||
{
|
||||
if ((cmd->buttons & BUTTON_JUMP) && !(pv->cam_oldbuttons & BUTTON_JUMP))
|
||||
autotrackmode = TM_USER;
|
||||
|
@ -755,7 +776,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
if (pv->cam_locked)
|
||||
if (pv->cam_state != CAM_FREECAM)
|
||||
{
|
||||
if ((cmd->buttons & BUTTON_JUMP) && (pv->cam_oldbuttons & BUTTON_JUMP))
|
||||
return; // don't pogo stick
|
||||
|
@ -770,8 +791,8 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
|
|||
|
||||
// Con_Printf("Selecting track target...\n");
|
||||
|
||||
if (pv->cam_locked && pv->cam_auto)
|
||||
end = (pv->cam_spec_track + 1) % MAX_CLIENTS;
|
||||
if (pv->cam_state != CAM_FREECAM)
|
||||
end = (pv->cam_spec_track + 1) % MAX_CLIENTS;
|
||||
else
|
||||
end = pv->cam_spec_track;
|
||||
i = end;
|
||||
|
@ -796,7 +817,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
|
|||
return;
|
||||
}
|
||||
Con_Printf("No target found ...\n");
|
||||
pv->cam_auto = pv->cam_locked = false;
|
||||
pv->cam_state = CAM_FREECAM;
|
||||
}
|
||||
|
||||
void Cam_Reset(void)
|
||||
|
@ -805,7 +826,7 @@ void Cam_Reset(void)
|
|||
for (pnum = 0; pnum < MAX_SPLITS; pnum++)
|
||||
{
|
||||
playerview_t *pv = &cl.playerview[pnum];
|
||||
pv->cam_auto = CAM_NONE;
|
||||
pv->cam_state = CAM_FREECAM;
|
||||
pv->cam_spec_track = 0;
|
||||
}
|
||||
}
|
||||
|
@ -919,11 +940,7 @@ void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg)
|
|||
}
|
||||
}
|
||||
|
||||
pv->cam_auto = CAM_TRACK;
|
||||
Cam_Lock(pv, slot);
|
||||
//and force the lock here and now
|
||||
pv->cam_locked = true;
|
||||
pv->viewentity = slot+1;
|
||||
}
|
||||
|
||||
void Cam_Track_f(void)
|
||||
|
|
|
@ -758,7 +758,7 @@ readit:
|
|||
for (seat = 0; seat < cl.splitclients; seat++)
|
||||
{
|
||||
tracknum = cl.playerview[seat].cam_spec_track;
|
||||
if (!cl.playerview[seat].cam_auto)
|
||||
if (cl.playerview[seat].cam_state == CAM_FREECAM)
|
||||
tracknum = -1;
|
||||
if (tracknum == -1 || !(cls_lastto & (1 << tracknum)))
|
||||
continue;
|
||||
|
@ -780,7 +780,7 @@ readit:
|
|||
for (seat = 0; seat < maxseat; seat++)
|
||||
{
|
||||
tracknum = cl.playerview[seat].cam_spec_track;
|
||||
if (!cl.playerview[seat].cam_auto)
|
||||
if (cl.playerview[seat].cam_state == CAM_FREECAM)
|
||||
tracknum = -1;
|
||||
if (tracknum == -1 || (cls_lastto != tracknum))
|
||||
continue;
|
||||
|
|
|
@ -2535,7 +2535,17 @@ void CLQ1_AddVisibleBBoxes(void)
|
|||
CLQ1_AddOrientedCylinder(s, rad*2, height*2, true, matrix, (e->v->solid || e->v->movetype)?0.1:0, (e->v->movetype == MOVETYPE_STEP || e->v->movetype == MOVETYPE_TOSS || e->v->movetype == MOVETYPE_BOUNCE)?0.1:0, ((int)e->v->flags & (FL_ONGROUND | ((e->v->movetype == MOVETYPE_STEP)?FL_FLY:0)))?0.1:0, 1);
|
||||
}
|
||||
else
|
||||
CLQ1_AddOrientedCube(s, min, max, NULL, (e->v->solid || e->v->movetype)?0.1:0, (e->v->movetype == MOVETYPE_STEP || e->v->movetype == MOVETYPE_TOSS || e->v->movetype == MOVETYPE_BOUNCE)?0.1:0, ((int)e->v->flags & (FL_ONGROUND | ((e->v->movetype == MOVETYPE_STEP)?FL_FLY:0)))?0.1:0, 1);
|
||||
{
|
||||
if (!e->v->solid && !e->v->movetype)
|
||||
{
|
||||
vec3_t ep = {1,1,1};
|
||||
VectorAdd(max, ep, max);
|
||||
VectorSubtract(min, ep, min);
|
||||
CLQ1_AddOrientedCube(s, min, max, NULL, 0, 0.1, 0, 1);
|
||||
}
|
||||
else
|
||||
CLQ1_AddOrientedCube(s, min, max, NULL, (e->v->solid || e->v->movetype)?0.1:0, (e->v->movetype == MOVETYPE_STEP || e->v->movetype == MOVETYPE_TOSS || e->v->movetype == MOVETYPE_BOUNCE)?0.1:0, ((int)e->v->flags & (FL_ONGROUND | ((e->v->movetype == MOVETYPE_STEP)?FL_FLY:0)))?0.1:0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3861,8 +3871,7 @@ void CL_ParsePlayerinfo (void)
|
|||
info->prevcount = cl.parsecount;
|
||||
|
||||
if (cls.findtrack && info->stats[STAT_HEALTH] > 0)
|
||||
{
|
||||
cl.playerview[0].cam_auto = CAM_TRACK;
|
||||
{ //FIXME: is this still needed with the autotrack stuff?
|
||||
Cam_Lock(&cl.playerview[0], num);
|
||||
cls.findtrack = false;
|
||||
}
|
||||
|
@ -3950,15 +3959,13 @@ void CL_ParsePlayerinfo (void)
|
|||
for (i = 0; i < cl.splitclients; i++)
|
||||
{
|
||||
playerview_t *pv = &cl.playerview[i];
|
||||
if (pv->cam_auto && pv->cam_spec_track == num)
|
||||
if (pv->cam_state != CAM_FREECAM && pv->cam_spec_track == num)
|
||||
return;
|
||||
}
|
||||
|
||||
if (i == cl.splitclients)
|
||||
{
|
||||
playerview_t *pv = &cl.playerview[cl.splitclients++];
|
||||
pv->cam_auto = CAM_TRACK;
|
||||
pv->cam_spec_track = num;
|
||||
Cam_Lock(pv, num);
|
||||
}
|
||||
}
|
||||
|
@ -4503,7 +4510,7 @@ void CL_LinkPlayers (void)
|
|||
angles[ROLL] = 0;
|
||||
angles[ROLL] = V_CalcRoll (angles, state->velocity)*4;
|
||||
|
||||
if (j+1 == r_refdef.playerview->viewentity || (cl.spectator && r_refdef.playerview->cam_locked && r_refdef.playerview->cam_spec_track == j))
|
||||
if (j+1 == r_refdef.playerview->viewentity || (r_refdef.playerview->cam_state == CAM_EYECAM && r_refdef.playerview->cam_spec_track == j))
|
||||
ent->flags |= RF_EXTERNALMODEL;
|
||||
// the player object gets added with flags | 2
|
||||
for (pnum = 0; pnum < cl.splitclients; pnum++)
|
||||
|
|
|
@ -286,7 +286,7 @@ void IN_JumpDown (void)
|
|||
cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playerview[pnum].playernum].messagenum == cl.validsequence && cl.playerview[pnum].waterlevel >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1))
|
||||
)
|
||||
KeyDown(&in_up);
|
||||
else if (condition && cl.spectator && Cam_TrackNum(&cl.playerview[pnum]) == -1)
|
||||
else if (condition && cl.spectator && !CAM_ISLOCKED(&cl.playerview[pnum]))
|
||||
KeyDown(&in_up);
|
||||
else
|
||||
KeyDown(&in_jump);
|
||||
|
|
|
@ -55,8 +55,9 @@ typedef enum
|
|||
|
||||
SLKEY_MOD,
|
||||
SLKEY_PROTOCOL,
|
||||
SLKEY_NUMBOTS,
|
||||
SLKEY_NUMHUMANS,
|
||||
SLKEY_NUMBOTS, //uninteresting bots that will presumably get kicked if people join.
|
||||
SLKEY_NUMSPECTATORS,//spectators
|
||||
SLKEY_NUMHUMANS, //actual players
|
||||
SLKEY_QCSTATUS,
|
||||
// SLKEY_PLAYERS, //eep!
|
||||
SLKEY_ISFAVORITE,//eep!
|
||||
|
@ -92,17 +93,18 @@ typedef struct serverdetailedinfo_s
|
|||
|
||||
int numplayers;
|
||||
|
||||
struct
|
||||
struct serverdetailedplayerinfo_s
|
||||
{
|
||||
int userid;
|
||||
int frags;
|
||||
float time;
|
||||
int ping;
|
||||
char name[64];
|
||||
char skin[16];
|
||||
char skin[16]; //is this even useful?
|
||||
char team[16];
|
||||
char topc;
|
||||
char botc;
|
||||
qbyte isspec;
|
||||
} players[MAX_CLIENTS];
|
||||
} serverdetailedinfo_t;
|
||||
|
||||
|
@ -115,15 +117,15 @@ typedef struct serverinfo_s
|
|||
short special; //flags
|
||||
short protocol;
|
||||
|
||||
unsigned char players;
|
||||
unsigned char maxplayers;
|
||||
qbyte players;
|
||||
qbyte maxplayers;
|
||||
qbyte sends;
|
||||
qbyte insortedlist;
|
||||
|
||||
qbyte numspectators;
|
||||
qbyte numhumans;
|
||||
qbyte numbots;
|
||||
qbyte freeslots;
|
||||
qbyte pad;
|
||||
|
||||
char modname[8+1];
|
||||
char qcstatus[8+1];
|
||||
|
|
|
@ -5764,7 +5764,7 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
|
|||
}
|
||||
else if (!strncmp(stufftext, "//at ", 5))
|
||||
{
|
||||
Cam_SetAutoTrack(atoi(stufftext+5));
|
||||
Cam_SetModAutoTrack(atoi(stufftext+5));
|
||||
}
|
||||
else if (!strncmp(stufftext, "//wps ", 5))
|
||||
{
|
||||
|
|
|
@ -752,14 +752,15 @@ static void CL_EntStateToPlayerState(player_state_t *plstate, entity_state_t *st
|
|||
else
|
||||
VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity);
|
||||
VectorCopy(state->angles, plstate->viewangles);
|
||||
if (state->u.q1.pmovetype)
|
||||
plstate->viewangles[0] *= -3;
|
||||
plstate->viewangles[2] = V_CalcRoll(plstate->viewangles, plstate->velocity);
|
||||
// plstate->viewangles[2] = V_CalcRoll(plstate->viewangles, plstate->velocity);
|
||||
|
||||
plstate->viewangles[0] = SHORT2ANGLE(state->u.q1.vangle[0]);
|
||||
plstate->viewangles[1] = SHORT2ANGLE(state->u.q1.vangle[1]);
|
||||
plstate->viewangles[2] = SHORT2ANGLE(state->u.q1.vangle[2]);
|
||||
|
||||
if (state->u.q1.pmovetype)
|
||||
plstate->viewangles[0] *= -3;
|
||||
|
||||
a[0] = ((-192-state->u.q1.gravitydir[0])/256.0f) * 360;
|
||||
a[1] = (state->u.q1.gravitydir[1]/256.0f) * 360;
|
||||
a[2] = 0;
|
||||
|
@ -850,6 +851,8 @@ void CL_PredictMovePNum (int seat)
|
|||
lerpents_t *le;
|
||||
qboolean nopred;
|
||||
qboolean lerpangles = false;
|
||||
int trackent;
|
||||
qboolean cam_nowlocked = false;
|
||||
|
||||
//these are to make svc_viewentity work better
|
||||
float netfps = cl_netfps.value;
|
||||
|
@ -890,6 +893,9 @@ void CL_PredictMovePNum (int seat)
|
|||
|
||||
pv->nolocalplayer = !!(cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) || (cls.protocol != CP_QUAKEWORLD);
|
||||
|
||||
if (!cl.spectator) //just in case
|
||||
pv->cam_state = CAM_FREECAM;
|
||||
|
||||
#ifdef Q2CLIENT
|
||||
if (cls.protocol == CP_QUAKE2)
|
||||
{
|
||||
|
@ -901,7 +907,7 @@ void CL_PredictMovePNum (int seat)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && (!cl.spectator || !pv->cam_auto))
|
||||
if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && pv->cam_state == CAM_FREECAM)
|
||||
return;
|
||||
|
||||
if (!cl.validsequence)
|
||||
|
@ -937,31 +943,23 @@ void CL_PredictMovePNum (int seat)
|
|||
}
|
||||
}
|
||||
|
||||
if (pv->cam_locked && pv->cam_spec_track >= 0)
|
||||
//if we now know where our target player is, we can finally lock on to them.
|
||||
if (pv->cam_state == CAM_PENDING && pv->cam_spec_track >= 0 && pv->cam_spec_track < cl.allocated_client_slots && pv->viewentity != pv->cam_spec_track+1)
|
||||
{
|
||||
extern cvar_t cl_chasecam;
|
||||
if (!cl_chasecam.ival)
|
||||
if ((cl.inframes[cl.validsequence & UPDATE_MASK].playerstate[pv->cam_spec_track].messagenum == cl.validsequence) ||
|
||||
(pv->cam_spec_track+1 < cl.maxlerpents && cl.lerpents[pv->cam_spec_track+1].sequence == cl.lerpentssequence))
|
||||
{
|
||||
//FIXME: don't early out, so that we can smooth out angles too
|
||||
VectorCopy(pv->cam_desired_position, pv->simorg);
|
||||
VectorClear(pv->simvel);
|
||||
return;
|
||||
extern cvar_t cl_chasecam;
|
||||
pv->cam_state = CAM_EYECAM;
|
||||
pv->viewentity = pv->cam_spec_track+1;
|
||||
cam_nowlocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pv->cam_locked && pv->cam_auto && cl.spectator && pv->cam_spec_track >= 0 && pv->cam_spec_track < cl.allocated_client_slots && pv->viewentity != pv->cam_spec_track+1)
|
||||
{
|
||||
if (cl.inframes[cl.validsequence & UPDATE_MASK].playerstate[pv->cam_spec_track].messagenum == cl.validsequence)
|
||||
{
|
||||
pv->cam_locked = true;
|
||||
pv->viewentity = pv->cam_spec_track+1;
|
||||
}
|
||||
else if (pv->cam_spec_track+1 < cl.maxlerpents && cl.lerpents[pv->cam_spec_track+1].sequence == cl.lerpentssequence)
|
||||
{
|
||||
pv->cam_locked = true;
|
||||
pv->viewentity = pv->cam_spec_track+1;
|
||||
}
|
||||
}
|
||||
if (pv->cam_state == CAM_WALLCAM)
|
||||
trackent = pv->cam_spec_track+1;
|
||||
else
|
||||
trackent = pv->viewentity;
|
||||
|
||||
nopred = cl_nopred.ival;
|
||||
|
||||
|
@ -973,7 +971,7 @@ void CL_PredictMovePNum (int seat)
|
|||
|
||||
//these things also force-disable prediction
|
||||
if ((cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV) ||
|
||||
cl.paused || pv->pmovetype == PM_NONE || pv->pmovetype == PM_FREEZE || pv->cam_locked)
|
||||
cl.paused || pv->pmovetype == PM_NONE || pv->pmovetype == PM_FREEZE || CAM_ISLOCKED(pv))
|
||||
{
|
||||
nopred = true;
|
||||
}
|
||||
|
@ -1044,10 +1042,10 @@ void CL_PredictMovePNum (int seat)
|
|||
|
||||
// Con_DPrintf("sim%f, %i(%i-%i): old%f, cur%f\n", simtime, cl.ackedmovesequence, fromframe, toframe, fromtime, totime);
|
||||
|
||||
if (pv->cam_locked && cl.spectator && pv->viewentity && pv->viewentity <= cl.allocated_client_slots)
|
||||
if ((pv->cam_state == CAM_WALLCAM || pv->cam_state == CAM_EYECAM) && trackent && trackent <= cl.allocated_client_slots)
|
||||
{
|
||||
fromstate = &cl.inframes[fromframe & UPDATE_MASK].playerstate[pv->viewentity-1];
|
||||
tostate = &cl.inframes[toframe & UPDATE_MASK].playerstate[pv->viewentity-1];
|
||||
fromstate = &cl.inframes[fromframe & UPDATE_MASK].playerstate[trackent-1];
|
||||
tostate = &cl.inframes[toframe & UPDATE_MASK].playerstate[trackent-1];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1078,7 +1076,7 @@ void CL_PredictMovePNum (int seat)
|
|||
pe = &cl.inframes[fromframe & UPDATE_MASK].packet_entities;
|
||||
for (i = 0; i < pe->num_entities; i++)
|
||||
{
|
||||
if (pe->entities[i].number == pv->viewentity)
|
||||
if (pe->entities[i].number == trackent)
|
||||
{
|
||||
CL_EntStateToPlayerState(fromstate, &pe->entities[i]);
|
||||
if (nopred)
|
||||
|
@ -1089,7 +1087,7 @@ void CL_PredictMovePNum (int seat)
|
|||
pe = &cl.inframes[toframe & UPDATE_MASK].packet_entities;
|
||||
for (i = 0; i < pe->num_entities; i++)
|
||||
{
|
||||
if (pe->entities[i].number == pv->viewentity)
|
||||
if (pe->entities[i].number == trackent)
|
||||
{
|
||||
CL_EntStateToPlayerState(tostate, &pe->entities[i]);
|
||||
if (nopred)
|
||||
|
@ -1107,14 +1105,14 @@ void CL_PredictMovePNum (int seat)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (pv->nolocalplayer && pv->viewentity < cl.maxlerpents)
|
||||
le = &cl.lerpents[pv->viewentity];
|
||||
if (pv->nolocalplayer && trackent < cl.maxlerpents)
|
||||
le = &cl.lerpents[trackent];
|
||||
}
|
||||
|
||||
// predict forward until cl.time <= to->senttime
|
||||
oldphysent = pmove.numphysent;
|
||||
CL_SetSolidPlayers();
|
||||
pmove.skipent = pv->viewentity;
|
||||
pmove.skipent = trackent;
|
||||
|
||||
//just in case we don't run any prediction
|
||||
VectorCopy(tostate->gravitydir, pmove.gravitydir);
|
||||
|
@ -1166,7 +1164,7 @@ void CL_PredictMovePNum (int seat)
|
|||
tostate = &framebuf[i&1];
|
||||
|
||||
// Con_DPrintf(" pred %i: %f-%f\n", cl.ackedmovesequence+i, fromtime, totime);
|
||||
CL_PredictUsercmd (seat, pv->viewentity, fromstate, tostate, cmdto);
|
||||
CL_PredictUsercmd (seat, trackent, fromstate, tostate, cmdto);
|
||||
}
|
||||
|
||||
if (simtime > totime)
|
||||
|
@ -1201,7 +1199,7 @@ void CL_PredictMovePNum (int seat)
|
|||
cmdto->msec = bound(0, msec, 250);
|
||||
|
||||
// Con_DPrintf(" extrap %i: %f-%f (%g)\n", toframe, fromtime, simtime, simtime-fromtime);
|
||||
CL_PredictUsercmd (seat, pv->viewentity, fromstate, tostate, cmdto);
|
||||
CL_PredictUsercmd (seat, trackent, fromstate, tostate, cmdto);
|
||||
}
|
||||
}
|
||||
pv->onground = pmove.onground;
|
||||
|
@ -1215,7 +1213,7 @@ void CL_PredictMovePNum (int seat)
|
|||
VectorCopy (tostate->velocity, pv->simvel);
|
||||
VectorCopy (tostate->origin, pv->simorg);
|
||||
|
||||
if (pv->viewentity && pv->viewentity != pv->playernum+1 && pv->cam_locked)
|
||||
if (trackent && trackent != pv->playernum+1 && pv->cam_state == CAM_EYECAM)
|
||||
VectorCopy(tostate->viewangles, pv->simangles);
|
||||
//Con_DPrintf("%f %f %f\n", fromtime, simtime, totime);
|
||||
}
|
||||
|
@ -1245,7 +1243,7 @@ void CL_PredictMovePNum (int seat)
|
|||
pv->simorg[i] = (1-f)*fromstate->origin[i] + f*tostate->origin[i];
|
||||
pv->simvel[i] = (1-f)*fromstate->velocity[i] + f*tostate->velocity[i];
|
||||
|
||||
if (pv->viewentity && pv->viewentity != pv->playernum+1 && pv->cam_locked)
|
||||
if (trackent && trackent != pv->playernum+1 && pv->cam_state == CAM_EYECAM)
|
||||
{
|
||||
pv->simangles[i] = LerpAngles360(fromstate->viewangles[i], tostate->viewangles[i], f);// * (360.0/65535);
|
||||
// pv->viewangles[i] = LerpAngles16(fromstate->command.angles[i], tostate->command.angles[i], f) * (360.0/65535);
|
||||
|
@ -1262,9 +1260,12 @@ void CL_PredictMovePNum (int seat)
|
|||
|
||||
CL_CalcCrouch (pv);
|
||||
pv->waterlevel = pmove.waterlevel;
|
||||
VectorCopy(pmove.gravitydir, pv->gravitydir);
|
||||
if (!DotProduct(pmove.gravitydir,pmove.gravitydir))
|
||||
VectorSet(pmove.gravitydir, 0, 0, -1);
|
||||
else
|
||||
VectorCopy(pmove.gravitydir, pv->gravitydir);
|
||||
|
||||
if (le)
|
||||
if (le && pv->cam_state == CAM_FREECAM)
|
||||
{
|
||||
//keep the entity tracking the prediction position, so mirrors don't go all weird
|
||||
VectorMA(pv->simorg, -pv->crouch, pv->gravitydir, le->origin);
|
||||
|
@ -1277,6 +1278,29 @@ void CL_PredictMovePNum (int seat)
|
|||
le->angles[0] *= -0.333;
|
||||
}
|
||||
}
|
||||
|
||||
if (cam_nowlocked)
|
||||
Cam_NowLocked(pv);
|
||||
if (pv->cam_state == CAM_WALLCAM)
|
||||
{
|
||||
vec3_t dir;
|
||||
|
||||
VectorSubtract(pv->simorg, pv->cam_desired_position, dir);
|
||||
VectorAngles(dir, NULL, pv->simangles);
|
||||
pv->simangles[0] *= -1;
|
||||
VectorCopy(pv->simangles, pv->viewangles);
|
||||
pv->viewangles[0] = anglemod(pv->viewangles[0]);
|
||||
if (pv->viewangles[0] > 180)
|
||||
pv->viewangles[0] -= 360;
|
||||
VectorCopy(pv->cam_desired_position, pv->simorg);
|
||||
VectorClear(pv->simvel);
|
||||
}
|
||||
if (cam_nowlocked)
|
||||
{
|
||||
//invalidate the roll, so we don't spin when switching povs
|
||||
pv->rollangle = V_CalcRoll(pv->simangles, pv->simvel);
|
||||
pv->vm.oldmodel = NULL; //invalidate the viewmodel, so the lerps get reset
|
||||
}
|
||||
}
|
||||
|
||||
void CL_PredictMove (void)
|
||||
|
|
|
@ -853,7 +853,7 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n
|
|||
for (i = 0; i < cl.splitclients; i++)
|
||||
{
|
||||
playerview_t *pv = &cl.playerview[i];
|
||||
if (ent == (pv->cam_auto?(pv->cam_spec_track+1):(pv->playernum+1)))
|
||||
if (ent == ((pv->cam_state == CAM_EYECAM)?(pv->cam_spec_track+1):(pv->playernum+1)))
|
||||
{
|
||||
VectorCopy(end, playerbeam_end[i]);
|
||||
break;
|
||||
|
@ -3435,7 +3435,7 @@ void CL_UpdateBeams (void)
|
|||
for (j = 0; j < cl.splitclients; j++)
|
||||
{
|
||||
playerview_t *pv = &cl.playerview[j];
|
||||
if (b->entity == ((cl.spectator&&pv->cam_auto)?pv->cam_spec_track+1:(pv->playernum+1)))
|
||||
if (b->entity == ((pv->cam_state == CAM_EYECAM)?pv->cam_spec_track+1:(pv->playernum+1)))
|
||||
{
|
||||
// player_state_t *pl;
|
||||
// VectorSubtract(cl.simorg, b->start, org);
|
||||
|
|
|
@ -628,17 +628,20 @@ struct playerview_s
|
|||
|
||||
|
||||
vec3_t cam_desired_position; // where the camera wants to be
|
||||
qboolean cam_locked; //
|
||||
int cam_oldbuttons; //
|
||||
vec3_t cam_viewangles; //
|
||||
double cam_lastviewtime; //
|
||||
double cam_lastviewtime; // timer for wallcam
|
||||
float cam_reautotrack; // timer to throttle tracking changes.
|
||||
int cam_spec_track; // player# of who we are tracking
|
||||
int cam_spec_track; // player# of who we are tracking / want to track / might want to track
|
||||
enum
|
||||
{
|
||||
CAM_NONE = 0,
|
||||
CAM_TRACK = 1
|
||||
} cam_auto; //
|
||||
CAM_FREECAM = 0, //not attached to another player. we are our own thing (or actually playing).
|
||||
CAM_PENDING = 1, //we want to lock on to cam_spec_track, but we don't have their position / stats yet. still freecamming
|
||||
CAM_WALLCAM = 2, //locked, cl_chasecam=0. we're watching them from a wall.
|
||||
CAM_EYECAM = 3 //locked, cl_chasecam=1. we know where they are, we're in their eyes.
|
||||
|
||||
#define CAM_ISLOCKED(pv) ((pv)->cam_state > CAM_PENDING)
|
||||
} cam_state; //
|
||||
|
||||
vec3_t vw_axis[3]; //weapons should be positioned relative to this
|
||||
vec3_t vw_origin; //weapons should be positioned relative to this
|
||||
|
@ -1277,18 +1280,18 @@ void CL_CalcClientTime(void);
|
|||
//
|
||||
qboolean Cam_DrawViewModel(playerview_t *pv);
|
||||
int Cam_TrackNum(playerview_t *pv);
|
||||
void Cam_Unlock(playerview_t *pv);
|
||||
void Cam_Lock(playerview_t *pv, int playernum);
|
||||
void Cam_Unlock(playerview_t *pv); //revert to freecam or so, because that entity failed.
|
||||
void Cam_Lock(playerview_t *pv, int playernum); //attempt to lock on to the given player.
|
||||
void Cam_NowLocked(playerview_t *pv); //player was located, track them now
|
||||
void Cam_SelfTrack(playerview_t *pv);
|
||||
void Cam_Track(playerview_t *pv, usercmd_t *cmd);
|
||||
void Cam_TrackCrosshairedPlayer(playerview_t *pv);
|
||||
void Cam_SetAutoTrack(int userid);
|
||||
void Cam_SetModAutoTrack(int userid);
|
||||
void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd);
|
||||
void Cam_Reset(void);
|
||||
void Cam_TrackPlayer(int seat, char *cmdname, char *plrarg);
|
||||
void Cam_Lock(playerview_t *pv, int playernum);
|
||||
void CL_InitCam(void);
|
||||
void Cam_AutoTrack_Update(const char *mode);
|
||||
void Cam_AutoTrack_Update(const char *mode); //reset autotrack setting (because we started a new map or whatever)
|
||||
|
||||
void QDECL vectoangles(vec3_t fwd, vec3_t ang);
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ void Stats_FragMessage(int p1, int wid, int p2, qboolean teamkill)
|
|||
struct wt_s *w = &fragstats.weapontotals[wid];
|
||||
const char *p1n = (p1 < 0)?nonplayers[-p1]:cl.players[p1].name;
|
||||
const char *p2n = (p2 < 0)?nonplayers[-p2]:cl.players[p2].name;
|
||||
int localplayer = (cl.spectator && cl.playerview[0].cam_locked)?cl.playerview[0].cam_spec_track:cl.playerview[0].playernum;
|
||||
int localplayer = (cl.playerview[0].cam_state == CAM_EYECAM)?cl.playerview[0].cam_spec_track:cl.playerview[0].playernum;
|
||||
|
||||
#define YOU_GOOD S_COLOR_GREEN
|
||||
#define YOU_BAD S_COLOR_BLUE
|
||||
|
|
|
@ -502,7 +502,7 @@ static void SL_PostDraw (menu_t *menu)
|
|||
int teamplay = atoi(Info_ValueForKey(server->moreinfo->info, "teamplay"));
|
||||
x = lx;
|
||||
Draw_FunStringWidth (x, y, "^mFrgs", 28, true, false);
|
||||
x += 28+8;
|
||||
x += 32+8;
|
||||
Draw_FunStringWidth (x, y, "^mPng", 28, true, false);
|
||||
x += 3*8+8;
|
||||
|
||||
|
@ -523,12 +523,17 @@ static void SL_PostDraw (menu_t *menu)
|
|||
for (i = 0; i < server->moreinfo->numplayers; i++)
|
||||
{
|
||||
x = lx;
|
||||
R2D_ImagePaletteColour (Sbar_ColorForMap(server->moreinfo->players[i].topc), 1.0);
|
||||
R2D_FillBlock (x, y+1, 28, 3);
|
||||
R2D_ImagePaletteColour (Sbar_ColorForMap(server->moreinfo->players[i].botc), 1.0);
|
||||
R2D_FillBlock (x, y+4, 28, 4);
|
||||
Draw_FunStringWidth (x, y, va("%3i", server->moreinfo->players[i].frags), 28, true, false);
|
||||
x += 28+8;
|
||||
if (server->moreinfo->players[i].isspec)
|
||||
Draw_FunStringWidth (x, y, "spec", 32, true, false);
|
||||
else
|
||||
{
|
||||
R2D_ImagePaletteColour (Sbar_ColorForMap(server->moreinfo->players[i].topc), 1.0);
|
||||
R2D_FillBlock (x, y+1, 32, 3);
|
||||
R2D_ImagePaletteColour (Sbar_ColorForMap(server->moreinfo->players[i].botc), 1.0);
|
||||
R2D_FillBlock (x, y+4, 32, 4);
|
||||
Draw_FunStringWidth (x, y, va("%3i", server->moreinfo->players[i].frags), 32, true, false);
|
||||
}
|
||||
x += 32+8;
|
||||
Draw_FunStringWidth (x, y, va("%3i", server->moreinfo->players[i].ping), 28, true, false);
|
||||
x += 3*8+8;
|
||||
|
||||
|
@ -956,6 +961,7 @@ void M_Menu_ServerList2_f(void)
|
|||
|
||||
serverpreview = false; //in case it was lingering.
|
||||
|
||||
Key_Dest_Remove(kdm_console);
|
||||
Key_Dest_Add(kdm_menu);
|
||||
m_state = m_complex;
|
||||
|
||||
|
|
|
@ -776,6 +776,8 @@ qboolean Master_ServerIsGreater(serverinfo_t *a, serverinfo_t *b)
|
|||
return Master_CompareInteger(a->players, b->players, SLIST_TEST_LESS);
|
||||
case SLKEY_NUMHUMANS:
|
||||
return Master_CompareInteger(a->numhumans, b->numhumans, SLIST_TEST_LESS);
|
||||
case SLKEY_NUMSPECTATORS:
|
||||
return Master_CompareInteger(a->numspectators, b->numspectators, SLIST_TEST_LESS);
|
||||
case SLKEY_NUMBOTS:
|
||||
return Master_CompareInteger(a->numbots, b->numbots, SLIST_TEST_LESS);
|
||||
case SLKEY_PING:
|
||||
|
@ -850,6 +852,9 @@ qboolean Master_PassesMasks(serverinfo_t *a)
|
|||
case SLKEY_NUMHUMANS:
|
||||
res = Master_CompareInteger(a->numhumans, visrules[i].operandi, visrules[i].compareop);
|
||||
break;
|
||||
case SLKEY_NUMSPECTATORS:
|
||||
res = Master_CompareInteger(a->numspectators, visrules[i].operandi, visrules[i].compareop);
|
||||
break;
|
||||
case SLKEY_TIMELIMIT:
|
||||
res = Master_CompareInteger(a->tl, visrules[i].operandi, visrules[i].compareop);
|
||||
break;
|
||||
|
@ -1052,6 +1057,8 @@ float Master_ReadKeyFloat(serverinfo_t *server, int keynum)
|
|||
return server->numbots;
|
||||
case SLKEY_NUMHUMANS:
|
||||
return server->numhumans;
|
||||
case SLKEY_NUMSPECTATORS:
|
||||
return server->numspectators;
|
||||
case SLKEY_ISFAVORITE:
|
||||
return !!(server->special & SS_FAVORITE);
|
||||
case SLKEY_ISLOCAL:
|
||||
|
@ -1184,6 +1191,8 @@ int Master_KeyForName(const char *keyname)
|
|||
return SLKEY_NUMBOTS;
|
||||
else if (!strcmp(keyname, "numhumans"))
|
||||
return SLKEY_NUMHUMANS;
|
||||
else if (!strcmp(keyname, "numspectators"))
|
||||
return SLKEY_NUMSPECTATORS;
|
||||
else if (!strcmp(keyname, "qcstatus"))
|
||||
return SLKEY_QCSTATUS;
|
||||
else if (!strcmp(keyname, "isfavorite"))
|
||||
|
@ -2594,7 +2603,7 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
|
|||
char *nl;
|
||||
char *name;
|
||||
int ping;
|
||||
int len;
|
||||
int len, j, k;
|
||||
serverinfo_t *info;
|
||||
char adr[MAX_ADR_SIZE];
|
||||
|
||||
|
@ -2748,6 +2757,8 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
|
|||
break;
|
||||
*nl = '\0';
|
||||
|
||||
details.players[clnum].isspec = false;
|
||||
|
||||
token = msg;
|
||||
if (!token)
|
||||
break;
|
||||
|
@ -2804,7 +2815,10 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
|
|||
if (len >= sizeof(details.players[clnum].name))
|
||||
len = sizeof(details.players[clnum].name);
|
||||
if (!strncmp(token, "\"\\s\\", 4))
|
||||
{
|
||||
details.players[clnum].isspec = true;
|
||||
Q_strncpyz(details.players[clnum].name, token+4, len-3);
|
||||
}
|
||||
else
|
||||
Q_strncpyz(details.players[clnum].name, token+1, len);
|
||||
details.players[clnum].name[len] = '\0';
|
||||
|
@ -2848,12 +2862,28 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
|
|||
|
||||
MasterInfo_AddPlayer(&info->adr, details.players[clnum].name, details.players[clnum].ping, details.players[clnum].frags, details.players[clnum].topc*4 | details.players[clnum].botc, details.players[clnum].skin, details.players[clnum].team);
|
||||
|
||||
|
||||
++details.numplayers;
|
||||
if (details.players[clnum].ping == 807 || !strncmp(details.players[clnum].name, "BOT:", 4))
|
||||
info->numbots++;
|
||||
else if (details.players[clnum].isspec)
|
||||
info->numspectators++;
|
||||
else
|
||||
info->numhumans++;
|
||||
|
||||
for (k = clnum, j = clnum-1; j >= 0; j--)
|
||||
{
|
||||
if ((details.players[k].isspec != details.players[j].isspec && !details.players[k].isspec) ||
|
||||
details.players[k].frags > details.players[j].frags)
|
||||
{
|
||||
struct serverdetailedplayerinfo_s t = details.players[j];
|
||||
details.players[j] = details.players[k];
|
||||
details.players[k] = t;
|
||||
k = j;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
details.numplayers++;
|
||||
|
||||
info->players++;
|
||||
|
||||
msg = nl;
|
||||
|
|
|
@ -346,7 +346,7 @@ void R_Clutter_Emit(batch_t **batches)
|
|||
{
|
||||
const float cluttersize = r_clutter_distance.value;
|
||||
int vx, vy, vz;
|
||||
int x, y, z, key, i;
|
||||
int x, y, z, key, i, j;
|
||||
cluttersector_t *sect;
|
||||
batch_t *b;
|
||||
qboolean rebuildlimit = false;
|
||||
|
@ -453,6 +453,8 @@ void R_Clutter_Emit(batch_t **batches)
|
|||
if (!b)
|
||||
return;
|
||||
memset(b, 0, sizeof(*b));
|
||||
for (j = 0; j < MAXRLIGHTMAPS; j++)
|
||||
b->lightmap[j] = -1;
|
||||
b->ent = &r_worldentity;
|
||||
b->meshes = 1;
|
||||
b->mesh = §->soups[i].pmesh;
|
||||
|
|
|
@ -358,6 +358,7 @@ cvar_t dpcompat_psa_ungroup = SCVAR ("dpcompat_psa_ungroup", "0");
|
|||
cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_shadows = CVARFD ("r_shadows", "0", CVAR_ARCHIVE, "Draw basic blob shadows underneath entities without using realtime lighting.");
|
||||
cvar_t r_showbboxes = CVARD("r_showbboxes", "0", "Debugging. Shows bounding boxes. 1=ssqc, 2=csqc. Red=solid, Green=stepping/toss/bounce, Blue=onground.");
|
||||
cvar_t r_showfields = CVARD("r_showfields", "0", "Debugging. Shows entity fields boxes (entity closest to crosshair). 1=ssqc, 2=csqc.");
|
||||
cvar_t r_lightprepass = CVARFD("r_lightprepass", "0", CVAR_SHADERSYSTEM, "Experimental. Attempt to use a different lighting mechanism.");
|
||||
|
||||
cvar_t r_shadow_bumpscale_basetexture = CVARD ("r_shadow_bumpscale_basetexture", "0", "bumpyness scaler for generation of fallback normalmap textures from models");
|
||||
|
@ -748,6 +749,7 @@ void Renderer_Init(void)
|
|||
Cvar_Register (&r_replacemodels, GRAPHICALNICETIES);
|
||||
|
||||
Cvar_Register (&r_showbboxes, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&r_showfields, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&r_polygonoffset_submodel_factor, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&r_polygonoffset_submodel_offset, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&r_polygonoffset_shadowmap_factor, GLRENDEREROPTIONS);
|
||||
|
|
|
@ -26,16 +26,16 @@ extern cvar_t *hud_tracking_show;
|
|||
|
||||
#define CON_ALTMASK (CON_2NDCHARSETTEXT|CON_WHITEMASK)
|
||||
|
||||
cvar_t scr_scoreboard_drawtitle = SCVAR("scr_scoreboard_drawtitle", "1");
|
||||
cvar_t scr_scoreboard_forcecolors = SCVAR("scr_scoreboard_forcecolors", "0"); //damn americans
|
||||
cvar_t scr_scoreboard_newstyle = SCVAR("scr_scoreboard_newstyle", "1"); // New scoreboard style ported from Electro, by Molgrum
|
||||
cvar_t scr_scoreboard_drawtitle = CVARD("scr_scoreboard_drawtitle", "1", "Wastes screen space when looking at the scoreboard.");
|
||||
cvar_t scr_scoreboard_forcecolors = CVARD("scr_scoreboard_forcecolors", "0", "Makes the scoreboard colours obey enemycolor/teamcolor rules."); //damn americans
|
||||
cvar_t scr_scoreboard_newstyle = CVARD("scr_scoreboard_newstyle", "1", "Display team colours and stuff in a style popularised by Electro. Looks more modern, but might not quite fit classic huds."); // New scoreboard style ported from Electro, by Molgrum
|
||||
cvar_t scr_scoreboard_showfrags = CVARD("scr_scoreboard_showfrags", "0", "Display kills+deaths+teamkills, as determined by fragfile.dat-based conprint parsing. These may be inaccurate if you join mid-game.");
|
||||
cvar_t scr_scoreboard_showflags = CVARD("scr_scoreboard_showflags", "2", "Display flag caps+touches on the scoreboard, where our fragfile.dat supports them.\n0: off\n1: on\n2: on only if someone appears to have interacted with a flag.");
|
||||
cvar_t scr_scoreboard_fillalpha = CVAR("scr_scoreboard_fillalpha", "0.7");
|
||||
cvar_t scr_scoreboard_teamscores = SCVAR("scr_scoreboard_teamscores", "1");
|
||||
cvar_t scr_scoreboard_teamsort = SCVAR("scr_scoreboard_teamsort", "1");
|
||||
cvar_t scr_scoreboard_fillalpha = CVARD("scr_scoreboard_fillalpha", "0.7", "Transparency amount for newstyle scoreboard.");
|
||||
cvar_t scr_scoreboard_teamscores = CVARD("scr_scoreboard_teamscores", "1", "Makes +showscores act as +showteamscores. Because reasons.");
|
||||
cvar_t scr_scoreboard_teamsort = CVARD("scr_scoreboard_teamsort", "0", "On the scoreboard, sort players by their team BEFORE their personal score.");
|
||||
cvar_t scr_scoreboard_titleseperator = SCVAR("scr_scoreboard_titleseperator", "1");
|
||||
cvar_t sbar_teamstatus = SCVAR("sbar_teamstatus", "1");
|
||||
cvar_t sbar_teamstatus = CVARD("sbar_teamstatus", "1", "Display the last team say from each of your team members just above the sbar area.");
|
||||
|
||||
//===========================================
|
||||
//rogue changed and added defines
|
||||
|
@ -2123,7 +2123,7 @@ void Sbar_DrawScoreboard (void)
|
|||
|
||||
#ifndef CLIENTONLY
|
||||
/*no scoreboard in single player (if you want bots, set deathmatch)*/
|
||||
if (sv.state && !cls.deathmatch && sv.allocated_client_slots == 1)
|
||||
if (sv.state && sv.allocated_client_slots == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -2757,7 +2757,7 @@ void Sbar_Draw (playerview_t *pv)
|
|||
// top line
|
||||
if (sb_lines > 24)
|
||||
{
|
||||
if (!cl.spectator || pv->cam_auto == CAM_TRACK)
|
||||
if (!cl.spectator || pv->cam_state == CAM_WALLCAM || pv->cam_state == CAM_EYECAM)
|
||||
Sbar_DrawInventory (pv);
|
||||
else if (cl_sbar.ival)
|
||||
Sbar_DrawPic (0, -24, 320, 24, sb_scorebar); //make sure we don't get HoM
|
||||
|
@ -2770,13 +2770,14 @@ void Sbar_Draw (playerview_t *pv)
|
|||
{
|
||||
if (cl.spectator)
|
||||
{
|
||||
if (pv->cam_auto != CAM_TRACK)
|
||||
if (pv->cam_state == CAM_FREECAM || pv->cam_state == CAM_PENDING)
|
||||
{
|
||||
if (hud_tracking_show->ival || cl_sbar.ival)
|
||||
{ //this is annoying.
|
||||
Sbar_DrawPic (0, 0, 320, 24, sb_scorebar);
|
||||
Sbar_DrawString (160-7*8,4, "SPECTATOR MODE");
|
||||
Sbar_DrawString(160-14*8+4, 12, "Press [ATTACK] for AutoCamera");
|
||||
if (pv->cam_state == CAM_FREECAM)
|
||||
Sbar_DrawString(160-14*8+4, 12, "Press [ATTACK] for AutoCamera");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2888,7 +2889,7 @@ void Sbar_IntermissionNumber (float x, float y, int num, int digits, int color,
|
|||
|
||||
#define COL_TEAM_LOWAVGHIGH COLUMN("low/avg/high", 12*8, {sprintf (num, "%3i/%3i/%3i", plow, pavg, phigh); Draw_FunString ( x, y, num); })
|
||||
#define COL_TEAM_TEAM COLUMN("team", 4*8, {Draw_FunStringWidth ( x, y, tm->team, 4*8, false, false); \
|
||||
if (!strncmp(cl.players[pv->playernum].team, tm->team, 16))\
|
||||
if (!strncmp(cl.players[trackplayer].team, tm->team, 16))\
|
||||
{\
|
||||
Draw_FunString ( x - 1*8, y, "^Ue010");\
|
||||
Draw_FunString ( x + 4*8, y, "^Ue011");\
|
||||
|
@ -2920,6 +2921,7 @@ void Sbar_TeamOverlay (void)
|
|||
|
||||
int rank_width = 320-32*2;
|
||||
int startx;
|
||||
int trackplayer;
|
||||
|
||||
if (!pv)
|
||||
pv = &cl.playerview[0];
|
||||
|
@ -2998,6 +3000,11 @@ void Sbar_TeamOverlay (void)
|
|||
// sort the teams
|
||||
Sbar_SortTeams(pv);
|
||||
|
||||
if (cl.spectator)
|
||||
trackplayer = Cam_TrackNum(pv);
|
||||
else
|
||||
trackplayer = pv->playernum;
|
||||
|
||||
// draw the text
|
||||
for (i=0 ; i < scoreboardteams && y <= vid.height-10 ; i++)
|
||||
{
|
||||
|
@ -3060,7 +3067,7 @@ void Sbar_TeamOverlay (void)
|
|||
sprintf (num, "%5i", tm->players);
|
||||
Draw_FunString (x + 104 + 88, y, num);
|
||||
|
||||
if (!strncmp(cl.players[cl.playernum[0]].team, tm->team, 16))
|
||||
if (!strncmp(cl.players[trackplayer].team, tm->team, 16))
|
||||
{
|
||||
Draw_FunString ( x + 104 - 8, y, "^Ue010");
|
||||
Draw_FunString ( x + 104 + 32, y, "^Ue011");
|
||||
|
@ -3132,20 +3139,20 @@ ping time frags name
|
|||
f = s->frags; \
|
||||
sprintf(num, "%3i",f); \
|
||||
\
|
||||
Font_BeginString(font_default, x+8, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, num[0] | 0xe000 | CON_WHITEMASK); \
|
||||
Font_BeginString(font_default, x+16, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, num[1] | 0xe000 | CON_WHITEMASK); \
|
||||
Font_BeginString(font_default, x+24, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, num[2] | 0xe000 | CON_WHITEMASK); \
|
||||
\
|
||||
if ((cl.spectator && k == Cam_TrackNum(pv)) ||\
|
||||
(!cl.spectator && k == pv->playernum)) \
|
||||
{ \
|
||||
Font_BeginString(font_default, x, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, 16 | 0xe000 | CON_WHITEMASK); \
|
||||
Font_BeginString(font_default, x+32, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, 17 | 0xe000 | CON_WHITEMASK); \
|
||||
Font_BeginString(font_default, x+8, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, num[0] | 0xe000 | CON_WHITEMASK); \
|
||||
Font_BeginString(font_default, x+16, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, num[1] | 0xe000 | CON_WHITEMASK); \
|
||||
Font_BeginString(font_default, x+24, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, num[2] | 0xe000 | CON_WHITEMASK); \
|
||||
\
|
||||
if ((pv->cam_state == CAM_FREECAM && k == pv->playernum) || \
|
||||
(pv->cam_state != CAM_FREECAM && k == pv->cam_spec_track)) \
|
||||
{ \
|
||||
Font_BeginString(font_default, x, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, 16 | 0xe000 | CON_WHITEMASK); \
|
||||
Font_BeginString(font_default, x+32, y, &cx, &cy); \
|
||||
Font_DrawChar(cx, cy, 17 | 0xe000 | CON_WHITEMASK); \
|
||||
} \
|
||||
Font_EndString(font_default); \
|
||||
} \
|
||||
|
@ -3590,7 +3597,7 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
|
|||
Font_BeginString(font_default, x+24, y, &px, &py);
|
||||
Font_DrawChar ( px, py, num[2] | 0xe000 | CON_WHITEMASK);
|
||||
|
||||
if ((cl.spectator && k == pv->cam_spec_track && pv->cam_locked) ||
|
||||
if ((cl.spectator && k == pv->cam_spec_track && pv->cam_state != CAM_FREECAM) ||
|
||||
(!cl.spectator && k == pv->playernum))
|
||||
{
|
||||
Font_BeginString(font_default, x, y, &px, &py);
|
||||
|
|
|
@ -1342,7 +1342,7 @@ void V_CalcRefdef (playerview_t *pv)
|
|||
|
||||
viewheight += pv->crouch;
|
||||
|
||||
if (pv->stats[STAT_HEALTH] < 0 && (!cl.spectator || pv->cam_locked) && v_deathtilt.value) // PF_GIB will also set PF_DEAD
|
||||
if (pv->stats[STAT_HEALTH] < 0 && (!cl.spectator || pv->cam_state == CAM_EYECAM) && v_deathtilt.value) // PF_GIB will also set PF_DEAD
|
||||
{
|
||||
if (!cl.spectator || cl_chasecam.ival)
|
||||
r_refdef.viewangles[ROLL] = 80*v_deathtilt.value; // dead view angle
|
||||
|
@ -1527,21 +1527,21 @@ void R_DrawNameTags(void)
|
|||
vec3_t tagcenter;
|
||||
lerpents_t *le;
|
||||
|
||||
extern cvar_t r_showbboxes;
|
||||
if (r_showbboxes.ival && cls.allow_cheats)
|
||||
extern cvar_t r_showfields;
|
||||
if (r_showfields.ival && cls.allow_cheats)
|
||||
{
|
||||
world_t *w = NULL;
|
||||
wedict_t *e;
|
||||
vec3_t org;
|
||||
vec3_t screenspace;
|
||||
vec3_t diff;
|
||||
if (r_showbboxes.ival == 1)
|
||||
if ((r_showfields.ival & 3) == 1)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
w = &sv.world;
|
||||
#endif
|
||||
}
|
||||
else if (r_showbboxes.ival == 2)
|
||||
else if ((r_showfields.ival & 3) == 2)
|
||||
{
|
||||
#ifdef CSQC_DAT
|
||||
extern world_t csqc_world;
|
||||
|
@ -1549,34 +1549,55 @@ void R_DrawNameTags(void)
|
|||
#endif
|
||||
}
|
||||
if (w && w->progs)
|
||||
for (i = 1; i < w->num_edicts; i++)
|
||||
{
|
||||
e = WEDICT_NUM(w->progs, i);
|
||||
if (e->isfree)
|
||||
continue;
|
||||
VectorInterpolate(e->v->mins, 0.5, e->v->maxs, org);
|
||||
VectorAdd(org, e->v->origin, org);
|
||||
VectorSubtract(org, r_refdef.vieworg, diff);
|
||||
if (DotProduct(diff, diff) > 256*256)
|
||||
continue;
|
||||
if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y))
|
||||
int best = 0;
|
||||
float bestscore = 0, score = 0;
|
||||
for (i = 1; i < w->num_edicts; i++)
|
||||
{
|
||||
char asciibuffer[8192];
|
||||
char *entstr;
|
||||
int buflen;
|
||||
int x, y;
|
||||
|
||||
sprintf(asciibuffer, "entity %i ", e->entnum);
|
||||
buflen = strlen(asciibuffer);
|
||||
entstr = w->progs->saveent(w->progs, asciibuffer, &buflen, sizeof(asciibuffer), (edict_t*)e); //will save just one entities vars
|
||||
if (entstr)
|
||||
e = WEDICT_NUM(w->progs, i);
|
||||
if (e->isfree)
|
||||
continue;
|
||||
VectorInterpolate(e->v->mins, 0.5, e->v->maxs, org);
|
||||
VectorAdd(org, e->v->origin, org);
|
||||
VectorSubtract(org, r_refdef.vieworg, diff);
|
||||
if (DotProduct(diff, diff) < 16*16)
|
||||
continue; //ignore stuff too close(like the player themselves)
|
||||
VectorNormalize(diff);
|
||||
score = DotProduct(diff, vpn);// r_refdef.viewaxis[0]);
|
||||
if (score > bestscore)
|
||||
{
|
||||
vec2_t scale = {8,8};
|
||||
x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x;
|
||||
y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y;
|
||||
R_DrawTextField(x, y, vid.width - x, vid.height - y, entstr, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, scale);
|
||||
vec3_t imp;
|
||||
if (!TraceLineN(r_refdef.vieworg, org, imp, NULL))
|
||||
{
|
||||
best = i;
|
||||
bestscore = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best)
|
||||
{
|
||||
e = WEDICT_NUM(w->progs, best);
|
||||
VectorInterpolate(e->v->mins, 0.5, e->v->maxs, org);
|
||||
VectorAdd(org, e->v->origin, org);
|
||||
if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y))
|
||||
{
|
||||
char asciibuffer[8192];
|
||||
char *entstr;
|
||||
int buflen;
|
||||
int x, y;
|
||||
|
||||
sprintf(asciibuffer, "entity %i ", e->entnum);
|
||||
buflen = strlen(asciibuffer);
|
||||
entstr = w->progs->saveent(w->progs, asciibuffer, &buflen, sizeof(asciibuffer), (edict_t*)e); //will save just one entities vars
|
||||
if (entstr)
|
||||
{
|
||||
vec2_t scale = {8,8};
|
||||
x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x;
|
||||
y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y;
|
||||
R_DrawTextField(x, y, vid.width - x, vid.height - y, entstr, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, scale);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2025,14 +2025,9 @@ void Cmd_ForwardToServer_f (void)
|
|||
{
|
||||
playerview_t *pv = &cl.playerview[CL_TargettedSplit(false)];
|
||||
if (!*Cmd_Argv(2))
|
||||
{
|
||||
Cam_Unlock(pv);
|
||||
}
|
||||
else
|
||||
{
|
||||
Cam_Lock(pv, atoi(Cmd_Argv(2)));
|
||||
pv->cam_auto = CAM_TRACK;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ void Netchan_Init (void)
|
|||
port = ((int)(getpid()+getuid()*1000) * time(NULL)) & 0xffff;
|
||||
#endif
|
||||
Q_snprintfz(qportstr, sizeof(qportstr), "%i", port);
|
||||
qport.string = qportstr;
|
||||
qport.enginevalue = qportstr;
|
||||
|
||||
Cvar_Register (&pext_predinfo, "Protocol Extensions");
|
||||
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
|
||||
|
|
|
@ -3,13 +3,15 @@
|
|||
bind mouse1 +attack //left area of the screen
|
||||
bind mouse2 +jump //right area of the screen
|
||||
bind menu "toggleconsole"
|
||||
bind volup +showteamscores
|
||||
// bind voldown +jump //removed because on most android devices power+voldown takes a screenshot
|
||||
bind volup inv volume 0.1
|
||||
bind voldown inv volume -0.1
|
||||
|
||||
|
||||
// Appearance settings
|
||||
brightness "0.2"
|
||||
contrast "1.2"
|
||||
|
||||
vid_conwidth "0" //make something up based upon aspect ratio
|
||||
vid_conheight "300" //not using autoscale as it can make the menu unusable.
|
||||
vid_conautoscale "0" // Text/Menu size. 2 is the default. 4 is bigger
|
||||
|
||||
|
|
|
@ -1531,7 +1531,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
|
|||
b->texture = NULL;
|
||||
b->shader = shader;
|
||||
for (j = 0; j < MAXRLIGHTMAPS; j++)
|
||||
b->lightmap[0] = -1;
|
||||
b->lightmap[j] = -1;
|
||||
b->surf_first = surfnum;
|
||||
b->flags = 0;
|
||||
sort = shader->sort;
|
||||
|
@ -1637,7 +1637,8 @@ void R_Sprite_GenerateBatches(entity_t *e, batch_t **batches)
|
|||
b->skin = frame-;
|
||||
b->texture = NULL;
|
||||
b->shader = frame->shader;
|
||||
b->lightmap = -1;
|
||||
for (j = 0; j < MAXRLIGHTMAPS; j++)
|
||||
b->lightmap[j] = -1;
|
||||
b->surf_first = surfnum;
|
||||
b->flags = 0;
|
||||
b->vbo = NULL;
|
||||
|
|
|
@ -4461,6 +4461,7 @@ static void GLBE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist)
|
|||
static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
||||
{
|
||||
batch_t *batch;
|
||||
shader_t *bs;
|
||||
for (batch = sortlist; batch; batch = batch->next)
|
||||
{
|
||||
if (batch->meshes == batch->firstmesh)
|
||||
|
@ -4482,31 +4483,33 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
batch->buildmeshes(batch);
|
||||
}
|
||||
|
||||
TRACE(("GLBE_SubmitMeshesSortList: shader %s\n", batch->shader->name));
|
||||
bs = batch->shader;
|
||||
|
||||
TRACE(("GLBE_SubmitMeshesSortList: shader %s\n", bs->name));
|
||||
|
||||
//FIXME:!!
|
||||
if (!batch->shader)
|
||||
if (!bs)
|
||||
{
|
||||
Con_Printf("Shader not set...\n");
|
||||
if (batch->texture)
|
||||
batch->shader = R_TextureAnimation(0, batch->texture)->shader;
|
||||
bs = R_TextureAnimation(0, batch->texture)->shader;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
if (batch->shader->flags & SHADER_NODRAW)
|
||||
if (bs->flags & SHADER_NODRAW)
|
||||
continue;
|
||||
if (batch->shader->flags & SHADER_NODLIGHT)
|
||||
if (bs->flags & SHADER_NODLIGHT)
|
||||
if (shaderstate.mode == BEM_LIGHT)
|
||||
continue;
|
||||
if (batch->shader->flags & SHADER_NOSHADOWS)
|
||||
if (bs->flags & SHADER_NOSHADOWS)
|
||||
if (shaderstate.mode == BEM_STENCIL || shaderstate.mode == BEM_DEPTHONLY) //fixme: depthonly is not just shadows.
|
||||
continue;
|
||||
if (batch->shader->flags & SHADER_SKY)
|
||||
if (bs->flags & SHADER_SKY)
|
||||
{
|
||||
if (shaderstate.mode == BEM_STANDARD || shaderstate.mode == BEM_DEPTHDARK)// || shaderstate.mode == BEM_WIREFRAME)
|
||||
{
|
||||
if (!batch->shader->prog)
|
||||
if (!bs->prog)
|
||||
{
|
||||
R_DrawSkyChain (batch);
|
||||
continue;
|
||||
|
@ -4516,7 +4519,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((batch->shader->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT | SHADER_HASRIPPLEMAP)) && shaderstate.mode != BEM_WIREFRAME)
|
||||
if ((bs->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT | SHADER_HASRIPPLEMAP)) && shaderstate.mode != BEM_WIREFRAME)
|
||||
{
|
||||
int oldfbo;
|
||||
float oldil;
|
||||
|
@ -4529,7 +4532,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
oldbem = shaderstate.mode;
|
||||
oldil = shaderstate.identitylighting;
|
||||
|
||||
if ((batch->shader->flags & SHADER_HASREFLECT) && gl_config.ext_framebuffer_objects)
|
||||
if ((bs->flags & SHADER_HASREFLECT) && gl_config.ext_framebuffer_objects)
|
||||
{
|
||||
vrect_t orect = r_refdef.vrect;
|
||||
pxrect_t oprect = r_refdef.pxrect;
|
||||
|
@ -4571,7 +4574,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
r_refdef.pxrect = oprect;
|
||||
GL_ViewportUpdate();
|
||||
}
|
||||
if (batch->shader->flags & (SHADER_HASREFRACT|SHADER_HASREFRACTDEPTH))
|
||||
if (bs->flags & (SHADER_HASREFRACT|SHADER_HASREFRACTDEPTH))
|
||||
{
|
||||
if (r_refract_fboival)
|
||||
{
|
||||
|
@ -4603,7 +4606,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
if (batch->shader->flags & SHADER_HASREFRACTDEPTH)
|
||||
if (bs->flags & SHADER_HASREFRACTDEPTH)
|
||||
{
|
||||
if (!shaderstate.tex_refractiondepth)
|
||||
{
|
||||
|
@ -4634,7 +4637,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
GL_ForceDepthWritable();
|
||||
qglClearColor(0, 0, 0, 1);
|
||||
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
GLR_DrawPortal(batch, cl.worldmodel->batches, NULL, ((batch->shader->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
|
||||
GLR_DrawPortal(batch, cl.worldmodel->batches, NULL, ((bs->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
|
||||
GLBE_FBO_Pop(oldfbo);
|
||||
|
||||
r_refdef.vrect = ovrect;
|
||||
|
@ -4644,7 +4647,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
else
|
||||
GLR_DrawPortal(batch, cl.worldmodel->batches, NULL, 3);
|
||||
}
|
||||
if ((batch->shader->flags & SHADER_HASRIPPLEMAP) && gl_config.ext_framebuffer_objects)
|
||||
if ((bs->flags & SHADER_HASRIPPLEMAP) && gl_config.ext_framebuffer_objects)
|
||||
{
|
||||
vrect_t orect = r_refdef.vrect;
|
||||
pxrect_t oprect = r_refdef.pxrect;
|
||||
|
@ -5324,19 +5327,19 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis)
|
|||
RSpeedRemark();
|
||||
GLBE_SubmitMeshes(true, SHADER_SORT_PORTAL, SHADER_SORT_DECAL);
|
||||
RSpeedEnd(RSPEED_WORLD);
|
||||
}
|
||||
|
||||
#ifdef RTLIGHTS
|
||||
if (drawworld)
|
||||
{
|
||||
RSpeedRemark();
|
||||
TRACE(("GLBE_DrawWorld: drawing lights\n"));
|
||||
GLBE_SelectEntity(&r_worldentity);
|
||||
Sh_DrawLights(vis);
|
||||
RSpeedEnd(RSPEED_STENCILSHADOWS);
|
||||
TRACE(("GLBE_DrawWorld: lights drawn\n"));
|
||||
}
|
||||
if (drawworld)
|
||||
{
|
||||
RSpeedRemark();
|
||||
TRACE(("GLBE_DrawWorld: drawing lights\n"));
|
||||
GLBE_SelectEntity(&r_worldentity);
|
||||
Sh_DrawLights(vis);
|
||||
RSpeedEnd(RSPEED_STENCILSHADOWS);
|
||||
TRACE(("GLBE_DrawWorld: lights drawn\n"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
shaderstate.identitylighting = 1;
|
||||
|
||||
|
|
|
@ -663,11 +663,18 @@ static hmsection_t *Terr_GenerateSection(heightmap_t *hm, int sx, int sy, qboole
|
|||
|
||||
s->loadstate = TSLS_LOADING1;
|
||||
|
||||
if (scheduleload)
|
||||
COM_AddWork(1, Terr_LoadSectionWorker, s, hm, sx, sy);
|
||||
}
|
||||
if (!scheduleload)
|
||||
return s;
|
||||
|
||||
#ifdef LOADERTHREAD
|
||||
Sys_UnlockMutex(com_resourcemutex);
|
||||
Sys_UnlockMutex(com_resourcemutex);
|
||||
#endif
|
||||
COM_AddWork(1, Terr_LoadSectionWorker, s, hm, sx, sy);
|
||||
return s;
|
||||
}
|
||||
if (scheduleload)
|
||||
#ifdef LOADERTHREAD
|
||||
Sys_UnlockMutex(com_resourcemutex);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
@ -1666,13 +1673,24 @@ static void Terr_LoadSectionWorker(void *ctx, void *data, size_t a, size_t b)
|
|||
{
|
||||
//noload avoids recursion.
|
||||
s = Terr_GenerateSection(hm, sx+x, sy+y, false);
|
||||
if (s->loadstate == TSLS_LOADING1)
|
||||
if (s)
|
||||
{
|
||||
offset = block->offset[x + y*SECTIONSPERBLOCK];
|
||||
if (!offset)
|
||||
Terr_ReadSection(hm, s, ver, NULL, 0); //no data in the file for this section
|
||||
if (s->loadstate == TSLS_LOADING1)
|
||||
{
|
||||
s->loadstate = TSLS_LOADING1;
|
||||
#ifdef LOADERTHREAD
|
||||
Sys_UnlockMutex(com_resourcemutex);
|
||||
#endif
|
||||
offset = block->offset[x + y*SECTIONSPERBLOCK];
|
||||
if (!offset)
|
||||
Terr_ReadSection(hm, s, ver, NULL, 0); //no data in the file for this section
|
||||
else
|
||||
Terr_ReadSection(hm, s, ver, (char*)diskimage + offset, len - offset);
|
||||
}
|
||||
#ifdef LOADERTHREAD
|
||||
else
|
||||
Terr_ReadSection(hm, s, ver, (char*)diskimage + offset, len - offset);
|
||||
Sys_UnlockMutex(com_resourcemutex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -719,10 +719,8 @@ void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
|
|||
b->skin = &shader->defaulttextures;
|
||||
b->texture = NULL;
|
||||
b->shader = shader;
|
||||
b->lightmap[0] = -1;
|
||||
b->lightmap[1] = -1;
|
||||
b->lightmap[2] = -1;
|
||||
b->lightmap[3] = -1;
|
||||
for (j = 0; j < MAXRLIGHTMAPS; j++)
|
||||
b->lightmap[j] = -1;
|
||||
b->surf_first = batchid;
|
||||
b->flags = 0;
|
||||
sort = shader->sort;
|
||||
|
|
|
@ -3004,6 +3004,8 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
|
|||
state->solid |= i<<5;
|
||||
i = bound(0, ((ent->v->maxs[2]+32)/8), 63); /*up can be negative*/
|
||||
state->solid |= i<<10;
|
||||
if (state->solid == 4096)
|
||||
state->solid = 0; //point sized stuff should just be non-solid. you'll thank me for splitscreens.
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -41,6 +41,8 @@ extern cvar_t *cl_multiview;
|
|||
#define Cam_TrackNum() cl.tracknum
|
||||
#define spec_track cl.tracknum
|
||||
#define autocam ((spec_track==-1)?CAM_NONE:CAM_TRACK)
|
||||
#define CAM_TRACK true
|
||||
#define CAM_NONE false
|
||||
//#define HAXX
|
||||
|
||||
#define vid plugvid
|
||||
|
|
|
@ -577,11 +577,17 @@ void SCR_HUD_DrawTracking(hud_t *hud)
|
|||
height *= hud_tracking_scale->value;
|
||||
width *= hud_tracking_scale->value;
|
||||
|
||||
if (!(cl.spectator && autocam == CAM_TRACK))
|
||||
height = 0;
|
||||
|
||||
if(!HUD_PrepareDraw(hud, width, height, &x, &y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (height == 0)
|
||||
return;
|
||||
|
||||
#ifdef HAXX
|
||||
if (cls.mvdplayback && cl_multiview->value && autocam == CAM_TRACK)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue