etqw-sdk/source/game/vehicles/Vehicle_RigidBody.cpp

841 lines
26 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#include "../precompiled.h"
#pragma hdrstop
#if defined( _DEBUG ) && !defined( ID_REDIRECT_NEWDELETE )
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "Vehicle_RigidBody.h"
#include "VehicleView.h"
#include "VehicleControl.h"
#include "TransportComponents.h"
#include "../Actor.h"
#include "../Player.h"
#include "../script/Script_Helper.h"
#include "../script/Script_ScriptObject.h"
#include "../../decllib/DeclSurfaceType.h"
#include "../botai/BotThreadData.h"
#include "../botai/Bot.h"
/*
===============================================================================
sdVehicle_RigidBody
===============================================================================
*/
const idEventDef EV_setDamageDealtScale( "setDamageDealtScale", '\0', DOC_TEXT( "Sets the scale factor applied to damage applied when this vehicle collides into something." ), 1, NULL, "f", "scale", "Scale factor to apply." );
CLASS_DECLARATION( sdTransport_RB, sdVehicle_RigidBody )
EVENT( EV_setDamageDealtScale, sdVehicle_RigidBody::Event_SetDamageDealtScale )
END_CLASS
/*
================
sdVehicle_RigidBody::sdVehicle_RigidBody
================
*/
sdVehicle_RigidBody::sdVehicle_RigidBody( void ) {
collideDamage = NULL;
collideFatalDamage = NULL;
onCollisionFunc = NULL;
onCollisionSideScrapeFunc = NULL;
nextCollisionTime = 0;
collideDamageDealtScale = 1.0f;
}
/*
================
sdVehicle_RigidBody::~sdVehicle_RigidBody
================
*/
sdVehicle_RigidBody::~sdVehicle_RigidBody( void ) {
}
/*
================
sdVehicle_RigidBody::DoLoadVehicleScript
================
*/
void sdVehicle_RigidBody::DoLoadVehicleScript( void ) {
if ( !spawnArgs.GetBool( "disableIK" ) ) {
ik.Init( this, IK_ANIM, vec3_origin );
}
ik.ClearWheels();
physicsObj.ClearClipModels();
physicsObj.SetFriction( spawnArgs.GetFloat( "linear_friction" ), spawnArgs.GetFloat( "angular_friction" ) );
physicsObj.SetWaterFriction( spawnArgs.GetFloat( "linear_friction_water" ), spawnArgs.GetFloat( "angular_friction_water" ) );
physicsObj.SetBouncyness( spawnArgs.GetFloat( "bouncyness" ) );
physicsObj.SetWaterRestThreshold( spawnArgs.GetFloat( "water_rest_threshold", "1" ) );
LoadParts( VPT_PART | VPT_WHEEL | VPT_HOVER | VPT_SIMPLE_PART | VPT_SCRIPTED_PART
| VPT_MASS | VPT_TRACK | VPT_ROTOR | VPT_THRUSTER | VPT_SUSPENSION | VPT_VTOL
| VPT_ANTIGRAV | VPT_PSEUDO_HOVER | VPT_DRAGPLANE | VPT_RUDDER
| VPT_AIRBRAKE | VPT_HURTZONE | VPT_ANTIROLL | VPT_ANTIPITCH );
physicsObj.CalculateMassProperties();
}
/*
================
sdVehicle_RigidBody::Spawn
================
*/
void sdVehicle_RigidBody::Spawn( void ) {
const char* damagename;
damagename = spawnArgs.GetString( "dmg_collide" );
if ( *damagename ) {
collideDamage = gameLocal.declDamageType.LocalFind( damagename, false );
if( !collideDamage ) {
gameLocal.Warning( "sdVehicle::Spawn Invalid Damage Type '%s'", damagename );
}
} else {
collideDamage = NULL;
}
damagename = spawnArgs.GetString( "dmg_collide_fatal" );
if ( *damagename ) {
collideFatalDamage = gameLocal.declDamageType.LocalFind( damagename, false );
if( !collideFatalDamage ) {
gameLocal.Warning( "sdVehicle::Spawn Invalid Damage Type '%s'", damagename );
}
}
if ( collideFatalDamage == NULL ) {
collideFatalDamage = collideDamage;
}
onCollisionFunc = scriptObject->GetFunction( "OnCollision" );
onCollisionSideScrapeFunc = scriptObject->GetFunction( "OnCollisionSideScrape" );
collideDotLimit = spawnArgs.GetFloat( "collide_dot_limit", "-0.5" );
physicsObj.SetSelf( this );
physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
physicsObj.SetAxis( GetPhysics()->GetAxis() );
physicsObj.SetFastPath( true );
SetPhysics( &physicsObj );
LoadVehicleScript();
BecomeActive( TH_THINK );
if( !health ) {
health = 2000;
}
float gravityScale;
if ( spawnArgs.GetFloat( "gravity", DEFAULT_GRAVITY_STRING, gravityScale ) ) {
physicsObj.SetGravity( physicsObj.GetGravityNormal() * gravityScale );
}
BecomeActive( TH_UPDATEVISUALS );
Present();
nextSelfCollisionTime = gameLocal.time + SEC2MS( 5 ); // 5s spawn invulnerability to allow it to drop to the ground
nextCollisionTime = 0;
nextCollisionSound = 0;
nextJumpSound = 0;
// NOTE: USE THIS ONLY TO LOCK DOWN THE HANDLING OF A VEHICLE!
// Tweak the mass distrubtion in the vscript, and ONLY use this if you
// need it to prevent collision model modifications upsetting the handling
idVec3 IDiagonal;
idVec3 IOther;
bool hasIDiagonal = spawnArgs.GetVector( "do_not_modify_itd", "1 1 1", IDiagonal );
bool hasIOther = spawnArgs.GetVector( "do_not_modify_ito", "0 0 0", IOther );
if ( hasIDiagonal || hasIOther ) {
if ( !hasIDiagonal ) {
idMat3 originalITT = physicsObj.GetInertiaTensor();
IDiagonal[0] = originalITT[0][0];
IDiagonal[1] = originalITT[1][1];
IDiagonal[2] = originalITT[2][2];
}
if ( !hasIOther ) {
idMat3 originalITT = physicsObj.GetInertiaTensor();
IOther[0] = originalITT[0][1];
IOther[1] = originalITT[0][2];
IOther[2] = originalITT[1][2];
}
idMat3 itt;
itt[0][0] = IDiagonal[0];
itt[1][1] = IDiagonal[1];
itt[2][2] = IDiagonal[2];
itt[0][1] = itt[1][0] = IOther[0];
itt[0][2] = itt[2][0] = IOther[1];
itt[1][2] = itt[2][1] = IOther[2];
physicsObj.SetInertiaTensor( itt );
}
}
/*
================
sdVehicle_RigidBody::Collide
================
*/
bool sdVehicle_RigidBody::Collide( const trace_t &collision, const idVec3 &velocity, int bodyId ) {
// FIXME: This stuff should be done on collisions against us too.
idVec3 normal = -collision.c.normal;
float length = ( velocity * normal );
idVec3 v = length * normal;
if ( collideDamage ) {
idEntity* other = gameLocal.entities[ collision.c.entityNum ];
sdTransport* otherTransport = other->Cast< sdTransport >();
const sdVehicleControlBase* otherControl = NULL;
if ( otherTransport != NULL ) {
otherControl = otherTransport->GetVehicleControl();
}
partDamageInfo_t damageInfo;
sdVehicleDriveObject* object = PartForCollisionById( collision, PFC_SELF_COLLISION );
if ( object ) {
damageInfo = *object->GetDamageInfo();
} else {
damageInfo.damageScale = 1.f;
damageInfo.collisionScale = 1.f;
damageInfo.collisionMinSpeed = 256.f;
damageInfo.collisionMaxSpeed = 1024.f;
}
if( ( gameLocal.time > nextCollisionTime ) && ( length > damageInfo.collisionMinSpeed ) ) {
float damage = ( length - damageInfo.collisionMinSpeed ) / ( damageInfo.collisionMaxSpeed - damageInfo.collisionMinSpeed );
if ( damage > 1.f ) {
damage = 1.f;
}
bool playerCollide = false;
if ( other->IsType( idPlayer::Type ) ) {
playerCollide = true;
if ( collision.c.normal.z > 0.9f ) {
// landed on their head, should crush them
damage *= 4.f;
}
}
bool otherIgnoreDamage = otherControl != NULL && otherControl->IgnoreCollisionDamage( -normal );
if ( other->fl.takedamage && !otherIgnoreDamage ) {
idPlayer* driver = positionManager.FindDriver();
int oldHealth = other->GetHealth();
other->Damage( this, driver != NULL ? ( idEntity* )driver : this, v, collideDamage, damage * collideDamageDealtScale, &collision );
if ( driver != NULL ) {
if ( oldHealth > 0 && other->GetHealth() <= 0 ) {
idPlayer* otherPlayer = other->Cast< idPlayer >();
if ( otherPlayer != NULL && driver->GetEntityAllegiance( otherPlayer ) == TA_ENEMY ) {
IncRoadKillStats( driver );
if ( driver->IsType( idBot::Type ) && !other->IsType( idBot::Type ) ) { //mal: smartass bot!
clientInfo_t& driverInfo = botThreadData.GetGameWorldState()->clientInfo[ driver->entityNumber ];
driverInfo.lastRoadKillTime = gameLocal.time + 3000;
}
}
}
}
}
bool ignoreDamage = GetVehicleControl() != NULL && GetVehicleControl()->IgnoreCollisionDamage( normal );
if ( !ignoreDamage && !playerCollide && gameLocal.time > nextSelfCollisionTime ) {
// HACK: take no collision damage from below if the other thing doesn't take any damage
// this basically makes it so that you don't take annoying damage from scraping terrain
float underneathNess = normal * GetPhysics()->GetAxis()[ 2 ];
if ( other->fl.takedamage || underneathNess > collideDotLimit ) {
if ( vehicleControl && IsCareening() ) {
damage *= vehicleControl->GetCareeningCollideScale();
}
Damage( this, this, -v, collideDamage, damage * damageInfo.collisionScale, &collision );
}
}
}
/* if( g_debugDamage.GetInteger() ) {
gameRenderWorld->DebugBox( colorGreen, idBox( collision.endpos, idVec3( 8, 8, 8 ), mat3_identity ), 3000 );
gameRenderWorld->DebugLine( colorBlue, collision.endpos, collision.endpos + collision.c.normal * length, 3000 );
gameRenderWorld->DebugBox( colorYellow, idBox( collision.c.point, idVec3( 8, 8, 8 ), mat3_identity ), 3000 );
gameRenderWorld->DebugLine( colorBlue, collision.c.point, collision.c.point + collision.c.normal * length, 3000 );
}*/
}
HandleCollision( collision, length );
return sdTransport::Collide( collision, velocity, bodyId );
}
/*
================
sdVehicle_RigidBody::CollideFatal
================
*/
void sdVehicle_RigidBody::CollideFatal( idEntity* other ) {
idEntity* driver = positionManager.FindDriver();
idPlayer* playerDriver = NULL;
if ( driver != NULL ) {
playerDriver = driver->Cast< idPlayer >();
assert( playerDriver != NULL );
}
if ( collideFatalDamage != NULL ) {
if ( other->fl.takedamage ) {
int oldHealth = other->GetHealth();
idVec3 dir = GetPhysics()->GetOrigin() - other->GetPhysics()->GetOrigin();
dir.Normalize();
other->Damage( this, driver ? driver : this, dir, collideFatalDamage, -1.0f, NULL, true );
if ( playerDriver != NULL ) {
idPlayer* otherPlayer = other->Cast< idPlayer >();
if ( otherPlayer != NULL && otherPlayer->GetEntityAllegiance( playerDriver ) == TA_ENEMY ) {
if ( oldHealth > 0 && otherPlayer->GetHealth() <= 0 ) {
IncRoadKillStats( playerDriver );
}
}
}
}
}
}
/*
================
sdVehicle_RigidBody::IncRoadKillStats
================
*/
void sdVehicle_RigidBody::IncRoadKillStats( idPlayer* player ) {
sdStatsTracker& tracker = sdGlobalStatsTracker::GetInstance();
sdPlayerStatEntry* entry = tracker.GetStat( tracker.AllocStat( "total_roadkills", sdNetStatKeyValue::SVT_INT ) );
entry->IncreaseValue( player->entityNumber, 1 );
}
/*
================
sdVehicle_RigidBody::UpdateAnimationControllers
================
*/
bool sdVehicle_RigidBody::UpdateAnimationControllers( void ) {
if ( !gameLocal.isNewFrame ) {
return false;
}
if ( ik.IsInitialized() ) {
if ( !ik.IsInhibited() ) {
return ik.Evaluate();
}
return false;
} else {
ik.ClearJointMods();
}
return false;
}
/*
================
sdVehicle_RigidBody::HandleCollision
================
*/
void sdVehicle_RigidBody::HandleCollision( const trace_t &collision, const float velocity ) {
idVec3 bodyOrigin;
idVec3 localCollisionPoint;
physicsObj.GetBodyOrigin( bodyOrigin, collision.c.selfId );
localCollisionPoint = ( collision.c.point - bodyOrigin ) * physicsObj.GetAxis().Transpose();
// get dot with forward facing direction
idVec3 localCollisionNormal = collision.c.normal * physicsObj.GetAxis().Transpose();
idVec3 v( 1, 0, 0 );
float dot = v * localCollisionNormal;
sdLoggedTrace* loggedTrace = gameLocal.RegisterLoggedTrace( collision );
const idBounds& bodyBounds = physicsObj.GetBounds( collision.c.selfId );
const idVec3 bodySize = bodyBounds.Size();
#if 0
bool foundCollisionPoint = false;
// sides
if ( localCollisionPoint.x > 0 && localCollisionPoint.y > 0 ) {
if ( idMath::Fabs( dot ) < .15f && localCollisionPoint.x > ( .5f * bodySize.x ) - 2.f ) {
gameLocal.Printf( "Collision with front left side. (dot = %f)\n", idMath::Fabs( dot ) );
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.y = ( .5f * bodySize.y ) - 2.f;
collisionCenter.z = 0.f;
idVec3 collisionExtents;
collisionExtents.y = 2.f;
collisionExtents.z = .5f * bodySize.z;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = 1.f - ( ( idMath::Fabs( dot ) - .06f ) / .09f );
collisionExtents.x = .0625f * bodySize.x + fraction * .1875f * bodySize.x;
collisionCenter.x = .5f * bodySize.x - collisionExtents.x;
} else {
collisionCenter.x = .25f * bodySize.x;
collisionExtents.x = .25f * bodySize.x;
}
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorRed, collisionBox, 3000 );
}*/
idVec3 mins, maxs;
mins.y = .5f * bodySize.y;
mins.z = -.5f * bodySize.z;
maxs.x = .5f * bodySize.x;
maxs.y = .5f * bodySize.y;
maxs.z = .5f * bodySize.z;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = ( idMath::Fabs( dot ) - .06f ) / .09f;
mins.x = fraction * ( .4375f * bodySize.x );
} else {
mins.x = 0.f;
}
foundCollisionPoint = true;
} else {
// just generate a small box around the collision point
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.x = localCollisionPoint.x;
collisionCenter.y = localCollisionPoint.y;
collisionCenter.z = 0.f;
idVec3 collisionExtents;
collisionExtents.x = 2.f;
collisionExtents.y = 2.f;
collisionExtents.z = .5f * bodySize.z;
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorCyan, collisionBox, 3000 );
}*/
idVec3 mins, maxs;
mins.y = -.5f * bodySize.y;
mins.z = -.5f * bodySize.z;
maxs.x = .5f * bodySize.x;
maxs.y = -.5f * bodySize.y;
maxs.z = .5f * bodySize.z;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = ( idMath::Fabs( dot ) - .06f ) / .09f;
mins.x = fraction * ( .4375f * bodySize.x );
} else {
mins.x = 0.f;
}
foundCollisionPoint = true;
}
}
if ( localCollisionPoint.x > 0 && localCollisionPoint.y < 0 ) {
if ( idMath::Fabs( dot ) < .15f && localCollisionPoint.x > ( .5f * bodySize.x ) - 2.f ) {
gameLocal.Printf( "Collision with front right side. (dot = %f)\n", idMath::Fabs( dot ) );
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.y = ( -.5f * bodySize.y ) + 2.f;
collisionCenter.z = 0.f;
idVec3 collisionExtents;
collisionExtents.y = 2.f;
collisionExtents.z = .5f * bodySize.z;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = 1.f - ( ( idMath::Fabs( dot ) - .06f ) / .09f );
collisionExtents.x = .0625f * bodySize.x + fraction * .1875f * bodySize.x;
collisionCenter.x = .5f * bodySize.x - collisionExtents.x;
} else {
collisionCenter.x = .25f * bodySize.x;
collisionExtents.x = .25f * bodySize.x;
}
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorRed, collisionBox, 3000 );
}*/
idVec3 mins, maxs;
mins.x = -.5f * bodySize.x;
mins.y = .5f * bodySize.y;
mins.z = -.5f * bodySize.z;
maxs.y = .5f * bodySize.y;
maxs.z = .5f * bodySize.z;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = ( idMath::Fabs( dot ) - .06f ) / .09f;
maxs.x = -fraction * ( .4375f * bodySize.x );
} else {
maxs.x = 0.f;
}
foundCollisionPoint = true;
} else {
// just generate a small box around the collision point
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.x = localCollisionPoint.x;
collisionCenter.y = localCollisionPoint.y;
collisionCenter.z = 0.f;
idVec3 collisionExtents;
collisionExtents.x = 2.f;
collisionExtents.y = 2.f;
collisionExtents.z = .5f * bodySize.z;
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorCyan, collisionBox, 3000 );
}*/
foundCollisionPoint = true;
}
}
if ( localCollisionPoint.x < 0 && localCollisionPoint.y > 0 ) {
if ( idMath::Fabs( dot ) < .15f && localCollisionPoint.x < ( -.5f * bodySize.x ) + 2.f ) {
gameLocal.Printf( "Collision with rear left side. (dot = %f)\n", idMath::Fabs( dot ) );
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.y = ( .5f * bodySize.y ) - 2.f;
collisionCenter.z = 0.f;
idVec3 collisionExtents;
collisionExtents.y = 2.f;
collisionExtents.z = .5f * bodySize.z;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = 1.f - ( ( idMath::Fabs( dot ) - .06f ) / .09f );
collisionExtents.x = .0625f * bodySize.x + fraction * .1875f * bodySize.x;
collisionCenter.x = -.5f * bodySize.x + collisionExtents.x;
} else {
collisionCenter.x = -.25f * bodySize.x;
collisionExtents.x = .25f * bodySize.x;
}
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorRed, collisionBox, 3000 );
}*/
idVec3 mins, maxs;
mins.x = -.5f * bodySize.x;
mins.y = -.5f * bodySize.y;
mins.z = -.5f * bodySize.z;
maxs.y = -.5f * bodySize.y;
maxs.z = .5f * bodySize.z;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = ( idMath::Fabs( dot ) - .06f ) / .09f;
maxs.x = -fraction * ( .4375f * bodySize.x );
} else {
maxs.x = 0.f;
}
foundCollisionPoint = true;
} else {
// just generate a small box around the collision point
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.x = localCollisionPoint.x;
collisionCenter.y = localCollisionPoint.y;
collisionCenter.z = 0.f;
idVec3 collisionExtents;
collisionExtents.x = 2.f;
collisionExtents.y = 2.f;
collisionExtents.z = .5f * bodySize.z;
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorCyan, collisionBox, 3000 );
}*/
foundCollisionPoint = true;
}
}
if ( localCollisionPoint.x < 0 && localCollisionPoint.y < 0 ) {
if ( idMath::Fabs( dot ) < .15f && localCollisionPoint.x < ( -.5f * bodySize.x ) + 2.f ) {
gameLocal.Printf( "Collision with rear right side. (dot = %f)\n", idMath::Fabs( dot ) );
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.y = ( -.5f * bodySize.y ) + 2.f;
collisionCenter.z = 0.f;
idVec3 collisionExtents;
collisionExtents.y = 2.f;
collisionExtents.z = .5f * bodySize.z;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = 1.f - ( ( idMath::Fabs( dot ) - .06f ) / .09f );
collisionExtents.x = .0625f * bodySize.x + fraction * .1875f * bodySize.x;
collisionCenter.x = -.5f * bodySize.x + collisionExtents.x;
} else {
collisionCenter.x = -.25f * bodySize.x;
collisionExtents.x = .25f * bodySize.x;
}
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorRed, collisionBox, 3000 );
}*/
foundCollisionPoint = true;
} else {
// just generate a small box around the collision point
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.x = localCollisionPoint.x;
collisionCenter.y = localCollisionPoint.y;
collisionCenter.z = 0.f;
idVec3 collisionExtents;
collisionExtents.x = 2.f;
collisionExtents.y = 2.f;
collisionExtents.z = .5f * bodySize.z;
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorCyan, collisionBox, 3000 );
}*/
foundCollisionPoint = true;
}
}
// top
if ( !foundCollisionPoint && localCollisionPoint.z > ( .5f * bodySize.z ) - 2.f ) {
// just generate a small box around the collision point
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.x = localCollisionPoint.x;
collisionCenter.y = localCollisionPoint.y;
collisionCenter.z = localCollisionPoint.z;
idVec3 collisionExtents;
collisionExtents.x = 2.f;
collisionExtents.y = 2.f;
collisionExtents.z = localCollisionPoint.z;
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorCyan, collisionBox, 3000 );
}*/
foundCollisionPoint = true;
}
// bottom
if ( !foundCollisionPoint && localCollisionPoint.z < ( -.5f * bodySize.z ) + 2.f ) {
// just generate a small box around the collision point
/* if ( g_debugDamage.GetInteger() ) {
idVec3 collisionCenter;
collisionCenter.x = localCollisionPoint.x;
collisionCenter.y = localCollisionPoint.y;
collisionCenter.z = localCollisionPoint.z;
idVec3 collisionExtents;
collisionExtents.x = 2.f;
collisionExtents.y = 2.f;
collisionExtents.z = localCollisionPoint.z;
idBox collisionBox( collisionCenter, collisionExtents, mat3_identity );
// move into world
collisionBox.RotateSelf( physicsObj.GetAxis() );
collisionBox.TranslateSelf( bodyOrigin );
gameRenderWorld->DebugBox( colorCyan, collisionBox, 3000 );
}*/
foundCollisionPoint = true;
}
#endif
bool scrape = false;
idVec3 mins, maxs;
// scraping
bool front;
if ( localCollisionPoint.x > 0 ) {
front = true;
if ( idMath::Fabs( dot ) < .15f && localCollisionPoint.x > ( .5f * bodySize.x ) - 2.f ) {
scrape = true;
}
} else {
front = false;
if ( idMath::Fabs( dot ) < .15f && localCollisionPoint.x < ( -.5f * bodySize.x ) + 2.f ) {
scrape = true;
}
}
if ( scrape ) {
mins.y = maxs.y = ( localCollisionPoint.y > 0 ? 1 : -1 ) * .5f * bodySize.y;
if ( front ) {
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = ( idMath::Fabs( dot ) - .06f ) / .09f;
mins.x = fraction * ( .4375f * bodySize.x );
} else {
mins.x = 0.f;
}
maxs.x = .5f * bodySize.x;
} else {
mins.x = -.5f * bodySize.x;
if ( idMath::Fabs( dot ) > .06f ) {
float fraction = ( idMath::Fabs( dot ) - .06f ) / .09f;
maxs.x = -fraction * ( .4375f * bodySize.x );
} else {
maxs.x = 0.f;
}
}
mins.z = -.5f * bodySize.z;
maxs.z = .5f * bodySize.z;
} else {
// not scraping
mins.x = maxs.x = localCollisionPoint.x;
mins.y = maxs.y = localCollisionPoint.y;
if ( localCollisionPoint.x > ( .5f * bodySize.x ) - 2.f ||
localCollisionPoint.x < ( -.5f * bodySize.x ) + 2.f ||
localCollisionPoint.y > ( .5f * bodySize.y ) - 2.f ||
localCollisionPoint.x < ( -.5f * bodySize.y ) + 2.f ) {
// sides
mins.z = -.5f * bodySize.z;
maxs.z = .5f * bodySize.z;
} else {
//if ( ( localCollisionPoint.z > ( .5f * bodySize.z ) - 2.f ) || ( localCollisionPoint.z < ( -.5f * bodySize.z ) + 2.f ) ) {
// top/bottom
mins.z = maxs.z = localCollisionPoint.z;
}
}
// transform to world
mins *= physicsObj.GetAxis();
mins += bodyOrigin;
maxs *= physicsObj.GetAxis();
maxs += bodyOrigin;
if ( onCollisionFunc ) {
sdScriptHelper helper;
helper.Push( loggedTrace ? loggedTrace->GetScriptObject() : NULL );
helper.Push( velocity );
helper.Push( mins );
helper.Push( maxs );
CallNonBlockingScriptEvent( onCollisionFunc, helper );
}
if ( scrape ) {
if ( onCollisionSideScrapeFunc ) {
sdScriptHelper helper;
helper.Push( loggedTrace ? loggedTrace->GetScriptObject() : NULL );
helper.Push( velocity );
helper.Push( mins );
helper.Push( maxs );
CallNonBlockingScriptEvent( onCollisionSideScrapeFunc, helper );
}
}
gameLocal.FreeLoggedTrace( loggedTrace );
}
/*
================
sdVehicle_RigidBody::FreezePhysics
================
*/
void sdVehicle_RigidBody::FreezePhysics( bool freeze ) {
physicsObj.SetFrozen( freeze );
physicsObj.SetLinearVelocity( vec3_origin );
physicsObj.SetAngularVelocity( vec3_origin );
}
/*
================
sdVehicle_RigidBody::Event_SetDamageDealtScale
================
*/
void sdVehicle_RigidBody::Event_SetDamageDealtScale( float scale ) {
SetDamageDealtScale( scale );
}
/*
================
sdVehicle_RigidBody::SetDamageDealtScale
================
*/
void sdVehicle_RigidBody::SetDamageDealtScale( float scale ) {
collideDamageDealtScale = scale;
}