Client: Allow mods to override entity updates of gs-entbase.

prop_vehicle_drivable: Initial work towards suspension.
This commit is contained in:
Marco Cawthorne 2022-02-11 17:09:08 -08:00
parent 22ab20a7b4
commit 47a37af545
Signed by: eukara
GPG key ID: C196CD8BA993248A
8 changed files with 707 additions and 585 deletions

View file

@ -200,4 +200,8 @@ struct
float m_flShakeAmp;
vector m_vecLag;
/* vehicles */
float m_flVehTransition;
vector m_vecVehEntry;
} g_seats[4], *pSeat;

View file

@ -45,6 +45,7 @@ CSQC_Init(float apilevel, string enginename, float engineversion)
registercommand("player_geomtest");
registercommand("way_menu");
registercommand("dev_explode");
registercommand("dev_modeltest");
/* basic actions */
registercommand("+attack");
@ -660,6 +661,15 @@ CSQC_ConsoleCommand(string sCMD)
traceline(getproperty(VF_ORIGIN), getproperty(VF_ORIGIN) + v_forward * 4096, FALSE, pSeat->m_ePlayer);
dynamiclight_spawnstatic(trace_endpos + (v_forward * -16), 1024, [1,1,1]);
break;
case "dev_modeltest":
entity mt = spawn();
mt.drawmask = MASK_ENGINE;
setmodel(mt, argv(1));
setsize(mt, [0,0,0], [0,0,0]);
setorigin(mt, getproperty(VF_ORIGIN));
mt.angles = getproperty(VF_ANGLES);
mt.angles[0] = mt.angles[2] = 0;
break;
case "dev_explode":
makevectors(getproperty(VF_ANGLES));
traceline(getproperty(VF_ORIGIN), getproperty(VF_ORIGIN) + v_forward * 4096, FALSE, pSeat->m_ePlayer);
@ -880,6 +890,11 @@ CSQC_Ent_Update(float new)
float t;
t = readbyte();
/* client didn't override anything */
if (ClientGame_EntityUpdate(t, new)) {
return;
}
switch (t) {
case ENT_ENTITY:
NSEntity me = (NSEntity)self;
@ -985,9 +1000,7 @@ CSQC_Ent_Update(float new)
ips.ReceiveEntity(new, readfloat());
break;
default:
if (ClientGame_EntityUpdate(t, new) == FALSE) {
//error(sprintf("Unknown entity type update received. (%d)\n", t));
}
}
}

View file

@ -51,6 +51,7 @@ class NSEntity:NSTrigger
vector net_origin;
vector net_angles;
vector net_velocity;
float net_modelindex;
string m_parent;

View file

@ -30,12 +30,24 @@ Point entity defining a 4-wheel vehicle that you can drive.
This entity was introduced in Half-Life 2 (2004).
*/
enumflags
{
VEHFL_DRIVER,
VEHFL_MODELINDEX,
VEHFL_ORIGIN,
VEHFL_ANGLES,
VEHFL_VELOCITY,
VEHFL_TURNING
};
class prop_vehicle_driveable_wheel
{
void() prop_vehicle_driveable_wheel;
float m_flSuspension;
float m_flSuspensionForce;
#ifdef CLIENT
vector origin_net;
vector velocity_net;
vector angles_net;
@ -43,6 +55,7 @@ class prop_vehicle_driveable_wheel
virtual void(void) PredictPostFrame;
#endif
virtual void(float) UpdateSuspension;
virtual void(float) Move;
virtual void(vector) Bounce;
virtual void(float, float m_flTurn) Accel;
@ -87,6 +100,7 @@ class prop_vehicle_driveable:NSVehicle
#else
virtual void(void) Respawn;
virtual void(void) OnPlayerUse;
virtual void(void) EvaluateEntity;
virtual float(entity, float) SendEntity;
#endif
};
@ -301,6 +315,26 @@ prop_vehicle_driveable_wheel::Accel(float flMoveTime, float m_flTurn)
velocity += vehParent.m_vecGravityDir * flMoveTime * serverkeyfloat("phy_gravity") * trace_fraction;
}
void
prop_vehicle_driveable_wheel::UpdateSuspension(float flTimeLength)
{
float flDamp;
float flForce;
if (fabs(m_flSuspension) > 0.001 || fabs(m_flSuspensionForce) > 0.001) {
m_flSuspension += m_flSuspensionForce * flTimeLength;
flForce = bound(0, flTimeLength * 65, 2);
flDamp = 1 - (flTimeLength * 4);
if (flDamp < 0) {
flDamp = 0;
}
m_flSuspensionForce *= flDamp;
m_flSuspensionForce -= m_flSuspension * flForce;
m_flSuspension = bound(-15, m_flSuspension, 15);
}
}
void
prop_vehicle_driveable_wheel::Physics(float turnrate, float flTimeLength)
{
@ -311,9 +345,23 @@ prop_vehicle_driveable_wheel::Physics(float turnrate, float flTimeLength)
tracebox(owner_pos, mins, maxs, origin, MOVE_NOMONSTERS, owner);
setorigin(this, trace_endpos);
/* see if we're in-air */
other = world;
tracebox(origin, mins, maxs, origin - [0,0,1], MOVE_OTHERONLY, this);
if (!trace_startsolid) {
if ((trace_fraction < 1) && (trace_plane_normal[2] > 0.7)) {
flags |= FL_ONGROUND;
} else {
flags &= ~FL_ONGROUND;
m_flSuspensionForce += flTimeLength * 200.0;
}
}
Accel(flTimeLength / 2, turnrate);
Move(flTimeLength);
Accel(flTimeLength / 2, turnrate);
UpdateSuspension(flTimeLength);
print(sprintf("suspension: %d, force: %d\n", m_flSuspension, m_flSuspensionForce));
}
void
@ -405,8 +453,6 @@ prop_vehicle_driveable::RunVehiclePhysics(void)
angles[0] = Math_FixDelta(angles[0]);
angles[1] = Math_FixDelta(angles[1]);
angles[2] = Math_FixDelta(angles[2]);
angles[0] = bound(-45, angles[0], 45);
angles[2] = bound(-45, angles[2], 45);
velocity[0] = bound(-1000, velocity[0], 1000);
velocity[1] = bound(-1000, velocity[1], 1000);
@ -504,23 +550,34 @@ prop_vehicle_driveable::Respawn(void)
void
prop_vehicle_driveable::ReadEntity(float flSendFlags, float flNew)
{
m_eDriver = findfloat(world, ::entnum, readentitynum());
if (flSendFlags & VEHFL_DRIVER) {
m_eDriver = findfloat(world, ::entnum, readentitynum());
}
modelindex = readshort();
if (flSendFlags & VEHFL_MODELINDEX) {
modelindex = readshort();
}
origin[0] = readcoord();
origin[1] = readcoord();
origin[2] = readcoord();
if (flSendFlags & VEHFL_ORIGIN) {
origin[0] = readcoord();
origin[1] = readcoord();
origin[2] = readcoord();
}
angles[0] = readfloat();
angles[1] = readfloat();
angles[2] = readfloat();
if (flSendFlags & VEHFL_ANGLES) {
angles[0] = readfloat();
angles[1] = readfloat();
angles[2] = readfloat();
}
velocity[0] = readfloat();
velocity[1] = readfloat();
velocity[2] = readfloat();
if (flSendFlags & VEHFL_VELOCITY) {
velocity[0] = readfloat();
velocity[1] = readfloat();
velocity[2] = readfloat();
}
m_flTurn = readfloat();
if (flSendFlags & VEHFL_TURNING)
m_flTurn = readfloat();
if (flNew) {
drawmask = MASK_ENGINE;
@ -532,29 +589,76 @@ prop_vehicle_driveable::ReadEntity(float flSendFlags, float flNew)
}
}
#else
void
prop_vehicle_driveable::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_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_ANGLES);
}
if (net_modelindex != modelindex) {
net_modelindex = modelindex;
SetSendFlags(VEHFL_MODELINDEX);
}
if (net_velocity != velocity) {
net_velocity = velocity;
SetSendFlags(VEHFL_VELOCITY);
}
if (m_flTurn_net != m_flTurn) {
m_flTurn_net = m_flTurn;
SetSendFlags(VEHFL_TURNING);
}
if (m_eDriver_net != m_eDriver) {
m_eDriver_net = m_eDriver;
SetSendFlags(VEHFL_DRIVER);
}
}
float
prop_vehicle_driveable::SendEntity(entity ePVSent, float flSendFlags)
{
WriteByte(MSG_ENTITY, ENT_VEH_4WHEEL);
WriteFloat(MSG_ENTITY, flSendFlags);
WriteEntity(MSG_ENTITY, m_eDriver);
if (flSendFlags & VEHFL_DRIVER) {
WriteEntity(MSG_ENTITY, m_eDriver);
}
WriteShort(MSG_ENTITY, modelindex);
if (flSendFlags & VEHFL_MODELINDEX) {
WriteShort(MSG_ENTITY, modelindex);
}
WriteCoord(MSG_ENTITY, origin[0]);
WriteCoord(MSG_ENTITY, origin[1]);
WriteCoord(MSG_ENTITY, origin[2]);
if (flSendFlags & VEHFL_ORIGIN) {
WriteCoord(MSG_ENTITY, origin[0]);
WriteCoord(MSG_ENTITY, origin[1]);
WriteCoord(MSG_ENTITY, origin[2]);
}
WriteFloat(MSG_ENTITY, angles[0]);
WriteFloat(MSG_ENTITY, angles[1]);
WriteFloat(MSG_ENTITY, angles[2]);
if (flSendFlags & VEHFL_ANGLES) {
WriteFloat(MSG_ENTITY, angles[0]);
WriteFloat(MSG_ENTITY, angles[1]);
WriteFloat(MSG_ENTITY, angles[2]);
}
WriteFloat(MSG_ENTITY, velocity[0]);
WriteFloat(MSG_ENTITY, velocity[1]);
WriteFloat(MSG_ENTITY, velocity[2]);
if (flSendFlags & VEHFL_VELOCITY) {
WriteFloat(MSG_ENTITY, velocity[0]);
WriteFloat(MSG_ENTITY, velocity[1]);
WriteFloat(MSG_ENTITY, velocity[2]);
}
if (flSendFlags & VEHFL_TURNING)
WriteFloat(MSG_ENTITY, m_flTurn);
WriteFloat(MSG_ENTITY, m_flTurn);
return TRUE;
}
#endif