mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-16 00:01:53 +02:00
Initial Prey Game integration support.
This commit is contained in:
@@ -0,0 +1,539 @@
|
||||
// Copyright (C) 2004 Id Software, Inc.
|
||||
//
|
||||
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "Game_local.h"
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
idMoveable
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
const idEventDef EV_BecomeNonSolid( "becomeNonSolid" );
|
||||
const idEventDef EV_SetOwnerFromSpawnArgs( "<setOwnerFromSpawnArgs>" );
|
||||
const idEventDef EV_IsAtRest( "isAtRest", NULL, 'd' );
|
||||
const idEventDef EV_EnableDamage( "enableDamage", "f" );
|
||||
|
||||
CLASS_DECLARATION( idEntity, idMoveable )
|
||||
EVENT( EV_Activate, idMoveable::Event_Activate )
|
||||
EVENT( EV_BecomeNonSolid, idMoveable::Event_BecomeNonSolid )
|
||||
EVENT( EV_SetOwnerFromSpawnArgs, idMoveable::Event_SetOwnerFromSpawnArgs )
|
||||
EVENT( EV_IsAtRest, idMoveable::Event_IsAtRest )
|
||||
EVENT( EV_EnableDamage, idMoveable::Event_EnableDamage )
|
||||
END_CLASS
|
||||
|
||||
|
||||
static const float BOUNCE_SOUND_MIN_VELOCITY = 80.0f;
|
||||
static const float BOUNCE_SOUND_MAX_VELOCITY = 200.0f;
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::idMoveable
|
||||
================
|
||||
*/
|
||||
idMoveable::idMoveable( void ) {
|
||||
minDamageVelocity = 100.0f;
|
||||
maxDamageVelocity = 200.0f;
|
||||
nextCollideFxTime = 0;
|
||||
nextDamageTime = 0;
|
||||
nextSoundTime = 0;
|
||||
initialSpline = NULL;
|
||||
initialSplineDir = vec3_zero;
|
||||
// explode = false; // HUMANHEAD pdm: Removed expode support, use health>0 to make it get removed
|
||||
unbindOnDeath = false;
|
||||
allowStep = false;
|
||||
canDamage = false;
|
||||
#ifdef HUMANHEAD //jsh
|
||||
fl.networkSync = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::~idMoveable
|
||||
================
|
||||
*/
|
||||
idMoveable::~idMoveable( void ) {
|
||||
delete initialSpline;
|
||||
initialSpline = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Spawn
|
||||
================
|
||||
*/
|
||||
void idMoveable::Spawn( void ) {
|
||||
idTraceModel trm;
|
||||
float density, friction, bouncyness, mass;
|
||||
int clipShrink;
|
||||
idStr clipModelName;
|
||||
|
||||
// check if a clip model is set
|
||||
spawnArgs.GetString( "clipmodel", "", clipModelName );
|
||||
if ( !clipModelName[0] ) {
|
||||
clipModelName = spawnArgs.GetString( "model" ); // use the visual model
|
||||
}
|
||||
|
||||
if ( !collisionModelManager->TrmFromModel( clipModelName, trm ) ) {
|
||||
gameLocal.Error( "idMoveable '%s': cannot load collision model %s", name.c_str(), clipModelName.c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
// if the model should be shrinked
|
||||
clipShrink = spawnArgs.GetInt( "clipshrink" );
|
||||
if ( clipShrink != 0 ) {
|
||||
trm.Shrink( clipShrink * CM_CLIP_EPSILON );
|
||||
}
|
||||
|
||||
// get rigid body properties
|
||||
spawnArgs.GetFloat( "density", "0.5", density );
|
||||
density = idMath::ClampFloat( 0.001f, 1000.0f, density );
|
||||
spawnArgs.GetFloat( "friction", "0.05", friction );
|
||||
friction = idMath::ClampFloat( 0.0f, 1.0f, friction );
|
||||
spawnArgs.GetFloat( "bouncyness", "0.6", bouncyness );
|
||||
bouncyness = idMath::ClampFloat( 0.0f, 1.0f, bouncyness );
|
||||
// explode = spawnArgs.GetBool( "explode" ); // HUMANHEAD pdm: Removed expode support, use health>0 to make it get removed
|
||||
unbindOnDeath = spawnArgs.GetBool( "unbindondeath" );
|
||||
|
||||
fxCollide = spawnArgs.GetString( "fx_collide" );
|
||||
nextCollideFxTime = 0;
|
||||
|
||||
fl.takedamage = true;
|
||||
damage = spawnArgs.GetString( "def_damage", "" );
|
||||
canDamage = spawnArgs.GetBool( "damageWhenActive" ) ? false : true;
|
||||
minDamageVelocity = spawnArgs.GetFloat( "minDamageVelocity", "100" );
|
||||
maxDamageVelocity = spawnArgs.GetFloat( "maxDamageVelocity", "200" );
|
||||
nextDamageTime = 0;
|
||||
nextSoundTime = 0;
|
||||
|
||||
health = spawnArgs.GetInt( "health", "0" );
|
||||
// HUMANHEAD pdm: unused
|
||||
// spawnArgs.GetString( "broken", "", brokenModel );
|
||||
|
||||
// HUMANHEAD pdm: unused
|
||||
// if ( health ) {
|
||||
// if ( brokenModel != "" && !renderModelManager->CheckModel( brokenModel ) ) {
|
||||
// gameLocal.Error( "idMoveable '%s' at (%s): cannot load broken model '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), brokenModel.c_str() );
|
||||
// }
|
||||
// }
|
||||
|
||||
// setup the physics
|
||||
physicsObj.SetSelf( this );
|
||||
physicsObj.SetClipModel( new idClipModel( trm ), density );
|
||||
physicsObj.GetClipModel()->SetMaterial( GetRenderModelMaterial() );
|
||||
physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
|
||||
physicsObj.SetAxis( GetPhysics()->GetAxis() );
|
||||
physicsObj.SetBouncyness( bouncyness );
|
||||
physicsObj.SetFriction( 0.6f, 0.6f, friction );
|
||||
physicsObj.SetGravity( gameLocal.GetGravity() );
|
||||
physicsObj.SetContents( CONTENTS_SOLID );
|
||||
physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
|
||||
SetPhysics( &physicsObj );
|
||||
|
||||
if ( spawnArgs.GetFloat( "mass", "10", mass ) ) {
|
||||
physicsObj.SetMass( mass );
|
||||
}
|
||||
|
||||
if ( spawnArgs.GetBool( "nodrop" ) ) {
|
||||
physicsObj.PutToRest();
|
||||
} else {
|
||||
physicsObj.DropToFloor();
|
||||
}
|
||||
|
||||
if ( spawnArgs.GetBool( "noimpact" ) || spawnArgs.GetBool( "notPushable" ) ) {
|
||||
physicsObj.DisableImpact();
|
||||
}
|
||||
|
||||
if ( spawnArgs.GetBool( "nonsolid" ) ) {
|
||||
BecomeNonSolid();
|
||||
}
|
||||
|
||||
allowStep = spawnArgs.GetBool( "allowStep", "1" );
|
||||
|
||||
PostEventMS( &EV_SetOwnerFromSpawnArgs, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Save
|
||||
================
|
||||
*/
|
||||
void idMoveable::Save( idSaveGame *savefile ) const {
|
||||
|
||||
// savefile->WriteString( brokenModel ); // HUMANHEAD pdm: unused
|
||||
savefile->WriteString( damage );
|
||||
savefile->WriteString( fxCollide );
|
||||
savefile->WriteInt( nextCollideFxTime );
|
||||
savefile->WriteFloat( minDamageVelocity );
|
||||
savefile->WriteFloat( maxDamageVelocity );
|
||||
// savefile->WriteBool( explode ); // HUMANHEAD pdm: Removed expode support, use health>0 to make it get removed
|
||||
savefile->WriteBool( unbindOnDeath );
|
||||
savefile->WriteBool( allowStep );
|
||||
savefile->WriteBool( canDamage );
|
||||
savefile->WriteInt( nextDamageTime );
|
||||
savefile->WriteInt( nextSoundTime );
|
||||
savefile->WriteInt( initialSpline != NULL ? initialSpline->GetTime( 0 ) : -1 );
|
||||
savefile->WriteVec3( initialSplineDir );
|
||||
|
||||
savefile->WriteStaticObject( physicsObj );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Restore
|
||||
================
|
||||
*/
|
||||
void idMoveable::Restore( idRestoreGame *savefile ) {
|
||||
int initialSplineTime;
|
||||
|
||||
// savefile->ReadString( brokenModel ); // HUMANHEAD pdm: unused
|
||||
savefile->ReadString( damage );
|
||||
savefile->ReadString( fxCollide );
|
||||
savefile->ReadInt( nextCollideFxTime );
|
||||
savefile->ReadFloat( minDamageVelocity );
|
||||
savefile->ReadFloat( maxDamageVelocity );
|
||||
// savefile->ReadBool( explode ); // HUMANHEAD pdm: Removed expode support, use health>0 to make it get removed
|
||||
savefile->ReadBool( unbindOnDeath );
|
||||
savefile->ReadBool( allowStep );
|
||||
savefile->ReadBool( canDamage );
|
||||
savefile->ReadInt( nextDamageTime );
|
||||
savefile->ReadInt( nextSoundTime );
|
||||
savefile->ReadInt( initialSplineTime );
|
||||
savefile->ReadVec3( initialSplineDir );
|
||||
|
||||
if ( initialSplineTime != -1 ) {
|
||||
InitInitialSpline( initialSplineTime );
|
||||
} else {
|
||||
initialSpline = NULL;
|
||||
}
|
||||
|
||||
savefile->ReadStaticObject( physicsObj );
|
||||
RestorePhysics( &physicsObj );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Hide
|
||||
================
|
||||
*/
|
||||
void idMoveable::Hide( void ) {
|
||||
idEntity::Hide();
|
||||
physicsObj.SetContents( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Show
|
||||
================
|
||||
*/
|
||||
void idMoveable::Show( void ) {
|
||||
idEntity::Show();
|
||||
if ( !spawnArgs.GetBool( "nonsolid" ) ) {
|
||||
physicsObj.SetContents( CONTENTS_SOLID );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idMoveable::Collide
|
||||
=================
|
||||
*/
|
||||
bool idMoveable::Collide( const trace_t &collision, const idVec3 &velocity ) {
|
||||
float v, f;
|
||||
idVec3 dir;
|
||||
idEntity *ent;
|
||||
|
||||
v = -( velocity * collision.c.normal );
|
||||
if ( v > BOUNCE_SOUND_MIN_VELOCITY && gameLocal.time > nextSoundTime ) {
|
||||
f = v > BOUNCE_SOUND_MAX_VELOCITY ? 1.0f : idMath::Sqrt( v - BOUNCE_SOUND_MIN_VELOCITY ) * ( 1.0f / idMath::Sqrt( BOUNCE_SOUND_MAX_VELOCITY - BOUNCE_SOUND_MIN_VELOCITY ) );
|
||||
if ( StartSound( "snd_bounce", SND_CHANNEL_ANY, 0, false, NULL ) ) {
|
||||
// don't set the volume unless there is a bounce sound as it overrides the entire channel
|
||||
// which causes footsteps on ai's to not honor their shader parms
|
||||
SetSoundVolume( f );
|
||||
}
|
||||
nextSoundTime = gameLocal.time + 500;
|
||||
}
|
||||
|
||||
if ( canDamage && damage.Length() && gameLocal.time > nextDamageTime ) {
|
||||
ent = gameLocal.entities[ collision.c.entityNum ];
|
||||
if ( ent && v > minDamageVelocity ) {
|
||||
f = v > maxDamageVelocity ? 1.0f : idMath::Sqrt( v - minDamageVelocity ) * ( 1.0f / idMath::Sqrt( maxDamageVelocity - minDamageVelocity ) );
|
||||
dir = velocity;
|
||||
dir.NormalizeFast();
|
||||
ent->Damage( this, GetPhysics()->GetClipModel()->GetOwner(), dir, damage, f, INVALID_JOINT );
|
||||
nextDamageTime = gameLocal.time + 1000;
|
||||
}
|
||||
}
|
||||
|
||||
if ( fxCollide.Length() && gameLocal.time > nextCollideFxTime ) {
|
||||
idEntityFx::StartFx( fxCollide, &collision.c.point, NULL, this, false );
|
||||
nextCollideFxTime = gameLocal.time + 3500;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idMoveable::Killed
|
||||
============
|
||||
*/
|
||||
void idMoveable::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
|
||||
/* HUMANHEAD pdm: overridden
|
||||
if ( unbindOnDeath ) {
|
||||
Unbind();
|
||||
}
|
||||
|
||||
if ( brokenModel != "" ) {
|
||||
SetModel( brokenModel );
|
||||
}
|
||||
|
||||
if ( explode ) {
|
||||
if ( brokenModel == "" ) {
|
||||
PostEventMS( &EV_Remove, 1000 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( renderEntity.gui[ 0 ] ) {
|
||||
renderEntity.gui[ 0 ] = NULL;
|
||||
}
|
||||
|
||||
ActivateTargets( this );
|
||||
|
||||
fl.takedamage = false;
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::AllowStep
|
||||
================
|
||||
*/
|
||||
bool idMoveable::AllowStep( void ) const {
|
||||
return allowStep;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::BecomeNonSolid
|
||||
================
|
||||
*/
|
||||
void idMoveable::BecomeNonSolid( void ) {
|
||||
// set CONTENTS_RENDERMODEL so bullets still collide with the moveable
|
||||
physicsObj.SetContents( CONTENTS_CORPSE | CONTENTS_RENDERMODEL );
|
||||
physicsObj.SetClipMask( MASK_SOLID | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::EnableDamage
|
||||
================
|
||||
*/
|
||||
void idMoveable::EnableDamage( bool enable, float duration ) {
|
||||
canDamage = enable;
|
||||
if ( duration ) {
|
||||
PostEventSec( &EV_EnableDamage, duration, ( !enable ) ? 0.0f : 1.0f );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::InitInitialSpline
|
||||
================
|
||||
*/
|
||||
void idMoveable::InitInitialSpline( int startTime ) {
|
||||
int initialSplineTime;
|
||||
|
||||
initialSpline = GetSpline();
|
||||
initialSplineTime = spawnArgs.GetInt( "initialSplineTime", "300" );
|
||||
|
||||
if ( initialSpline != NULL ) {
|
||||
initialSpline->MakeUniform( initialSplineTime );
|
||||
initialSpline->ShiftTime( startTime - initialSpline->GetTime( 0 ) );
|
||||
initialSplineDir = initialSpline->GetCurrentFirstDerivative( startTime );
|
||||
initialSplineDir *= physicsObj.GetAxis().Transpose();
|
||||
initialSplineDir.Normalize();
|
||||
BecomeActive( TH_THINK );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::FollowInitialSplinePath
|
||||
================
|
||||
*/
|
||||
bool idMoveable::FollowInitialSplinePath( void ) {
|
||||
if ( initialSpline != NULL ) {
|
||||
if ( gameLocal.time < initialSpline->GetTime( initialSpline->GetNumValues() - 1 ) ) {
|
||||
idVec3 splinePos = initialSpline->GetCurrentValue( gameLocal.time );
|
||||
idVec3 linearVelocity = ( splinePos - physicsObj.GetOrigin() ) * USERCMD_HZ;
|
||||
physicsObj.SetLinearVelocity( linearVelocity );
|
||||
|
||||
idVec3 splineDir = initialSpline->GetCurrentFirstDerivative( gameLocal.time );
|
||||
idVec3 dir = initialSplineDir * physicsObj.GetAxis();
|
||||
idVec3 angularVelocity = dir.Cross( splineDir );
|
||||
angularVelocity.Normalize();
|
||||
angularVelocity *= idMath::ACos16( dir * splineDir / splineDir.Length() ) * USERCMD_HZ;
|
||||
physicsObj.SetAngularVelocity( angularVelocity );
|
||||
return true;
|
||||
} else {
|
||||
delete initialSpline;
|
||||
initialSpline = NULL;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Think
|
||||
================
|
||||
*/
|
||||
void idMoveable::Think( void ) {
|
||||
if ( thinkFlags & TH_THINK ) {
|
||||
if ( !FollowInitialSplinePath() ) {
|
||||
BecomeInactive( TH_THINK );
|
||||
}
|
||||
}
|
||||
idEntity::Think();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::GetRenderModelMaterial
|
||||
================
|
||||
*/
|
||||
const idMaterial *idMoveable::GetRenderModelMaterial( void ) const {
|
||||
if ( renderEntity.customShader ) {
|
||||
return renderEntity.customShader;
|
||||
}
|
||||
if ( renderEntity.hModel && renderEntity.hModel->NumSurfaces() ) {
|
||||
return renderEntity.hModel->Surface( 0 )->shader;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::WriteToSnapshot
|
||||
================
|
||||
*/
|
||||
void idMoveable::WriteToSnapshot( idBitMsgDelta &msg ) const {
|
||||
physicsObj.WriteToSnapshot( msg );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::ReadFromSnapshot
|
||||
================
|
||||
*/
|
||||
void idMoveable::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
||||
physicsObj.ReadFromSnapshot( msg );
|
||||
if ( msg.HasChanged() ) {
|
||||
UpdateVisuals();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Event_BecomeNonSolid
|
||||
================
|
||||
*/
|
||||
void idMoveable::Event_BecomeNonSolid( void ) {
|
||||
BecomeNonSolid();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Event_Activate
|
||||
================
|
||||
*/
|
||||
void idMoveable::Event_Activate( idEntity *activator ) {
|
||||
float delay;
|
||||
idVec3 init_velocity, init_avelocity;
|
||||
|
||||
Show();
|
||||
|
||||
if ( !spawnArgs.GetInt( "notPushable" ) ) {
|
||||
physicsObj.EnableImpact();
|
||||
}
|
||||
|
||||
physicsObj.Activate();
|
||||
|
||||
spawnArgs.GetVector( "init_velocity", "0 0 0", init_velocity );
|
||||
spawnArgs.GetVector( "init_avelocity", "0 0 0", init_avelocity );
|
||||
|
||||
delay = spawnArgs.GetFloat( "init_velocityDelay", "0" );
|
||||
if ( delay == 0.0f ) {
|
||||
physicsObj.SetLinearVelocity( init_velocity );
|
||||
} else {
|
||||
PostEventSec( &EV_SetLinearVelocity, delay, init_velocity );
|
||||
}
|
||||
|
||||
delay = spawnArgs.GetFloat( "init_avelocityDelay", "0" );
|
||||
if ( delay == 0.0f ) {
|
||||
physicsObj.SetAngularVelocity( init_avelocity );
|
||||
} else {
|
||||
PostEventSec( &EV_SetAngularVelocity, delay, init_avelocity );
|
||||
}
|
||||
|
||||
InitInitialSpline( gameLocal.time );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Event_SetOwnerFromSpawnArgs
|
||||
================
|
||||
*/
|
||||
void idMoveable::Event_SetOwnerFromSpawnArgs( void ) {
|
||||
idStr owner;
|
||||
|
||||
if ( spawnArgs.GetString( "owner", "", owner ) ) {
|
||||
ProcessEvent( &EV_SetOwner, gameLocal.FindEntity( owner ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Event_IsAtRest
|
||||
================
|
||||
*/
|
||||
void idMoveable::Event_IsAtRest( void ) {
|
||||
idThread::ReturnInt( physicsObj.IsAtRest() );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idMoveable::Event_EnableDamage
|
||||
================
|
||||
*/
|
||||
void idMoveable::Event_EnableDamage( float enable ) {
|
||||
canDamage = ( enable != 0.0f );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
idBarrel
|
||||
|
||||
HUMANHEAD pdm: removed, re-inherited from hhMoveable
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
idExplodingBarrel
|
||||
HUMANHEAD pdm: removed, unused
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user