| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** Confidential - Westwood Studios ***
- ***********************************************************************************************
- * *
- * Project Name : Commando *
- * *
- * $Archive:: /Commando/Code/Combat/surfaceeffects.cpp $*
- * *
- * $Author:: Greg_h $*
- * *
- * $Modtime:: 6/14/02 10:48a $*
- * *
- * $Revision:: 56 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "surfaceeffects.h"
- #include "w3d_file.h"
- #include "part_emt.h"
- #include "assets.h"
- #include "pscene.h"
- #include "debug.h"
- #include "wwstring.h"
- #include "crandom.h"
- #include "physcon.h"
- #include "wwaudio.h"
- #include "rndstrng.h"
- #include "sound3d.h"
- #include "phys.h"
- #include "wwprofile.h"
- #include "gameobjref.h"
- #include "physicalgameobj.h"
- #include "combat.h"
- #include "ccamera.h"
- #include "effectrecycler.h"
- #include "timeddecophys.h"
- #define RECYCLE_EMITTERS 1
- const float _MAX_SURFACE_EFFECT_DISTANCE2 = 50.0f * 50.0f; // no surface effects created farther than this from camera
- const float _SURFACE_EFFECT_NEAR_DISTANCE2 = 10.0f * 10.0f; // force surface effects within this distance
- #define SECTION_BULLET_STOPPING "Bullet_Stopping"
- #define SECTION_DAMAGE_WARHEAD "Damage_Warhead"
- #define SECTION_DAMAGE_RATE "Damage_Rate"
- SurfaceEffectsManager::MODE SurfaceEffectsManager::Mode = SurfaceEffectsManager::MODE_FULL;
- int SurfaceEffectsManager::OverrideSurfaceType = -1;
- bool _IsSurfaceEffectsInitted = false;
- // If there exist more than this many particle buffers, don't make emitters
- #define PARTICLE_BUFFER_LIMIT 5
- /*
- ** These are the names for each Hitter Type. If you add a hitter type, add the name here
- */
- static const char * _HitterTypeName[ SurfaceEffectsManager::NUM_HITTER_TYPES ] = {
- "None", // HITTER_TYPE_NONE, // used to shut off persistant effects
- "Generic Object", // HITTER_TYPE_GENERIC_OBJECT, // generic dynamic object
- "Footstep Run", // HITTER_TYPE_FOOTSTEP_RUN,
- "Footstep Walk", // HITTER_TYPE_FOOTSTEP_WALK,
- "Footstep Crouched", // HITTER_TYPE_FOOTSTEP_CROUCHED,
- "Footstep Jump", // HITTER_TYPE_FOOTSTEP_JUMP,
- "Footstep Land", // HITTER_TYPE_FOOTSTEP_LAND,
- "Bullet", // HITTER_TYPE_BULLET,
- "Bullet Fire", // HITTER_TYPE_BULLET_FIRE,
- "Bullet Grenade", // HITTER_TYPE_BULLET_GRENADE,
- "Bullet Chem", // HITTER_TYPE_BULLET_CHEM,
- "Bullet Electric", // HITTER_TYPE_BULLET_ELECTRIC,
- "Bullet Laser", // HITTER_TYPE_BULLET_LASER,
- "Bullet Squish", // HITTER_TYPE_BULLET_SQUISH,
- "Bullet Tib Spray", // HITTER_TYPE_BULLET_TIB_SPRAY,
- "Bullet Tib", // HITTER_TYPE_BULLET_TIB_BULLET,
- "Bullet Shotgun", // HITTER_TYPE_BULLET_SHOTGUN,
- "Bullet Silenced", // HITTER_TYPE_BULLET_SILENCED,
- "Bullet Sniper", // HITTER_TYPE_BULLET_SNIPER,
- "Bullet Water", // HITTER_TYPE_BULLET_WATER,
- "Eject Casing", // HITTER_TYPE_EJECT_CASING, // casings ejected from weapons (all are assumed to make the same sounds)
- "Shell Shotgun", // HITTER_TYPE_SHELL_SHOTGUN,
- "Tire Rolling", // HITTER_TYPE_TIRE_ROLLING, // wheels on humvees, etc...
- "Tire Sliding", // HITTER_TYPE_TIRE_SLIDING,
- "Track Rolling", // HITTER_TYPE_TRACK_ROLLING, // tank tracks...
- "Track Sliding", // HITTER_TYPE_TRACK_SLIDING,
- "Footstep Ladder", // HITTER_TYPE_FOOTSTEP_LADDER,
- };
- /*
- ** Recycler for all "fire-and-forget" surface effect emitters
- */
- #if (RECYCLE_EMITTERS)
- static EffectRecyclerClass _EmitterRecycler;
- #endif
- /*
- ** Persistant Surface Effects
- */
- class PersistantSurfaceEffectClass
- {
- public:
- PersistantSurfaceEffectClass( void );
- ~PersistantSurfaceEffectClass( void );
- int CurrentSurfaceType;
- int CurrentHitterType;
- friend SurfaceEffectsManager;
- };
- class PersistantSurfaceSoundClass : public PersistantSurfaceEffectClass
- {
- public:
- PersistantSurfaceSoundClass( void );
- ~PersistantSurfaceSoundClass( void );
- void Set_Sound( const char * name );
- AudibleSoundClass * Sound;
- friend SurfaceEffectsManager;
- };
- class PersistantSurfaceEmitterClass : public PersistantSurfaceEffectClass
- {
- private:
- PersistantSurfaceEmitterClass( void );
- ~PersistantSurfaceEmitterClass( void );
- void Set_Emitter( const char * name );
- ParticleEmitterClass * Emitter;
- friend SurfaceEffectsManager;
- };
- /*
- ** PersistantSurfaceEffectClass
- */
- PersistantSurfaceEffectClass::PersistantSurfaceEffectClass(void) :
- CurrentSurfaceType( -1 ),
- CurrentHitterType( -1 )
- {
- }
- PersistantSurfaceEffectClass::~PersistantSurfaceEffectClass(void)
- {
- }
- /*
- ** PersistantSurfaceSoundClass
- */
- PersistantSurfaceSoundClass::PersistantSurfaceSoundClass( void ) :
- Sound( NULL )
- {
- }
- PersistantSurfaceSoundClass::~PersistantSurfaceSoundClass( void )
- {
- Set_Sound( NULL );
- }
- void PersistantSurfaceSoundClass::Set_Sound( const char * name )
- {
- // Stop Old Sound
- if ( Sound != NULL ) {
- Sound->Stop();
- Sound->Remove_From_Scene();
- Sound->Release_Ref();
- Sound = NULL;
- }
- // Start new Sound
- if ( name != NULL ) {
- Sound = WWAudioClass::Get_Instance()->Create_Continuous_Sound( name );
- if ( Sound != NULL ) {
- Sound->Add_To_Scene( true );
- }
- }
- }
- /*
- ** PersistantSurfaceEmitterClass
- */
- PersistantSurfaceEmitterClass::PersistantSurfaceEmitterClass( void ) :
- Emitter( NULL )
- {
- }
- PersistantSurfaceEmitterClass::~PersistantSurfaceEmitterClass( void )
- {
- Set_Emitter( NULL );
- }
- void PersistantSurfaceEmitterClass::Set_Emitter( const char * name )
- {
- // Stop Old Emitter
- if ( Emitter != NULL ) {
- // Check if it is in the scene, it may ahve already been remove by completion
- if ( Emitter->Peek_Scene() != NULL ) {
- PhysicsSceneClass::Get_Instance()->Remove_Render_Object( Emitter );
- }
- Emitter->Stop();
- Emitter->Release_Ref();
- Emitter = NULL;
- }
- // Start new Emitter
- if ( name != NULL ) {
- Emitter = (ParticleEmitterClass *)WW3DAssetManager::Get_Instance()->Create_Render_Obj( name );
- if ( Emitter ) {
- SET_REF_OWNER( Emitter );
- // Emitter->Set_Remove_On_Complete( false );
- Emitter->Start();
- PhysicsSceneClass::Get_Instance()->Add_Render_Object( Emitter );
- }
- }
- }
- /*
- ** Surface Effect Database
- */
- class SurfaceEffectClass {
- public:
- RandomStringClass Sound;
- RandomStringClass Emitter;
- RandomStringClass Decal;
- float DecalSize;
- float DecalSizeRandom;
- };
- SurfaceEffectClass * SurfaceEffectsDatabase[SURFACE_TYPE_MAX][SurfaceEffectsManager::NUM_HITTER_TYPES];
- bool SurfaceStopsBullets[SURFACE_TYPE_MAX];
- int SurfaceDamageWarhead[SURFACE_TYPE_MAX];
- float SurfaceDamageRate[SURFACE_TYPE_MAX];
- /*
- ** These are the physics object types for each Hitter Type. These are only used to pass
- ** the friction and drag constants on to the physics system. If your hitter type does not
- ** correspond to a physics object type, put a -1 for its entry here.
- */
- const int HitterPhysicsTypes[SurfaceEffectsManager::NUM_HITTER_TYPES] =
- {
- -1, //"Bullet",
- -1, //"Eject Casing"
- -1, //"Footstep Run",
- -1, //"Footstep Walk",
- -1, //"Footstep Crouch",
- PhysicsConstants::DYNAMIC_OBJ_TYPE_TIRE, //"Tire Rolling",
- -1, //"Tire Sliding",
- PhysicsConstants::DYNAMIC_OBJ_TYPE_TRACK, //"Track Rolling",
- -1, //"Track Sliding",
- PhysicsConstants::DYNAMIC_OBJ_TYPE_GENERIC, //"Generic Object"
- -1,
- };
- #define SURFACE_EFFECTS_INI_FILENAME "surfaceeffects.ini"
- bool SurfaceEffectsManagerDebug = false;
- void SurfaceEffectsManager::Toggle_Debug( void )
- {
- SurfaceEffectsManagerDebug = !SurfaceEffectsManagerDebug;
- }
- /*
- **
- */
- void SurfaceEffectsManager::Init( void )
- {
- if (_IsSurfaceEffectsInitted) {
- Shutdown();
- }
-
- for ( int i = 0; i < SURFACE_TYPE_MAX; i++ ) {
- SurfaceStopsBullets[i] = true;
- SurfaceDamageWarhead[i] = 0;
- SurfaceDamageRate[i] = 0;
- }
- // Read Database INI file
- INIClass * ini = Get_INI( SURFACE_EFFECTS_INI_FILENAME );
- if ( ini != NULL ) {
- WWASSERT( ini && ini->Section_Count() > 0 );
- int surface;
- // Read Bullet Stopping
- for ( surface = 0; surface < SURFACE_TYPE_MAX; surface++ ) {
- SurfaceStopsBullets[ surface ] = ini->Get_Bool( SECTION_BULLET_STOPPING, SURFACE_TYPE_STRINGS[surface], true );
- }
- // Read Surface Damage Data
- for ( surface = 0; surface < SURFACE_TYPE_MAX; surface++ ) {
- StringClass warhead(0,true);
- ini->Get_String(warhead,SECTION_DAMAGE_WARHEAD, SURFACE_TYPE_STRINGS[surface] );
- if ( !warhead.Is_Empty() ) {
- SurfaceDamageWarhead[surface] = ArmorWarheadManager::Get_Warhead_Type( warhead );
- }
- SurfaceDamageRate[surface] = ini->Get_Float( SECTION_DAMAGE_RATE, SURFACE_TYPE_STRINGS[surface], 0 );
- if ( SurfaceDamageRate[surface] != 0 ) {
- // Debug_Say(( "Surface %s Rate %f Warhead %s\n", SURFACE_TYPE_STRINGS[surface],
- // SurfaceDamageRate[surface], ArmorWarheadManager::Get_Warhead_Name( SurfaceDamageWarhead[surface] ) ));
- }
- }
- for ( surface = 0; surface < SURFACE_TYPE_MAX; surface++ ) {
- for ( int hitter = 0; hitter < NUM_HITTER_TYPES; hitter++ ) {
- StringClass section_name;
- section_name.Format( "%s_%s", SURFACE_TYPE_STRINGS[surface], _HitterTypeName[hitter] );
- if ( ini->Entry_Count( section_name ) == 0 ) {
- SurfaceEffectsDatabase[ surface ][ hitter ] = NULL;
- continue;
- }
- // Debug_Say(( "Surface Effect Section %s\n", section_name ));
- // create the effect
- SurfaceEffectClass * surface_effect = new SurfaceEffectClass;
- // Read sounds
- for ( int sound = 0; ; sound++ ) {
- StringClass sound_entry(0,true);
- sound_entry.Format( "Sound%d", sound );
- StringClass sound_name(0,true);
- ini->Get_String(sound_name, section_name, sound_entry );
- if ( sound_name.Is_Empty() ) {
- break;
- }
- // Debug_Say(( "Add Sound %s\n", sound_name ));
- surface_effect->Sound.Add_String( sound_name );
- }
- // Read emitters
- for ( int emitter = 0; ; emitter++ ) {
- StringClass emitter_entry(0,true);
- emitter_entry.Format( "Emitter%d", emitter );
- StringClass emitter_name(0,true);
- ini->Get_String(emitter_name, section_name, emitter_entry );
- if ( emitter_name.Is_Empty() ) {
- break;
- }
- // Debug_Say(( "Add Emitter %s\n", emitter_name ));
- surface_effect->Emitter.Add_String( emitter_name );
- }
- // Read decals
- for ( int decal = 0; ; decal++ ) {
- StringClass decal_entry(0,true);
- decal_entry.Format( "Decal%d", decal );
- StringClass decal_name(0,true);
- ini->Get_String(decal_name, section_name, decal_entry );
- if ( decal_name.Is_Empty() ) {
- break;
- }
- // Debug_Say(( "Add Decal %s\n", decal_name ));
- surface_effect->Decal.Add_String( decal_name );
- }
- surface_effect->DecalSize = ini->Get_Float( section_name, "DecalSize", 1 );
- surface_effect->DecalSizeRandom = ini->Get_Float( section_name, "DecalSizeRandom", 0 );
- // save the effect
- SurfaceEffectsDatabase[ surface ][ hitter ] = surface_effect;
- // (gth) if this is one of the physics "hitter types" copy the
- // constants into the physics engine
- if (HitterPhysicsTypes[hitter] != -1) {
- float friction = ini->Get_Float( section_name,
- "Friction",
- PhysicsConstants::DefaultContactFriction );
- float drag = ini->Get_Float( section_name,
- "Drag",
- PhysicsConstants::DefaultContactDrag );
- PhysicsConstants::Set_Contact_Friction_Coefficient( HitterPhysicsTypes[hitter],
- surface,
- friction );
- PhysicsConstants::Set_Contact_Drag_Coefficient( HitterPhysicsTypes[hitter],
- surface,
- drag );
- }
- }
- }
- Release_INI( ini );
- ini = NULL;
- } else {
- Debug_Say(("SurfaceEffectsManager::Init - Unable to load %s\n", SURFACE_EFFECTS_INI_FILENAME ));
- }
- WWASSERT(ini == NULL);
- _IsSurfaceEffectsInitted = true;
- }
- void SurfaceEffectsManager::Shutdown( void )
- {
- #if (RECYCLE_EMITTERS)
- _EmitterRecycler.Reset();
- #endif
- for ( int surface = 0; surface < SURFACE_TYPE_MAX; surface++ ) {
- for ( int hitter = 0; hitter < NUM_HITTER_TYPES; hitter++ ) {
- if ( SurfaceEffectsDatabase[ surface ][ hitter ] ) {
- delete SurfaceEffectsDatabase[ surface ][ hitter ];
- SurfaceEffectsDatabase[ surface ][ hitter ] = NULL;
- }
- }
- }
- _IsSurfaceEffectsInitted = false;
- }
- const char * SurfaceEffectsManager::Hitter_Type_Name( int hitter )
- {
- return _HitterTypeName[ hitter ];
- }
- void SurfaceEffectsManager::Apply_Effect
- (
- int surface_type,
- int hitter_type,
- const Matrix3D & tm,
- PhysClass * hit_obj,
- PhysicalGameObj * creator,
- bool allow_decals,
- bool allow_emitters
- )
- {
- WWPROFILE( "Apply Surface Effect" );
- bool ok = ( (surface_type >= 0) &&
- (surface_type < SURFACE_TYPE_MAX) &&
- (hitter_type >=0 ) &&
- (hitter_type < NUM_HITTER_TYPES) );
- if (!ok) {
- WWDEBUG_SAY(("Invalid surface params. surface_type: %d hitter_type: %d\r\n",surface_type,hitter_type));
- return;
- }
- // Return if all surface effects are currently disabled
- if ( Mode == MODE_OFF ) {
- return;
- }
-
- // If the user has specified an override type, use it.
- if (OverrideSurfaceType != -1) { surface_type = OverrideSurfaceType; }
- // Return if we don't find any surface effect settings for this combination of surface_type, hitter_type
- SurfaceEffectClass * surface_effect = SurfaceEffectsDatabase[ surface_type ][ hitter_type ];
- if ( surface_effect == NULL ) {
- if ( SurfaceEffectsManagerDebug ) {
- Debug_Say(( "No Surface Effect for %s and %s\n", SURFACE_TYPE_STRINGS[surface_type], _HitterTypeName[hitter_type] ));
- }
- return;
- }
- const char * sound_name = surface_effect->Sound.Get_String();
- const char * emitter_name = surface_effect->Emitter.Get_String();
- const char * decal_name = surface_effect->Decal.Get_String();
- if ( SurfaceEffectsManagerDebug ) {
- Debug_Say(( "Applying Surface Effect for %s and %s\n--Sound:%s Emitter:%s Decal:%s\n",
- SURFACE_TYPE_STRINGS[surface_type],
- _HitterTypeName[hitter_type],
- sound_name ? sound_name : "none",
- emitter_name ? emitter_name : "none",
- decal_name ? decal_name : "none" ));
- }
- // Create the sound
- if ( sound_name ) {
- WWPROFILE( "Sound" );
- // I may need to plug an owner in here
- RefCountedGameObjReference *owner_ref = new RefCountedGameObjReference;
- owner_ref->Set_Ptr( creator );
- WWAudioClass::Get_Instance()->Create_Instant_Sound( sound_name, tm, owner_ref, 0, CLASSID_PSEUDO3D );
- REF_PTR_RELEASE( owner_ref );
- }
- // Return if this effect is far from the camera or not within the view frustum
- // But, do this after the sound is created!!!
- Vector3 effect_point;
- tm.Get_Translation(&effect_point);
- float dist2 = (effect_point - COMBAT_CAMERA->Get_Position()).Length2();
- if ( (dist2 > _SURFACE_EFFECT_NEAR_DISTANCE2) ) {
- if ( (dist2 > _MAX_SURFACE_EFFECT_DISTANCE2) ||
- (CollisionMath::Overlap_Test(COMBAT_CAMERA->Get_Frustum(),effect_point) == CollisionMath::OUTSIDE) )
- {
- return;
- }
- }
- // Create the emitter
- if ((allow_emitters) && (emitter_name) && (Mode != MODE_NO_EMITTERS)) {
- WWPROFILE( "Emitter" );
- #if (RECYCLE_EMITTERS)
- _EmitterRecycler.Spawn_Effect(emitter_name,tm);
- #else
- ParticleEmitterClass * emitter = (ParticleEmitterClass *)WW3DAssetManager::Get_Instance()->Create_Render_Obj( emitter_name );
- if ( emitter ) {
- SET_REF_OWNER( emitter );
- emitter->Set_Transform( tm );
- emitter->Start();
- emitter->Enable_Remove_On_Complete(true);
- PhysicsSceneClass::Get_Instance()->Add_Render_Object( emitter );
- emitter->Release_Ref();
- }
- #endif
- }
- // Create decal, (will only apply to static physics objects)
- if ((allow_decals) && (decal_name)) {
- WWPROFILE( "Decal" );
- float size = surface_effect->DecalSize;
- size += FreeRandom.Get_Float( -surface_effect->DecalSizeRandom, surface_effect->DecalSizeRandom );
- StringClass new_name( true );
- Strip_Path_From_Filename( new_name, decal_name );
- // If this is a glass decal, we enable "apply_to_translucent_meshes" and we
- // also pass in the object that was hit so the decal is *only* applied to that
- // object. Otherwise, we use normal decal processing which collects the meshes
- // that overlap the volume and applies the decal to all of them
- if ((surface_type == SURFACE_TYPE_GLASS) || (surface_type == SURFACE_TYPE_GLASS_PERMEABLE)) {
- PhysicsSceneClass::Get_Instance()->Create_Decal( tm, new_name, size, false, true, hit_obj );
- } else {
- PhysicsSceneClass::Get_Instance()->Create_Decal( tm, new_name, size );
- }
- }
- }
- PersistantSurfaceSoundClass * SurfaceEffectsManager::Create_Persistant_Sound( void )
- {
- return new PersistantSurfaceSoundClass;
- }
- void SurfaceEffectsManager::Destroy_Persistant_Sound( PersistantSurfaceSoundClass * effect )
- {
- delete effect;
- }
- void SurfaceEffectsManager::Update_Persistant_Sound( PersistantSurfaceSoundClass * effect,
- int surface_type, int hitter_type, const Matrix3D & tm )
- {
- WWASSERT( surface_type >= 0 );
- WWASSERT( surface_type < SURFACE_TYPE_MAX );
- WWASSERT( hitter_type >= 0 );
- WWASSERT( hitter_type < NUM_HITTER_TYPES );
- if ( Mode == MODE_OFF ) {
- return;
- }
- // If the user has specified an override type, use it.
- if (OverrideSurfaceType != -1) { surface_type = OverrideSurfaceType; }
- // If something changed, re-lookup the sound
- if ( ( surface_type != effect->CurrentSurfaceType ) || ( hitter_type != effect->CurrentHitterType ) ) {
- effect->CurrentSurfaceType = surface_type;
- effect->CurrentHitterType = hitter_type;
- SurfaceEffectClass * surface_effect = SurfaceEffectsDatabase[ surface_type ][ hitter_type ];
- if ( surface_effect == NULL ) {
- if ( SurfaceEffectsManagerDebug ) {
- Debug_Say(( "No Surface Effect for %s and %s\n", SURFACE_TYPE_STRINGS[surface_type], _HitterTypeName[hitter_type] ));
- }
- effect->Set_Sound( NULL );
- } else {
- const char * sound_name = surface_effect->Sound.Get_String();
- if ( SurfaceEffectsManagerDebug ) {
- Debug_Say(( "Applying Persistant Surface Sound for %s and %s Sound:%s\n",
- SURFACE_TYPE_STRINGS[surface_type],
- _HitterTypeName[hitter_type],
- sound_name ? sound_name : "none" ));
- }
- effect->Set_Sound( sound_name );
- }
- }
- // Update Position
- if ( effect->Sound != NULL ) {
- effect->Sound->Set_Transform( tm );
- }
- }
- PersistantSurfaceEmitterClass * SurfaceEffectsManager::Create_Persistant_Emitter( void )
- {
- return new PersistantSurfaceEmitterClass;
- }
- void SurfaceEffectsManager::Destroy_Persistant_Emitter( PersistantSurfaceEmitterClass * effect )
- {
- delete effect;
- }
- void SurfaceEffectsManager::Update_Persistant_Emitter( PersistantSurfaceEmitterClass * effect,
- int surface_type, int hitter_type, const Matrix3D & tm )
- {
- WWASSERT( surface_type >= 0 );
- WWASSERT( surface_type < SURFACE_TYPE_MAX );
- WWASSERT( hitter_type >= 0 );
- WWASSERT( hitter_type < NUM_HITTER_TYPES );
- if ( Mode != MODE_FULL ) {
- return;
- }
- // If the user has specified an override type, use it.
- if (OverrideSurfaceType != -1) { surface_type = OverrideSurfaceType; }
- // If something changed, re-lookup the emitter
- if ( ( surface_type != effect->CurrentSurfaceType ) || ( hitter_type != effect->CurrentHitterType ) ) {
- effect->CurrentSurfaceType = surface_type;
- effect->CurrentHitterType = hitter_type;
- SurfaceEffectClass * surface_effect = SurfaceEffectsDatabase[ surface_type ][ hitter_type ];
- if ( surface_effect == NULL ) {
- if ( SurfaceEffectsManagerDebug ) {
- Debug_Say(( "No Surface Effect for %s and %s\n", SURFACE_TYPE_STRINGS[surface_type], _HitterTypeName[hitter_type] ));
- }
- effect->Set_Emitter( NULL );
- } else {
- const char * emitter_name = surface_effect->Emitter.Get_String();
- if ( SurfaceEffectsManagerDebug ) {
- Debug_Say(( "Applying Persistant Surface Emitter for %s and %s Emitter:%s\n",
- SURFACE_TYPE_STRINGS[surface_type],
- _HitterTypeName[hitter_type],
- emitter_name ? emitter_name : "none" ));
- }
- effect->Set_Emitter( emitter_name );
- }
- }
- // Update the transform
- if ( effect->Emitter != NULL ) {
- effect->Emitter->Set_Transform( tm );
- }
- }
- bool SurfaceEffectsManager::Does_Surface_Stop_Bullets( int surface_type )
- {
- WWASSERT( surface_type >= 0 );
- WWASSERT( surface_type < SURFACE_TYPE_MAX );
- return SurfaceStopsBullets[ surface_type ];
- }
- void SurfaceEffectsManager::Apply_Damage( int surface_type, PhysicalGameObj * obj )
- {
- #ifndef PARAM_EDITING_ON
- // If the user has specified an override type, use it.
- if (OverrideSurfaceType != -1) { surface_type = OverrideSurfaceType; }
- if ( SurfaceDamageRate[surface_type] > 0 ) {
- OffenseObjectClass offense_obj( SurfaceDamageRate[surface_type], SurfaceDamageWarhead[surface_type] );
- obj->Apply_Damage_Extended( offense_obj, TimeManager::Get_Frame_Seconds() );
- }
- #endif //PARAM_EDITING_ON
- }
- bool SurfaceEffectsManager::Is_Surface_Permeable( int surface )
- {
- switch (surface) {
- case SURFACE_TYPE_FOLIAGE_PERMEABLE:
- case SURFACE_TYPE_GLASS_PERMEABLE:
- case SURFACE_TYPE_ICE_PERMEABLE:
- case SURFACE_TYPE_CLOTH_PERMEABLE:
- case SURFACE_TYPE_ELECTRICAL_PERMEABLE:
- case SURFACE_TYPE_FLAMMABLE_PERMEABLE:
- case SURFACE_TYPE_STEAM_PERMEABLE:
- case SURFACE_TYPE_WATER_PERMEABLE:
- case SURFACE_TYPE_TIBERIUM_WATER_PERMEABLE:
- return true;
- }
- return false;
- }
- void SurfaceEffectsManager::Set_Override_Surface_Type(int type)
- {
- if ((type < 0) || (type >= SURFACE_TYPE_MAX)) {
- OverrideSurfaceType = -1;
- } else {
- OverrideSurfaceType = type;
- }
- PhysicsConstants::Set_Override_Surface_Type(OverrideSurfaceType);
- }
|