Fix light_dynamic (static) from not spawning in CSQC. Add r_skipDiffuse to rtlight.glsl,

add SURF_PENETRATE, which will make bullets pass right through them when
BULLETPENETRATION is set. Go over and refactor a lot of base_client, player
and spectator code to facilitate both permanent and temporary spectators
better. Add experimental env_glow lens flare code. Fix material ID detection
bug for Q3 based BSPs. A couple helper functions were added to src/client/utils.cpp
but they are not yet final.
This commit is contained in:
Marco Cawthorne 2022-03-17 21:05:47 -07:00
parent 96f3a1224a
commit 143a00e94e
Signed by: eukara
GPG Key ID: C196CD8BA993248A
28 changed files with 484 additions and 185 deletions

View File

@ -160,7 +160,7 @@ Scores_Draw(void)
pos = video_mins + [(video_res[0] / 2) - 145, 30];
}
if (serverkeyfloat("teams") > 0) {
if (Util_IsTeamPlay()) {
Scores_DrawTeam(pl, pos);
} else {
Scores_DrawNormal(pl, pos);

View File

@ -22,6 +22,8 @@
!!samps =PCF shadowmap
!!samps =CUBE projectionmap
!!cvardf r_skipDiffuse
#include "sys/defs.h"
//if there's no vertex normals known, disable some stuff.
@ -125,7 +127,11 @@ varying vec3 lightvector;
#if defined(FLAT)
vec4 bases = vec4(FLAT, FLAT, FLAT, 1.0);
#else
vec4 bases = texture2D(s_diffuse, tex_c);
#if r_skipDiffuse == 0
vec4 bases = texture2D(s_diffuse, tex_c);
#else
vec4 bases = vec4(1.0, 1.0, 1.0, 1.0);
#endif
#endif
#ifdef BUMP

View File

@ -1,32 +1,32 @@
{
climb 0x00004000
vehicleclip 0x00008000
{
climb 0x00004000
vehicleclip 0x00008000
grenadeclip 0x00000080
}
{
leakssteam 0x00080000
leakswater 0x00100000
fl_r1 0x00200000
fl_r2 0x00400000
fl_r3 0x00800000
fl_r4 0x01000000
fl_r5 0x02000000
fl_r6 0x04000000
fl_r7 0x08000000
alien 0x10000000
flesh 0x20000000
foliage 0x30000000
computer 0x40000000
dirt 0x50000000
vent 0x60000000
grate 0x70000000
metal 0x80000000
glass 0x90000000
sand 0xA0000000
slosh 0xB0000000
snow 0xC0000000
tile 0xD0000000
wood 0xE0000000
concrete 0xF0000000
}
}
{
leakssteam 0x00080000
leakswater 0x00100000
fl_r1 0x00200000
fl_r2 0x00400000
fl_r3 0x00800000
fl_r4 0x01000000
fl_r5 0x02000000
fl_r6 0x04000000
penetrate 0x08000000
alien 0x10000000
flesh 0x20000000
foliage 0x30000000
computer 0x40000000
dirt 0x50000000
vent 0x60000000
grate 0x70000000
metal 0x80000000
glass 0x90000000
sand 0xA0000000
slosh 0xB0000000
snow 0xC0000000
tile 0xD0000000
wood 0xE0000000
concrete 0xF0000000
}

View File

@ -5,6 +5,7 @@
surfaceParm nodraw
surfaceParm trans
surfaceParm metal
surfaceParm penetrate
surfaceParm nolightmap
nomipmaps
}

View File

@ -19,6 +19,7 @@
#include "font.h"
#include "fade.h"
#include "cmd.h"
#include "util.h"
/* flags for 2d drawing */
#define DRAWFLAG_NORMAL 0

View File

@ -143,6 +143,7 @@ void
CSQC_UpdateView(float w, float h, float focus)
{
player pl = __NULL__;
base_client cl = __NULL__;
spectator spec;
int s;
@ -202,6 +203,7 @@ CSQC_UpdateView(float w, float h, float focus)
pSeat->m_ePlayer = self = findfloat(world, entnum, player_localentnum);
pl = (player)self;
cl = (base_client)self;
/* player slot not present */
if (!self) {
@ -210,8 +212,9 @@ CSQC_UpdateView(float w, float h, float focus)
/* this needs to be moved into a base_client method */
#if 1
if (self.classname == "player") {
Predict_PlayerPreFrame(pl);
cl.PreFrame();
if (!Client_IsSpectator(pl)) {
pSeat->m_vecPredictedOrigin = pl.origin;
pSeat->m_vecPredictedVelocity = pl.velocity;
@ -252,9 +255,8 @@ CSQC_UpdateView(float w, float h, float focus)
pl.viewzoom = oldzoom;
View_PreDraw();
} else if (self.classname == "spectator") {
} else if (Client_IsSpectator(pl)) {
spec = (spectator)self;
Predict_SpectatorPreFrame(spec);
if (spec.spec_mode == SPECMODE_FIRSTPERSON || spec.spec_mode == SPECMODE_THIRDPERSON) {
entity c = findfloat(world, ::entnum, spec.spec_ent);
@ -279,7 +281,8 @@ CSQC_UpdateView(float w, float h, float focus)
setproperty(VF_CL_VIEWANGLES, view_angles);
setproperty(VF_ANGLES, view_angles);
} else {
if (getplayerkeyvalue(pl.entnum-1, "*spec") == "0") {
/* we're not spectating at all */
if (!Client_IsSpectator(pl)) {
setproperty(VF_ORIGIN, pSeat->m_vecPredictedOrigin + pl.view_ofs);
if (pl.flags & FL_INVEHICLE) {
@ -299,7 +302,7 @@ CSQC_UpdateView(float w, float h, float focus)
Shake_Update(pl);
setproperty(VF_ANGLES, view_angles + pl.punchangle);
} else if (getplayerkeyvalue(pl.entnum-1, "*spec") == "1") {
} else if (Client_IsSpectator(pl)) {
spec = (spectator)self;
switch (spec.spec_mode) {
case SPECMODE_THIRDPERSON:
@ -328,13 +331,9 @@ CSQC_UpdateView(float w, float h, float focus)
default:
setproperty(VF_ORIGIN, pSeat->m_vecPredictedOrigin);
}
} else if (getplayerkeyvalue(pl.entnum-1, "*spec") == "2") {
setproperty(VF_ORIGIN, pSeat->m_vecPredictedOrigin);
Shake_Update(pl);
setproperty(VF_ANGLES, view_angles + pl.punchangle);
}
if (g_iIntermission) {
if (Client_InIntermission()) {
view_angles = pSeat->m_vecCameraAngle;
view_angles += [sin(time), sin(time * 2)];
setproperty(VF_ORIGIN, pSeat->m_vecCameraOrigin);
@ -357,10 +356,27 @@ CSQC_UpdateView(float w, float h, float focus)
setproperty(VF_AFOV, autocvar_r_viewmodelfov);
setproperty(VF_ORIGIN, pSeat->m_vecPredictedOrigin + pl.view_ofs);
View_DrawViewModel();
} else if (pl.health > 0) {
View_DrawViewModel();
} else if (getplayerkeyvalue(pl.entnum-1, "*dead") == "1") {
pl.UpdateDeathcam();
} else {
if (Client_IsSpectator(pl)) {
/* 0 means world */
if (spec.spec_ent) {
spec = (spectator)self;
entity c = findfloat(world, ::entnum, spec.spec_ent);
/* we found them */
if (c && c != spec) {
player ps = (player)c;
if (ps.health <= 0)
pl.UpdateDeathcam();
else
View_DrawViewModel();
}
}
} else if (Client_IsDead(pl)) {
pl.UpdateDeathcam();
} else {
View_DrawViewModel();
}
}
/* this is running whenever we're doing 'buildcubemaps' */
@ -368,7 +384,6 @@ CSQC_UpdateView(float w, float h, float focus)
setproperty(VF_ORIGIN, g_vecCubePos);
setproperty(VF_SIZE_X, g_dCubeSize);
setproperty(VF_SIZE_Y, g_dCubeSize);
print(sprintf("cubesize: %d\n", g_dCubeSize));
setproperty(VF_AFOV, 90);
}
@ -385,15 +400,15 @@ CSQC_UpdateView(float w, float h, float focus)
Fade_Update((int)video_mins[0],(int)video_mins[1], (int)w, (int)h);
View_PostDraw();
if (g_iIntermission) {
if (Client_InIntermission()) {
Scores_Draw();
} else if (focus == TRUE) {
GameText_Draw();
PointMessage_Draw();
if (getplayerkeyvalue(pl.entnum-1, "*spec") == "0") {
if (!Client_IsSpectator(pl)) {
HUD_Draw();
} else if (self.classname == "player") {
} else {
HUD_DrawSpectator();
}
@ -412,10 +427,7 @@ CSQC_UpdateView(float w, float h, float focus)
/* move this into base_client methods */
#if 1
if (self.classname == "player")
Predict_PlayerPostFrame((player)self);
else if (self.classname == "spectator")
Predict_SpectatorPostFrame((spectator)self);
cl.PostFrame();
#endif
}

View File

@ -26,4 +26,5 @@ shake.qc
cmd.qc
event.qc
entry.qc
util.cpp
#endlist

View File

@ -46,8 +46,10 @@ player::predraw(void)
/* make sure we're enabling shadow rendering on us */
effects &= ~EF_NOSHADOW;
base_client cl = (base_client)pSeat->m_ePlayer;
if (getplayerkeyvalue(pSeat->m_ePlayer.entnum-1, "*spec") == "1") {
/* it's either us or us spectating */
if (Client_IsSpectator(cl)) {
spectator spec = (spectator)pSeat->m_ePlayer;
if (entnum == spec.spec_ent && spec.spec_mode == SPECMODE_FIRSTPERSON) {
this_us = 1;

View File

@ -74,39 +74,7 @@ Propagate our pmove state to whatever the current frame before its stomped on
void
Predict_PlayerPreFrame(player pl)
{
/* this is where a game/mod would decide to add more prediction rollback
* information. */
pl.PredictPreFrame();
if (pl.flags & FL_INVEHICLE)
if (pl.vehicle) {
NSVehicle veh = (NSVehicle)pl.vehicle;
veh.PredictPreFrame();
}
/* run physics code for all the input frames which we've not heard back
* from yet. This continues on in Player_ReceiveEntity! */
for (int i = pl.sequence + 1; i <= clientcommandframe; i++) {
float flSuccess = getinputstate(i);
if (flSuccess == FALSE) {
continue;
}
/* don't do partial frames, aka incomplete input packets */
if (input_timelength == 0) {
break;
}
if (i==clientcommandframe){
CSQC_Input_Frame();
}
/* this global is for our shared random number seed */
input_sequence = i;
/* run our custom physics */
pl.Physics_Run();
}
}
/*
@ -121,17 +89,7 @@ Rewind our pmove state back to before we started predicting.
void
Predict_PlayerPostFrame(player pl)
{
/* give the game/mod a chance to roll back its values too */
pl.PredictPostFrame();
if (pl.flags & FL_INVEHICLE)
if (pl.vehicle) {
NSVehicle veh = (NSVehicle)pl.vehicle;
veh.PredictPostFrame();
}
/* update bounds */
setorigin(pl, pl.origin);
}
/*
@ -146,7 +104,6 @@ Propagate our pmove state to whatever the current frame before its stomped on
void
Predict_SpectatorPreFrame(spectator pl)
{
pl.PreFrame();
}
/*
@ -161,5 +118,4 @@ Rewind our pmove state back to before we started predicting.
void
Predict_SpectatorPostFrame(spectator pl)
{
pl.PostFrame();
}

40
src/client/util.cpp Normal file
View File

@ -0,0 +1,40 @@
float
Client_IsSpectator(base_client cl)
{
return (getplayerkeyfloat(cl.entnum - 1, "*spec") > 0) ? TRUE : FALSE;
}
float
Client_IsRealSpectator(base_client cl)
{
return (cl.classname == "spectator") ? TRUE : FALSE;
}
float
Client_IsFakeSpectator(base_client cl)
{
return (getplayerkeyvalue(cl.entnum - 1, "*spec") == "2") ? TRUE : FALSE;
}
float
Client_IsDead(base_client cl)
{
if (Client_IsSpectator(cl) == TRUE)
return FALSE;
else
return (getplayerkeyvalue(cl.entnum - 1, "*dead") == "1") ? TRUE : FALSE;
}
float
Client_IsPlayer(base_client cl)
{
return (cl.classname == "player") ? TRUE : FALSE;
}
float
Client_InIntermission(void)
{
return g_iIntermission;
}

17
src/client/util.h Normal file
View File

@ -0,0 +1,17 @@
/* Returns if the specified client is a spectator, doesn't matter if real or fake */
float Client_IsSpectator(base_client);
/* Returns if we're a permanent spectator, USE THIS if you want to access spectator class attributes */
float Client_IsRealSpectator(base_client cl);
/* Returns if we're a fake spectator, in case you need to be certain */
float Client_IsFakeSpectator(base_client cl);
/* Return if the specified client is dead. If they're a spectator they're always alive. */
float Client_IsDead(base_client);
/* Returns if the specified client is a playable client class */
float Client_IsPlayer(base_client cl);
/* Are we in an intermission? (Match ending screen) */
float Client_InIntermission(void);

View File

@ -129,9 +129,10 @@ View_DrawViewModel(void)
entity m_eMuzzleflashL = pSeat->m_eMuzzleflashL;
player pl = __NULL__;
base_client cl = (base_client)pSeat->m_ePlayer;
/* it's either us or us spectating */
if (self.classname == "spectator") {
if (Client_IsSpectator(cl)) {
spectator spec = (spectator)self;
pl = (player)findfloat(world, ::entnum, spec.spec_ent);
@ -139,27 +140,24 @@ View_DrawViewModel(void)
return;
} else {
pl = (player)self;
if (pl.health <= 0) {
return;
}
}
if (!pl)
return;
if (pl.health <= 0) {
return;
}
if (cvar("r_drawviewmodel") == 0 || autocvar_cl_thirdperson == TRUE) {
return;
}
// print(sprintf("%s: %f %d\n", pl.classname, pl.weapontime, pl.activeweapon));
View_UpdateWeapon(pl, m_eViewModel, m_eMuzzleflash);
View_UpdateWeapon(pl, m_eViewModelL, m_eMuzzleflashL);
float fBaseTime2 = m_eViewModel.frame1time;
float fBaseTime = m_eViewModel.frame1time;
m_eViewModel.frame = pl.weaponframe;
m_eViewModelL.frame = m_eViewModel.frame = pl.weaponframe;
m_eViewModelL.frame1time =
m_eViewModelL.frame2time =
m_eViewModel.frame2time =
@ -326,6 +324,16 @@ View_PlayAnimation(int iSequence)
pSeat->m_eViewModel.frame =
pSeat->m_eViewModelL.frame = (float)iSequence;
}
void
View_PlayAnimationLeft(int iSequence)
{
pSeat->m_eViewModelL.frame = (float)iSequence;
}
void
View_PlayAnimationRight(int iSequence)
{
pSeat->m_eViewModel.frame = (float)iSequence;
}
int
View_GetAnimation(void)

View File

@ -28,7 +28,8 @@ Client-side glare/glow orb effect like the flares in 1997's Unreal.
This entity was introduced in Half-Life (1998).
*/
var int autocvar_r_skipFlares = 0;
var int autocvar_r_skipGlows = 0;
var int autocvar_r_skipLensFlares = 0;
class env_glow:NSEntity /* change to renderablentity? */
{
@ -44,10 +45,19 @@ class env_glow:NSEntity /* change to renderablentity? */
void(void) env_glow;
virtual float() predraw;
virtual void() postdraw;
virtual void(string, string) SpawnKey;
virtual void(void) RendererRestarted;
};
void env_sun_lensflare(vector, float, vector);
void
env_glow::postdraw(void)
{
if (!autocvar_r_skipLensFlares)
env_sun_lensflare(origin, m_flAlpha, m_vecColor);
}
void
env_glow::RendererRestarted(void)
{
@ -74,7 +84,7 @@ env_glow::predraw(void)
vector fsize;
vector vecPlayer;
if (autocvar_r_skipFlares)
if (autocvar_r_skipGlows)
return PREDRAW_NEXT;
int s = (float)getproperty(VF_ACTIVESEAT);
@ -108,9 +118,9 @@ env_glow::predraw(void)
makevectors(vectoangles(origin - vecPlayer));
forg = origin + (v_forward * -16);
if (spawnflags & 1)
if (spawnflags & 1) {
makevectors(m_vecOrientation+[0,0,angles[2]]);
else {
} else {
makevectors(view_angles+[0,0,angles[2]]);
}

View File

@ -164,4 +164,53 @@ env_sun::env_sun(void)
setsize(this, [0,0,0], [0,0,0]);
setorigin(this, origin);
Init();
}
}
void
env_sun_lensflare(vector m_vecLensPos, float m_flLensAlpha, vector vecColor)
{
vector lens_pos = project(m_vecLensPos);
vector lens_1 = lens_pos - (FLARE_SIZE / 2);
vector player_pos = getproperty(VF_ORIGIN);
vector player_angle = getproperty(VF_CL_VIEWANGLES);
m_flLensAlpha *= 0.15f;
if (m_flLensAlpha <= 0.0f) {
return;
}
{
vector delta;
float fov;
makevectors(player_angle);
delta = normalize (m_vecLensPos - player_pos);
fov = delta * v_forward;
/* we're in field-of-view */
if (fov > 0.3) {
traceline(player_pos, m_vecLensPos, TRUE, self);
if (trace_fraction != 1.0) {
return;
}
} else {
return;
}
}
player_angle[0] *= -1;
vector test1, test2;
makevectors(vectoangles(m_vecLensPos - player_pos));
test1 = v_forward;
makevectors(player_angle);
test2 = v_forward;
vector c = (test1 - test2) * 512;
drawpic(lens_1, "textures/sfx/flare1", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE);
drawpic(lens_1 - c * 0.1, "textures/sfx/flare2", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE);
drawpic(lens_1 + c * 0.2, "textures/sfx/flare3", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE);
drawpic(lens_1 - c * 0.3, "textures/sfx/flare4", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE);
drawpic(lens_1 + c * 0.4, "textures/sfx/flare2", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE);
drawpic(lens_1 - c * 0.5, "textures/sfx/flare3", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE);
}

View File

@ -480,6 +480,7 @@ NSEntity::Respawn(void)
void
NSEntity::Save(float handle)
{
SaveFloat(handle, "spawnflags", spawnflags);
SaveVector(handle, "origin", origin);
SaveVector(handle, "absmin", absmin);
SaveVector(handle, "absmax", absmax);
@ -498,6 +499,9 @@ void
NSEntity::Restore(string strKey, string strValue)
{
switch (strKey) {
case "spawnflags":
spawnflags = stof(strValue);
break;
case "origin":
origin = stov(strValue);
setorigin(this, origin);
@ -589,6 +593,9 @@ NSEntity::SpawnKey(string strKey, string strValue)
/* we do re-read a lot of the builtin fields in case we want to set
defaults. just in case anybody is wondering. */
switch (strKey) {
case "spawnflags":
spawnflags = stof(strValue);
break;
case "origin":
origin = stov(strValue);
break;

View File

@ -174,7 +174,7 @@ light_dynamic::ReceiveEntity(float flNew, float flFlags)
void
light_dynamic::RendererRestarted(void)
{
#if 0
#if 1
float p = dynamiclight_spawnstatic(origin, m_flDistance, m_vecLight / 255);
dynamiclight_set(p, LFIELD_ANGLES, angles);

View File

@ -372,3 +372,9 @@ CGameRules::CGameRules(void)
/* our currently running mode */
CGameRules g_grMode;
int
Gamerules_IsTeamPlay(void)
{
return (g_grMode.IsTeamPlay()) ? TRUE : FALSE;
}

View File

@ -138,7 +138,8 @@ TraceAttack_FireSingle(vector vecPos, vector vAngle, int iDamage, int iWeapon, f
#ifdef BULLETPENETRATION
if (iTotalPenetrations > 0) {
iTotalPenetrations -= 1;
if (!(trace_surfaceflagsi & SURF_PENETRATE))
iTotalPenetrations -= 1;
TraceAttack_FireSingle(trace_endpos + (v_forward * 2), vAngle, iDamage / 2, iWeapon, dist);
}
#endif

View File

@ -3,13 +3,28 @@
class
base_client:NSSurfacePropEntity
{
vector origin_net;
vector velocity_net;
void(void) base_client;
virtual void(void) ClientInputFrame;
/* final input handling of the client */
virtual void(void) ClientInput;
virtual void(void) PreFrame;
virtual void(void) PostFrame;
virtual int(void) IsFakeSpectator;
#ifdef CLIENT
/* gives the chance to override input variables before networking */
virtual void(void) ClientInputFrame;
/* our camera when we're dead */
virtual void(void) UpdateDeathcam;
/* run every frame before renderscene() */
virtual float(void) predraw;
#endif
};

View File

@ -1,10 +1,30 @@
void
base_client::ClientInputFrame(void)
base_client::ClientInput(void)
{
}
void
base_client::PreFrame(void)
{
}
void
base_client::PostFrame(void)
{
}
int
base_client::IsFakeSpectator(void)
{
return (FALSE);
}
#ifdef CLIENT
void
base_client::ClientInputFrame(void)
{
}
void
base_client::UpdateDeathcam(void)
{

View File

@ -39,6 +39,7 @@
#include "../gs-entbase/shared/baseentity.h"
#include "client.h"
#include "spectator.h"
#include "player.h"
#include "damage.h"
#include "flags.h"
@ -50,7 +51,6 @@
#include "math.h"
#include "pmove.h"
#include "memory.h"
#include "spectator.h"
#include "platform.h"
#include "propdata.h"
#include "surfaceproperties.h"
@ -138,6 +138,21 @@ Util_TimeToString(float fTime)
}
}
/* returns whether or not the mode we're playing is a team game */
#ifdef SERVER
int Gamerules_IsTeamPlay(void);
#endif
int
Util_IsTeamPlay(void)
{
#ifdef SERVER
return Gamerules_IsTeamPlay();
#else
return (serverkeyfloat("teams") > 0) ? TRUE : FALSE;
#endif
}
__wrap void
dprint(string m)
{

View File

@ -132,7 +132,7 @@ typedef enum
#define SURF_RESERVED4 0x01000000i
#define SURF_RESERVED5 0x02000000i
#define SURF_RESERVED6 0x04000000i
#define SURF_RESERVED7 0x08000000i
#define SURF_PENETRATE 0x08000000i
/* material surfaceflags (need to be masked) */
#define SURF_MASK 0x0FFFFFFFi

View File

@ -15,7 +15,7 @@
*/
class
base_player:base_client
base_player:spectator
{
PREDICTED_INT(weaponframe);
PREDICTED_FLOAT(health);
@ -53,6 +53,11 @@ base_player:base_client
void(void) base_player;
virtual void(void) ClientInput;
virtual void(void) PreFrame;
virtual void(void) PostFrame;
virtual void(float) Physics_Fall;
virtual void(void) Physics_Crouch;
virtual void(void) Physics_Jump;
@ -65,6 +70,8 @@ base_player:base_client
virtual void(void) Physics_InputPostMove;
virtual void(void) Physics_Run;
virtual int(void) IsFakeSpectator;
#ifdef CLIENT
int sequence;

View File

@ -14,6 +14,93 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
int
base_player::IsFakeSpectator(void)
{
#ifdef SERVER
if (infokey(this, "*spec") == "2")
#else
if (getplayerkeyfloat(entnum - 1, "*spec") == 2)
#endif
return (TRUE);
return (FALSE);
}
void
base_player::PreFrame(void)
{
#ifdef CLIENT
/* this is where a game/mod would decide to add more prediction rollback
* information. */
PredictPreFrame();
if (flags & FL_INVEHICLE)
if (vehicle) {
NSVehicle veh = (NSVehicle)vehicle;
veh.PredictPreFrame();
}
/* run physics code for all the input frames which we've not heard back
* from yet. This continues on in Player_ReceiveEntity! */
for (int i = sequence + 1; i <= clientcommandframe; i++) {
float flSuccess = getinputstate(i);
if (flSuccess == FALSE) {
continue;
}
/* don't do partial frames, aka incomplete input packets */
if (input_timelength == 0) {
break;
}
if (i==clientcommandframe){
CSQC_Input_Frame();
}
/* this global is for our shared random number seed */
input_sequence = i;
/* run our custom physics */
Physics_Run();
}
#endif
}
void
base_player::PostFrame(void)
{
#ifdef CLIENT
/* give the game/mod a chance to roll back its values too */
PredictPostFrame();
if (flags & FL_INVEHICLE)
if (vehicle) {
NSVehicle veh = (NSVehicle)vehicle;
veh.PredictPostFrame();
}
/* update bounds */
setorigin(this, origin);
#endif
}
void
base_player::ClientInput(void)
{
if (IsFakeSpectator()) {
spectator::ClientInput();
SpectatorTrackPlayer();
return;
}
/* allow vehicles to prevent weapon logic from happening */
Vehicle_Input(this);
/* weapon/item logic of what the player controls */
Game_Input((player)this);
}
#ifdef CLIENT
void
base_player::ClientRemove(void)
@ -32,6 +119,11 @@ This is basically CSQC_Input_Frame! So games can override this as they please.
void
base_player::ClientInputFrame(void)
{
if (IsFakeSpectator()) {
spectator::ClientInputFrame();
return;
}
/* If we are inside a VGUI, don't let the client do stuff outside */
if (VGUI_Active()) {
input_impulse = 0;
@ -177,6 +269,11 @@ base_player::ReceiveEntity(float new, float fl)
punchangle[1] = readfloat();
punchangle[2] = readfloat();
vehicle = findfloat(world, ::entnum, readentitynum());
/* FIXME: Make this temp spec only */
spec_ent = readbyte();
spec_mode = readbyte();
spec_flags = readbyte();
}
/*
@ -217,6 +314,10 @@ base_player::PredictPreFrame(void)
SAVE_STATE(w_idle_next);
SAVE_STATE(punchangle);
SAVE_STATE(vehicle);
SAVE_STATE(spec_ent);
SAVE_STATE(spec_mode);
SAVE_STATE(spec_flags);
}
/*
@ -258,6 +359,10 @@ base_player::PredictPostFrame(void)
ROLL_BACK(w_idle_next);
ROLL_BACK(punchangle);
ROLL_BACK(vehicle);
ROLL_BACK(spec_ent);
ROLL_BACK(spec_mode);
ROLL_BACK(spec_flags);
}
#else
void
@ -439,10 +544,9 @@ base_player::Death(void)
/*
=================
base_player::MakeTempSpectator
base_player::MakePlayer
This is what dead players in round matches become, or when we spawn
for the first time before selecting a loadout or something.
True participating player, can walk around and everything.
=================
*/
void
@ -571,6 +675,11 @@ base_player::EvaluateEntity(void)
SAVE_STATE(w_idle_next);
SAVE_STATE(punchangle);
SAVE_STATE(vehicle);
/* FIXME: Make this temp spec only */
SAVE_STATE(spec_ent);
SAVE_STATE(spec_mode);
SAVE_STATE(spec_flags);
}
/*
@ -663,6 +772,11 @@ base_player::SendEntity(entity ePEnt, float fChanged)
else
WriteEntity(MSG_ENTITY, __NULL__);
/* FIXME: Make this fake spectator only. */
WriteByte(MSG_ENTITY, spec_ent);
WriteByte(MSG_ENTITY, spec_mode);
WriteByte(MSG_ENTITY, spec_flags);
return (1);
}
#endif

View File

@ -265,11 +265,7 @@ base_player::Physics_InputPostMove(void)
flags &= ~FL_FROZEN;
/* allow vehicles to prevent weapon logic from happening */
Vehicle_Input(this);
/* weapon/item logic of what the player controls */
Game_Input((player)this);
ClientInput();
}
/* the main physics routine, the head */

View File

@ -15,12 +15,15 @@ typedef enum
SPECMODE_OVERVIEW
} spectatorMode_t;
typedef enumflags
{
SPECFLAG_BUTTON_RELEASED,
};
class spectator:base_client
{
vector origin_net;
vector velocity_net;
float spec_ent; float spec_ent_net;
float spec_flags; float spec_flags_net;
PREDICTED_FLOAT(spec_ent);
PREDICTED_FLOAT(spec_flags);
spectatorMode_t spec_mode; spectatorMode_t spec_mode_net;
vector spec_org;
@ -29,18 +32,20 @@ class spectator:base_client
void(void) spectator;
virtual void(void) ClientInput;
virtual void(void) InputNext;
virtual void(void) InputPrevious;
virtual void(void) InputMode;
virtual void(void) PreFrame;
virtual void(void) PostFrame;
virtual void(void) SpectatorInput;
virtual void(void) WarpToTarget;
virtual void(void) PreFrame;
virtual void(void) PostFrame;
virtual void(void) SpectatorTrackPlayer;
#ifdef SERVER
virtual void(void) EvaluateEntity;
virtual float(entity, float) SendEntity;
virtual void(void) RunClientCommand;
#else

View File

@ -15,15 +15,7 @@
*/
void
spectator::WarpToTarget(void)
{
entity b = edict_num(spec_ent);
setorigin(this, b.origin);
}
void
spectator::SpectatorInput(void)
spectator::ClientInput(void)
{
if (input_buttons & INPUT_BUTTON0) {
InputNext();
@ -32,10 +24,19 @@ spectator::SpectatorInput(void)
} else if (input_buttons & INPUT_BUTTON2) {
InputMode();
} else {
spec_flags &= ~GF_SEMI_TOGGLED;
spec_flags &= ~SPECFLAG_BUTTON_RELEASED;
}
input_buttons = 0;
//crossprint(sprintf("%d %d %d\n", spec_ent, spec_mode, spec_flags));
}
void
spectator::WarpToTarget(void)
{
entity b = edict_num(spec_ent);
setorigin(this, b.origin);
}
#ifdef SERVER
@ -81,7 +82,7 @@ void
spectator::RunClientCommand(void)
{
runstandardplayerphysics(this);
SpectatorInput();
ClientInput();
}
#else
@ -103,7 +104,6 @@ spectator::ClientInputFrame(void)
void
spectator::ReceiveEntity(float new, float fl)
{
if (new == FALSE) {
/* Go through all the physics code between the last received frame
* and the newest frame and keep the changes this time around instead
@ -121,7 +121,7 @@ spectator::ReceiveEntity(float new, float fl)
}
input_sequence = i;
runstandardplayerphysics(this);
SpectatorInput();
ClientInput();
}
/* any differences in things that are read below are now
@ -164,7 +164,7 @@ spectator::predraw(void)
void
spectator::InputNext(void)
{
if (spec_flags & GF_SEMI_TOGGLED)
if (spec_flags & SPECFLAG_BUTTON_RELEASED)
return;
#if 0
@ -190,14 +190,14 @@ spectator::InputNext(void)
if (i <= sep && best == 0) {
f = edict_num(i);
if (f && f.classname == "player") {
if (f && f.classname == "player" && f != this) {
best = i;
}
}
if (i > sep) {
f = edict_num(i);
if (f && f.classname == "player") {
if (f && f.classname == "player" && f != this) {
best = i;
break;
}
@ -209,7 +209,7 @@ spectator::InputNext(void)
spec_ent = best;
#endif
spec_flags |= GF_SEMI_TOGGLED;
spec_flags |= SPECFLAG_BUTTON_RELEASED;
WarpToTarget();
if (spec_mode == SPECMODE_FREE)
@ -219,7 +219,7 @@ spectator::InputNext(void)
void
spectator::InputPrevious(void)
{
if (spec_flags & GF_SEMI_TOGGLED)
if (spec_flags & SPECFLAG_BUTTON_RELEASED)
return;
#if 0
float max_edict;
@ -264,7 +264,7 @@ spectator::InputPrevious(void)
spec_ent = best;
#endif
spec_flags |= GF_SEMI_TOGGLED;
spec_flags |= SPECFLAG_BUTTON_RELEASED;
WarpToTarget();
@ -275,29 +275,28 @@ spectator::InputPrevious(void)
void
spectator::InputMode(void)
{
if (spec_flags & GF_SEMI_TOGGLED)
if (spec_flags & SPECFLAG_BUTTON_RELEASED)
return;
crossprint("MODE\n");
spec_mode++;
if (spec_mode > SPECMODE_FIRSTPERSON)
spec_mode = SPECMODE_FREE;
spec_flags |= GF_SEMI_TOGGLED;
spec_flags |= SPECFLAG_BUTTON_RELEASED;
}
void
spectator::PreFrame(void)
{
#ifdef SERVER
#else
#ifdef CLIENT
/* base player attributes/fields we're going to roll back */
origin_net = origin;
velocity_net = velocity;
spec_ent_net = spec_ent;
spec_mode_net = spec_mode;
spec_flags_net = spec_flags;
SAVE_STATE(origin);
SAVE_STATE(velocity);
SAVE_STATE(spec_ent);
SAVE_STATE(spec_mode);
SAVE_STATE(spec_flags);
/* run physics code for all the input frames which we've not heard back
* from yet. This continues on in Player_ReceiveEntity! */
@ -321,10 +320,16 @@ spectator::PreFrame(void)
/* run our custom physics */
runstandardplayerphysics(this);
SpectatorInput();
ClientInput();
}
#endif
SpectatorTrackPlayer();
}
void
spectator::SpectatorTrackPlayer(void)
{
if (spec_mode == SPECMODE_THIRDPERSON || spec_mode == SPECMODE_FIRSTPERSON ) {
entity b;
@ -345,10 +350,10 @@ spectator::PreFrame(void)
}
}
void
spectator::PostFrame(void)
{
#ifdef SERVER
void
spectator::EvaluateEntity(void)
{
/* check for which values have changed in this frame
and announce to network said changes */
if (origin != origin_net)
@ -366,19 +371,23 @@ spectator::PostFrame(void)
if (spec_flags != spec_flags_net)
SetSendFlags(SPECFL_FLAGS);
origin_net = origin;
velocity_net = velocity;
spec_ent_net = spec_ent;
spec_mode_net = spec_mode;
spec_flags_net = spec_flags;
#else
/* finally roll the values back */
origin = origin_net;
velocity = velocity_net;
spec_ent = spec_ent_net;
spec_mode = spec_mode_net;
spec_flags = spec_flags_net;
setorigin(this, origin);
SAVE_STATE(origin);
SAVE_STATE(velocity);
SAVE_STATE(spec_ent);
SAVE_STATE(spec_mode);
SAVE_STATE(spec_flags);
}
#endif
void
spectator::PostFrame(void)
{
#ifdef CLIENT
ROLL_BACK(origin);
ROLL_BACK(velocity);
ROLL_BACK(spec_ent);
ROLL_BACK(spec_mode);
ROLL_BACK(spec_flags);
#endif
}

View File

@ -475,6 +475,7 @@ SurfData_Impact(entity e, int fl, vector org, vector ang)
case BSPVER_Q3: /* Q3 */
case BSPVER_RTCW: /* RtCW */
case BSPVER_RBSP: /* RFVBSP */
fl &= ~SURF_MASK;
FX_Impact(SurfData_SurfaceFlagtoImpact(fl), org, ang);
break;
default: