#include "../../idlib/precompiled.h" #pragma hdrstop #include "../Game_local.h" CLASS_DECLARATION( idForce, idForce_Field ) END_CLASS /* ================ idForce_Field::idForce_Field ================ */ idForce_Field::idForce_Field( void ) { type = FORCEFIELD_UNIFORM; applyType = FORCEFIELD_APPLY_FORCE; magnitude = 0.0f; dir.Set( 0, 0, 1 ); randomTorque = 0.0f; playerOnly = false; monsterOnly = false; clipModel = NULL; // RAVEN BEGIN // bdube: added last apply time lastApplyTime = -1; owner = NULL; // RAVEN END } /* ================ idForce_Field::~idForce_Field ================ */ idForce_Field::~idForce_Field( void ) { if ( this->clipModel ) { delete this->clipModel; } } /* ================ idForce_Field::Save ================ */ void idForce_Field::Save( idSaveGame *savefile ) const { savefile->WriteInt( type ); savefile->WriteInt( applyType); savefile->WriteFloat( magnitude ); savefile->WriteVec3( dir ); savefile->WriteFloat( randomTorque ); savefile->WriteBool( playerOnly ); savefile->WriteBool( monsterOnly ); savefile->WriteClipModel( clipModel ); savefile->WriteInt ( lastApplyTime ); // cnicholson: Added unsaved var // TOSAVE: idEntity* owner; } /* ================ idForce_Field::Restore ================ */ void idForce_Field::Restore( idRestoreGame *savefile ) { savefile->ReadInt( (int &)type ); savefile->ReadInt( (int &)applyType); savefile->ReadFloat( magnitude ); savefile->ReadVec3( dir ); savefile->ReadFloat( randomTorque ); savefile->ReadBool( playerOnly ); savefile->ReadBool( monsterOnly ); savefile->ReadClipModel( clipModel ); savefile->ReadInt ( lastApplyTime ); // cnicholson: Added unrestored var } /* ================ idForce_Field::SetClipModel ================ */ void idForce_Field::SetClipModel( idClipModel *clipModel ) { if ( this->clipModel && clipModel != this->clipModel ) { delete this->clipModel; } this->clipModel = clipModel; } /* ================ idForce_Field::Uniform ================ */ void idForce_Field::Uniform( const idVec3 &force ) { dir = force; magnitude = dir.Normalize(); type = FORCEFIELD_UNIFORM; } /* ================ idForce_Field::Explosion ================ */ void idForce_Field::Explosion( float force ) { magnitude = force; type = FORCEFIELD_EXPLOSION; } /* ================ idForce_Field::Implosion ================ */ void idForce_Field::Implosion( float force ) { magnitude = force; type = FORCEFIELD_IMPLOSION; } /* ================ idForce_Field::RandomTorque ================ */ void idForce_Field::RandomTorque( float force ) { randomTorque = force; } /* ================ idForce_Field::Evaluate ================ */ void idForce_Field::Evaluate( int time ) { int numClipModels, i; idBounds bounds; idVec3 force, torque, angularVelocity; idClipModel *cm, *clipModelList[ MAX_GENTITIES ]; assert( clipModel ); bounds.FromTransformedBounds( clipModel->GetBounds(), clipModel->GetOrigin(), clipModel->GetAxis() ); // RAVEN BEGIN // ddynerman: multiple clip worlds numClipModels = gameLocal.ClipModelsTouchingBounds( owner, bounds, -1, clipModelList, MAX_GENTITIES ); // RAVEN END for ( i = 0; i < numClipModels; i++ ) { cm = clipModelList[ i ]; if ( !cm->IsTraceModel() ) { continue; } idEntity *entity = cm->GetEntity(); if ( !entity ) { continue; } idPhysics *physics = entity->GetPhysics(); if ( playerOnly ) { // RAVEN BEGIN // jnewquist: Use accessor for static class type if ( !physics->IsType( idPhysics_Player::GetClassType() ) ) { // RAVEN END continue; } } else if ( monsterOnly ) { // RAVEN BEGIN // jnewquist: Use accessor for static class type if ( !physics->IsType( idPhysics_Monster::GetClassType() ) ) { continue; } } // nrausch: It was undesireable to have gibs and discarded weapons bouncing on jump pads if ( gameLocal.isMultiplayer ) { if ( entity->IsType( idItem::GetClassType() ) ) { continue; } if ( entity->IsType( rvClientPhysics::GetClassType() ) ) { continue; } if ( entity->IsType( idPlayer::GetClassType() ) ) { if ( ((idPlayer*)entity)->health <= 0 ) { continue; } } } // ddynerman: multiple clip worlds if ( !gameLocal.ContentsModel( owner, cm->GetOrigin(), cm, cm->GetAxis(), -1, clipModel->GetCollisionModel(), clipModel->GetOrigin(), clipModel->GetAxis() ) ) { // RAVEN END continue; } switch( type ) { case FORCEFIELD_UNIFORM: { force = dir; break; } case FORCEFIELD_EXPLOSION: { force = cm->GetOrigin() - clipModel->GetOrigin(); force.Normalize(); break; } case FORCEFIELD_IMPLOSION: { force = clipModel->GetOrigin() - cm->GetOrigin(); force.Normalize(); break; } default: { gameLocal.Error( "idForce_Field: invalid type" ); break; } } if ( randomTorque != 0.0f ) { torque[0] = gameLocal.random.CRandomFloat(); torque[1] = gameLocal.random.CRandomFloat(); torque[2] = gameLocal.random.CRandomFloat(); if ( torque.Normalize() == 0.0f ) { torque[2] = 1.0f; } } switch( applyType ) { case FORCEFIELD_APPLY_FORCE: { if ( randomTorque != 0.0f ) { entity->AddForce( gameLocal.world, cm->GetId(), cm->GetOrigin() + torque.Cross( dir ) * randomTorque, dir * magnitude ); } else { entity->AddForce( gameLocal.world, cm->GetId(), cm->GetOrigin(), force * magnitude ); } break; } case FORCEFIELD_APPLY_VELOCITY: { physics->SetLinearVelocity( force * magnitude, cm->GetId() ); if ( randomTorque != 0.0f ) { angularVelocity = physics->GetAngularVelocity( cm->GetId() ); physics->SetAngularVelocity( 0.5f * (angularVelocity + torque * randomTorque), cm->GetId() ); } break; } case FORCEFIELD_APPLY_IMPULSE: { if ( randomTorque != 0.0f ) { entity->ApplyImpulse( gameLocal.world, cm->GetId(), cm->GetOrigin() + torque.Cross( dir ) * randomTorque, dir * magnitude ); } else { entity->ApplyImpulse( gameLocal.world, cm->GetId(), cm->GetOrigin(), force * magnitude ); } break; } default: { gameLocal.Error( "idForce_Field: invalid apply type" ); break; } } // RAVEN BEGIN // bdube: added last apply time lastApplyTime = time; // RAVEN END } }