GS-EntBase: Add client-side prediction for func_tankmortar.

This commit is contained in:
Marco Cawthorne 2021-09-08 20:17:13 +02:00
parent 05fe98e0ca
commit 5578b0e602
Signed by: eukara
GPG key ID: C196CD8BA993248A
5 changed files with 207 additions and 25 deletions

View file

@ -927,6 +927,9 @@ CSQC_Ent_Update(float new)
case ENT_VEHICLE:
basevehicle_readentity(new);
break;
case ENT_VEH_TANKMORTAR:
func_tankmortar_readentity(new);
break;
case ENT_PLAYER:
player pl = (player)self;

View file

@ -24,14 +24,6 @@ enumflags
void
CBaseVehicle::UpdateView(void)
{
vector vecStart, vecEnd;
pSeat->m_vecPredictedOrigin = origin;
makevectors(view_angles);
vecStart = [pSeat->m_vecPredictedOrigin[0], pSeat->m_vecPredictedOrigin[1], pSeat->m_vecPredictedOrigin[2] + 16] + (v_right * 4);
vecEnd = vecStart + (v_forward * -256) + [0,0,16] + (v_right * 4);
traceline(vecStart, vecEnd, FALSE, self);
setproperty(VF_ORIGIN, trace_endpos + (v_forward * 16));
}
void

View file

@ -50,7 +50,6 @@ some random sprites needs to be treated additive.
This entity was introduced in Half-Life (1998).
*/
#ifdef SERVER
/* TODO: Implement these */
enumflags
{
@ -84,17 +83,176 @@ class func_tankmortar:CBaseVehicle
float m_flFireTime;
void(void) func_tankmortar;
virtual void(void) customphysics;
virtual void(void) PlayerInput;
virtual void(void) Respawn;
virtual void(vector) SpriteSmoke;
virtual void(vector) SpriteFlash;
#ifdef CLIENT
virtual void(void) PredictPreFrame;
virtual void(void) PredictPostFrame;
virtual void(float, float) ReadEntity;
virtual void(void) UpdateView;
#else
virtual float(entity, float) SendEntity;
virtual void(void) Respawn;
virtual void(string, string) SpawnKey;
#endif
};
#ifdef CLIENT
void
func_tankmortar::UpdateView(void)
{
}
void
func_tankmortar::PredictPreFrame(void)
{
SAVE_STATE(angles);
SAVE_STATE(origin);
SAVE_STATE(velocity);
}
void
func_tankmortar::PredictPostFrame(void)
{
ROLL_BACK(angles);
ROLL_BACK(origin);
ROLL_BACK(velocity);
}
void
func_tankmortar::ReadEntity(float fChanged, float new)
{
if (fChanged & VEHFL_CHANGED_ORIGIN) {
origin[0] = readcoord();
origin[1] = readcoord();
origin[2] = readcoord();
}
if (fChanged & VEHFL_CHANGED_ANGLES) {
angles[0] = readshort() / (32767 / 360);
angles[1] = readshort() / (32767 / 360);
angles[2] = readshort() / (32767 / 360);
}
if (fChanged & VEHFL_CHANGED_MODELINDEX) {
setmodelindex(this, readshort());
}
if (fChanged & VEHFL_CHANGED_SOLID) {
solid = readbyte();
}
if (fChanged & VEHFL_CHANGED_MOVETYPE) {
movetype = readbyte();
}
if (fChanged & VEHFL_CHANGED_SIZE) {
mins[0] = readcoord();
mins[1] = readcoord();
mins[2] = readcoord();
maxs[0] = readcoord();
maxs[1] = readcoord();
maxs[2] = readcoord();
}
if (fChanged & VEHFL_CHANGED_VELOCITY) {
velocity[0] = readfloat();
velocity[1] = readfloat();
velocity[2] = readfloat();
}
if (fChanged & VEHFL_CHANGED_DRIVER) {
m_eDriver = findfloat(world, ::entnum, readentitynum());
}
if (new)
drawmask = MASK_ENGINE;
}
#else
void
func_tankmortar::EvaluateEntity(void)
{
/* while the engine is still handling physics for these, we can't
* predict when origin/angle might change */
if (net_origin != origin) {
net_origin = origin;
SetSendFlags(VEHFL_CHANGED_ORIGIN);
}
if (net_angles != angles) {
angles[0] = Math_FixDelta(angles[0]);
angles[1] = Math_FixDelta(angles[1]);
angles[2] = Math_FixDelta(angles[2]);
net_angles = angles;
SetSendFlags(VEHFL_CHANGED_ANGLES);
}
if (net_velocity != velocity) {
net_velocity = velocity;
SetSendFlags(VEHFL_CHANGED_VELOCITY);
}
}
float
func_tankmortar::SendEntity(entity ePEnt, float fChanged)
{
WriteByte(MSG_ENTITY, ENT_VEH_TANKMORTAR);
WriteFloat(MSG_ENTITY, fChanged);
/* really trying to get our moneys worth with 23 bits of mantissa */
if (fChanged & VEHFL_CHANGED_ORIGIN) {
WriteCoord(MSG_ENTITY, origin[0]);
WriteCoord(MSG_ENTITY, origin[1]);
WriteCoord(MSG_ENTITY, origin[2]);
}
if (fChanged & VEHFL_CHANGED_ANGLES) {
WriteShort(MSG_ENTITY, angles[0] * 32767 / 360);
WriteShort(MSG_ENTITY, angles[1] * 32767 / 360);
WriteShort(MSG_ENTITY, angles[2] * 32767 / 360);
}
if (fChanged & VEHFL_CHANGED_MODELINDEX) {
WriteShort(MSG_ENTITY, modelindex);
}
if (fChanged & VEHFL_CHANGED_SOLID) {
WriteByte(MSG_ENTITY, solid);
}
if (fChanged & VEHFL_CHANGED_MOVETYPE) {
WriteByte(MSG_ENTITY, movetype);
}
if (fChanged & VEHFL_CHANGED_SIZE) {
WriteCoord(MSG_ENTITY, mins[0]);
WriteCoord(MSG_ENTITY, mins[1]);
WriteCoord(MSG_ENTITY, mins[2]);
WriteCoord(MSG_ENTITY, maxs[0]);
WriteCoord(MSG_ENTITY, maxs[1]);
WriteCoord(MSG_ENTITY, maxs[2]);
}
if (fChanged & VEHFL_CHANGED_VELOCITY) {
WriteFloat(MSG_ENTITY, velocity[0]);
WriteFloat(MSG_ENTITY, velocity[1]);
WriteFloat(MSG_ENTITY, velocity[2]);
}
if (fChanged & VEHFL_CHANGED_DRIVER) {
WriteEntity(MSG_ENTITY, m_eDriver);
}
return (1);
}
#endif
void
func_tankmortar::SpriteSmoke(vector org)
{
#ifdef SERVER
static void Die(void) {
remove(self);
}
@ -109,11 +267,13 @@ func_tankmortar::SpriteSmoke(vector org)
smoke.nextthink = time + 0.1f;
smoke.scale = m_flSpriteScale;
smoke.effects = EF_FLAG2;
#endif
}
void
func_tankmortar::SpriteFlash(vector org)
{
#ifdef SERVER
static void Die(void) {
remove(self);
}
@ -128,19 +288,24 @@ func_tankmortar::SpriteFlash(vector org)
smoke.nextthink = time + 0.1f;
smoke.scale = m_flSpriteScale;
smoke.effects = EF_FLAG2;
#endif
}
void
func_tankmortar::customphysics(void)
func_tankmortar::PlayerInput(void)
{
#ifdef SERVER
if (m_eDriver && m_eDriver.health <= 0)
PlayerLeave((base_player)m_eDriver);
#else
print("foooo\n");
#endif
if (m_eDriver) {
vector wantang, endang;
vector aimorg;
makevectors(m_eDriver.v_angle);
makevectors(input_angles);
aimorg = m_eDriver.origin + v_forward * 4086;
/* lerp */
@ -148,17 +313,14 @@ func_tankmortar::customphysics(void)
wantang = v_forward;
makevectors(angles);
endang[0] = Math_Lerp(v_forward[0], wantang[0], frametime);
endang[1] = Math_Lerp(v_forward[1], wantang[1], frametime);
endang[2] = Math_Lerp(v_forward[2], wantang[2], frametime);
endang[0] = Math_Lerp(v_forward[0], wantang[0], input_timelength);
endang[1] = Math_Lerp(v_forward[1], wantang[1], input_timelength);
endang[2] = Math_Lerp(v_forward[2], wantang[2], input_timelength);
angles = vectoangles(endang);
PlayerUpdateFlags();
}
}
void
func_tankmortar::PlayerInput(void)
{
#ifdef SERVER
if (m_flFireTime < time)
if (input_buttons & INPUT_BUTTON0) {
vector spos;
@ -191,8 +353,10 @@ func_tankmortar::PlayerInput(void)
}
input_buttons &= ~INPUT_BUTTON0;
#endif
}
#ifdef SERVER
void
func_tankmortar::Respawn(void)
{
@ -265,6 +429,7 @@ func_tankmortar::SpawnKey(string strKey, string strValue)
CBaseTrigger::SpawnKey(strValue, strKey);
}
}
#endif
void
func_tankmortar::func_tankmortar(void)
@ -273,9 +438,24 @@ func_tankmortar::func_tankmortar(void)
CBaseVehicle::CBaseVehicle();
#ifdef SERVER
if (m_strSpriteFlash)
precache_model(m_strSpriteFlash);
if (m_strSpriteSmoke)
precache_model(m_strSpriteSmoke);
}
#endif
}
#ifdef CLIENT
void
func_tankmortar_readentity(float isnew)
{
func_tankmortar veh = (func_tankmortar)self;
float flags = readfloat();
if (isnew)
spawnfunc_func_tankmortar();
veh.ReadEntity(flags, isnew);
}
#endif

View file

@ -32,6 +32,7 @@ enum
ENT_OLDCAMERA,
ENT_MONITOR,
ENT_VEHICLE,
ENT_VEH_TANKMORTAR,
ENT_SEPARATOR,
};

View file

@ -50,10 +50,13 @@ base_player::ReceiveEntity(float new, float fl)
origin[2] = readcoord();
if (fl & PLAYER_ANGLES_X) {
v_angle[0] = pitch = readshort() / (32767 / 360);
v_angle[1] = pitch = readshort() / (32767 / 360);
v_angle[2] = pitch = readshort() / (32767 / 360);
}
if (fl & PLAYER_ANGLES_Y) {
angles[0] = readshort() / (32767 / 360);
angles[1] = readshort() / (32767 / 360);
angles[1] = readshort() / (32767 / 360);
v_angle[1] = readshort() / (32767 / 360);
}
if (fl & PLAYER_COLORMAP)
colormap = readbyte();
@ -213,10 +216,10 @@ base_player::EvaluateEntity(void)
if (VEC_CHANGED(origin, 2))
SetSendFlags(PLAYER_ORIGIN_Z);
if (VEC_CHANGED(v_angle, 0))
if (VEC_CHANGED(v_angle, 0) || VEC_CHANGED(v_angle, 1) || VEC_CHANGED(v_angle, 2))
SetSendFlags(PLAYER_ANGLES_X);
if (VEC_CHANGED(angles, 1))
if (VEC_CHANGED(angles, 0) || VEC_CHANGED(angles, 1) || VEC_CHANGED(angles, 2))
SetSendFlags(PLAYER_ANGLES_Y);
if (ATTR_CHANGED(colormap))
@ -311,10 +314,13 @@ base_player::SendEntity(entity ePEnt, float fChanged)
if (fChanged & PLAYER_ANGLES_X) {
WriteShort(MSG_ENTITY, v_angle[0] * 32767 / 360);
WriteShort(MSG_ENTITY, v_angle[1] * 32767 / 360);
WriteShort(MSG_ENTITY, v_angle[2] * 32767 / 360);
}
if (fChanged & PLAYER_ANGLES_Y) {
WriteShort(MSG_ENTITY, angles[0] * 32767 / 360);
WriteShort(MSG_ENTITY, angles[1] * 32767 / 360);
WriteShort(MSG_ENTITY, v_angle[1] * 32767 / 360);
WriteShort(MSG_ENTITY, angles[2] * 32767 / 360);
}
if (fChanged & PLAYER_COLORMAP)
WriteByte(MSG_ENTITY, colormap);