Add the following physics entities from Source: phys_ballsocket, phys_constraint, phys_constraintsystem, phys_convert, phys_hinge, phys_keepupright, phys_slideconstraint & env_physexplosion
Add new class phys_rope, which will handle move_rope and keyframe_rope from Source.
This commit is contained in:
parent
81a498d49e
commit
11deea5b3d
36 changed files with 2618 additions and 240 deletions
|
@ -123,15 +123,17 @@ varying mat3 invsurface;
|
|||
|
||||
#if defined(BUMP) && r_skipEnvmap==0
|
||||
vec3 cube_c;
|
||||
#if r_showEnvCubemap == 0
|
||||
float refl = 1.0 - texture2D(s_normalmap, tex_c).a;
|
||||
#else
|
||||
float refl = 1.0;
|
||||
#endif
|
||||
cube_c = reflect(normalize(eyevector), normal_f.rgb);
|
||||
float refl = 1.0 - texture2D(s_normalmap, tex_c).a;
|
||||
|
||||
cube_c = reflect(normalize(eyevector), norm);
|
||||
cube_c = cube_c.x * invsurface[0] + cube_c.y * invsurface[1] + cube_c.z * invsurface[2];
|
||||
cube_c = (m_model * vec4(cube_c.xyz, 0.0)).xyz;
|
||||
|
||||
#if r_showEnvCubemap == 0
|
||||
diff_f.rgb += textureCube(s_reflectcube, cube_c).rgb * refl;
|
||||
#else
|
||||
diff_f.rgb = textureCube(s_reflectcube, cube_c).rgb;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(FULLBRIGHT) && r_skipFullbright==0
|
||||
|
|
|
@ -14,13 +14,6 @@
|
|||
* 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)
|
||||
{
|
||||
|
@ -37,7 +30,7 @@ Route_RoundDistance(float flDist)
|
|||
|
||||
|
||||
/* returns a botinfo point that's nearest to us */
|
||||
entity
|
||||
NSEntity
|
||||
Route_SelectFarthest(float type, vector org, optional vector lastpoi = [0,0,0])
|
||||
{
|
||||
entity temp;
|
||||
|
@ -61,7 +54,7 @@ Route_SelectFarthest(float type, vector org, optional vector lastpoi = [0,0,0])
|
|||
}
|
||||
|
||||
/* returns a botinfo point that's nearest to us */
|
||||
entity
|
||||
NSEntity
|
||||
Route_SelectNearest(float type, vector org, optional vector lastpoi = [0,0,0])
|
||||
{
|
||||
entity temp;
|
||||
|
@ -85,7 +78,7 @@ Route_SelectNearest(float type, vector org, optional vector lastpoi = [0,0,0])
|
|||
}
|
||||
|
||||
/* returns a botinfo point belonging to our team */
|
||||
entity
|
||||
NSEntity
|
||||
Route_SelectNearestTeam(float type, vector org, float tt)
|
||||
{
|
||||
entity temp;
|
||||
|
@ -110,7 +103,7 @@ Route_SelectNearestTeam(float type, vector org, float tt)
|
|||
}
|
||||
|
||||
/* returns a botinfo point belonging to the enemy team */
|
||||
entity
|
||||
NSEntity
|
||||
Route_SelectNearestEnemyTeam(float type, vector org, float tt)
|
||||
{
|
||||
entity temp;
|
||||
|
@ -140,7 +133,7 @@ Route_SelectNearestEnemyTeam(float type, vector org, float tt)
|
|||
Spawn_SelectRandom
|
||||
================
|
||||
*/
|
||||
entity
|
||||
NSEntity
|
||||
Route_SelectRandom(string sEntname)
|
||||
{
|
||||
static entity eLastSpot;
|
||||
|
@ -153,7 +146,7 @@ Route_SelectRandom(string sEntname)
|
|||
Route_SelectRandomSpot
|
||||
================
|
||||
*/
|
||||
entity
|
||||
NSEntity
|
||||
Route_SelectRandomSpot(void)
|
||||
{
|
||||
static entity eLastSpot;
|
||||
|
|
|
@ -369,7 +369,9 @@ NSView::UpdateView(void)
|
|||
/* all 2D operations happen after this point */
|
||||
for (entity b = world; (b = findfloat(b, ::isCSQC, 1));) {
|
||||
NSEntity pf = (NSEntity) b;
|
||||
pf.postdraw();
|
||||
|
||||
if (pf.postdraw)
|
||||
pf.postdraw();
|
||||
}
|
||||
|
||||
/* the blinding stuff */
|
||||
|
|
|
@ -122,6 +122,9 @@ Entity_EntityUpdate(float type, float new)
|
|||
case ENT_PROPROPE:
|
||||
NSENTITY_READENTITY(prop_rope, new)
|
||||
break;
|
||||
case ENT_PHYSROPE:
|
||||
NSENTITY_READENTITY(phys_rope, new)
|
||||
break;
|
||||
case ENT_BUBBLES:
|
||||
NSENTITY_READENTITY(env_bubbles, new)
|
||||
break;
|
||||
|
|
|
@ -16,27 +16,26 @@
|
|||
|
||||
var string g_strSkyName;
|
||||
|
||||
bool
|
||||
Sky_SourceBSPCheck(string sky)
|
||||
{
|
||||
if not (whichpack(strcat("materials/skybox/", sky, "bk.vmt")))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Sky_Update(int force)
|
||||
{
|
||||
if (g_strSkyName != serverkey("skyname") || force == TRUE) {
|
||||
string skyPath;
|
||||
string skyPrefix;
|
||||
|
||||
g_strSkyName = serverkey("skyname");
|
||||
skyPrefix = substring(g_strSkyName, 0, 4);
|
||||
|
||||
print(sprintf("SKY PREFIX: %S\n", skyPrefix));
|
||||
|
||||
/* is it a Source Engine material? */
|
||||
if (Sky_SourceBSPCheck(g_strSkyName))
|
||||
localcmd(sprintf("sky \"materials/skybox/%s\"\n", g_strSkyName));
|
||||
else
|
||||
localcmd(sprintf("sky \"%s\"\n", g_strSkyName));
|
||||
if (skyPrefix == "sky_") {
|
||||
skyPath = strcat("materials/skybox/", g_strSkyName);
|
||||
} else {
|
||||
skyPath = g_strSkyName;
|
||||
}
|
||||
|
||||
print(sprintf("sky update applying %s.\n", g_strSkyName));
|
||||
localcmd(sprintf("sky \"%s\"\n", skyPath));
|
||||
print(sprintf("sky update applying %s.\n", skyPath));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,5 +19,4 @@ client/infodecal.qc
|
|||
client/sky_camera.qc
|
||||
client/info_notnull.qc
|
||||
client/point_message.qc
|
||||
client/prop_static.qc
|
||||
#endlist
|
||||
|
|
|
@ -17,6 +17,7 @@ server/env_fade.qc
|
|||
server/env_hudhint.qc
|
||||
server/env_spark.qc
|
||||
server/env_explosion.qc
|
||||
server/env_physexplosion.qc
|
||||
server/env_render.qc
|
||||
server/env_shake.qc
|
||||
server/env_message.qc
|
||||
|
@ -64,6 +65,14 @@ server/player_weaponstrip.qc
|
|||
server/player_loadsaved.qc
|
||||
server/prop_dynamic.qc
|
||||
server/prop_physics.qc
|
||||
server/phys_ballsocket.qc
|
||||
server/phys_convert.qc
|
||||
server/phys_constraint.qc
|
||||
server/phys_keepupright.qc
|
||||
server/phys_hinge.qc
|
||||
server/phys_slideconstraint.qc
|
||||
//server/phys_constraintsystem.qc
|
||||
server/prop_static.qc
|
||||
server/point_camera.qc
|
||||
server/point_servercommand.qc
|
||||
server/point_trigger.qc
|
||||
|
|
184
src/gs-entbase/server/env_physexplosion.qc
Normal file
184
src/gs-entbase/server/env_physexplosion.qc
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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_physexplosion (1 .5 0) (-8 -8 -8) (8 8 8) NODAMAGE PUSHCLIENTS RADIAL TRACE SHAKE
|
||||
# OVERVIEW
|
||||
A force-centered explosion, primarily targetted at physics objects and optionally, players/clients.
|
||||
|
||||
# KEYS
|
||||
- "targetname" : Name
|
||||
- "magnitude" : Amount of force applied.
|
||||
- "radius" : Optional, overrides the radius of the 'explosion'.
|
||||
- "targetentityname" : Optional, will only target the named entity if specified.
|
||||
- "inner_radius" : Optional, will test from within this inner radius when TRACE (8) is set.
|
||||
|
||||
# SPAWNFLAGS
|
||||
- NODAMAGE (1) : Do not damage physics entities.
|
||||
- PUSHCLIENTS (2) : Allow pushing of players.
|
||||
- RADIAL (4) : Disables any up/down forces from being applied.
|
||||
- TRACE (8) : Does a collision test with its targets.
|
||||
- SHAKE (16) : Push the view of the players around a bit.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
env_physexplosion:NSPhysicsConstraint
|
||||
{
|
||||
public:
|
||||
void env_physexplosion(void);
|
||||
|
||||
/* overrides */
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string, string);
|
||||
virtual void Respawn(void);
|
||||
virtual void Input(entity, string, string);
|
||||
|
||||
nonvirtual void TriggerExplosion(void);
|
||||
|
||||
private:
|
||||
float m_flMagnitude;
|
||||
float m_flRadius;
|
||||
string m_strTargetEntity;
|
||||
float m_flInnerRadius;
|
||||
};
|
||||
|
||||
void
|
||||
env_physexplosion::env_physexplosion(void)
|
||||
{
|
||||
m_flMagnitude = 0.0f;
|
||||
m_flRadius = 0.0f;
|
||||
m_strTargetEntity = __NULL__;
|
||||
m_flInnerRadius = 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
env_physexplosion::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
SaveFloat(handle, "m_flMagnitude", m_flMagnitude);
|
||||
SaveFloat(handle, "m_flRadius", m_flRadius);
|
||||
SaveString(handle, "m_strTargetEntity", m_strTargetEntity);
|
||||
SaveFloat(handle, "m_flInnerRadius", m_flInnerRadius);
|
||||
}
|
||||
|
||||
void
|
||||
env_physexplosion::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_flMagnitude":
|
||||
m_flMagnitude = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_flRadius":
|
||||
m_flRadius = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_strTargetEntity":
|
||||
m_strTargetEntity = ReadString(strValue);
|
||||
break;
|
||||
case "m_flInnerRadius":
|
||||
m_flInnerRadius = ReadFloat(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_physexplosion::SpawnKey(string keyName, string setValue)
|
||||
{
|
||||
switch (keyName) {
|
||||
case "magnitude":
|
||||
m_flMagnitude = ReadFloat(setValue);
|
||||
break;
|
||||
case "radius":
|
||||
m_flRadius = ReadFloat(setValue);
|
||||
break;
|
||||
case "targetentityname":
|
||||
m_strTargetEntity = ReadString(setValue);
|
||||
break;
|
||||
case "inner_radius":
|
||||
m_flInnerRadius = ReadFloat(setValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(keyName, setValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_physexplosion::Respawn(void)
|
||||
{
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
}
|
||||
|
||||
void
|
||||
env_physexplosion::TriggerExplosion(void)
|
||||
{
|
||||
float entityDistance = 0.0f;
|
||||
float targetForce = 0.0f;
|
||||
float explosionRadius = m_flRadius;
|
||||
NSPhysicsEntity physEnt;
|
||||
|
||||
if (m_flRadius == 0.0) {
|
||||
explosionRadius = m_flMagnitude * 2.5;
|
||||
}
|
||||
|
||||
/* only target them if set */
|
||||
if (m_strTargetEntity) {
|
||||
physEnt = (NSPhysicsEntity)find(world, ::targetname, m_strTargetEntity);
|
||||
|
||||
if (!physEnt) {
|
||||
NSEntWarning("Target set, but not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
entityDistance = vlen(GetOrigin() - physEnt.WorldSpaceCenter());
|
||||
|
||||
if (entityDistance <= explosionRadius) {
|
||||
targetForce = (explosionRadius - entityDistance) / explosionRadius;
|
||||
targetForce = rint(m_flMagnitude * targetForce);
|
||||
physEnt.ApplyForceOffset(v_forward * targetForce, origin);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (entity e = world; (e = findfloat(e, ::isPhysics, true));) {
|
||||
physEnt = (NSPhysicsEntity)e;
|
||||
entityDistance = vlen(GetOrigin() - physEnt.WorldSpaceCenter());
|
||||
|
||||
if (entityDistance <= explosionRadius) {
|
||||
makevectors(vectoangles(physEnt.WorldSpaceCenter() - GetOrigin()));
|
||||
targetForce = (explosionRadius - entityDistance) / explosionRadius;
|
||||
targetForce = rint(m_flMagnitude * targetForce);
|
||||
physEnt.ApplyForceOffset(v_forward * targetForce, origin);
|
||||
physEnt.velocity += v_forward * targetForce;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_physexplosion::Input(entity activatorEnt, string inputName, string dataString)
|
||||
{
|
||||
switch (inputName) {
|
||||
case "Explode":
|
||||
TriggerExplosion();
|
||||
break;
|
||||
default:
|
||||
super::Input(activatorEnt, inputName, dataString);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -106,6 +106,8 @@ private:
|
|||
string m_strSndStop;
|
||||
|
||||
int m_waterType;
|
||||
|
||||
string m_strFullyClosed;
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -133,6 +135,7 @@ func_door::func_door(void)
|
|||
m_strSndStop = __NULL__;
|
||||
|
||||
m_waterType = 0i;
|
||||
m_strFullyClosed = __NULL__;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -158,6 +161,7 @@ func_door::Save(float handle)
|
|||
SaveString(handle, "m_strSndMove", m_strSndMove);
|
||||
SaveString(handle, "targetClose", targetClose);
|
||||
SaveInt(handle, "m_waterType", m_waterType);
|
||||
SaveString(handle, "m_strFullyClosed", m_strFullyClosed);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -215,6 +219,9 @@ func_door::Restore(string strKey, string strValue)
|
|||
case "m_waterType":
|
||||
m_waterType = ReadInt(strValue);
|
||||
break;
|
||||
case "m_strFullyClosed":
|
||||
m_strFullyClosed = ReadString(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
|
@ -281,6 +288,10 @@ func_door::SpawnKey(string strKey, string strValue)
|
|||
x = stoi(strValue);
|
||||
m_strUnlockedSfx = sprintf("func_button.hlsfx_%i", x+1i);
|
||||
break;
|
||||
/* I/O */
|
||||
case "OnFullyClosed":
|
||||
m_strFullyClosed = PrepareOutput(m_strFullyClosed, strValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
}
|
||||
|
@ -305,6 +316,10 @@ func_door::Spawned(void)
|
|||
Sound_Precache(m_strLockedSfx);
|
||||
if (m_strUnlockedSfx)
|
||||
Sound_Precache(m_strUnlockedSfx);
|
||||
|
||||
/* I/O */
|
||||
if (m_strFullyClosed)
|
||||
m_strFullyClosed = CreateOutput(m_strFullyClosed);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -371,10 +386,10 @@ func_door::Input(entity eAct, string strInput, string strData)
|
|||
{
|
||||
switch (strInput) {
|
||||
case "Open":
|
||||
Trigger(eAct, TRIG_OFF);
|
||||
Trigger(eAct, TRIG_ON);
|
||||
break;
|
||||
case "Close":
|
||||
Trigger(eAct, TRIG_ON);
|
||||
Trigger(eAct, TRIG_OFF);
|
||||
break;
|
||||
case "Toggle":
|
||||
Trigger(eAct, TRIG_TOGGLE);
|
||||
|
@ -420,6 +435,9 @@ func_door::MoverFinishesMoving(void)
|
|||
if (m_strSndMove)
|
||||
StartSound("common/null.wav", CHAN_WEAPON, 0, true);
|
||||
|
||||
if (m_strFullyClosed)
|
||||
UseOutput(this, m_strFullyClosed);
|
||||
|
||||
} else if (GetMoverState() == MOVER_POS2) {
|
||||
if (m_strSndStop) {
|
||||
StartSoundDef(m_strSndStop, CHAN_VOICE, true);
|
||||
|
|
|
@ -49,9 +49,9 @@ func_physbox::Respawn(void)
|
|||
NSPhysicsEntity::Respawn();
|
||||
|
||||
if (HasSpawnFlags(FNCPHYBX_ASLEEP))
|
||||
PhysicsDisable();
|
||||
Sleep();
|
||||
else
|
||||
PhysicsEnable();
|
||||
Wake();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -85,7 +85,7 @@ func_physbox::Death(void)
|
|||
void
|
||||
func_physbox::Respawn(void)
|
||||
{
|
||||
NSSurfacePropEntity::Respawn();
|
||||
super::Respawn();
|
||||
health = GetSpawnHealth();
|
||||
SetTakedamage(DAMAGE_YES);
|
||||
SetSolid(SOLID_BBOX);
|
||||
|
|
|
@ -82,7 +82,7 @@ private:
|
|||
void
|
||||
logic_auto::logic_auto(void)
|
||||
{
|
||||
m_iFromSaveGame = 0;
|
||||
m_iFromSaveGame = 0i;
|
||||
m_strOnMapSpawn = __NULL__;
|
||||
m_strOnNewGame = __NULL__;
|
||||
m_strOnLoadGame = __NULL__;
|
||||
|
@ -108,7 +108,7 @@ logic_auto::Save(float handle)
|
|||
void
|
||||
logic_auto::Restore(string strKey, string strValue)
|
||||
{
|
||||
m_iFromSaveGame = 1;
|
||||
m_iFromSaveGame = 1i;
|
||||
|
||||
switch (strKey) {
|
||||
case "m_strOnMapSpawn":
|
||||
|
@ -198,8 +198,6 @@ logic_auto::Spawned(void)
|
|||
void
|
||||
logic_auto::Respawn(void)
|
||||
{
|
||||
|
||||
m_iFromSaveGame = 1;
|
||||
ScheduleThink(Processing, 0.2f);
|
||||
}
|
||||
|
||||
|
@ -220,8 +218,9 @@ logic_auto::Processing(void)
|
|||
cvar_set("_bsp_change_auto", "");
|
||||
} else
|
||||
UseOutput(this, m_strOnLoadGame);
|
||||
} else
|
||||
} else {
|
||||
UseOutput(this, m_strOnNewGame);
|
||||
}
|
||||
} else {
|
||||
/* TODO: more reliable way of figuring out round restarts */
|
||||
if (time > 5)
|
||||
|
|
|
@ -39,8 +39,8 @@ Compares an input value sent from another entity with one of the constant values
|
|||
|
||||
# INPUTS
|
||||
- "InValue" : Compares the input in the data field with one of the constant values, then firing a matching output.
|
||||
- "PickRandom" : Not yet implemented. Triggers a random, valid output.
|
||||
- "PickRandomShuffle" : Not yet implemented. Triggers a random, valid output, but without repeats.
|
||||
- "PickRandom" : Triggers a random, valid output.
|
||||
- "PickRandomShuffle" : Triggers a random, valid output, but without repeats.
|
||||
|
||||
# OUTPUTS
|
||||
- "OnCase01" - Triggered when Case01 matches the InValue input data.
|
||||
|
@ -81,6 +81,8 @@ public:
|
|||
virtual void Input(entity, string, string);
|
||||
|
||||
nonvirtual void CompareCase(entity, string);
|
||||
nonvirtual void PickRandom(entity);
|
||||
nonvirtual void PickRandomShuffle(entity);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -476,16 +478,28 @@ logic_case::Input(entity activatorEntity, string inputName, string dataField)
|
|||
CompareCase(activatorEntity, dataField);
|
||||
break;
|
||||
case "PickRandom":
|
||||
error("Not implemented.");
|
||||
PickRandom(activatorEntity);
|
||||
break;
|
||||
case "PickRandomShuffle":
|
||||
error("Not implemented.");
|
||||
PickRandomShuffle(activatorEntity);
|
||||
break;
|
||||
default:
|
||||
super::Input(activatorEntity, inputName, dataField);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
logic_case::PickRandom(entity activatorEntity)
|
||||
{
|
||||
NSEntWarning("Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
logic_case::PickRandomShuffle(entity activatorEntity)
|
||||
{
|
||||
NSEntWarning("Not implemented.");
|
||||
}
|
||||
|
||||
void
|
||||
logic_case::CompareCase(entity activatorEntity, string inputValue)
|
||||
{
|
||||
|
|
|
@ -51,7 +51,7 @@ path_corner:NSPointTrigger
|
|||
{
|
||||
public:
|
||||
void path_corner(void);
|
||||
|
||||
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string,string);
|
||||
|
|
80
src/gs-entbase/server/phys_ballsocket.qc
Normal file
80
src/gs-entbase/server/phys_ballsocket.qc
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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 phys_ballsocket (.5 .3 0) (-8 -8 -8) (8 8 8) BREAKCOLL x INACTIVE MASS NOCONNECT
|
||||
# OVERVIEW
|
||||
Creates a connection between two entities in the form of a 'ballsocket'.
|
||||
|
||||
# KEYS
|
||||
- "targetname" : Name
|
||||
- "attach1" : Entity 1
|
||||
- "attach2" : Entity 2
|
||||
|
||||
# INPUTS
|
||||
- "Break" : Forcefully break the constraint.
|
||||
- "TurnOn" : Turn
|
||||
- "TurnOff" : Disables the constraint
|
||||
|
||||
# SPAWNFLAGS
|
||||
- BREAKCOLL (1) : No collision until the connection breaks.
|
||||
- INACTIVE (4) : Starts inactive.
|
||||
- MASS (8) : Mass Hack.
|
||||
- NOCONNECT (16) : Will not connect entities until turned on via Inputs.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
phys_ballsocket:NSPhysicsConstraint
|
||||
{
|
||||
public:
|
||||
void phys_ballsocket(void);
|
||||
|
||||
virtual void Respawn(void);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
};
|
||||
|
||||
void
|
||||
phys_ballsocket::phys_ballsocket(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
phys_ballsocket::Respawn(void)
|
||||
{
|
||||
ScheduleThink(AfterSpawn, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
phys_ballsocket::AfterSpawn(void)
|
||||
{
|
||||
vector centerPos;
|
||||
SetConstraintType(CONSTRAINT_POINT);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
|
||||
SetEntity1(find(world, ::targetname, m_strEnt1));
|
||||
|
||||
if (m_strEnt2)
|
||||
SetEntity2(find(world, ::targetname, m_strEnt2));
|
||||
else
|
||||
SetEntity2(this);
|
||||
|
||||
centerPos = (enemy.origin + aiment.origin) / 2;
|
||||
origin = velocity = centerPos;
|
||||
|
||||
WakeTargets();
|
||||
}
|
74
src/gs-entbase/server/phys_constraint.qc
Normal file
74
src/gs-entbase/server/phys_constraint.qc
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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 phys_constraint (.5 .3 0) (-8 -8 -8) (8 8 8) BREAKCOLL x INACTIVE MASS NOCONNECT
|
||||
# OVERVIEW
|
||||
Creates a fixed connection between two entities.
|
||||
|
||||
# KEYS
|
||||
- "targetname" : Name
|
||||
- "attach1" : Entity 1
|
||||
- "attach2" : Entity 2
|
||||
|
||||
# INPUTS
|
||||
- "Break" : Forcefully break the constraint.
|
||||
- "TurnOn" : Turn
|
||||
- "TurnOff" : Disables the constraint
|
||||
|
||||
# SPAWNFLAGS
|
||||
- BREAKCOLL (1) : No collision until the connection breaks.
|
||||
- INACTIVE (4) : Starts inactive.
|
||||
- MASS (8) : Mass Hack.
|
||||
- NOCONNECT (16) : Will not connect entities until turned on via Inputs.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
phys_constraint:NSPhysicsConstraint
|
||||
{
|
||||
public:
|
||||
void phys_constraint(void);
|
||||
|
||||
virtual void Respawn(void);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
};
|
||||
|
||||
void
|
||||
phys_constraint::phys_constraint(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
phys_constraint::Respawn(void)
|
||||
{
|
||||
ScheduleThink(AfterSpawn, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
phys_constraint::AfterSpawn(void)
|
||||
{
|
||||
SetConstraintType(CONSTRAINT_FIXED);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
|
||||
SetEntity1(find(world, ::targetname, m_strEnt1));
|
||||
|
||||
if (m_strEnt2)
|
||||
SetEntity2(find(world, ::targetname, m_strEnt2));
|
||||
else
|
||||
SetEntity2(this);
|
||||
}
|
68
src/gs-entbase/server/phys_constraintsystem.qc
Normal file
68
src/gs-entbase/server/phys_constraintsystem.qc
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var int g_phys_constraintsystems;
|
||||
|
||||
/*!QUAKED phys_constraintsystem (.5 .3 0) (-8 -8 -8) (8 8 8)
|
||||
# OVERVIEW
|
||||
Turns a series of constraints into a ragdoll, so it can be managed better by the physics simulator.
|
||||
|
||||
# KEYS
|
||||
- "targetname" : Name
|
||||
|
||||
# NOTES
|
||||
|
||||
You specify the constraintsystem that the constraints belong to not in this entity, but
|
||||
in the individual constraints themselves. Set the 'constraintsystem' key to an instance of this entity.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
phys_constraintsystem:NSPhysicsConstraint
|
||||
{
|
||||
public:
|
||||
void phys_constraintsystem(void);
|
||||
|
||||
virtual void Respawn(void);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
nonvirtual float GetSystemID(void);
|
||||
};
|
||||
|
||||
void
|
||||
phys_constraintsystem::phys_constraintsystem(void)
|
||||
{
|
||||
g_phys_constraintsystems += 1;
|
||||
jointgroup = (float)g_phys_constraintsystems;
|
||||
}
|
||||
|
||||
void
|
||||
phys_constraintsystem::Respawn(void)
|
||||
{
|
||||
ScheduleThink(AfterSpawn, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
phys_constraintsystem::AfterSpawn(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float
|
||||
phys_constraintsystem::GetSystemID(void)
|
||||
{
|
||||
return jointgroup;
|
||||
}
|
209
src/gs-entbase/server/phys_convert.qc
Normal file
209
src/gs-entbase/server/phys_convert.qc
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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 phys_convert (.5 .3 0) (-8 -8 -8) (8 8 8) ASLEEP DEBRIS
|
||||
# OVERVIEW
|
||||
Turns a standard entity into a physically simulated one.
|
||||
|
||||
# KEYS
|
||||
- "targetname" : Name
|
||||
- "target" : Entity 1
|
||||
- "swapmodel" : Model override.
|
||||
- "massoverride" : Optional new mass.
|
||||
|
||||
# INPUTS
|
||||
- "ConvertTarget" : Triggers the conversion.
|
||||
|
||||
# OUTPUTS
|
||||
- "OnConvert" : Triggered after successful conversion.
|
||||
|
||||
# SPAWNFLAGS
|
||||
- ASLEEP (1) : Don't activate motion when conversion is done.
|
||||
- DEBRIS (2) : Makes converted entity non-solid.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
phys_convert:NSPhysicsConstraint
|
||||
{
|
||||
public:
|
||||
void phys_convert(void);
|
||||
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string, string);
|
||||
virtual void Spawned(void);
|
||||
virtual void Respawn(void);
|
||||
virtual void Input(entity, string, string);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
nonvirtual void ConvertTarget(entity);
|
||||
|
||||
private:
|
||||
string m_strSwapModel;
|
||||
float m_flMassOverride;
|
||||
string m_strOnConvert;
|
||||
};
|
||||
|
||||
void
|
||||
phys_convert::phys_convert(void)
|
||||
{
|
||||
m_strSwapModel = __NULL__;
|
||||
m_flMassOverride = 0.0f;
|
||||
m_strOnConvert = __NULL__;
|
||||
}
|
||||
|
||||
void
|
||||
phys_convert::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
SaveString(handle, "m_strSwapModel", m_strSwapModel);
|
||||
SaveFloat(handle, "m_flMassOverride", m_flMassOverride);
|
||||
SaveString(handle, "m_strOnConvert", m_strOnConvert);
|
||||
}
|
||||
|
||||
void
|
||||
phys_convert::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_strSwapModel":
|
||||
m_strSwapModel = ReadString(strValue);
|
||||
break;
|
||||
case "m_flMassOverride":
|
||||
m_flMassOverride = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_strOnConvert":
|
||||
m_strOnConvert = ReadString(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_convert::SpawnKey(string keyName, string setValue)
|
||||
{
|
||||
switch (keyName) {
|
||||
case "target":
|
||||
m_strEnt1 = ReadString(setValue);
|
||||
break;
|
||||
case "swapmodel":
|
||||
m_strSwapModel = ReadString(setValue);
|
||||
break;
|
||||
case "massoverride":
|
||||
m_flMassOverride = ReadFloat(setValue);
|
||||
break;
|
||||
case "OnConvert":
|
||||
m_strOnConvert = PrepareOutput(m_strOnConvert, setValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(keyName, setValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_convert::Spawned(void)
|
||||
{
|
||||
super::Spawned();
|
||||
|
||||
if (m_strOnConvert)
|
||||
m_strOnConvert = CreateOutput(m_strOnConvert);
|
||||
}
|
||||
|
||||
void
|
||||
phys_convert::Respawn(void)
|
||||
{
|
||||
ScheduleThink(AfterSpawn, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
phys_convert::AfterSpawn(void)
|
||||
{
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
SetEntity1(find(world, ::targetname, m_strEnt1));
|
||||
}
|
||||
|
||||
void
|
||||
phys_convert::ConvertTarget(entity activatorEnt)
|
||||
{
|
||||
NSEntity targetEnt = (NSEntity)GetEntity1();
|
||||
string targetModel;
|
||||
vector targetAngle;
|
||||
vector targetPos;
|
||||
vector targetVelocity;
|
||||
string targetName;
|
||||
NSPhysicsEntity new;
|
||||
|
||||
if (!targetEnt) {
|
||||
NSEntWarning("Cannot find target to convert.");
|
||||
return;
|
||||
}
|
||||
|
||||
targetModel = targetEnt.GetModel();
|
||||
targetAngle = targetEnt.GetAngles();
|
||||
targetPos = targetEnt.GetOrigin();
|
||||
targetVelocity = targetEnt.GetVelocity();
|
||||
targetName = targetEnt.targetname;
|
||||
|
||||
new = spawn(NSPhysicsEntity);
|
||||
new.Respawn();
|
||||
|
||||
/* may have an override */
|
||||
if (m_strSwapModel) {
|
||||
targetModel = m_strSwapModel;
|
||||
}
|
||||
|
||||
new.SetModel(targetModel);
|
||||
new.SetOrigin(targetPos);
|
||||
new.SetAngles(targetAngle);
|
||||
new.SetVelocity(targetVelocity);
|
||||
new.targetname = (targetName);
|
||||
|
||||
if (m_flMassOverride > 0.0f) {
|
||||
new.SetMass(m_flMassOverride);
|
||||
}
|
||||
|
||||
/* Spawnflags ASLEEP */
|
||||
if (HasSpawnFlags(1)) {
|
||||
new.Sleep();
|
||||
} else {
|
||||
new.Wake();
|
||||
}
|
||||
|
||||
/* Spawnflag DEBRIS */
|
||||
if (HasSpawnFlags(2)) {
|
||||
new.SetSolid(SOLID_NOT);
|
||||
}
|
||||
|
||||
targetEnt.Destroy();
|
||||
|
||||
if (m_strOnConvert)
|
||||
UseOutput(activatorEnt, m_strOnConvert);
|
||||
}
|
||||
|
||||
void
|
||||
phys_convert::Input(entity activatorEnt, string inputName, string dataString)
|
||||
{
|
||||
switch (inputName) {
|
||||
case "ConvertTarget":
|
||||
ConvertTarget(activatorEnt);
|
||||
break;
|
||||
default:
|
||||
super::Input(activatorEnt, inputName, dataString);
|
||||
break;
|
||||
}
|
||||
}
|
144
src/gs-entbase/server/phys_hinge.qc
Normal file
144
src/gs-entbase/server/phys_hinge.qc
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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 phys_hinge (.5 .3 0) (-8 -8 -8) (8 8 8) BREAKCOLL x INACTIVE MASS NOCONNECT
|
||||
# OVERVIEW
|
||||
Creates a connection between two entities in the form of a hinge.
|
||||
|
||||
# KEYS
|
||||
- "targetname" : Name
|
||||
- "attach1" : Entity 1
|
||||
- "attach2" : Entity 2
|
||||
- "hingefriction" : Friction in the hinge.
|
||||
- "hingeaxis" : Axis of the hinge. Technically the position it is aiming at.
|
||||
|
||||
# INPUTS
|
||||
- "Break" : Forcefully break the constraint.
|
||||
- "TurnOn" : Turn
|
||||
- "TurnOff" : Disables the constraint
|
||||
- "SetAngularVelocity" : Applies rotation to the hinge motor.
|
||||
|
||||
# SPAWNFLAGS
|
||||
- BREAKCOLL (1) : No collision until the connection breaks.
|
||||
- INACTIVE (4) : Starts inactive.
|
||||
- MASS (8) : Mass Hack.
|
||||
- NOCONNECT (16) : Will not connect entities until turned on via Inputs.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
phys_hinge:NSPhysicsConstraint
|
||||
{
|
||||
public:
|
||||
void phys_hinge(void);
|
||||
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string, string);
|
||||
virtual void Input(entity, string, string);
|
||||
virtual void Respawn(void);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
|
||||
private:
|
||||
float m_flHingeFriction;
|
||||
vector m_vecHingeAxis;
|
||||
};
|
||||
|
||||
void
|
||||
phys_hinge::phys_hinge(void)
|
||||
{
|
||||
m_flHingeFriction = 1.0f;
|
||||
m_vecHingeAxis = g_vec_null;
|
||||
}
|
||||
|
||||
void
|
||||
phys_hinge::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
SaveFloat(handle, "m_flHingeFriction", m_flHingeFriction);
|
||||
SaveVector(handle, "m_vecHingeAxis", m_vecHingeAxis);
|
||||
}
|
||||
|
||||
void
|
||||
phys_hinge::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_flHingeFriction":
|
||||
m_flHingeFriction = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_vecHingeAxis":
|
||||
m_vecHingeAxis = ReadVector(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_hinge::SpawnKey(string keyName, string setValue)
|
||||
{
|
||||
switch (keyName) {
|
||||
case "hingefriction":
|
||||
m_flHingeFriction = ReadFloat(setValue);
|
||||
break;
|
||||
case "hingeaxis":
|
||||
m_vecHingeAxis = ReadVector(setValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(keyName, setValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_hinge::Respawn(void)
|
||||
{
|
||||
ScheduleThink(AfterSpawn, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
phys_hinge::AfterSpawn(void)
|
||||
{
|
||||
SetConstraintType(CONSTRAINT_HINGE);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
|
||||
SetEntity1(find(world, ::targetname, m_strEnt1));
|
||||
|
||||
if (m_strEnt2)
|
||||
SetEntity2(find(world, ::targetname, m_strEnt2));
|
||||
else
|
||||
SetEntity2(this);
|
||||
|
||||
SetAngles(vectoangles(m_vecHingeAxis - GetOrigin()));
|
||||
SetSliderMaxVelocity(99999);
|
||||
SetSliderFriction(m_flHingeFriction);
|
||||
|
||||
WakeTargets();
|
||||
}
|
||||
|
||||
void
|
||||
phys_hinge::Input(entity activatorEnt, string inputName, string dataString)
|
||||
{
|
||||
switch (inputName) {
|
||||
case "SetAngularVelocity":
|
||||
SetSliderVelocity(stof(dataString));
|
||||
break;
|
||||
default:
|
||||
super::Input(activatorEnt, inputName, dataString);
|
||||
break;
|
||||
}
|
||||
}
|
125
src/gs-entbase/server/phys_keepupright.qc
Normal file
125
src/gs-entbase/server/phys_keepupright.qc
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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 phys_keepupright (.5 .3 0) (-8 -8 -8) (8 8 8) INACTIVE
|
||||
# OVERVIEW
|
||||
Keep an entity upright.
|
||||
|
||||
# KEYS
|
||||
- "targetname" : Name
|
||||
- "attach1" : Entity 1
|
||||
- "angularlimit" : The limit of angular velocity this can clamp.
|
||||
|
||||
# INPUTS
|
||||
- "TurnOn" : Make Entity 1 upright.
|
||||
- "TurnOff" : Make Entity 1 no longer upright.
|
||||
|
||||
# SPAWNFLAGS
|
||||
- INACTIVE (1) : Starts inactive.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
phys_keepupright:NSPhysicsConstraint
|
||||
{
|
||||
public:
|
||||
void phys_keepupright(void);
|
||||
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string, string);
|
||||
virtual void Respawn(void);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
virtual void Input(entity, string, string);
|
||||
|
||||
private:
|
||||
float m_flAngularLimit;
|
||||
};
|
||||
|
||||
void
|
||||
phys_keepupright::phys_keepupright(void)
|
||||
{
|
||||
m_flAngularLimit = -1.0f;
|
||||
}
|
||||
|
||||
void
|
||||
phys_keepupright::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
SaveFloat(handle, "m_flAngularLimit", m_flAngularLimit);
|
||||
}
|
||||
|
||||
void
|
||||
phys_keepupright::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_flAngularLimit":
|
||||
m_flAngularLimit = ReadFloat(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_keepupright::SpawnKey(string keyName, string setValue)
|
||||
{
|
||||
switch (keyName) {
|
||||
case "angularlimit":
|
||||
m_flAngularLimit = ReadFloat(setValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(keyName, setValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_keepupright::Respawn(void)
|
||||
{
|
||||
if (HasSpawnFlags(1) == false)
|
||||
ScheduleThink(AfterSpawn, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
phys_keepupright::AfterSpawn(void)
|
||||
{
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
SetEntity1(find(world, ::targetname, m_strEnt1));
|
||||
NSEntity targetEnt = (NSEntity)GetEntity1();
|
||||
KeepUpright(targetEnt, targetEnt.GetSpawnAngles(), m_flAngularLimit);
|
||||
}
|
||||
|
||||
void
|
||||
phys_keepupright::Input(entity activatorEnt, string inputName, string dataString)
|
||||
{
|
||||
NSEntity targetEnt;
|
||||
|
||||
switch (inputName) {
|
||||
case "TurnOn":
|
||||
targetEnt = (NSEntity)GetEntity1();
|
||||
KeepUpright(targetEnt, targetEnt.GetSpawnAngles(), m_flAngularLimit);
|
||||
break;
|
||||
case "TurnOff":
|
||||
targetEnt = (NSEntity)GetEntity1();
|
||||
KeepUpright(targetEnt, targetEnt.GetSpawnAngles(), -1);
|
||||
break;
|
||||
default:
|
||||
super::Input(activatorEnt, inputName, dataString);
|
||||
break;
|
||||
}
|
||||
}
|
149
src/gs-entbase/server/phys_slideconstraint.qc
Normal file
149
src/gs-entbase/server/phys_slideconstraint.qc
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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 phys_slideconstraint (.5 .3 0) (-8 -8 -8) (8 8 8) BREAKCOLL LIMITENDS
|
||||
# OVERVIEW
|
||||
Will slide an entity along a segment.
|
||||
|
||||
# KEYS
|
||||
- "targetname" : Name
|
||||
- "attach1" : Entity 1
|
||||
- "attach2" : Entity 2
|
||||
- "slideaxis" : Axis onto which the entity slides along. Technically the position it is aiming at.
|
||||
- "slidefriction" : Friction the entity experiences along the slide.
|
||||
|
||||
# INPUTS
|
||||
- "Break" : Forcefully break the constraint.
|
||||
- "TurnOn" : Turn
|
||||
- "TurnOff" : Disables the constraint
|
||||
|
||||
# SPAWNFLAGS
|
||||
- BREAKCOLL (1) : No collision until the connection breaks.
|
||||
- LIMITENDS (2) : Limit endpoints.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
phys_slideconstraint:NSPhysicsConstraint
|
||||
{
|
||||
public:
|
||||
void phys_slideconstraint(void);
|
||||
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string, string);
|
||||
virtual void Input(entity, string, string);
|
||||
virtual void Respawn(void);
|
||||
nonvirtual void AfterSpawn(void);
|
||||
|
||||
private:
|
||||
vector m_vecSliderAxis;
|
||||
float m_flSliderFriction;
|
||||
};
|
||||
|
||||
void
|
||||
phys_slideconstraint::phys_slideconstraint(void)
|
||||
{
|
||||
m_vecSliderAxis = g_vec_null;
|
||||
m_flSliderFriction = 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
phys_slideconstraint::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
SaveVector(handle, "m_vecSliderAxis", m_vecSliderAxis);
|
||||
SaveFloat(handle, "m_flSliderFriction", m_flSliderFriction);
|
||||
}
|
||||
|
||||
void
|
||||
phys_slideconstraint::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_vecSliderAxis":
|
||||
m_vecSliderAxis = ReadVector(strValue);
|
||||
break;
|
||||
case "m_flSliderFriction":
|
||||
m_flSliderFriction = ReadFloat(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_slideconstraint::SpawnKey(string keyName, string setValue)
|
||||
{
|
||||
switch (keyName) {
|
||||
case "slideaxis":
|
||||
m_vecSliderAxis = ReadVector(setValue);
|
||||
break;
|
||||
case "slidefriction":
|
||||
m_flSliderFriction = ReadFloat(setValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(keyName, setValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_slideconstraint::Respawn(void)
|
||||
{
|
||||
ScheduleThink(AfterSpawn, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
phys_slideconstraint::AfterSpawn(void)
|
||||
{
|
||||
SetConstraintType(CONSTRAINT_SLIDER);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
|
||||
SetEntity1(find(world, ::targetname, m_strEnt1));
|
||||
|
||||
if (m_strEnt2)
|
||||
SetEntity2(find(world, ::targetname, m_strEnt2));
|
||||
else
|
||||
SetEntity2(this);
|
||||
|
||||
SetAngles(vectoangles(m_vecSliderAxis - GetOrigin()));
|
||||
SetSliderMaxVelocity(99999);
|
||||
SetSliderFriction(m_flSliderFriction);
|
||||
|
||||
if (HasSpawnFlags(2))
|
||||
SetSliderStop(vlen(m_vecSliderAxis - GetOrigin()));
|
||||
|
||||
WakeTargets();
|
||||
}
|
||||
|
||||
void
|
||||
phys_slideconstraint::Input(entity activatorEnt, string inputName, string dataString)
|
||||
{
|
||||
switch (inputName) {
|
||||
case "SetVelocity":
|
||||
if (GetSliderVelocity() > 0.0f)
|
||||
SetSliderVelocity(-stof(dataString));
|
||||
else
|
||||
SetSliderVelocity(stof(dataString));
|
||||
|
||||
WakeTargets();
|
||||
break;
|
||||
default:
|
||||
super::Input(activatorEnt, inputName, dataString);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -86,3 +86,6 @@ prop_dynamic::Respawn(void)
|
|||
if (HasSpawnFlags(PRPDYN_NONSOLID))
|
||||
SetSolid(SOLID_NOT);
|
||||
}
|
||||
|
||||
CLASSEXPORT(prop_dynamic_override, prop_dynamic)
|
||||
CLASSEXPORT(prop_dynamic_respawnable, prop_dynamic)
|
||||
|
|
|
@ -15,9 +15,21 @@
|
|||
*/
|
||||
|
||||
#ifndef PHYSICS_STATIC
|
||||
#define PRPPHYS_ASLEEP 1
|
||||
|
||||
/*!QUAKED prop_physics (1 0 0) (-16 -16 -16) (16 16 16) PRPPHYS_ASLEEP
|
||||
enumflags
|
||||
{
|
||||
PHYSPROPSFL_ASLEEP,
|
||||
PHYSPROPSFL_NOPHYSDMG,
|
||||
PHYSPROPSFL_DEBRIS,
|
||||
PHYSPROPSFL_NOMOTION,
|
||||
PHYSPROPSFL_UNUSED1,
|
||||
PHYSPROPSFL_UNUSED2,
|
||||
PHYSPROPSFL_PHYSDEVICE,
|
||||
PHYSPROPSFL_NOROTOR,
|
||||
PHYSPROPSFL_USEOUT,
|
||||
};
|
||||
|
||||
/*!QUAKED prop_physics (1 0 0) (-16 -16 -16) (16 16 16) ASLEEP NOPHYSDMG DEBRIS NOMOTION x x PHYSDEVICE NOROTOR USEOUT
|
||||
# OVERVIEW
|
||||
Physics model
|
||||
|
||||
|
@ -25,7 +37,13 @@ Physics model
|
|||
- "targetname" : Name
|
||||
|
||||
# SPAWNFLAGS
|
||||
- PRPPHYS_ASLEEP (1) : Prop starts without physics and stays until it is impacted.
|
||||
- ASLEEP (1) : Prop starts without physics and stays until it is impacted.
|
||||
- NOPHYSDMG (2) : Will not take physics damage.
|
||||
- DEBRIS (4) : Will not collide with players, or other types of debris
|
||||
- NOMOTION (8) : Disable motion
|
||||
- PHYSDEVICE (64) : Enable motion when grabbed with a physics device.
|
||||
- NOROTOR (128) : Unaffected by rotor contraptions.
|
||||
- USEOUT (256) : Generate output on +use.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in Half-Life 2 (2004).
|
||||
|
@ -50,19 +68,27 @@ prop_physics::SpawnKey(string strKey, string strValue)
|
|||
{
|
||||
switch (strKey) {
|
||||
default:
|
||||
NSPhysicsEntity::SpawnKey(strKey, strValue);
|
||||
super::SpawnKey(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
prop_physics::Respawn(void)
|
||||
{
|
||||
NSPhysicsEntity::Respawn();
|
||||
super::Respawn();
|
||||
|
||||
if (HasSpawnFlags(PRPPHYS_ASLEEP))
|
||||
PhysicsDisable();
|
||||
if (HasSpawnFlags(PHYSPROPSFL_ASLEEP))
|
||||
Sleep();
|
||||
else
|
||||
PhysicsEnable();
|
||||
Wake();
|
||||
|
||||
if (HasSpawnFlags(PHYSPROPSFL_NOMOTION))
|
||||
Sleep();
|
||||
|
||||
if (HasSpawnFlags(PHYSPROPSFL_PHYSDEVICE))
|
||||
Sleep();
|
||||
|
||||
//Sleep();
|
||||
}
|
||||
#else
|
||||
class
|
||||
|
@ -85,3 +111,6 @@ prop_physics::Respawn(void)
|
|||
SetSolid(SOLID_BBOX);
|
||||
}
|
||||
#endif
|
||||
|
||||
CLASSEXPORT(prop_physics_override, prop_physics)
|
||||
CLASSEXPORT(prop_physics_respawnable, prop_physics)
|
||||
|
|
|
@ -39,7 +39,7 @@ waste disk space and memory. Use wisely.
|
|||
This entity was introduced in Half-Life 2 (2004).
|
||||
*/
|
||||
class
|
||||
prop_static:NSRenderableEntity
|
||||
prop_static:NSPhysicsEntity
|
||||
{
|
||||
public:
|
||||
void prop_static(void);
|
||||
|
@ -56,10 +56,13 @@ prop_static::prop_static(void)
|
|||
void
|
||||
prop_static::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_NOT);
|
||||
SetModel(GetSpawnModel());
|
||||
mins = [0,0,0];
|
||||
maxs = [0,0,0];
|
||||
SetSize(mins, maxs);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
SetMovetype(MOVETYPE_PHYSICS);
|
||||
SetSolid(SOLID_PHYSICS_BOX);
|
||||
geomtype = GEOMTYPE_TRIMESH;
|
||||
|
||||
Sleep();
|
||||
SetTakedamage(DAMAGE_NO);
|
||||
touch = __NULL__;
|
||||
}
|
||||
|
|
|
@ -35,5 +35,6 @@ shared/point_spotlight.qc
|
|||
shared/trigger_push.qc
|
||||
shared/func_conveyor.qc
|
||||
shared/prop_rope.qc
|
||||
shared/phys_rope.qc
|
||||
shared/worldspawn.qc
|
||||
#endlist
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
void env_muzzleflash(void);
|
||||
|
||||
#ifdef SERVER
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void SpawnKey(string, string);
|
||||
virtual void Input(entity, string, string);
|
||||
virtual void Input(entity, string, string);
|
||||
|
@ -63,10 +65,50 @@ env_muzzleflash::env_muzzleflash(void)
|
|||
m_eOwner = __NULL__;
|
||||
m_strModel = __NULL__;
|
||||
m_strParticle = __NULL__;
|
||||
m_eMuzzler = __NULL__;
|
||||
scale = 1.0f;
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
env_muzzleflash::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
SaveString(handle, "m_strAttachmentName", m_strAttachmentName);
|
||||
SaveInt(handle, "m_iAttachment", m_iAttachment);
|
||||
SaveEntity(handle, "m_eOwner", m_eOwner);
|
||||
SaveString(handle, "m_strModel", m_strModel);
|
||||
SaveString(handle, "m_strParticle", m_strParticle);
|
||||
SaveEntity(handle, "m_eMuzzler", m_eMuzzler);
|
||||
}
|
||||
|
||||
void
|
||||
env_muzzleflash::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_strAttachmentName":
|
||||
m_strAttachmentName = ReadString(strValue);
|
||||
break;
|
||||
case "m_iAttachment":
|
||||
m_iAttachment = ReadInt(strValue);
|
||||
break;
|
||||
case "m_eOwner":
|
||||
m_eOwner = (NSRenderableEntity)ReadEntity(strValue);
|
||||
break;
|
||||
case "m_strModel":
|
||||
m_strModel = ReadString(strValue);
|
||||
break;
|
||||
case "m_strParticle":
|
||||
m_strParticle = ReadString(strValue);
|
||||
break;
|
||||
case "m_eMuzzler":
|
||||
m_eMuzzler = ReadEntity(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
env_muzzleflash::SpawnKey(string keyName, string setValue)
|
||||
{
|
||||
|
@ -107,11 +149,16 @@ env_muzzleflash::Input(entity eAct, string strKey, string strValue)
|
|||
void
|
||||
env_muzzleflash::Trigger(entity theActivator, triggermode_t triggerState)
|
||||
{
|
||||
NSEntity targetEnt;
|
||||
NSEntity targetEnt = __NULL__;
|
||||
vector targetPosition = GetOrigin();
|
||||
|
||||
if (m_parent) {
|
||||
targetEnt = (NSEntity)find(world, ::targetname, m_parent);
|
||||
|
||||
if (!targetEnt) {
|
||||
NSEntWarning("Entity specified but not found.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
|
@ -155,7 +202,7 @@ EV_MuzzleFlash_Parse(void)
|
|||
{
|
||||
env_muzzleflash tempMuzzle = spawn(env_muzzleflash);
|
||||
|
||||
tempMuzzle.m_eOwner = findfloat(world, entnum, readentitynum());
|
||||
tempMuzzle.m_eOwner = (NSRenderableEntity)findfloat(world, entnum, readentitynum());
|
||||
tempMuzzle.m_iAttachment = readbyte();
|
||||
tempMuzzle.scale = readfloat();
|
||||
tempMuzzle.modelindex = readshort();
|
||||
|
@ -171,7 +218,7 @@ EV_MuzzleFlash_Create(entity muzzleOwner, int attachmentID, float muzzleScale, i
|
|||
{
|
||||
env_muzzleflash tempMuzzle = spawn(env_muzzleflash);
|
||||
|
||||
tempMuzzle.m_eOwner = muzzleOwner;
|
||||
tempMuzzle.m_eOwner = (NSRenderableEntity)muzzleOwner;
|
||||
tempMuzzle.m_iAttachment = attachmentID;
|
||||
tempMuzzle.scale = muzzleScale;
|
||||
tempMuzzle.alpha = 1.0f;
|
||||
|
|
|
@ -86,7 +86,7 @@ env_shockwave::env_shockwave(void)
|
|||
m_flHeight = 32.0f;
|
||||
m_flNoiseAmp = 0.0f;
|
||||
m_vecColor = [1,1,1];
|
||||
m_flBrightness = 1.0f;;
|
||||
m_flBrightness = 1.0f;
|
||||
m_flScrollSpeed = 0.0f;
|
||||
}
|
||||
|
||||
|
|
363
src/gs-entbase/shared/phys_rope.qc
Normal file
363
src/gs-entbase/shared/phys_rope.qc
Normal file
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Vera Visions LLC.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
enumflags
|
||||
{
|
||||
PHYSROPE_CHANGED_MAT,
|
||||
PHYSROPE_CHANGED_SAG,
|
||||
PHYSROPE_CHANGED_SWING,
|
||||
PHYSROPE_CHANGED_SEGMENTS,
|
||||
PHYSROPE_CHANGED_ORIGIN,
|
||||
PHYSROPE_CHANGED_TARGET,
|
||||
PHYSROPE_CHANGED_FLAGS,
|
||||
PHYSROPE_CHANGED_WIDTH
|
||||
};
|
||||
|
||||
/*!QUAKED phys_rope (1 0 0) (-8 -8 -8) (8 8 8) ROPE_VERTICAL
|
||||
# OVERVIEW
|
||||
Client-side decorative rope entity.
|
||||
Connect the entity to a named info_notnull and watch it swing around.
|
||||
|
||||
# KEYS
|
||||
- "sag" : Multiplier on how much sagginess will be applied to the rope.
|
||||
- "segments" : Number of total segments. Default is "16".
|
||||
- "material" : The texture to use on the rope.
|
||||
- "swingfactor" : Multiplier on how much the rope swings about.
|
||||
- "target" : The info_notnull to connect the rope to.
|
||||
|
||||
# SPAWNFLAGS
|
||||
- ROPE_VERTICAL (1) : Only draw the first half of the rope, useful for vertical setups.
|
||||
|
||||
# TRIVIA
|
||||
This entity was introduced in The Wastes (2018).
|
||||
*/
|
||||
class phys_rope:NSEntity
|
||||
{
|
||||
public:
|
||||
void phys_rope(void);
|
||||
|
||||
#ifdef CLIENT
|
||||
virtual float predraw(void);
|
||||
virtual void ReceiveEntity(float,float);
|
||||
virtual void DrawSegment(vector, vector, vector);
|
||||
#else
|
||||
virtual void SpawnKey(string,string);
|
||||
virtual void Respawn(void);
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string, string);
|
||||
virtual void EvaluateEntity(void);
|
||||
virtual float SendEntity(entity,float);
|
||||
#endif
|
||||
|
||||
private:
|
||||
string m_strShader;
|
||||
PREDICTED_FLOAT(m_flSag)
|
||||
PREDICTED_FLOAT(m_flSwingFactor)
|
||||
PREDICTED_INT(m_iSegments)
|
||||
PREDICTED_VECTOR(m_vecTarget)
|
||||
PREDICTED_FLOAT(m_flWidth)
|
||||
};
|
||||
|
||||
#ifdef CLIENT
|
||||
|
||||
void
|
||||
phys_rope::DrawSegment(vector pos1, vector pos2, vector vecPlayer)
|
||||
{
|
||||
vector lit1 = /*[0.1,0.1,0.1] */ getlight(pos1) / 255;
|
||||
vector lit2 = /*[0.1,0.1,0.1] */ getlight(pos2) / 255;
|
||||
|
||||
R_BeginPolygon(m_strShader, 0, 0);
|
||||
R_PolygonVertex(pos1, [0,0], lit1, 1.0f);
|
||||
R_PolygonVertex(pos2, [0,1], lit2, 1.0f);
|
||||
R_EndPolygonRibbon(1, [-1,0]);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
phys_rope::predraw(void)
|
||||
{
|
||||
vector pos1;
|
||||
vector pos2;
|
||||
float segments;
|
||||
vector vecPlayer;
|
||||
NSClientPlayer pl;
|
||||
|
||||
int s = (float)getproperty(VF_ACTIVESEAT);
|
||||
pSeat = &g_seats[s];
|
||||
pl = (NSClientPlayer)pSeat->m_ePlayer;
|
||||
vecPlayer = pl.GetEyePos();
|
||||
|
||||
/* draw the start/end without segments */
|
||||
if (autocvar_rope_debug == TRUE) {
|
||||
R_BeginPolygon("", 0, 0);
|
||||
R_PolygonVertex(origin, [0,1], [0,1,0], 1.0f);
|
||||
R_PolygonVertex(m_vecTarget, [1,1], [0,1,0], 1.0f);
|
||||
R_EndPolygon();
|
||||
}
|
||||
|
||||
if (autocvar_rope_maxsegments > 0)
|
||||
segments = bound(1, autocvar_rope_maxsegments, (float)m_iSegments);
|
||||
else
|
||||
segments = (float)m_iSegments;
|
||||
|
||||
float travel = 1.0f / segments;
|
||||
float progress= 0.0f;
|
||||
pos1 = origin;
|
||||
|
||||
makevectors(getproperty(VF_CL_VIEWANGLES));
|
||||
setproperty(VF_ORIGIN, vecPlayer);
|
||||
|
||||
/* get the direction */
|
||||
makevectors(vectoangles(m_vecTarget - origin));
|
||||
|
||||
for (float i = 0; i < segments; i++) {
|
||||
float sag = 0.0f;
|
||||
float swing = 0.0f;
|
||||
progress += travel;
|
||||
float c1 = (ropecos(progress) * M_PI) * 2.25f;
|
||||
|
||||
/* loose hanging rope */
|
||||
if (flags & 1) {
|
||||
sag = c1 * m_flSag;
|
||||
swing = c1 * m_flSwingFactor;
|
||||
} else {
|
||||
sag = c1 * m_flSag;
|
||||
swing = c1 * m_flSwingFactor;
|
||||
}
|
||||
|
||||
/* travel further and sag */
|
||||
pos2[0] = Math_Lerp(origin[0], m_vecTarget[0], progress);
|
||||
pos2[1] = Math_Lerp(origin[1], m_vecTarget[1], progress);
|
||||
pos2[2] = Math_Lerp(origin[2], m_vecTarget[2], progress);
|
||||
pos2 += (v_up * -sag) * autocvar_rope_sag;
|
||||
|
||||
if (!autocvar_rope_fast)
|
||||
pos2 += ((v_right * swing) * sin(time)) * autocvar_rope_swing;
|
||||
|
||||
DrawSegment(pos1, pos2, vecPlayer);
|
||||
pos1 = pos2;
|
||||
}
|
||||
|
||||
return (PREDRAW_NEXT);
|
||||
}
|
||||
|
||||
void
|
||||
phys_rope::ReceiveEntity(float new, float flSendFlags)
|
||||
{
|
||||
if (flSendFlags & PHYSROPE_CHANGED_MAT)
|
||||
m_strShader = readstring();
|
||||
if (flSendFlags & PHYSROPE_CHANGED_SAG)
|
||||
m_flSag = readfloat();
|
||||
if (flSendFlags & PHYSROPE_CHANGED_SWING)
|
||||
m_flSwingFactor = readfloat();
|
||||
if (flSendFlags & PHYSROPE_CHANGED_SEGMENTS)
|
||||
m_iSegments = readint();
|
||||
if (flSendFlags & PHYSROPE_CHANGED_ORIGIN) {
|
||||
origin[0] = readcoord();
|
||||
origin[1] = readcoord();
|
||||
origin[2] = readcoord();
|
||||
setsize(this, [0,0,0], [0,0,0]);
|
||||
setorigin(this, origin);
|
||||
}
|
||||
if (flSendFlags & PHYSROPE_CHANGED_TARGET) {
|
||||
m_vecTarget[0] = readcoord();
|
||||
m_vecTarget[1] = readcoord();
|
||||
m_vecTarget[2] = readcoord();
|
||||
}
|
||||
if (flSendFlags & PHYSROPE_CHANGED_FLAGS)
|
||||
flags = readfloat();
|
||||
if (flSendFlags & PHYSROPE_CHANGED_WIDTH)
|
||||
m_flWidth = readfloat();
|
||||
}
|
||||
#else
|
||||
void
|
||||
phys_rope::Respawn(void)
|
||||
{
|
||||
if (HasSpawnFlags(1)) {
|
||||
flags = 1;
|
||||
}
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
SetSize([0,0,0], [0,0,0]);
|
||||
}
|
||||
void
|
||||
phys_rope::EvaluateEntity(void)
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
entity eFind = find(world, ::targetname, target);
|
||||
|
||||
if (!eFind) {
|
||||
print(sprintf("phys_rope: Unable to find target %S\n", target));
|
||||
return;
|
||||
}
|
||||
|
||||
m_vecTarget = eFind.origin;
|
||||
|
||||
if (ATTR_CHANGED(m_flSag)) {
|
||||
SetSendFlags(PHYSROPE_CHANGED_SAG);
|
||||
}
|
||||
if (ATTR_CHANGED(m_flSwingFactor)) {
|
||||
SetSendFlags(PHYSROPE_CHANGED_SWING);
|
||||
}
|
||||
if (ATTR_CHANGED(m_iSegments)) {
|
||||
SetSendFlags(PHYSROPE_CHANGED_SEGMENTS);
|
||||
}
|
||||
|
||||
if (ATTR_CHANGED(origin)) {
|
||||
SetSendFlags(PHYSROPE_CHANGED_ORIGIN);
|
||||
}
|
||||
if (ATTR_CHANGED(m_vecTarget)) {
|
||||
SetSendFlags(PHYSROPE_CHANGED_TARGET);
|
||||
}
|
||||
if (ATTR_CHANGED(flags)) {
|
||||
SetSendFlags(PHYSROPE_CHANGED_FLAGS);
|
||||
}
|
||||
if (ATTR_CHANGED(m_flWidth)) {
|
||||
SetSendFlags(PHYSROPE_CHANGED_WIDTH);
|
||||
}
|
||||
|
||||
SAVE_STATE(m_flSag)
|
||||
SAVE_STATE(m_flSwingFactor)
|
||||
SAVE_STATE(m_iSegments)
|
||||
SAVE_STATE(origin)
|
||||
SAVE_STATE(m_vecTarget)
|
||||
SAVE_STATE(flags)
|
||||
SAVE_STATE(m_flWidth)
|
||||
}
|
||||
|
||||
float
|
||||
phys_rope::SendEntity(entity ePVEnt, float flSendFlags)
|
||||
{
|
||||
if (!target)
|
||||
return 0;
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_PHYSROPE);
|
||||
WriteFloat(MSG_ENTITY, flSendFlags);
|
||||
|
||||
if (flSendFlags & PHYSROPE_CHANGED_MAT)
|
||||
WriteString(MSG_ENTITY, m_strShader);
|
||||
if (flSendFlags & PHYSROPE_CHANGED_SAG)
|
||||
WriteFloat(MSG_ENTITY, m_flSag);
|
||||
if (flSendFlags & PHYSROPE_CHANGED_SWING)
|
||||
WriteFloat(MSG_ENTITY, m_flSwingFactor);
|
||||
if (flSendFlags & PHYSROPE_CHANGED_SEGMENTS)
|
||||
WriteInt(MSG_ENTITY, m_iSegments);
|
||||
if (flSendFlags & PHYSROPE_CHANGED_ORIGIN) {
|
||||
WriteCoord(MSG_ENTITY, origin[0]);
|
||||
WriteCoord(MSG_ENTITY, origin[1]);
|
||||
WriteCoord(MSG_ENTITY, origin[2]);
|
||||
}
|
||||
if (flSendFlags & PHYSROPE_CHANGED_TARGET) {
|
||||
WriteCoord(MSG_ENTITY, m_vecTarget[0]);
|
||||
WriteCoord(MSG_ENTITY, m_vecTarget[1]);
|
||||
WriteCoord(MSG_ENTITY, m_vecTarget[2]);
|
||||
}
|
||||
if (flSendFlags & PHYSROPE_CHANGED_FLAGS) {
|
||||
WriteFloat(MSG_ENTITY, flags);
|
||||
}
|
||||
if (flSendFlags & PHYSROPE_CHANGED_WIDTH) {
|
||||
WriteFloat(MSG_ENTITY, m_flWidth);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
phys_rope::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "sag":
|
||||
m_flSag = stof(strValue);
|
||||
break;
|
||||
case "segments":
|
||||
m_iSegments = stoi(strValue);
|
||||
break;
|
||||
case "shader":
|
||||
m_strShader = strValue;
|
||||
break;
|
||||
case "swingfactor":
|
||||
m_flSwingFactor = stof(strValue);
|
||||
break;
|
||||
case "NextKey":
|
||||
target = ReadString(strValue);
|
||||
break;
|
||||
case "Width":
|
||||
m_flWidth = ReadFloat(strValue);
|
||||
break;
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phys_rope::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
|
||||
SaveString(handle, "m_strShader", m_strShader);
|
||||
SaveFloat(handle, "m_flSag", m_flSag);
|
||||
SaveFloat(handle, "m_flSwingFactor", m_flSwingFactor);
|
||||
SaveInt(handle, "m_iSegments", m_iSegments);
|
||||
SaveVector(handle, "m_vecTarget", m_vecTarget);
|
||||
SaveFloat(handle, "m_flWidth", m_flWidth);
|
||||
}
|
||||
|
||||
void
|
||||
phys_rope::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "RopeMaterial":
|
||||
m_strShader = ReadString(strValue);
|
||||
break;
|
||||
case "m_flSag":
|
||||
m_flSag = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_flSwingFactor":
|
||||
m_flSwingFactor = ReadFloat(strValue);
|
||||
break;
|
||||
case "Subdiv":
|
||||
m_iSegments = ReadInt(strValue);
|
||||
break;
|
||||
case "m_vecTarget":
|
||||
m_vecTarget = ReadVector(strValue);
|
||||
break;
|
||||
case "m_flWidth":
|
||||
m_flWidth = ReadFloat(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
phys_rope::phys_rope(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
m_flSwingFactor = random();
|
||||
m_flSag = 15.0f;
|
||||
m_iSegments = 16;
|
||||
m_flWidth = 2.0f;
|
||||
m_strShader = "materials/cable/cable.vmt";
|
||||
#else
|
||||
/* this is empty for a good reason */
|
||||
drawmask = MASK_ENGINE;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLASSEXPORT(move_rope, phys_rope)
|
||||
CLASSEXPORT(keyframe_rope, phys_rope)
|
|
@ -75,9 +75,9 @@ prop_physics_multiplayer::TouchThink(void)
|
|||
|
||||
if (trace_ent.flags & FL_CLIENT) {
|
||||
//print(sprintf("%s %f\n", trace_ent.classname, trace_fraction));
|
||||
PhysicsEnable();
|
||||
Wake();
|
||||
makevectors(origin - trace_ent.origin);
|
||||
ApplyForceCenter(v_forward * 64);
|
||||
ApplyForceOffset(v_forward * 64, trace_endpos);
|
||||
velocity = v_forward * 64;
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ prop_physics_multiplayer::TouchThink(void)
|
|||
} else {
|
||||
if (vlen(velocity) < 2) {
|
||||
velocity = [0,0,0];
|
||||
PhysicsDisable();
|
||||
Sleep();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,9 +127,9 @@ prop_physics_multiplayer::Respawn(void)
|
|||
super::Respawn();
|
||||
|
||||
if (HasSpawnFlags(PRPPHYS_ASLEEP))
|
||||
PhysicsDisable();
|
||||
Sleep();
|
||||
else
|
||||
PhysicsEnable();
|
||||
Wake();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -451,7 +451,7 @@ NSGameRules::DamageRadius(vector org, entity attacker, float dmg, float r, int c
|
|||
new_dmg = rint(dmg * diff);
|
||||
|
||||
if (diff > 0) {
|
||||
g_dmg_vecLocation = org;
|
||||
g_dmg_vecLocation = trace_endpos;
|
||||
DamageApply(e, attacker, new_dmg, w, DMG_EXPLODE);
|
||||
|
||||
/* approximate, feel free to tweak */
|
||||
|
|
111
src/shared/NSPhysicsConstraint.h
Normal file
111
src/shared/NSPhysicsConstraint.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CONSTRAINT_FIXED = -1, /**< Fixed constraint, aka weld, aka phys_constraint. */
|
||||
CONSTRAINT_INVALID, /**< Nothing. Default. */
|
||||
CONSTRAINT_POINT, /**< Point constraint, aka ballsocket or ball constraint, like phys_ballsocket. */
|
||||
CONSTRAINT_HINGE, /**< Hinge joint constraint. Like phys_hinge */
|
||||
CONSTRAINT_SLIDER, /**< Slider setup. Like phys_slideconstraint. */
|
||||
CONSTRAINT_UNIVERSAL, /**< Universal? TBA. */
|
||||
CONSTRAINT_HINGE2 /**< Hinge 2. TBA. */
|
||||
} constraint_t;
|
||||
|
||||
/** This entity class represents constraints for physically-simulated entities.
|
||||
|
||||
If you want to create an easy 'weld' type connection, a ballsocket or even a rope
|
||||
type connection - this class is what you need.*/
|
||||
class
|
||||
NSPhysicsConstraint:NSEntity
|
||||
{
|
||||
public:
|
||||
void NSPhysicsConstraint(void);
|
||||
|
||||
|
||||
virtual void SpawnKey(string, string);
|
||||
|
||||
#ifdef SERVER
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void Input(entity, string, string);
|
||||
#endif
|
||||
|
||||
virtual void Spawned(void);
|
||||
virtual void OnRemoveEntity(void);
|
||||
|
||||
/** Awakes the entities this constraint is connected to. */
|
||||
nonvirtual void WakeTargets(void);
|
||||
|
||||
/** Breaks the constraint. */
|
||||
nonvirtual void Break(entity);
|
||||
|
||||
/** Returns the type of this constraint entity. */
|
||||
nonvirtual constraint_t GetConstraintType(void);
|
||||
/** Returns the first entity connection. Should not return world/__NULL__ */
|
||||
nonvirtual entity GetEntity1(void);
|
||||
/** Returns the second entity connection. Can also return world/__NULL__ */
|
||||
nonvirtual entity GetEntity2(void);
|
||||
|
||||
/** Will override the constraint type this entity represents. See constraint_t for choices. */
|
||||
nonvirtual void SetConstraintType(constraint_t);
|
||||
/** Sets the first entity in the connection. Needs to be set. */
|
||||
nonvirtual void SetEntity1(entity);
|
||||
/** Sets the second entity in the connection. Can be world. */
|
||||
nonvirtual void SetEntity2(entity);
|
||||
//nonvirtual void SetBone1(float);
|
||||
//nonvirtual void SetBone2(float);
|
||||
|
||||
/** Sets the velocity on a CONSTRAINT_SLIDER type NSPhysicsConstraint. */
|
||||
nonvirtual void SetSliderVelocity(float);
|
||||
/** Sets the max velocity on a CONSTRAINT_SLIDER type NSPhysicsConstraint. */
|
||||
nonvirtual void SetSliderMaxVelocity(float);
|
||||
/** Sets the maximum travel distance of the slider. */
|
||||
nonvirtual void SetSliderStop(float);
|
||||
/** Sets the friction of the slider. */
|
||||
nonvirtual void SetSliderFriction(float);
|
||||
|
||||
/** Returns the velocity of a CONSTRAINT_SLIDER type NSPhysicsConstraint. */
|
||||
nonvirtual float GetSliderVelocity(void);
|
||||
/** Returns the max velocity of a CONSTRAINT_SLIDER type NSPhysicsConstraint. */
|
||||
nonvirtual float GetSliderMaxVelocity(void);
|
||||
/** Returns the maximum travel distance of the slider. */
|
||||
nonvirtual float GetSliderStop(void);
|
||||
/** Returns the friction of the slider. */
|
||||
nonvirtual float GetSliderFriction(void);
|
||||
/** Returns the unique joint group ID associated with a phys_constraintsystem. */
|
||||
nonvirtual float GetConstraintSystemID(void);
|
||||
|
||||
/** Creates a ballsocket constraint and returns it. */
|
||||
nonvirtual NSPhysicsConstraint Ballsocket(entity, entity, vector, vector, float, bool);
|
||||
/** Creates a ballsocket constraint and returns it. */
|
||||
nonvirtual NSPhysicsConstraint Weld(entity, entity, float, float, float, bool, bool);
|
||||
/** Creates a ballsocket constraint and returns it. */
|
||||
nonvirtual NSPhysicsConstraint Rope(entity, entity, vector, vector);
|
||||
|
||||
nonvirtual NSPhysicsConstraint KeepUpright(entity, vector, float);
|
||||
|
||||
nonvirtual void ConstraintThink(void);
|
||||
|
||||
private:
|
||||
|
||||
float m_flTorqueLimit;
|
||||
float m_flForceLimit;
|
||||
string m_strEnt1;
|
||||
string m_strEnt2;
|
||||
string m_strBreakSound;
|
||||
string m_strOnBreak;
|
||||
string m_strConstraintSystem;
|
||||
};
|
375
src/shared/NSPhysicsConstraint.qc
Normal file
375
src/shared/NSPhysicsConstraint.qc
Normal file
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Vera Visions LLC.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.vector movedir;
|
||||
.entity aiment;
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::NSPhysicsConstraint(void)
|
||||
{
|
||||
m_flTorqueLimit = 0.0f;
|
||||
m_flForceLimit = 0.0f;
|
||||
m_strEnt1 = __NULL__;
|
||||
m_strEnt2 = __NULL__;
|
||||
m_strBreakSound = __NULL__;
|
||||
m_strOnBreak = __NULL__;
|
||||
m_strConstraintSystem = __NULL__;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::ConstraintThink(void)
|
||||
{
|
||||
NSPhysicsEntity target1 = (NSPhysicsEntity)GetEntity1();
|
||||
NSPhysicsEntity target2 = (NSPhysicsEntity)GetEntity1();
|
||||
|
||||
/* never run again */
|
||||
if (m_flForceLimit <= 0 && m_flTorqueLimit <= 0)
|
||||
return;
|
||||
|
||||
if (m_flForceLimit > 0)
|
||||
if (vlen(target1.GetVelocity()) > m_flForceLimit) {
|
||||
Break(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_flTorqueLimit > 0)
|
||||
if (vlen(target1.GetAngularVelocity()) > m_flTorqueLimit) {
|
||||
Break(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_flForceLimit > 0)
|
||||
if (vlen(target2.GetVelocity()) > m_flForceLimit) {
|
||||
Break(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_flTorqueLimit > 0)
|
||||
if (vlen(target2.GetAngularVelocity()) > m_flTorqueLimit) {
|
||||
Break(this);
|
||||
return;
|
||||
}
|
||||
SetNextThink(0.0f);
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
NSPhysicsConstraint::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
SaveFloat(handle, "m_flTorqueLimit", m_flTorqueLimit);
|
||||
SaveFloat(handle, "m_flForceLimit", m_flForceLimit);
|
||||
SaveString(handle, "m_strEnt1", m_strEnt1);
|
||||
SaveString(handle, "m_strEnt2", m_strEnt2);
|
||||
SaveString(handle, "m_strBreakSound", m_strBreakSound);
|
||||
SaveString(handle, "m_strOnBreak", m_strOnBreak);
|
||||
SaveString(handle, "m_strConstraintSystem", m_strConstraintSystem);
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "m_flTorqueLimit":
|
||||
m_flTorqueLimit = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_flForceLimit":
|
||||
m_flForceLimit = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_strEnt1":
|
||||
m_strEnt1 = ReadString(strValue);
|
||||
break;
|
||||
case "m_strEnt2":
|
||||
m_strEnt2 = ReadString(strValue);
|
||||
break;
|
||||
case "m_strBreakSound":
|
||||
m_strBreakSound = ReadString(strValue);
|
||||
break;
|
||||
case "m_strOnBreak":
|
||||
m_strOnBreak = ReadString(strValue);
|
||||
break;
|
||||
case "m_strConstraintSystem":
|
||||
m_strConstraintSystem = ReadString(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::SpawnKey(string keyName, string setValue)
|
||||
{
|
||||
switch (keyName) {
|
||||
case "attach1":
|
||||
m_strEnt1 = ReadString(setValue);
|
||||
break;
|
||||
case "attach2":
|
||||
m_strEnt2 = ReadString(setValue);
|
||||
break;
|
||||
case "torquelimit":
|
||||
m_flTorqueLimit = ReadFloat(setValue);
|
||||
break;
|
||||
case "forcelimit":
|
||||
m_flForceLimit = ReadFloat(setValue);
|
||||
break;
|
||||
case "breaksound":
|
||||
m_strBreakSound = ReadString(setValue);
|
||||
break;
|
||||
case "teleportfollowdistance":
|
||||
break;
|
||||
case "constraintsystem":
|
||||
m_strConstraintSystem = ReadString(setValue);
|
||||
break;
|
||||
#ifdef SERVER
|
||||
case "OnBreak":
|
||||
m_strOnBreak = PrepareOutput(m_strOnBreak, setValue);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
super::SpawnKey(keyName, setValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsConstraint::GetConstraintSystemID(void)
|
||||
{
|
||||
entity system;
|
||||
|
||||
/* default to group 0 */
|
||||
if (!m_strConstraintSystem)
|
||||
return 0;
|
||||
|
||||
system = find(world, ::targetname, m_strConstraintSystem);
|
||||
|
||||
/* must have been invalid/mappers error */
|
||||
if (!system) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return system.jointgroup;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::Spawned(void)
|
||||
{
|
||||
super::Spawned();
|
||||
|
||||
#ifdef SERVER
|
||||
if (m_strOnBreak)
|
||||
m_strOnBreak = CreateOutput(m_strOnBreak);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
NSPhysicsConstraint::Input(entity activatorEnt, string inputName, string dataString)
|
||||
{
|
||||
switch (inputName) {
|
||||
case "Break":
|
||||
Break(activatorEnt);
|
||||
break;
|
||||
case "TurnOn":
|
||||
break;
|
||||
case "TurnOff":
|
||||
break;
|
||||
default:
|
||||
super::Input(activatorEnt, inputName, dataString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::Break(entity activatingEnt)
|
||||
{
|
||||
#ifdef SERVER
|
||||
if (m_strOnBreak)
|
||||
UseOutput(activatingEnt, m_strOnBreak);
|
||||
#endif
|
||||
|
||||
if (m_strBreakSound)
|
||||
StartSoundDef(m_strBreakSound, CHAN_AUTO, true);
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::OnRemoveEntity(void)
|
||||
{
|
||||
WakeTargets();
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::WakeTargets(void)
|
||||
{
|
||||
NSPhysicsEntity physTarget;
|
||||
|
||||
if (enemy.isPhysics) {
|
||||
physTarget = (NSPhysicsEntity)enemy;
|
||||
physTarget.Wake();
|
||||
}
|
||||
if (aiment.isPhysics) {
|
||||
physTarget = (NSPhysicsEntity)aiment;
|
||||
physTarget.Wake();
|
||||
}
|
||||
}
|
||||
|
||||
constraint_t
|
||||
NSPhysicsConstraint::GetConstraintType(void)
|
||||
{
|
||||
return (constraint_t )jointtype;
|
||||
}
|
||||
|
||||
entity
|
||||
NSPhysicsConstraint::GetEntity1(void)
|
||||
{
|
||||
return enemy;
|
||||
}
|
||||
|
||||
entity
|
||||
NSPhysicsConstraint::GetEntity2(void)
|
||||
{
|
||||
return aiment;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::SetConstraintType(constraint_t setValue)
|
||||
{
|
||||
jointtype = (float)setValue;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::SetEntity1(entity targetEnt)
|
||||
{
|
||||
enemy = targetEnt;
|
||||
jointgroup = GetConstraintSystemID();
|
||||
|
||||
/* give it some time to think. */
|
||||
ScheduleThink(ConstraintThink, 0.25f);
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::SetEntity2(entity targetEnt)
|
||||
{
|
||||
aiment = targetEnt;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::SetSliderVelocity(float slideVel)
|
||||
{
|
||||
movedir[0] = slideVel;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::SetSliderMaxVelocity(float maxVel)
|
||||
{
|
||||
movedir[1] = -fabs(maxVel);
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::SetSliderStop(float stopVal)
|
||||
{
|
||||
movedir[2] = stopVal;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsConstraint::SetSliderFriction(float frictionValue)
|
||||
{
|
||||
friction = frictionValue;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsConstraint::GetSliderVelocity(void)
|
||||
{
|
||||
return movedir[0];
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsConstraint::GetSliderMaxVelocity(void)
|
||||
{
|
||||
return movedir[1];
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsConstraint::GetSliderStop(void)
|
||||
{
|
||||
return movedir[2];
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsConstraint::GetSliderFriction(void)
|
||||
{
|
||||
return friction;
|
||||
}
|
||||
|
||||
NSPhysicsConstraint
|
||||
NSPhysicsConstraint::Ballsocket(entity firstEnt, entity secondEnt, vector pos1, vector pos2, float forceLimit, bool noCollide)
|
||||
{
|
||||
NSPhysicsConstraint new = spawn(NSPhysicsConstraint);
|
||||
new.SetConstraintType(CONSTRAINT_POINT);
|
||||
new.SetEntity1(firstEnt);
|
||||
new.SetEntity2(secondEnt);
|
||||
new.origin = pos1;
|
||||
new.velocity = pos2;
|
||||
new.WakeTargets();
|
||||
|
||||
print(sprintf("Created ballsocket between %s and %s\n", firstEnt.classname, secondEnt.classname));
|
||||
return new;
|
||||
}
|
||||
|
||||
NSPhysicsConstraint
|
||||
NSPhysicsConstraint::Weld(entity firstEnt, entity secondEnt, float bone1, float bone2, float forceLimit, bool noCollide, bool deleteEnt1OnBreak)
|
||||
{
|
||||
if (firstEnt == secondEnt) {
|
||||
print("^1Cannot weld the entity with itself!\n");
|
||||
return __NULL__;
|
||||
}
|
||||
|
||||
NSPhysicsConstraint new = spawn(NSPhysicsConstraint);
|
||||
new.SetConstraintType(CONSTRAINT_FIXED);
|
||||
new.SetEntity1(firstEnt);
|
||||
new.SetEntity2(secondEnt);
|
||||
new.WakeTargets();
|
||||
|
||||
print(sprintf("Created weld between %s and %s\n", firstEnt.classname, secondEnt.classname));
|
||||
return new;
|
||||
}
|
||||
|
||||
NSPhysicsConstraint
|
||||
NSPhysicsConstraint::Rope(entity firstEnt, entity secondEnt, vector pos1, vector pos2)
|
||||
{
|
||||
NSPhysicsConstraint new = spawn(NSPhysicsConstraint);
|
||||
new.SetConstraintType(CONSTRAINT_POINT);
|
||||
new.SetEntity1(firstEnt);
|
||||
new.SetEntity2(secondEnt);
|
||||
new.origin = pos1;
|
||||
new.velocity = pos2;
|
||||
new.WakeTargets();
|
||||
|
||||
print(sprintf("Created rope between %s and %s\n", firstEnt.classname, secondEnt.classname));
|
||||
return new;
|
||||
}
|
||||
|
||||
.float max_angular;
|
||||
NSPhysicsConstraint
|
||||
NSPhysicsConstraint::KeepUpright(entity firstEnt, vector uprightAngle, float angleLimit)
|
||||
{
|
||||
firstEnt.angles = uprightAngle;
|
||||
firstEnt.max_angular = angleLimit;
|
||||
return __NULL__;
|
||||
}
|
|
@ -14,6 +14,27 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
var bool autocvar_phys_developer = false;
|
||||
void
|
||||
_NSPhysics_Log(string msg)
|
||||
{
|
||||
if (autocvar_phys_developer == true)
|
||||
print(sprintf("%f %s\n", time, msg));
|
||||
}
|
||||
#define NSPhysics_Log(...) _NSPhysics_Log(sprintf(__VA_ARGS__))
|
||||
|
||||
|
||||
var float autocvar_phys_pushscale = 1.0f;
|
||||
var float autocvar_phys_impactforcescale = 1.0f;
|
||||
|
||||
#ifdef CLIENT
|
||||
var bool autocvar_r_showPhysicsInfo = false;
|
||||
#endif
|
||||
|
||||
.float damp_linear;
|
||||
.float damp_angular;
|
||||
.float jointgroup;
|
||||
|
||||
enum
|
||||
{
|
||||
PHYSM_BOX,
|
||||
|
@ -54,7 +75,13 @@ typedef enumflags
|
|||
PHYENT_CHANGED_RENDERMODE,
|
||||
} nsphyricsentity_changed_t;
|
||||
|
||||
/** This entity class represents physically-simulated entities. */
|
||||
/** This entity class represents physically-simulated entities.
|
||||
|
||||
The physics simulator used is controlled by the engine and may be
|
||||
subject to change.
|
||||
|
||||
Units of mass is defined in kilograms, a standard unit of measurement.
|
||||
You will find the API to be mostly compatible of that offered by Garry's Mod. */
|
||||
class NSPhysicsEntity:NSSurfacePropEntity
|
||||
{
|
||||
private:
|
||||
|
@ -63,11 +90,20 @@ private:
|
|||
int m_iMaterial;
|
||||
int m_iFlags;
|
||||
float m_flInertiaScale;
|
||||
float m_flBuoyancyRatio;
|
||||
|
||||
/* performance sanity checks */
|
||||
vector m_vecPrevOrigin;
|
||||
vector m_vecPrevAngles;
|
||||
float m_flCheckTime;
|
||||
|
||||
virtual void _TouchThink(void);
|
||||
|
||||
#ifdef SERVER
|
||||
PREDICTED_VECTOR(m_vecNetAngles)
|
||||
PREDICTED_FLOAT_N(mass)
|
||||
|
||||
string m_strOnDamaged;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
@ -77,49 +113,101 @@ public:
|
|||
virtual void Respawn(void);
|
||||
virtual void SpawnKey(string,string);
|
||||
#ifdef SERVER
|
||||
virtual void Spawned(void);
|
||||
virtual void Pain(void);
|
||||
virtual void Death(void);
|
||||
virtual void EvaluateEntity(void);
|
||||
virtual float SendEntity(entity,float);
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
virtual void Touch(entity);
|
||||
#endif
|
||||
#ifdef CLIENT
|
||||
virtual void ReceiveEntity(float,float);
|
||||
virtual void postdraw(void);
|
||||
#endif
|
||||
|
||||
/** Sets the mass of the entity in ??? */
|
||||
nonvirtual void SetMass(float);
|
||||
/** Returns the mass of the entity. */
|
||||
nonvirtual float GetMass(void);
|
||||
/** Sets the friction multiplier for this entity. Default is 1.0 */
|
||||
nonvirtual void SetFriction(float);
|
||||
/** Returns the friction multiplayer for this entity. */
|
||||
nonvirtual float GetFriction(void);
|
||||
/** Sets the bounce factor for this entity. Default is 1.0 */
|
||||
nonvirtual void SetBounceFactor(float);
|
||||
/** Returns the bounce factor of this entity. */
|
||||
nonvirtual float GetBounceFactor(void);
|
||||
/** Sets the bounce stop factor for this entity. */
|
||||
nonvirtual void SetBounceStop(float);
|
||||
/** Returns the bounce stop factor of this entity. */
|
||||
nonvirtual float GetBounceStop(void);
|
||||
/** Sets the inertia modifier for this entity. */
|
||||
nonvirtual void SetInertia(float);
|
||||
/** Returns the inertia modifier of this entity. */
|
||||
nonvirtual float GetInertia(void);
|
||||
/** Call to enable physics simulation on this entity. */
|
||||
nonvirtual void PhysicsEnable(void);
|
||||
/** Call to freeze physics simulation on this entity. */
|
||||
nonvirtual void PhysicsDisable(void);
|
||||
|
||||
/** Called by the physics routine to figure out the impact damage. */
|
||||
nonvirtual float CalculateImpactDamage(int,int);
|
||||
|
||||
/* this merely mirrors the GMod API: https://wiki.facepunch.com/gmod/PhysObj */
|
||||
|
||||
/** Call to align angles of the object to the ones passed. */
|
||||
nonvirtual vector AlignAngles(vector, vector);
|
||||
/** Call to apply a force (absolute velocity vector) to the center of the entity. */
|
||||
nonvirtual void ApplyForceCenter(vector);
|
||||
/** Call to apply force (absolute velocity vector) to a specific position on the entity. */
|
||||
/** Call to apply force (absolute velocity vector) to an absolute position on the entity. */
|
||||
nonvirtual void ApplyForceOffset(vector,vector);
|
||||
/** Call to apply torque (angular velocity vector) to the center of the entity. */
|
||||
nonvirtual void ApplyTorqueCenter(vector);
|
||||
/** Called by the physics routine to figure out the impact damage. */
|
||||
nonvirtual float CalculateImpactDamage(int,int);
|
||||
/** Call to set whether the entity should be affected by drag. */
|
||||
nonvirtual void EnableDrag(bool);
|
||||
/** Call to set whether the entity should be affected by gravity. */
|
||||
nonvirtual void EnableGravity(bool);
|
||||
/** Call to set whether the entity should be able to move. */
|
||||
nonvirtual void EnableMotion(bool);
|
||||
/** Returns the linear damping of the entity. */
|
||||
nonvirtual float GetLinearDamping(void);
|
||||
/** Returns the angular damping of the entity. */
|
||||
nonvirtual float GetAngularDamping(void);
|
||||
/** Returns the linear and rotational kinetic energy combined. */
|
||||
nonvirtual float GetEnergy(void);
|
||||
/** Returns the inertia modifier of this entity. */
|
||||
nonvirtual float GetInertia(void);
|
||||
/** Returns 1 divided by the angular inertia of this entity. */
|
||||
nonvirtual float GetInvInertia(void);
|
||||
/** Returns 1 divided by the mass of this entity. */
|
||||
nonvirtual float GetInvMass(void);
|
||||
/** Returns the mass of the entity. */
|
||||
nonvirtual float GetMass(void);
|
||||
/** Returns the center of mass of the entity. */
|
||||
nonvirtual vector GetMassCenter(void);
|
||||
/** Returns the rotational damping of the entity. */
|
||||
nonvirtual float GetRotDamping(void);
|
||||
/** Returns the speed damping of the entity. */
|
||||
nonvirtual float GetSpeedDamping(void);
|
||||
/** Returns the surface area of the entity. */
|
||||
nonvirtual float GetSurfaceArea(void);
|
||||
/** Returns the volume of the entity. */
|
||||
nonvirtual float GetVolume(void);
|
||||
/** Returns whether the entity is at rest and not moving. */
|
||||
nonvirtual bool IsAsleep(void);
|
||||
/** Returns whether the entity is able to collide with anything. */
|
||||
nonvirtual bool IsCollisionEnabled(void);
|
||||
/** Returns whether the entity is affected by drag. */
|
||||
nonvirtual bool IsDragEnabled(void);
|
||||
/** Returns whether the entity is affected by gravity. */
|
||||
nonvirtual bool IsGravityEnabled(void);
|
||||
/** Returns whether the entity is able to move by itself. */
|
||||
nonvirtual bool IsMotionEnabled(void);
|
||||
/** Returns whether the entity is able to move. */
|
||||
nonvirtual bool IsMoveable(void);
|
||||
/** Returns whether the entity is penetrating another object. */
|
||||
nonvirtual bool IsPenetrating(void);
|
||||
|
||||
/** Call to set the amount of rotational drag the entity experiences. */
|
||||
nonvirtual void SetAngleDragCoefficient(float);
|
||||
/** Call to set the buoyancy ratio of the entity. 0 is not buoyant, 1 is very buoyant. */
|
||||
nonvirtual void SetBuoyancyRatio(float);
|
||||
/** Call to set the linear and angular damping of the entity. */
|
||||
nonvirtual void SetDamping(float, float);
|
||||
/** Call to set how much drag affects the entity. */
|
||||
nonvirtual void SetDragCoefficient(float);
|
||||
|
||||
/** Sets the angular inertia for this entity. */
|
||||
nonvirtual void SetInertia(float);
|
||||
/** Sets the mass of the entity in kilograms. */
|
||||
nonvirtual void SetMass(float);
|
||||
|
||||
/** Call to enable physics simulation on this entity. */
|
||||
nonvirtual void Wake(void);
|
||||
/** Call to freeze physics simulation on this entity. */
|
||||
nonvirtual void Sleep(void);
|
||||
};
|
||||
|
||||
noref .bool isPhysics;
|
|
@ -14,30 +14,64 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define ODE_MODE 1
|
||||
.float max_angular;
|
||||
|
||||
void
|
||||
NSPhysicsEntity::NSPhysicsEntity(void)
|
||||
{
|
||||
isPhysics = true;
|
||||
mass = 1.0f;
|
||||
isPhysics = true;
|
||||
m_flInertiaScale = 1.0f;
|
||||
|
||||
m_iEnabled = 0i;
|
||||
m_iShape = PHYSM_BOX;
|
||||
m_iMaterial = 0i;
|
||||
m_iFlags = 0i;
|
||||
damp_linear = 1.0f;
|
||||
damp_angular = 1.0f;
|
||||
max_angular = -1.0f;
|
||||
|
||||
#ifdef ODE_MODE
|
||||
cvar_set("physics_ode_iterationsperframe", "1");
|
||||
cvar_set("physics_ode_movelimit", "0.1");
|
||||
#else
|
||||
cvar_set("physics_bullet_maxiterationsperframe", "10");
|
||||
cvar_set("physics_bullet_framerate", "60");
|
||||
|
||||
cvar_set("physics_ode_quadtree_depth", "10");
|
||||
cvar_set("physics_ode_contactsurfacelayer", "0");
|
||||
cvar_set("physics_ode_worldquickstep", "1");
|
||||
cvar_set("physics_ode_worldquickstep_iterations", "20");
|
||||
cvar_set("physics_ode_contact_mu", "-1");
|
||||
cvar_set("physics_ode_contact_erp", "0.96");
|
||||
cvar_set("physics_ode_contact_cfm", "0.001");
|
||||
cvar_set("physics_ode_world_damping", "1");
|
||||
cvar_set("physics_ode_world_damping_linear", "-1");
|
||||
cvar_set("physics_ode_world_damping_linear_threshold", "-1");
|
||||
cvar_set("physics_ode_world_damping_angular", "-1");
|
||||
cvar_set("physics_ode_world_damping_angular_threshold", "-1");
|
||||
cvar_set("physics_ode_world_erp", "-1");
|
||||
cvar_set("physics_ode_world_cfm", "-1");
|
||||
cvar_set("physics_ode_iterationsperframe", "4");
|
||||
cvar_set("physics_ode_movelimit", "0.5");
|
||||
cvar_set("physics_ode_spinlimit", "10000");
|
||||
cvar_set("physics_ode_autodisable", "1");
|
||||
cvar_set("physics_ode_autodisable_steps", "10");
|
||||
cvar_set("physics_ode_autodisable_time", "0.1");
|
||||
cvar_set("physics_ode_autodisable_threshold_linear", "0.2");
|
||||
cvar_set("physics_ode_autodisable_threshold_angular", "0.3");
|
||||
cvar_set("physics_ode_autodisable_threshold_samples", "5");
|
||||
|
||||
#ifdef SERVER
|
||||
m_strOnDamaged = __NULL__;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
NSPhysicsEntity::Spawned(void)
|
||||
{
|
||||
super::Spawned();
|
||||
|
||||
/* I/O */
|
||||
if (m_strOnDamaged)
|
||||
m_strOnDamaged = CreateOutput(m_strOnDamaged);
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::Save(float handle)
|
||||
{
|
||||
|
@ -47,6 +81,7 @@ NSPhysicsEntity::Save(float handle)
|
|||
SaveInt(handle, "m_iMaterial", m_iMaterial);
|
||||
SaveInt(handle, "m_iFlags", m_iFlags);
|
||||
SaveFloat(handle, "m_flInertiaScale", m_flInertiaScale);
|
||||
SaveString(handle, "m_strOnDamaged", m_strOnDamaged);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -68,6 +103,9 @@ NSPhysicsEntity::Restore(string strKey, string strValue)
|
|||
case "m_flInertiaScale":
|
||||
m_flInertiaScale = ReadFloat(strValue);
|
||||
break;
|
||||
case "m_strOnDamaged":
|
||||
m_strOnDamaged = ReadString(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
|
@ -141,6 +179,7 @@ NSPhysicsEntity::EvaluateEntity(void)
|
|||
EVALUATE_FIELD(m_flBoneControl3, RDENT_CHANGED_CONTROLLER)
|
||||
EVALUATE_FIELD(m_flBoneControl4, RDENT_CHANGED_CONTROLLER)
|
||||
EVALUATE_FIELD(m_flBoneControl5, RDENT_CHANGED_CONTROLLER)
|
||||
EVALUATE_FIELD(mass, RDENT_CHANGED_SOLIDMOVETYPE)
|
||||
}
|
||||
|
||||
float
|
||||
|
@ -229,6 +268,9 @@ NSPhysicsEntity::SendEntity(entity ePEnt, float flChanged)
|
|||
SENDENTITY_ANGLE(m_flBoneControl4, RDENT_CHANGED_CONTROLLER)
|
||||
SENDENTITY_ANGLE(m_flBoneControl5, RDENT_CHANGED_CONTROLLER)
|
||||
|
||||
/* physics specific flags */
|
||||
SENDENTITY_FLOAT(mass, RDENT_CHANGED_SOLIDMOVETYPE)
|
||||
|
||||
return (1);
|
||||
}
|
||||
#else
|
||||
|
@ -290,6 +332,9 @@ NSPhysicsEntity::ReceiveEntity(float flNew, float flChanged)
|
|||
READENTITY_ANGLE(m_flBoneControl4, RDENT_CHANGED_CONTROLLER)
|
||||
READENTITY_ANGLE(m_flBoneControl5, RDENT_CHANGED_CONTROLLER)
|
||||
|
||||
/* physics specific flags */
|
||||
READENTITY_FLOAT(mass, RDENT_CHANGED_SOLIDMOVETYPE)
|
||||
|
||||
if (scale == 0.0)
|
||||
scale = 1.0f;
|
||||
|
||||
|
@ -300,47 +345,23 @@ NSPhysicsEntity::ReceiveEntity(float flNew, float flChanged)
|
|||
|
||||
movetype = MOVETYPE_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::postdraw(void)
|
||||
{
|
||||
if not (autocvar_r_showPhysicsInfo)
|
||||
return;
|
||||
|
||||
if not (PointMessage_Visible(WorldSpaceCenter(), g_view.GetCameraOrigin(), g_view.GetCameraAngle()))
|
||||
return;
|
||||
|
||||
string renderString = sprintf("Mass: %f\nEnergy: %f\nInertia:%d",
|
||||
GetMass(), GetEnergy(), GetInertia());
|
||||
|
||||
PointMessage_StringAtPos(WorldSpaceCenter(), renderString);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
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_NONE);
|
||||
SetSolid(SOLID_BBOX);
|
||||
}
|
||||
m_iEnabled = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetMass(float val)
|
||||
{
|
||||
mass = val;
|
||||
}
|
||||
float
|
||||
NSPhysicsEntity::GetMass(void)
|
||||
{
|
||||
return mass;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetFriction(float val)
|
||||
{
|
||||
|
@ -352,38 +373,6 @@ 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)
|
||||
|
@ -403,57 +392,30 @@ NSPhysicsEntity::CalculateImpactDamage(int iDamage, int dmgType)
|
|||
filter |= (dmgType & DMG_SLOWFREEZE);
|
||||
|
||||
if (filter == 0i)
|
||||
return (float)iDamage * 100;
|
||||
return (float)iDamage * autocvar_phys_impactforcescale;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyForceCenter(vector vecForce)
|
||||
int
|
||||
NSPhysicsEntity_Contents(vector org)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
physics_addforce(this, vecForce, [0,0,0]);
|
||||
#ifdef ODE_MODE
|
||||
//velocity += vecForce;
|
||||
int oldhitcontents = self.hitcontentsmaski;
|
||||
self.hitcontentsmaski = -1;
|
||||
traceline(org, org, MOVE_EVERYTHING, self);
|
||||
self.hitcontentsmaski = oldhitcontents;
|
||||
return trace_endcontentsi;
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
NSPhysicsEntity::Touch(entity eToucher)
|
||||
{
|
||||
if (eToucher)
|
||||
if (eToucher.movetype)
|
||||
Wake();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
velocity += vecForce;
|
||||
}
|
||||
|
||||
/* make sure touch think is called */
|
||||
nextthink = time;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyForceOffset(vector vecForce, vector vecOffset)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
physics_addforce(this, vecForce, vecOffset);
|
||||
#ifdef ODE_MODE
|
||||
//velocity += vecForce;
|
||||
#endif
|
||||
} else {
|
||||
velocity += vecForce;
|
||||
}
|
||||
|
||||
/* make sure touch think is called */
|
||||
nextthink = time;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyTorqueCenter(vector vecTorque)
|
||||
{
|
||||
if (physics_supported() == TRUE)
|
||||
physics_addtorque(this, vecTorque * m_flInertiaScale);
|
||||
else {
|
||||
avelocity = vecTorque;
|
||||
velocity = vecTorque;
|
||||
velocity[2] = 96;
|
||||
}
|
||||
|
||||
/* make sure touch think is called */
|
||||
nextthink = time;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::_TouchThink(void)
|
||||
|
@ -473,21 +435,36 @@ NSPhysicsEntity::_TouchThink(void)
|
|||
if (trace_startsolid) {
|
||||
if (trace_ent.flags & FL_CLIENT) {
|
||||
if (trace_ent.absmin[2] < absmax[2]) {
|
||||
PhysicsEnable();
|
||||
makevectors(vectoangles(origin - trace_ent.origin));
|
||||
Wake();
|
||||
makevectors(vectoangles(trace_endpos - trace_ent.origin));
|
||||
ApplyTorqueCenter(v_forward * 240);
|
||||
} else {
|
||||
PhysicsDisable();
|
||||
Sleep();
|
||||
velocity = [0,0,0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (m_flCheckTime < time) {
|
||||
bool should
|
||||
if (vlen(m_vecPrevAngles - angles) < 1) {
|
||||
avelocity = [0,0,0];
|
||||
}
|
||||
if (vlen(m_vecPrevOrigin - origin) < 1) {
|
||||
velocity = [0,0,0];
|
||||
}
|
||||
m_flCheckTime = time + 1.0f;
|
||||
m_vecPrevOrigin = origin;
|
||||
m_vecPrevAngles = angles;
|
||||
}
|
||||
|
||||
/* If we barely move, disable the physics simulator */
|
||||
if (vlen(velocity) <= 1) {
|
||||
if (velocity == g_vec_null && avelocity == g_vec_null) {
|
||||
if (m_iEnabled) {
|
||||
PhysicsDisable();
|
||||
NSPhysics_Log("%s is now sleeping.", classname);
|
||||
Sleep();
|
||||
velocity = [0,0,0];
|
||||
avelocity = [0,0,0];
|
||||
}
|
||||
|
@ -508,6 +485,18 @@ NSPhysicsEntity::_TouchThink(void)
|
|||
angles = vectoangles(newangle);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (m_flBuoyancyRatio > 0.0)
|
||||
if (NSPhysicsEntity_Contents(origin) & CONTENTBIT_WATER) {
|
||||
makevectors([0,0,0]);
|
||||
velocity[2] += m_flBuoyancyRatio;
|
||||
print(sprintf("in water... applying %v\n", v_up * (GetMass() * m_flBuoyancyRatio)));
|
||||
}
|
||||
#endif
|
||||
|
||||
hitcontentsmaski &= ~CONTENTBITS_FLUID;
|
||||
|
||||
if (physics_supported() == FALSE) {
|
||||
/* don't let players collide */
|
||||
|
@ -524,18 +513,22 @@ NSPhysicsEntity::_TouchThink(void)
|
|||
void
|
||||
NSPhysicsEntity::Pain(void)
|
||||
{
|
||||
vector forceDir;
|
||||
float force;
|
||||
|
||||
if (m_strOnDamaged)
|
||||
UseOutput(this, m_strOnDamaged);
|
||||
|
||||
if (m_iFlags & BPHY_NODMGPUSH)
|
||||
return;
|
||||
|
||||
PhysicsEnable();
|
||||
Wake();
|
||||
|
||||
makevectors(vectoangles(origin - trace_endpos));
|
||||
forceDir = normalize(GetOrigin() - g_dmg_vecLocation);
|
||||
force = CalculateImpactDamage(g_dmg_iDamage, g_dmg_iFlags);
|
||||
|
||||
if (force > 0.0f)
|
||||
ApplyForceOffset(v_forward * force, origin - trace_endpos);
|
||||
ApplyForceOffset(forceDir * force, g_dmg_vecLocation);
|
||||
|
||||
/* if we don't have prop data, don't consider death */
|
||||
if (HasPropData() == false)
|
||||
|
@ -564,28 +557,35 @@ NSPhysicsEntity::Death(void)
|
|||
void
|
||||
NSPhysicsEntity::Respawn(void)
|
||||
{
|
||||
ClearVelocity();
|
||||
SetMovetype(MOVETYPE_PHYSICS);
|
||||
SetSolid(SOLID_PHYSICS_BOX + m_iShape);
|
||||
SetSolid(SOLID_BSP);
|
||||
SetModel(GetSpawnModel());
|
||||
|
||||
#ifdef SERVER
|
||||
SetTakedamage(DAMAGE_YES);
|
||||
#endif
|
||||
|
||||
#ifndef ODE_MODE
|
||||
PhysicsDisable();
|
||||
SetFriction(4.0f);
|
||||
SetBounceFactor(0.05f);
|
||||
SetMass(1.0f);
|
||||
#else
|
||||
PhysicsDisable();
|
||||
SetMass(1.0f);
|
||||
Sleep();
|
||||
SetMass(10.0f);
|
||||
SetFriction(1.0f);
|
||||
SetBounceFactor(0.1f);
|
||||
SetBuoyancyRatio(1.0f);
|
||||
bouncefactor = 0.9f;
|
||||
bouncestop = 0.1f / cvar("sv_gravity");
|
||||
|
||||
//bouncefactor = 0.0f;
|
||||
//bouncestop = 0.0f;
|
||||
|
||||
geomtype = GEOMTYPE_TRIMESH;
|
||||
#endif
|
||||
friction = 100.0f;
|
||||
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
m_flBuoyancyRatio = 1.0f;
|
||||
|
||||
SetDamping(0.0f, 0.0f);
|
||||
EnableGravity(true);
|
||||
|
||||
hitcontentsmaski &= ~CONTENTBITS_FLUID;
|
||||
|
||||
if (physics_supported() == FALSE) {
|
||||
/* don't let players collide */
|
||||
|
@ -641,8 +641,292 @@ NSPhysicsEntity::SpawnKey(string strKey, string strValue)
|
|||
if (tempCheck == true)
|
||||
m_iFlags |= BPHY_SHARP;
|
||||
break;
|
||||
#ifdef SERVER
|
||||
case "OnDamaged":
|
||||
m_strOnDamaged = PrepareOutput(m_strOnDamaged, strValue);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
super::SpawnKey(strKey, strValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* GMod API starts here */
|
||||
|
||||
vector
|
||||
NSPhysicsEntity::AlignAngles(vector from, vector to)
|
||||
{
|
||||
NSEntWarning("Not implemented");
|
||||
return angles;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyForceCenter(vector vecForce)
|
||||
{
|
||||
Wake();
|
||||
|
||||
if (physics_supported() == TRUE) {
|
||||
vector finalForce = vecForce;
|
||||
physics_addforce(this, finalForce, GetMassCenter());
|
||||
|
||||
NSPhysics_Log("%s::ApplyForceCenter: %v (val: %v)",
|
||||
classname, finalForce, vecForce);
|
||||
} else {
|
||||
velocity += vecForce;
|
||||
}
|
||||
|
||||
/* make sure touch think is called */
|
||||
nextthink = time;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyForceOffset(vector vecForce, vector vecOffset)
|
||||
{
|
||||
Wake();
|
||||
|
||||
if (physics_supported() == TRUE) {
|
||||
vector finalForce = vecForce;
|
||||
physics_addforce(this, finalForce, vecOffset);
|
||||
|
||||
NSPhysics_Log("%s::ApplyForceOffset: %v at pos %v (val: %v)",
|
||||
classname, finalForce, vecOffset, vecForce);
|
||||
|
||||
#ifdef ODE_MODE
|
||||
//velocity += vecForce;
|
||||
#endif
|
||||
} else {
|
||||
velocity += vecForce;
|
||||
}
|
||||
|
||||
/* make sure touch think is called */
|
||||
nextthink = time;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::ApplyTorqueCenter(vector vecTorque)
|
||||
{
|
||||
Wake();
|
||||
|
||||
if (physics_supported() == TRUE) {
|
||||
vector finalTorque = vecTorque * m_flInertiaScale;
|
||||
physics_addtorque(this, finalTorque);
|
||||
|
||||
NSPhysics_Log("%s::ApplyTorqueCenter: %v (val: %v, scale: %f)",
|
||||
classname, finalTorque, vecTorque, m_flInertiaScale);
|
||||
} else {
|
||||
avelocity = vecTorque;
|
||||
velocity = vecTorque;
|
||||
velocity[2] = 96;
|
||||
}
|
||||
|
||||
/* make sure touch think is called */
|
||||
nextthink = time;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::EnableDrag(bool setEnabled)
|
||||
{
|
||||
NSEntWarning("Not implemented");
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::EnableGravity(bool setEnabled)
|
||||
{
|
||||
/* the engine checks if .gravity is < 0.01...) */
|
||||
gravity = setEnabled ? 1.0f : 0.005;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::EnableMotion(bool setEnabled)
|
||||
{
|
||||
NSEntWarning("Not implemented");
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetLinearDamping(void)
|
||||
{
|
||||
return damp_linear;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetAngularDamping(void)
|
||||
{
|
||||
return damp_angular;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetEnergy(void)
|
||||
{
|
||||
float linearEnergy;
|
||||
float rotationalEnergy;
|
||||
|
||||
linearEnergy = (0.5f * GetMass() * vlen(GetVelocity()));
|
||||
linearEnergy *= linearEnergy;
|
||||
|
||||
rotationalEnergy = (0.5f * GetMass() * vlen(GetAngularVelocity()));
|
||||
rotationalEnergy *= rotationalEnergy;
|
||||
|
||||
return linearEnergy + rotationalEnergy;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetInertia(void)
|
||||
{
|
||||
return m_flInertiaScale;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetInvInertia(void)
|
||||
{
|
||||
return 1.0f / m_flInertiaScale;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetInvMass(void)
|
||||
{
|
||||
return 1.0f / mass;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetMass(void)
|
||||
{
|
||||
return mass;
|
||||
}
|
||||
|
||||
vector
|
||||
NSPhysicsEntity::GetMassCenter(void)
|
||||
{
|
||||
return WorldSpaceCenter();
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetRotDamping(void)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetSpeedDamping(void)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetSurfaceArea(void)
|
||||
{
|
||||
return vlen(size) / 4;
|
||||
}
|
||||
|
||||
float
|
||||
NSPhysicsEntity::GetVolume(void)
|
||||
{
|
||||
return vlen(size);
|
||||
}
|
||||
|
||||
bool
|
||||
NSPhysicsEntity::IsAsleep(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NSPhysicsEntity::IsCollisionEnabled(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NSPhysicsEntity::IsDragEnabled(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NSPhysicsEntity::IsGravityEnabled(void)
|
||||
{
|
||||
return (gravity < 0.01) ? false : true;
|
||||
}
|
||||
|
||||
bool
|
||||
NSPhysicsEntity::IsMotionEnabled(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NSPhysicsEntity::IsMoveable(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NSPhysicsEntity::IsPenetrating(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetAngleDragCoefficient(float setValue)
|
||||
{
|
||||
NSEntWarning("Not implemented");
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetBuoyancyRatio(float setValue)
|
||||
{
|
||||
m_flBuoyancyRatio = setValue;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetDamping(float linearDamp, float angleDamp)
|
||||
{
|
||||
damp_linear = linearDamp;
|
||||
damp_angular = angleDamp;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetDragCoefficient(float dragValue)
|
||||
{
|
||||
NSEntWarning("Not implemented");
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetInertia(float val)
|
||||
{
|
||||
m_flInertiaScale = val;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::SetMass(float val)
|
||||
{
|
||||
mass = val;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::Wake(void)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
SetMovetype(MOVETYPE_PHYSICS);
|
||||
SetSolid(SOLID_BSP);
|
||||
physics_enable(this, TRUE);
|
||||
} else {
|
||||
SetMovetype(MOVETYPE_BOUNCE);
|
||||
SetSolid(SOLID_CORPSE);
|
||||
}
|
||||
m_iEnabled = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
NSPhysicsEntity::Sleep(void)
|
||||
{
|
||||
if (physics_supported() == TRUE) {
|
||||
ClearVelocity();
|
||||
physics_enable(this, FALSE);
|
||||
SetMovetype(MOVETYPE_NONE);
|
||||
} else {
|
||||
SetMovetype(MOVETYPE_NONE);
|
||||
SetSolid(SOLID_BBOX);
|
||||
}
|
||||
m_iEnabled = FALSE;
|
||||
}
|
|
@ -87,6 +87,7 @@ string __fullspawndata;
|
|||
#include "NSRenderableEntity.h"
|
||||
#include "NSSurfacePropEntity.h"
|
||||
#include "NSMoverEntity.h"
|
||||
#include "NSPhysicsConstraint.h"
|
||||
#include "NSPhysicsEntity.h"
|
||||
#include "NSBrushTrigger.h"
|
||||
#include "NSPointTrigger.h"
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef enum
|
|||
ENT_VEH_TANKMORTAR, /**< of type func_tankmortar */
|
||||
ENT_VEH_4WHEEL, /**< of type prop_vehicle_driveable */
|
||||
ENT_PROPROPE, /**< of type prop_rope */
|
||||
ENT_PHYSROPE, /**< of type phys_rope */
|
||||
ENT_BUBBLES, /**< of type env_bubbles */
|
||||
ENT_CONVEYOR, /**< of type func_conveyor */
|
||||
ENT_WAYPOINT, /**< of type info_waypoint */
|
||||
|
|
|
@ -7,6 +7,7 @@ NSTimer.qc
|
|||
NSRenderableEntity.qc
|
||||
NSSurfacePropEntity.qc
|
||||
NSMoverEntity.qc
|
||||
NSPhysicsConstraint.qc
|
||||
NSPhysicsEntity.qc
|
||||
NSBrushTrigger.qc
|
||||
NSPointTrigger.qc
|
||||
|
|
Loading…
Reference in a new issue