Client: Allow mods to override entity updates of gs-entbase.
prop_vehicle_drivable: Initial work towards suspension.
This commit is contained in:
parent
22ab20a7b4
commit
47a37af545
8 changed files with 707 additions and 585 deletions
|
@ -21,27 +21,27 @@ entity g_bodies;
|
|||
void
|
||||
FX_Corpse_Init(void)
|
||||
{
|
||||
entity next = spawn(NSRenderableEntity);
|
||||
g_bodies = next;
|
||||
entity next = spawn(NSRenderableEntity);
|
||||
g_bodies = next;
|
||||
|
||||
for ( int i = 0; i <= CORPSES_MAX; i++ ) {
|
||||
next.classname = "corpse";
|
||||
next.owner = spawn(NSRenderableEntity);
|
||||
|
||||
if ( i == CORPSES_MAX ) {
|
||||
next.owner = g_bodies;
|
||||
} else {
|
||||
next = next.owner;
|
||||
}
|
||||
}
|
||||
for ( int i = 0; i <= CORPSES_MAX; i++ ) {
|
||||
next.classname = "corpse";
|
||||
next.owner = spawn(NSRenderableEntity);
|
||||
|
||||
if ( i == CORPSES_MAX ) {
|
||||
next.owner = g_bodies;
|
||||
} else {
|
||||
next = next.owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entity
|
||||
FX_Corpse_Next(void)
|
||||
{
|
||||
entity r = g_bodies;
|
||||
g_bodies = g_bodies.owner;
|
||||
return r;
|
||||
entity r = g_bodies;
|
||||
g_bodies = g_bodies.owner;
|
||||
return r;
|
||||
}
|
||||
|
||||
entity
|
||||
|
|
|
@ -1,107 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Begin calculating a route.
|
||||
* The callback function will be called once the route has finished being calculated.
|
||||
* The route must be memfreed once it is no longer needed.
|
||||
* The route must be followed in reverse order (ie: the first node that must be reached
|
||||
* is at index numnodes-1). If no route is available then the callback will be called with no nodes.
|
||||
*/
|
||||
int
|
||||
Route_RoundDistance(float flDist)
|
||||
{
|
||||
float r = fabs(flDist) % 2;
|
||||
|
||||
if (r == 0)
|
||||
return (flDist);
|
||||
|
||||
if (flDist < 0)
|
||||
return -(fabs(flDist) - r);
|
||||
else
|
||||
return (flDist + 2 - r);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Spawn_SelectRandom
|
||||
================
|
||||
*/
|
||||
entity
|
||||
Route_SelectRandom(string sEntname)
|
||||
{
|
||||
static entity eLastSpot;
|
||||
eLastSpot = find(eLastSpot, classname, sEntname);
|
||||
return (eLastSpot);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Route_SelectRandomSpot
|
||||
================
|
||||
*/
|
||||
entity
|
||||
Route_SelectRandomSpot(void)
|
||||
{
|
||||
static entity eLastSpot;
|
||||
eLastSpot = findfloat(eLastSpot, ::botinfo, BOTINFO_SPAWNPOINT);
|
||||
return (eLastSpot);
|
||||
}
|
||||
|
||||
void
|
||||
Bot_RouteCB(entity ent, vector dest, int numnodes, nodeslist_t *nodelist)
|
||||
{
|
||||
bot b = (bot)ent;
|
||||
b.m_iNodes = numnodes;
|
||||
b.m_iCurNode = numnodes - 1;
|
||||
b.m_pRoute = nodelist;
|
||||
b.m_vecLastNode = dest;
|
||||
|
||||
//dprint("Bot: Route calculated.\n");
|
||||
//dprint(sprintf("Bot: # of nodes: %i\n", bot.m_iNodes) );
|
||||
//dprint(sprintf("Bot: # current node: %i\n", bot.m_iCurNode) );
|
||||
//dprint(sprintf("Bot: # endpos: %v\n", dest));
|
||||
}
|
||||
|
||||
vector
|
||||
Route_SelectDestination(bot target)
|
||||
{
|
||||
entity dest = world;
|
||||
|
||||
if (target.health < 50) {
|
||||
entity temp;
|
||||
int bestrange = COST_INFINITE;
|
||||
int range;
|
||||
|
||||
for (temp = world; (temp = findfloat(temp, ::botinfo, BOTINFO_HEALTH));) {
|
||||
range = vlen(temp.origin - target.origin);
|
||||
if ((range < bestrange) && (temp.solid == SOLID_TRIGGER)) {
|
||||
bestrange = range;
|
||||
dest = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (dest) {
|
||||
//dprint("Route: Going for health!");
|
||||
return (dest.origin + [0,0,32]);
|
||||
}
|
||||
}
|
||||
|
||||
dest = Route_SelectRandomSpot();
|
||||
target.m_eDestination = dest;
|
||||
return (dest.origin);
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Begin calculating a route.
|
||||
* The callback function will be called once the route has finished being calculated.
|
||||
* The route must be memfreed once it is no longer needed.
|
||||
* The route must be followed in reverse order (ie: the first node that must be reached
|
||||
* is at index numnodes-1). If no route is available then the callback will be called with no nodes.
|
||||
*/
|
||||
int
|
||||
Route_RoundDistance(float flDist)
|
||||
{
|
||||
float r = fabs(flDist) % 2;
|
||||
|
||||
if (r == 0)
|
||||
return (flDist);
|
||||
|
||||
if (flDist < 0)
|
||||
return -(fabs(flDist) - r);
|
||||
else
|
||||
return (flDist + 2 - r);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Spawn_SelectRandom
|
||||
================
|
||||
*/
|
||||
entity
|
||||
Route_SelectRandom(string sEntname)
|
||||
{
|
||||
static entity eLastSpot;
|
||||
eLastSpot = find(eLastSpot, classname, sEntname);
|
||||
return (eLastSpot);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Route_SelectRandomSpot
|
||||
================
|
||||
*/
|
||||
entity
|
||||
Route_SelectRandomSpot(void)
|
||||
{
|
||||
static entity eLastSpot;
|
||||
eLastSpot = findfloat(eLastSpot, ::botinfo, BOTINFO_SPAWNPOINT);
|
||||
return (eLastSpot);
|
||||
}
|
||||
|
||||
void
|
||||
Bot_RouteCB(entity ent, vector dest, int numnodes, nodeslist_t *nodelist)
|
||||
{
|
||||
bot b = (bot)ent;
|
||||
b.m_iNodes = numnodes;
|
||||
b.m_iCurNode = numnodes - 1;
|
||||
b.m_pRoute = nodelist;
|
||||
b.m_vecLastNode = dest;
|
||||
|
||||
//dprint("Bot: Route calculated.\n");
|
||||
//dprint(sprintf("Bot: # of nodes: %i\n", bot.m_iNodes) );
|
||||
//dprint(sprintf("Bot: # current node: %i\n", bot.m_iCurNode) );
|
||||
//dprint(sprintf("Bot: # endpos: %v\n", dest));
|
||||
}
|
||||
|
||||
vector
|
||||
Route_SelectDestination(bot target)
|
||||
{
|
||||
entity dest = world;
|
||||
|
||||
if (target.health < 50) {
|
||||
entity temp;
|
||||
int bestrange = COST_INFINITE;
|
||||
int range;
|
||||
|
||||
for (temp = world; (temp = findfloat(temp, ::botinfo, BOTINFO_HEALTH));) {
|
||||
range = vlen(temp.origin - target.origin);
|
||||
if ((range < bestrange) && (temp.solid == SOLID_TRIGGER)) {
|
||||
bestrange = range;
|
||||
dest = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (dest) {
|
||||
//dprint("Route: Going for health!");
|
||||
return (dest.origin + [0,0,32]);
|
||||
}
|
||||
}
|
||||
|
||||
dest = Route_SelectRandomSpot();
|
||||
target.m_eDestination = dest;
|
||||
return (dest.origin);
|
||||
}
|
||||
|
|
|
@ -200,4 +200,8 @@ struct
|
|||
float m_flShakeAmp;
|
||||
|
||||
vector m_vecLag;
|
||||
|
||||
/* vehicles */
|
||||
float m_flVehTransition;
|
||||
vector m_vecVehEntry;
|
||||
} g_seats[4], *pSeat;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,105 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED env_particle (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
Client-side particle effect. Active at runtime, fully client-side.
|
||||
Cannot be triggered. Repeats automatically.
|
||||
|
||||
-------- KEYS --------
|
||||
"message" : Particle material to use.
|
||||
"wait" : Delay between emits.
|
||||
"target" : Name of target, like an info_notnull (client-side)
|
||||
"velocity" : Speed in units.
|
||||
"count" : Number of particles to emit.
|
||||
|
||||
-------- TRIVIA --------
|
||||
This entity was introduced in The Wastes (2018).
|
||||
*/
|
||||
|
||||
class env_particle:NSEntity
|
||||
{
|
||||
entity m_eTarget;
|
||||
float m_flNextTime;
|
||||
float m_flPartID;
|
||||
float m_flVelocity;
|
||||
float m_flWait;
|
||||
int m_iCount;
|
||||
string m_strTarget;
|
||||
|
||||
void(void) env_particle;
|
||||
virtual void(void) customphysics;
|
||||
virtual void(string, string) SpawnKey;
|
||||
};
|
||||
|
||||
void env_particle::customphysics(void)
|
||||
{
|
||||
vector vecPlayer;
|
||||
|
||||
int s = (float)getproperty(VF_ACTIVESEAT);
|
||||
pSeat = &g_seats[s];
|
||||
vecPlayer = pSeat->m_vecPredictedOrigin;
|
||||
|
||||
if (checkpvs(vecPlayer, this) == FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_flVelocity) {
|
||||
m_flVelocity = 1.0f;
|
||||
}
|
||||
|
||||
if (m_flNextTime > time) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_strTarget) {
|
||||
m_eTarget = find(world, ::targetname, m_strTarget);
|
||||
makevectors(vectoangles(m_eTarget.origin - origin) * -1);
|
||||
angles = v_forward;
|
||||
}
|
||||
pointparticles(m_flPartID, origin, angles * m_flVelocity, m_iCount);
|
||||
m_flNextTime = time + m_flWait;
|
||||
}
|
||||
|
||||
void env_particle::SpawnKey(string strField, string strKey)
|
||||
{
|
||||
switch (strField) {
|
||||
case "message":
|
||||
m_flPartID = particleeffectnum(strKey);
|
||||
break;
|
||||
case "wait":
|
||||
m_flWait = stof(strKey);
|
||||
break;
|
||||
case "target":
|
||||
m_strTarget = strKey;
|
||||
break;
|
||||
case "velocity":
|
||||
m_flVelocity = stof(strKey);
|
||||
break;
|
||||
case "count":
|
||||
m_iCount = stoi(strKey);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strField, strKey);
|
||||
}
|
||||
}
|
||||
|
||||
void env_particle::env_particle(void)
|
||||
{
|
||||
drawmask = MASK_ENGINE;
|
||||
Init();
|
||||
setorigin(this, origin);
|
||||
setsize(this, [0,0,0], [0,0,0]);
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED env_particle (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
Client-side particle effect. Active at runtime, fully client-side.
|
||||
Cannot be triggered. Repeats automatically.
|
||||
|
||||
-------- KEYS --------
|
||||
"message" : Particle material to use.
|
||||
"wait" : Delay between emits.
|
||||
"target" : Name of target, like an info_notnull (client-side)
|
||||
"velocity" : Speed in units.
|
||||
"count" : Number of particles to emit.
|
||||
|
||||
-------- TRIVIA --------
|
||||
This entity was introduced in The Wastes (2018).
|
||||
*/
|
||||
|
||||
class env_particle:NSEntity
|
||||
{
|
||||
entity m_eTarget;
|
||||
float m_flNextTime;
|
||||
float m_flPartID;
|
||||
float m_flVelocity;
|
||||
float m_flWait;
|
||||
int m_iCount;
|
||||
string m_strTarget;
|
||||
|
||||
void(void) env_particle;
|
||||
virtual void(void) customphysics;
|
||||
virtual void(string, string) SpawnKey;
|
||||
};
|
||||
|
||||
void env_particle::customphysics(void)
|
||||
{
|
||||
vector vecPlayer;
|
||||
|
||||
int s = (float)getproperty(VF_ACTIVESEAT);
|
||||
pSeat = &g_seats[s];
|
||||
vecPlayer = pSeat->m_vecPredictedOrigin;
|
||||
|
||||
if (checkpvs(vecPlayer, this) == FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_flVelocity) {
|
||||
m_flVelocity = 1.0f;
|
||||
}
|
||||
|
||||
if (m_flNextTime > time) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_strTarget) {
|
||||
m_eTarget = find(world, ::targetname, m_strTarget);
|
||||
makevectors(vectoangles(m_eTarget.origin - origin) * -1);
|
||||
angles = v_forward;
|
||||
}
|
||||
pointparticles(m_flPartID, origin, angles * m_flVelocity, m_iCount);
|
||||
m_flNextTime = time + m_flWait;
|
||||
}
|
||||
|
||||
void env_particle::SpawnKey(string strField, string strKey)
|
||||
{
|
||||
switch (strField) {
|
||||
case "message":
|
||||
m_flPartID = particleeffectnum(strKey);
|
||||
break;
|
||||
case "wait":
|
||||
m_flWait = stof(strKey);
|
||||
break;
|
||||
case "target":
|
||||
m_strTarget = strKey;
|
||||
break;
|
||||
case "velocity":
|
||||
m_flVelocity = stof(strKey);
|
||||
break;
|
||||
case "count":
|
||||
m_iCount = stoi(strKey);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strField, strKey);
|
||||
}
|
||||
}
|
||||
|
||||
void env_particle::env_particle(void)
|
||||
{
|
||||
drawmask = MASK_ENGINE;
|
||||
Init();
|
||||
setorigin(this, origin);
|
||||
setsize(this, [0,0,0], [0,0,0]);
|
||||
}
|
||||
|
|
|
@ -1,330 +1,330 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define ODE_MODE 1
|
||||
|
||||
.float geomtype;
|
||||
.float friction;
|
||||
.float erp;
|
||||
.float jointtype;
|
||||
.float mass;
|
||||
.float bouncefactor;
|
||||
.float bouncestop;
|
||||
|
||||
void
|
||||
NSPhysicsEntity::PhysicsEnable(void)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
SetMovetype(MOVETYPE_PHYSICS);
|
||||
SetSolid(SOLID_PHYSICS_BOX + m_iShape);
|
||||
physics_enable(this, TRUE);
|
||||
} else {
|
||||
SetMovetype(MOVETYPE_BOUNCE);
|
||||
SetSolid(SOLID_CORPSE);
|
||||
}
|
||||
m_iEnabled = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::PhysicsDisable(void)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
physics_enable(this, FALSE);
|
||||
SetMovetype(MOVETYPE_NONE);
|
||||
} else {
|
||||
SetMovetype(MOVETYPE_BOUNCE);
|
||||
SetSolid(SOLID_CORPSE);
|
||||
}
|
||||
m_iEnabled = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetMass(float val)
|
||||
{
|
||||
mass = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetMass(void)
|
||||
{
|
||||
return mass;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetFriction(float val)
|
||||
{
|
||||
friction = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetFriction(void)
|
||||
{
|
||||
return friction;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetBounceFactor(float val)
|
||||
{
|
||||
bouncefactor = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetBounceFactor(void)
|
||||
{
|
||||
return bouncefactor;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetBounceStop(float val)
|
||||
{
|
||||
bouncestop = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetBounceStop(void)
|
||||
{
|
||||
return bouncestop;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetInertia(float val)
|
||||
{
|
||||
m_flInertiaScale = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetInertia(void)
|
||||
{
|
||||
return m_flInertiaScale;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::CalculateImpactDamage(int iDamage, int dmgType)
|
||||
{
|
||||
int filter = 0i;
|
||||
|
||||
/* if we're any of these dmg types, we don't transfer any kinetic energy */
|
||||
filter |= (dmgType & DMG_BURN);
|
||||
filter |= (dmgType & DMG_ELECTRO);
|
||||
filter |= (dmgType & DMG_SOUND);
|
||||
filter |= (dmgType & DMG_ENERGYBEAM);
|
||||
filter |= (dmgType & DMG_DROWN);
|
||||
filter |= (dmgType & DMG_POISON);
|
||||
filter |= (dmgType & DMG_RADIATION);
|
||||
filter |= (dmgType & DMG_ACID);
|
||||
filter |= (dmgType & DMG_ACID);
|
||||
filter |= (dmgType & DMG_SLOWFREEZE);
|
||||
|
||||
if (filter == 0i)
|
||||
return (float)iDamage * 100;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyForceCenter(vector vecForce)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
physics_addforce(this, vecForce, [0,0,0]);
|
||||
} else {
|
||||
velocity = vecForce;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyForceOffset(vector vecForce, vector vecOffset)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
physics_addforce(this, vecForce, vecOffset);
|
||||
} else {
|
||||
velocity = vecForce;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyTorqueCenter(vector vecTorque)
|
||||
{
|
||||
if (physics_supported() == TRUE)
|
||||
physics_addtorque(this, vecTorque * m_flInertiaScale);
|
||||
else {
|
||||
avelocity = vecTorque;
|
||||
velocity = vecTorque;
|
||||
velocity[2] = 96;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::TouchThink(void)
|
||||
{
|
||||
#if 0
|
||||
/* let players collide */
|
||||
dimension_solid = 255;
|
||||
dimension_hit = 255;
|
||||
|
||||
tracebox(origin, mins, maxs, origin, FALSE, this);
|
||||
|
||||
/* stuck */
|
||||
if (trace_startsolid) {
|
||||
if (trace_ent.flags & FL_CLIENT) {
|
||||
PhysicsEnable();
|
||||
makevectors(vectoangles(origin - trace_ent.origin));
|
||||
ApplyTorqueCenter(v_forward * 240);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* If we barely move, disable the physics simulator */
|
||||
if (vlen(velocity) <= 1) {
|
||||
if (m_iEnabled) {
|
||||
PhysicsDisable();
|
||||
velocity = [0,0,0];
|
||||
avelocity = [0,0,0];
|
||||
}
|
||||
|
||||
if (physics_supported() == FALSE) {
|
||||
vector wantangle;
|
||||
vector newangle;
|
||||
wantangle[0] = (int)((angles[0] + 45) / 90) * 90;
|
||||
wantangle[1] = angles[1];
|
||||
wantangle[2] = (int)((angles[2] + 45) / 90) * 90;
|
||||
|
||||
makevectors(angles);
|
||||
angles = v_forward;
|
||||
makevectors(wantangle);
|
||||
newangle[0] = Math_Lerp(angles[0], v_forward[0], frametime * 5.0f);
|
||||
newangle[1] = Math_Lerp(angles[1], v_forward[1], frametime * 5.0f);
|
||||
newangle[2] = Math_Lerp(angles[2], v_forward[2], frametime * 5.0f);
|
||||
angles = vectoangles(newangle);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* don't let players collide */
|
||||
dimension_solid = 1;
|
||||
dimension_hit = 1;
|
||||
#endif
|
||||
|
||||
/* continue testing next frame */
|
||||
nextthink = time;
|
||||
effects &= ~EF_NOSHADOW;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::touch(void)
|
||||
{
|
||||
PhysicsEnable();
|
||||
makevectors(vectoangles(origin - other.origin));
|
||||
ApplyForceOffset(v_forward * 100, origin - other.origin);
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::Pain(void)
|
||||
{
|
||||
float force;
|
||||
|
||||
if (m_iFlags & BPHY_NODMGPUSH)
|
||||
return;
|
||||
|
||||
PhysicsEnable();
|
||||
|
||||
makevectors(vectoangles(origin - trace_endpos));
|
||||
force = CalculateImpactDamage(g_dmg_iDamage, g_dmg_iFlags);
|
||||
|
||||
if (force > 0.0f)
|
||||
ApplyForceOffset(v_forward * force, origin - trace_endpos);
|
||||
|
||||
if (!HasPropData()) {
|
||||
health = 100000;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::Respawn(void)
|
||||
{
|
||||
SetMovetype(MOVETYPE_PHYSICS);
|
||||
SetSolid(SOLID_PHYSICS_BOX + m_iShape);
|
||||
SetModel(GetSpawnModel());
|
||||
geomtype = GEOMTYPE_TRIMESH;
|
||||
takedamage = DAMAGE_YES;
|
||||
|
||||
#ifndef ODE_MODE
|
||||
PhysicsDisable();
|
||||
SetFriction(2.0f);
|
||||
SetBounceFactor(0.25f);
|
||||
#else
|
||||
PhysicsDisable();
|
||||
SetMass(1.0f);
|
||||
SetFriction(1.0f);
|
||||
SetBounceFactor(0.1f);
|
||||
#endif
|
||||
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
|
||||
/* don't let players collide */
|
||||
//dimension_solid = 1;
|
||||
//dimension_hit = 1;
|
||||
|
||||
think = TouchThink;
|
||||
nextthink = time + 0.1f;
|
||||
|
||||
effects &= ~EF_NOSHADOW;
|
||||
|
||||
if (HasPropData()) {
|
||||
health = GetPropData(PROPINFO_HEALTH);
|
||||
} else {
|
||||
health = 100000;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "physmodel":
|
||||
m_iShape = stoi(strValue);
|
||||
if (m_iShape > PHYSM_CYLINDER)
|
||||
m_iShape = 0;
|
||||
break;
|
||||
case "massscale":
|
||||
mass = stof(strValue);
|
||||
break;
|
||||
case "inertiascale":
|
||||
m_flInertiaScale = stof(strValue);
|
||||
break;
|
||||
case "physdamagescale":
|
||||
break;
|
||||
case "material":
|
||||
m_iMaterial = stof(strValue);
|
||||
break;
|
||||
case "nodamageforces":
|
||||
if (strValue == "1")
|
||||
m_iFlags |= BPHY_NODMGPUSH;
|
||||
break;
|
||||
case "Damagetype":
|
||||
if (strValue == "1")
|
||||
m_iFlags |= BPHY_SHARP;
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::NSPhysicsEntity(void)
|
||||
{
|
||||
mass = 1.0f;
|
||||
m_flInertiaScale = 1.0f;
|
||||
super::NSSurfacePropEntity();
|
||||
|
||||
cvar_set("physics_ode_iterationsperframe", "1");
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define ODE_MODE 1
|
||||
|
||||
.float geomtype;
|
||||
.float friction;
|
||||
.float erp;
|
||||
.float jointtype;
|
||||
.float mass;
|
||||
.float bouncefactor;
|
||||
.float bouncestop;
|
||||
|
||||
void
|
||||
NSPhysicsEntity::PhysicsEnable(void)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
SetMovetype(MOVETYPE_PHYSICS);
|
||||
SetSolid(SOLID_PHYSICS_BOX + m_iShape);
|
||||
physics_enable(this, TRUE);
|
||||
} else {
|
||||
SetMovetype(MOVETYPE_BOUNCE);
|
||||
SetSolid(SOLID_CORPSE);
|
||||
}
|
||||
m_iEnabled = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::PhysicsDisable(void)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
physics_enable(this, FALSE);
|
||||
SetMovetype(MOVETYPE_NONE);
|
||||
} else {
|
||||
SetMovetype(MOVETYPE_BOUNCE);
|
||||
SetSolid(SOLID_CORPSE);
|
||||
}
|
||||
m_iEnabled = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetMass(float val)
|
||||
{
|
||||
mass = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetMass(void)
|
||||
{
|
||||
return mass;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetFriction(float val)
|
||||
{
|
||||
friction = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetFriction(void)
|
||||
{
|
||||
return friction;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetBounceFactor(float val)
|
||||
{
|
||||
bouncefactor = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetBounceFactor(void)
|
||||
{
|
||||
return bouncefactor;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetBounceStop(float val)
|
||||
{
|
||||
bouncestop = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetBounceStop(void)
|
||||
{
|
||||
return bouncestop;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetInertia(float val)
|
||||
{
|
||||
m_flInertiaScale = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetInertia(void)
|
||||
{
|
||||
return m_flInertiaScale;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::CalculateImpactDamage(int iDamage, int dmgType)
|
||||
{
|
||||
int filter = 0i;
|
||||
|
||||
/* if we're any of these dmg types, we don't transfer any kinetic energy */
|
||||
filter |= (dmgType & DMG_BURN);
|
||||
filter |= (dmgType & DMG_ELECTRO);
|
||||
filter |= (dmgType & DMG_SOUND);
|
||||
filter |= (dmgType & DMG_ENERGYBEAM);
|
||||
filter |= (dmgType & DMG_DROWN);
|
||||
filter |= (dmgType & DMG_POISON);
|
||||
filter |= (dmgType & DMG_RADIATION);
|
||||
filter |= (dmgType & DMG_ACID);
|
||||
filter |= (dmgType & DMG_ACID);
|
||||
filter |= (dmgType & DMG_SLOWFREEZE);
|
||||
|
||||
if (filter == 0i)
|
||||
return (float)iDamage * 100;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyForceCenter(vector vecForce)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
physics_addforce(this, vecForce, [0,0,0]);
|
||||
} else {
|
||||
velocity = vecForce;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyForceOffset(vector vecForce, vector vecOffset)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
physics_addforce(this, vecForce, vecOffset);
|
||||
} else {
|
||||
velocity = vecForce;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyTorqueCenter(vector vecTorque)
|
||||
{
|
||||
if (physics_supported() == TRUE)
|
||||
physics_addtorque(this, vecTorque * m_flInertiaScale);
|
||||
else {
|
||||
avelocity = vecTorque;
|
||||
velocity = vecTorque;
|
||||
velocity[2] = 96;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::TouchThink(void)
|
||||
{
|
||||
#if 0
|
||||
/* let players collide */
|
||||
dimension_solid = 255;
|
||||
dimension_hit = 255;
|
||||
|
||||
tracebox(origin, mins, maxs, origin, FALSE, this);
|
||||
|
||||
/* stuck */
|
||||
if (trace_startsolid) {
|
||||
if (trace_ent.flags & FL_CLIENT) {
|
||||
PhysicsEnable();
|
||||
makevectors(vectoangles(origin - trace_ent.origin));
|
||||
ApplyTorqueCenter(v_forward * 240);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* If we barely move, disable the physics simulator */
|
||||
if (vlen(velocity) <= 1) {
|
||||
if (m_iEnabled) {
|
||||
PhysicsDisable();
|
||||
velocity = [0,0,0];
|
||||
avelocity = [0,0,0];
|
||||
}
|
||||
|
||||
if (physics_supported() == FALSE) {
|
||||
vector wantangle;
|
||||
vector newangle;
|
||||
wantangle[0] = (int)((angles[0] + 45) / 90) * 90;
|
||||
wantangle[1] = angles[1];
|
||||
wantangle[2] = (int)((angles[2] + 45) / 90) * 90;
|
||||
|
||||
makevectors(angles);
|
||||
angles = v_forward;
|
||||
makevectors(wantangle);
|
||||
newangle[0] = Math_Lerp(angles[0], v_forward[0], frametime * 5.0f);
|
||||
newangle[1] = Math_Lerp(angles[1], v_forward[1], frametime * 5.0f);
|
||||
newangle[2] = Math_Lerp(angles[2], v_forward[2], frametime * 5.0f);
|
||||
angles = vectoangles(newangle);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* don't let players collide */
|
||||
dimension_solid = 1;
|
||||
dimension_hit = 1;
|
||||
#endif
|
||||
|
||||
/* continue testing next frame */
|
||||
nextthink = time;
|
||||
effects &= ~EF_NOSHADOW;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::touch(void)
|
||||
{
|
||||
PhysicsEnable();
|
||||
makevectors(vectoangles(origin - other.origin));
|
||||
ApplyForceOffset(v_forward * 100, origin - other.origin);
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::Pain(void)
|
||||
{
|
||||
float force;
|
||||
|
||||
if (m_iFlags & BPHY_NODMGPUSH)
|
||||
return;
|
||||
|
||||
PhysicsEnable();
|
||||
|
||||
makevectors(vectoangles(origin - trace_endpos));
|
||||
force = CalculateImpactDamage(g_dmg_iDamage, g_dmg_iFlags);
|
||||
|
||||
if (force > 0.0f)
|
||||
ApplyForceOffset(v_forward * force, origin - trace_endpos);
|
||||
|
||||
if (!HasPropData()) {
|
||||
health = 100000;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::Respawn(void)
|
||||
{
|
||||
SetMovetype(MOVETYPE_PHYSICS);
|
||||
SetSolid(SOLID_PHYSICS_BOX + m_iShape);
|
||||
SetModel(GetSpawnModel());
|
||||
geomtype = GEOMTYPE_TRIMESH;
|
||||
takedamage = DAMAGE_YES;
|
||||
|
||||
#ifndef ODE_MODE
|
||||
PhysicsDisable();
|
||||
SetFriction(2.0f);
|
||||
SetBounceFactor(0.25f);
|
||||
#else
|
||||
PhysicsDisable();
|
||||
SetMass(1.0f);
|
||||
SetFriction(1.0f);
|
||||
SetBounceFactor(0.1f);
|
||||
#endif
|
||||
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
|
||||
/* don't let players collide */
|
||||
//dimension_solid = 1;
|
||||
//dimension_hit = 1;
|
||||
|
||||
think = TouchThink;
|
||||
nextthink = time + 0.1f;
|
||||
|
||||
effects &= ~EF_NOSHADOW;
|
||||
|
||||
if (HasPropData()) {
|
||||
health = GetPropData(PROPINFO_HEALTH);
|
||||
} else {
|
||||
health = 100000;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "physmodel":
|
||||
m_iShape = stoi(strValue);
|
||||
if (m_iShape > PHYSM_CYLINDER)
|
||||
m_iShape = 0;
|
||||
break;
|
||||
case "massscale":
|
||||
mass = stof(strValue);
|
||||
break;
|
||||
case "inertiascale":
|
||||
m_flInertiaScale = stof(strValue);
|
||||
break;
|
||||
case "physdamagescale":
|
||||
break;
|
||||
case "material":
|
||||
m_iMaterial = stof(strValue);
|
||||
break;
|
||||
case "nodamageforces":
|
||||
if (strValue == "1")
|
||||
m_iFlags |= BPHY_NODMGPUSH;
|
||||
break;
|
||||
case "Damagetype":
|
||||
if (strValue == "1")
|
||||
m_iFlags |= BPHY_SHARP;
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::NSPhysicsEntity(void)
|
||||
{
|
||||
mass = 1.0f;
|
||||
m_flInertiaScale = 1.0f;
|
||||
super::NSSurfacePropEntity();
|
||||
|
||||
cvar_set("physics_ode_iterationsperframe", "1");
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ class NSEntity:NSTrigger
|
|||
vector net_origin;
|
||||
vector net_angles;
|
||||
vector net_velocity;
|
||||
float net_modelindex;
|
||||
|
||||
string m_parent;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue