| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906 |
- /*
- ** 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/c4.cpp $*
- * *
- * $Author:: Byon_g $*
- * *
- * $Modtime:: 2/12/02 10:25a $*
- * *
- * $Revision:: 72 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "c4.h"
- #include "debug.h"
- #include "phys.h"
- #include "combat.h"
- #include "explosion.h"
- #include "soldier.h"
- #include "persistfactory.h"
- #include "combatchunkid.h"
- #include "weaponmanager.h"
- #include "simpledefinitionfactory.h"
- #include "wwhack.h"
- #include "decophys.h"
- #include "assets.h"
- #include "gameobjmanager.h"
- #include "wwaudio.h"
- #include "wwprofile.h"
- #include "projectile.h"
- #include "wwphysids.h"
- #include "buildingaggregate.h"
- #include "rendobj.h"
- #include "definitionmgr.h"
- #include "apppackettypes.h"
- #include "bitpackids.h"
- #include "surfaceeffects.h"
- #include "gametype.h"
- /*
- ** C4GameObjDef
- */
- DECLARE_FORCE_LINK( C4 )
- SimplePersistFactoryClass<C4GameObjDef, CHUNKID_GAME_OBJECT_DEF_C4> _C4GameObjDefPersistFactory;
- DECLARE_DEFINITION_FACTORY(C4GameObjDef, CLASSID_GAME_OBJECT_DEF_C4, "C4") _C4GameObjDefDefFactory;
- C4GameObjDef::C4GameObjDef( void ) :
- ThrowVelocity( 5 )
- {
- EDITABLE_PARAM (C4GameObjDef, ParameterClass::TYPE_FLOAT, ThrowVelocity);
- }
- uint32 C4GameObjDef::Get_Class_ID (void) const
- {
- return CLASSID_GAME_OBJECT_DEF_C4;
- }
- PersistClass * C4GameObjDef::Create( void ) const
- {
- C4GameObj * obj = new C4GameObj;
- obj->Init( *this );
- return obj;
- }
- enum {
- CHUNKID_DEF_PARENT = 930991700,
- CHUNKID_DEF_VARIABLES,
- MICROCHUNKID_DEF_THROW_VELOCITY = 1,
- };
- bool C4GameObjDef::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_DEF_PARENT );
- PhysicalGameObjDef::Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_THROW_VELOCITY, ThrowVelocity );
- csave.End_Chunk();
- return true;
- }
- bool C4GameObjDef::Load( ChunkLoadClass &cload )
- {
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_DEF_PARENT:
- PhysicalGameObjDef::Load( cload );
- break;
- case CHUNKID_DEF_VARIABLES:
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_THROW_VELOCITY, ThrowVelocity );
- default:
- Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- break;
-
- default:
- Debug_Say(( "Unrecognized SimpleDef chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- return true;
- }
- const PersistFactoryClass & C4GameObjDef::Get_Factory (void) const
- {
- return _C4GameObjDefPersistFactory;
- }
- /*
- **
- */
- SimplePersistFactoryClass<C4GameObj, CHUNKID_GAME_OBJECT_C4> _C4GameObjPersistFactory;
- const PersistFactoryClass & C4GameObj::Get_Factory (void) const
- {
- return _C4GameObjPersistFactory;
- }
- /*
- **
- */
- C4GameObj::C4GameObj( void ) :
- AmmoDefinition( NULL ),
- Stuck( false ),
- StuckMCT( false ),
- StuckToObject( false ),
- StuckBone( 0 ),
- StuckStaticAnimObj(NULL),
- OwnerBackup( NULL ),
- Age( 0 )
- {
- Set_App_Packet_Type(APPPACKETTYPE_C4);
- }
- C4GameObj::~C4GameObj()
- {
- REF_PTR_RELEASE(StuckStaticAnimObj);
- }
- /*
- **
- */
- void C4GameObj::Init( void )
- {
- Init( Get_Definition() );
- }
- /*
- **
- */
- void C4GameObj::Init( const C4GameObjDef & definition )
- {
- SimpleGameObj::Init( definition );
- Peek_Physical_Object()->Set_Collision_Group( TERRAIN_AND_BULLET_COLLISION_GROUP );
- Peek_Physical_Object()->Set_Collision_Group( DEFAULT_COLLISION_GROUP );
- }
- const C4GameObjDef & C4GameObj::Get_Definition( void ) const
- {
- return (const C4GameObjDef &)BaseGameObj::Get_Definition();
- }
- void C4GameObj::Init_C4( const AmmoDefinitionClass * def, SoldierGameObj *owner, int detonation_mode, const Matrix3D & tm )
- {
- WWASSERT( AmmoDefinition == NULL );
- AmmoDefinition = def;
- if ( !def->ModelName.Is_Empty() ) {
- Peek_Physical_Object()->Set_Model_By_Name( def->ModelName ) ;
- }
- Owner = owner;
- DetonationMode = detonation_mode;
- Set_Transform( tm );
- Stuck = false;
- StuckMCT = false;
- StuckToObject = false;
- Peek_Physical_Object()->Set_Collision_Group( DEFAULT_COLLISION_GROUP );
- OwnerBackup = NULL;
- if ( owner ) {
- Set_Player_Type( owner->Get_Player_Type() );
- OwnerBackup = owner->Get_Player_Data();
- if ( CombatManager::I_Am_Server() && !IS_MISSION ) {
- Maintain_C4_Limit( Get_Player_Type() );
- }
- }
- int type = AmmoDefinition->AmmoType;
- if ( type != AmmoDefinitionClass::AMMO_TYPE_C4_REMOTE ) {
- // Setup Arming Timer
- float time = def->C4TriggerTime1;
- if ( detonation_mode == 2 ) time = def->C4TriggerTime2;
- if ( detonation_mode == 3 ) time = def->C4TriggerTime3;
- Timer = time;
- }
- float sound_id = def->C4TimingSound1ID;
- if ( detonation_mode == 2 ) sound_id = def->C4TimingSound1ID;
- if ( detonation_mode == 3 ) sound_id = def->C4TimingSound1ID;
- if ( sound_id ) {
- RefCountedGameObjReference *owner_ref = new RefCountedGameObjReference(Owner);
- WWAudioClass::Get_Instance()->Create_Instant_Sound( sound_id, Get_Transform(), owner_ref);
- REF_PTR_RELEASE(owner_ref);
- }
- ProjectileClass * po = Peek_Physical_Object()->As_ProjectileClass();
- if ( po ) {
- po->Set_Velocity( tm.Get_X_Vector() * Get_Definition().ThrowVelocity );
- }
- //
- // "Dirty" the object for networking
- //
- Set_Object_Dirty_Bit( NetworkObjectClass::BIT_RARE, true );
- }
- CollisionReactionType C4GameObj::Collision_Occurred( const CollisionEventClass & event )
- {
- Debug_Say(( "C4 collision\n" ));
- // if ( ( !Stuck ) && (CombatManager::I_Am_Server()) )
- if (!Stuck)
- {
- // Figure out who/what/where we hit
- PhysicalGameObj * other = NULL;
- BuildingGameObj * building = NULL;
- bool hit_projectile = event.OtherObj->As_ProjectileClass() != NULL;
- if ( event.OtherObj->Get_Observer() != NULL ) {
- other = ((CombatPhysObserverClass *)event.OtherObj->Get_Observer())->As_PhysicalGameObj();
- building = ((CombatPhysObserverClass *)event.OtherObj->Get_Observer())->As_BuildingGameObj();
- }
- Restore_Owner();
- // Ignore my owner and my owners vehicle
- if ( other != NULL && Get_Owner() != NULL ) {
- VehicleGameObj * vehicle = other->As_VehicleGameObj();
- SoldierGameObj * soldier = Get_Owner()->As_SoldierGameObj();
- if ( vehicle != NULL && vehicle == soldier->Get_Vehicle() ) {
- return COLLISION_REACTION_NO_BOUNCE;
- }
- if ( other == Get_Owner() ) {
- return COLLISION_REACTION_NO_BOUNCE;
- }
- // if ( !other->Is_Teammate( Get_Owner() ) )
- {
- Debug_Say(( "Sticking to game object %p (%p)\n", other, Get_Owner() ));
- Stuck = true;
- StuckToObject = true;
- StuckObject = other;
- StuckBone = 0;
- RenderObjClass * parent_model = other->Peek_Model();
- if ( parent_model ) {
- StuckBone = parent_model->Get_Sub_Object_Bone_Index( event.CollidedRenderObj );
- }
- Vector3 my_pos;
- Get_Position(&my_pos);
- Matrix3D::Inverse_Transform_Vector( parent_model->Get_Bone_Transform( StuckBone ), my_pos, &StuckOffset );
- Peek_Physical_Object()->Enable_User_Control( true );
-
- if (CombatManager::I_Am_Server()) {
- Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
- }
- return COLLISION_REACTION_STOP_MOTION;
- }
- } else if ( building != NULL ) {
- // Stick to the building
- Stuck = true;
- StuckObject = (ScriptableGameObj*)building;
- StuckMCT = false;
- // Check for MCT collision
- if (event.OtherObj->Get_Factory().Chunk_ID() == PHYSICS_CHUNKID_BUILDINGAGGREGATE) {
- if (((BuildingAggregateClass *)event.OtherObj)->Is_MCT()) {
- StuckMCT = true;
- }
- }
- Peek_Physical_Object()->Enable_User_Control( true );
- if (CombatManager::I_Am_Server()) {
- Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
- }
- return COLLISION_REACTION_STOP_MOTION;
- } else if ( other == NULL && !hit_projectile ) {
-
- // if this is a static anim, then try to stick to it
- if (event.OtherObj->As_StaticAnimPhysClass() != NULL) {
- Debug_Say(( "Sticking to static anim object %p (%p)\n", event.OtherObj ));
- REF_PTR_SET(StuckStaticAnimObj,(StaticAnimPhysClass *)event.OtherObj);
-
- StuckBone = 0;
- if ( StuckStaticAnimObj->Peek_Model() ) {
- StuckBone = StuckStaticAnimObj->Peek_Model()->Get_Sub_Object_Bone_Index( event.CollidedRenderObj );
- Vector3 my_pos;
- Get_Position(&my_pos);
- Matrix3D::Inverse_Transform_Vector( StuckStaticAnimObj->Peek_Model()->Get_Bone_Transform( StuckBone ), my_pos, &StuckOffset );
- }
- }
- // If we hit permiable, pass through
- if ( event.CollisionResult != NULL &&
- SurfaceEffectsManager::Is_Surface_Permeable( event.CollisionResult->SurfaceType ) ) {
- Debug_Say(( "C4 passes through permeable\n" ));
- return COLLISION_REACTION_NO_BOUNCE;
- }
- // We are hitting a static terrain, just stick
- Debug_Say(( "Sticking to terrain\n" ));
- Peek_Physical_Object()->Enable_User_Control( true );
- Stuck = true;
- if (CombatManager::I_Am_Server()) {
- Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
- }
- return COLLISION_REACTION_STOP_MOTION;
- }
- }
- return COLLISION_REACTION_NO_BOUNCE;
- }
- /*
- ** C4GameObj Save and Load
- */
- enum {
- CHUNKID_PARENT = 922991750,
- CHUNKID_VARIABLES,
- XXXCHUNKID_C4_TIMER,
- CHUNKID_OWNER,
- CHUNKID_STUCK_OBJECT,
- XXXXMICROCHUNKID_PARAMS_NAME = 1,
- XXXXXMICROCHUNKID_PARAMS_NAME,
- MICROCHUNKID_AMMO_DEF_ID,
- MICROCHUNKID_DETONATION_MODE,
- MICROCHUNKID_TIMER,
- MICROCHUNKID_STUCK,
- MICROCHUNKID_STUCK_OFFSET,
- MICROCHUNKID_STUCK_MCT,
- MICROCHUNKID_STUCK_BONE,
- MICROCHUNKID_STUCK_STATIC_ANIM_OBJ_ID,
- MICROCHUNKID_STUCK_TO_OBJECT,
- MICROCHUNKID_AGE,
- };
- bool C4GameObj::Save( ChunkSaveClass & csave )
- {
- csave.Begin_Chunk( CHUNKID_PARENT );
- SimpleGameObj::Save( csave );
- csave.End_Chunk();
- csave.Begin_Chunk( CHUNKID_VARIABLES );
- int ammo_def_id = AmmoDefinition->Get_ID();
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_AMMO_DEF_ID, ammo_def_id );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DETONATION_MODE, DetonationMode );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TIMER, Timer );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK, Stuck );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_OFFSET, StuckOffset );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_MCT, StuckMCT );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_BONE, StuckBone );
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_TO_OBJECT, StuckToObject );
- if (StuckStaticAnimObj != NULL) {
- uint32 id = StuckStaticAnimObj->Get_ID();
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_STATIC_ANIM_OBJ_ID, id);
- }
- WRITE_MICRO_CHUNK( csave, MICROCHUNKID_AGE, Age );
- csave.End_Chunk();
- if ( Owner != NULL ) {
- csave.Begin_Chunk( CHUNKID_OWNER );
- Owner.Save( csave );
- csave.End_Chunk();
- }
- if ( StuckObject != NULL ) {
- csave.Begin_Chunk( CHUNKID_STUCK_OBJECT );
- StuckObject.Save( csave );
- csave.End_Chunk();
- }
- return true;
- }
- bool C4GameObj::Load( ChunkLoadClass &cload )
- {
- REF_PTR_RELEASE(StuckStaticAnimObj);
- uint32 static_anim_obj_id = 0xFFFFFFFF;
- while (cload.Open_Chunk()) {
- switch(cload.Cur_Chunk_ID()) {
- case CHUNKID_PARENT:
- SimpleGameObj::Load( cload );
- break;
-
- case CHUNKID_VARIABLES:
- {
- int ammo_def_id = 0;
- while (cload.Open_Micro_Chunk()) {
- switch(cload.Cur_Micro_Chunk_ID()) {
- READ_MICRO_CHUNK( cload, MICROCHUNKID_AMMO_DEF_ID, ammo_def_id );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_DETONATION_MODE, DetonationMode );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_TIMER, Timer );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK, Stuck );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_OFFSET, StuckOffset );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_MCT, StuckMCT );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_BONE, StuckBone );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_STATIC_ANIM_OBJ_ID, static_anim_obj_id);
- READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_TO_OBJECT, StuckToObject );
- READ_MICRO_CHUNK( cload, MICROCHUNKID_AGE, Age );
- default:
- Debug_Say(( "Unrecognized C4 Variable chunkID\n" ));
- break;
- }
- cload.Close_Micro_Chunk();
- }
- WWASSERT( AmmoDefinition == NULL );
- AmmoDefinition = WeaponManager::Find_Ammo_Definition( ammo_def_id );
- WWASSERT( AmmoDefinition != NULL );
- break;
- }
- case CHUNKID_OWNER:
- Owner.Load( cload );
- break;
- case CHUNKID_STUCK_OBJECT:
- StuckObject.Load( cload );
- break;
- default:
- Debug_Say(( "Unrecognized C4 chunkID\n" ));
- break;
- }
- cload.Close_Chunk();
- }
- if (static_anim_obj_id != 0xFFFFFFFF) {
- StaticPhysClass * pobj = PhysicsSceneClass::Get_Instance()->Get_Static_Object_By_ID(static_anim_obj_id);
- if (pobj && (pobj->As_StaticAnimPhysClass() != NULL)) {
- REF_PTR_SET(StuckStaticAnimObj,(StaticAnimPhysClass *)pobj);
- }
- REF_PTR_RELEASE(pobj);
- }
- return true;
- }
- void C4GameObj::Think( void )
- {
- SimpleGameObj::Think();
- WWPROFILE( "C4 Think" );
- if ( !CombatManager::I_Am_Server() ) {
- return;
- }
- Age += TimeManager::Get_Frame_Seconds();
- int type = AmmoDefinition->AmmoType;
- WWASSERT( type >= AmmoDefinitionClass::AMMO_TYPE_C4_REMOTE );
- WWASSERT( type <= AmmoDefinitionClass::AMMO_TYPE_C4_PROXIMITY );
- Restore_Owner();
- if ( type == AmmoDefinitionClass::AMMO_TYPE_C4_REMOTE ) {
- if ( CombatManager::I_Am_Server() ) {
- // Check for owner to detonate
- SoldierGameObj * owner = Get_Owner();
- if ( owner == NULL ) {
- Defuse();
- } else if ( owner->Detonate_C4() ) {
- Detonate();
- }
- } else {
- Set_Delete_Pending();
- }
- }
- if ( type == AmmoDefinitionClass::AMMO_TYPE_C4_TIMED ) {
- // Check for time's up
- Timer -= TimeManager::Get_Frame_Seconds();
- if ( Timer <= 0 ) {
- Detonate();
- }
- }
- if ( type == AmmoDefinitionClass::AMMO_TYPE_C4_PROXIMITY ) {
- Timer -= TimeManager::Get_Frame_Seconds();
- if ( Timer <= 0 ) {
- // Reset Timer
- // Timer += 1; // Check every second
- Timer += 0.25; // Check every 1/4 second
- // Check for smart objs in proximity
- float trigger_range = AmmoDefinition->C4TriggerRange1;
- if ( DetonationMode == 2 ) trigger_range = AmmoDefinition->C4TriggerRange2;
- if ( DetonationMode == 3 ) trigger_range = AmmoDefinition->C4TriggerRange3;
- Vector3 c4_pos;
- Get_Position( &c4_pos );
- SLNode<SmartGameObj> * smart_objnode;
- for (smart_objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head(); smart_objnode; smart_objnode = smart_objnode->Next()) {
- SmartGameObj * obj = smart_objnode->Data();
- if ( obj && Is_Enemy( obj ) ) {
- Vector3 obj_pos;
- obj->Get_Position( &obj_pos );
- float range = (obj_pos - c4_pos).Length();
- if ( range <= trigger_range ) {
- Detonate();
- }
- }
- }
- }
- }
- }
- void C4GameObj::Post_Think( void )
- {
- SimpleGameObj::Post_Think();
- WWPROFILE( "C4 Post_Think" );
- // Follow your stuck object
- if ( Stuck ) {
- if ( StuckObject.Get_Ptr() != NULL ) {
- PhysicalGameObj * obj = StuckObject.Get_Ptr()->As_PhysicalGameObj();
- if ( obj ) {
- RenderObjClass * parent_model = obj->Peek_Model();
- Vector3 pos;
- if ( parent_model ) {
- pos = parent_model->Get_Bone_Transform( StuckBone ) * StuckOffset;
- } else {
- pos = obj->Get_Transform() * StuckOffset;
- }
- Set_Position( pos );
- if (obj->As_SoldierGameObj()) {
- bool hide = (obj->As_SoldierGameObj()->Get_Vehicle() != NULL);
- if (Peek_Model()) {
- Peek_Model()->Set_Hidden(hide);
- }
- }
- }
-
- } else if ( StuckStaticAnimObj != NULL) {
-
- Vector3 pos;
- pos = StuckStaticAnimObj->Peek_Model()->Get_Bone_Transform( StuckBone ) * StuckOffset;
- Set_Position(pos);
-
- } else {
- // Delete without exploding if my object is gone
- if ( StuckToObject ) {
- Set_Delete_Pending();
- }
- }
- }
- }
- void C4GameObj::Detonate( void )
- {
- if ( CombatManager::I_Am_Server() ) {
- Restore_Owner();
- if ( AmmoDefinition && AmmoDefinition->ExplosionDefID ) {
- int owner_id = 0;
- if ( Get_Owner() ) {
- owner_id = Get_Owner()->Get_ID();
- }
- DamageableGameObj * force_victim = NULL;
- if ( Stuck && StuckToObject ) {
- force_victim = (DamageableGameObj *)StuckObject.Get_Ptr();
- }
- ExplosionManager::Server_Explode( AmmoDefinition->ExplosionDefID, Get_Transform().Get_Translation(), owner_id, force_victim );
- }
- // If I am stuck to a building, apply damage to that building
- if ( Stuck ) {
- if ( StuckObject.Get_Ptr() != NULL ) {
- BuildingGameObj * building = StuckObject.Get_Ptr()->As_BuildingGameObj();
- if ( building ) {
- ExplosionManager::Explosion_Damage_Building( AmmoDefinition->ExplosionDefID, building, StuckMCT, Get_Owner() );
- }
- }
- }
- }
- Set_Delete_Pending();
- }
- void C4GameObj::Completely_Damaged( const OffenseObjectClass & damager )
- {
- Defuse();
- }
- /*
- **
- */
- void C4GameObj::Get_Information( StringClass & string )
- {
- SimpleGameObj::Get_Information( string );
- int type = AmmoDefinition->AmmoType;
- if ( type == AmmoDefinitionClass::AMMO_TYPE_C4_TIMED ) {
- StringClass temp(0,true);
- temp.Format( "Timer: %1.1f\n", Timer );
- string += temp;
- }
- }
- /*
- **
- */
- void C4GameObj::Export_Rare( BitStreamClass &packet )
- {
- SimpleGameObj::Export_Rare( packet );
- int ammo_def_id = 0;
- if ( AmmoDefinition != NULL ) {
- ammo_def_id = AmmoDefinition->Get_ID();
- }
- packet.Add( ammo_def_id );
- int owner_id = 0;
- if (Get_Owner()) {
- owner_id = Get_Owner()->Get_ID();
- }
- packet.Add(owner_id);
- Vector3 pos(0,0,0);
- Vector3 vel(0,0,0);
- ProjectileClass * po = Peek_Physical_Object()->As_ProjectileClass();
- if ( po ) {
- po->Get_Velocity(&vel);
- po->Get_Position(&pos);
- }
- packet.Add(vel.X, BITPACK_VEHICLE_VELOCITY);
- packet.Add(vel.Y, BITPACK_VEHICLE_VELOCITY);
- packet.Add(vel.Z, BITPACK_VEHICLE_VELOCITY);
- //
- // Synchronize the stuck state of C4
- //
- packet.Add(Stuck);
- if (Stuck) {
-
- packet.Add(pos.X, BITPACK_WORLD_POSITION_X);
- packet.Add(pos.Y, BITPACK_WORLD_POSITION_Y);
- packet.Add(pos.Z, BITPACK_WORLD_POSITION_Z);
- packet.Add(StuckMCT);
- packet.Add(StuckToObject);
- int stuck_object_id=0;
- if (StuckObject.Get_Ptr()) {
- stuck_object_id = StuckObject.Get_Ptr()->Get_ID();
- }
- packet.Add(stuck_object_id);
-
- if (StuckToObject) {
- packet.Add(StuckOffset.X, BITPACK_VEHICLE_VELOCITY); // offset, using velocity packing...
- packet.Add(StuckOffset.Y, BITPACK_VEHICLE_VELOCITY);
- packet.Add(StuckOffset.Z, BITPACK_VEHICLE_VELOCITY);
- packet.Add(StuckBone);
- }
- bool stuck_static_anim = (StuckStaticAnimObj != NULL);
- packet.Add(stuck_static_anim);
- if (stuck_static_anim) {
- packet.Add(StuckStaticAnimObj->Get_ID());
- }
- }
- }
- void C4GameObj::Import_Rare( BitStreamClass &packet )
- {
- SimpleGameObj::Import_Rare( packet );
- int ammo_def_id = packet.Get( ammo_def_id );
- if ( ammo_def_id != 0 ) {
- AmmoDefinition = (AmmoDefinitionClass *)DefinitionMgrClass::Find_Definition( ammo_def_id );
- if ( !AmmoDefinition->ModelName.Is_Empty() ) {
- Peek_Physical_Object()->Set_Model_By_Name( AmmoDefinition->ModelName ) ;
- }
- }
- int owner_id = packet.Get(owner_id);
- if (owner_id != 0) {
- Owner = GameObjManager::Find_SmartGameObj(owner_id);
- } else {
- Owner = NULL;
- }
- Vector3 vel;
- packet.Get(vel.X, BITPACK_VEHICLE_VELOCITY);
- packet.Get(vel.Y, BITPACK_VEHICLE_VELOCITY);
- packet.Get(vel.Z, BITPACK_VEHICLE_VELOCITY);
- ProjectileClass * po = Peek_Physical_Object()->As_ProjectileClass();
- if ( po ) {
- po->Set_Velocity(vel);
- }
- //
- // Synchronize the stuck state of C4
- //
- Stuck = packet.Get(Stuck);
- if (Stuck) {
- Peek_Physical_Object()->Enable_User_Control( true );
- // Update the position
- Vector3 pos;
- packet.Get(pos.X, BITPACK_WORLD_POSITION_X);
- packet.Get(pos.Y, BITPACK_WORLD_POSITION_Y);
- packet.Get(pos.Z, BITPACK_WORLD_POSITION_Z);
- ProjectileClass * po = Peek_Physical_Object()->As_ProjectileClass();
- if ( po ) {
- Vector3 local_pos;
- po->Get_Position(&local_pos);
- if ((local_pos - pos).Length2() > 0.5f * 0.5f) {
- po->Set_Position(pos);
- }
- }
- WWDEBUG_SAY(("C4 %d is now STUCK, pos= %f, %f, %f",(int)this, pos.X,pos.Y,pos.Z));
- packet.Get(StuckMCT);
- packet.Get(StuckToObject);
- int stuck_object_id;
- packet.Get(stuck_object_id);
- StuckObject = GameObjManager::Find_ScriptableGameObj(stuck_object_id);
- if (StuckToObject) {
- packet.Get(StuckOffset.X, BITPACK_VEHICLE_VELOCITY); // offset, using velocity packing...
- packet.Get(StuckOffset.Y, BITPACK_VEHICLE_VELOCITY);
- packet.Get(StuckOffset.Z, BITPACK_VEHICLE_VELOCITY);
- packet.Get(StuckBone);
- }
- bool stuck_static_anim;
- packet.Get(stuck_static_anim);
- if (stuck_static_anim) {
-
- uint32 static_anim_obj_id = 0;
- packet.Get(static_anim_obj_id);
- if (static_anim_obj_id != 0xFFFFFFFF) {
- StaticPhysClass * pobj = PhysicsSceneClass::Get_Instance()->Get_Static_Object_By_ID(static_anim_obj_id);
- if (pobj && (pobj->As_StaticAnimPhysClass() != NULL)) {
- REF_PTR_SET(StuckStaticAnimObj,(StaticAnimPhysClass *)pobj);
- }
- REF_PTR_RELEASE(pobj);
- }
- }
- }
- }
- void C4GameObj::Defuse( void )
- {
- if ( CombatManager::I_Am_Server() ) {
- Restore_Owner();
- const AmmoDefinitionClass * disarmed_ammo = WeaponManager::Find_Ammo_Definition( "KilledC4" );
- if ( disarmed_ammo && disarmed_ammo->ExplosionDefID ) {
- int owner_id = 0;
- if ( Get_Owner() ) {
- owner_id = Get_Owner()->Get_ID();
- }
- ExplosionManager::Server_Explode( disarmed_ammo->ExplosionDefID, Get_Transform().Get_Translation(), owner_id );
- }
- }
- Set_Delete_Pending();
- }
- void C4GameObj::Restore_Owner( void )
- {
- if ( Get_Owner() == NULL && OwnerBackup != NULL &&
- AmmoDefinition && (int)AmmoDefinition->AmmoType != (int)AmmoDefinitionClass::AMMO_TYPE_C4_REMOTE ) {
- // Try and find a smart game obj with the same playerdata
- SLNode<SmartGameObj> * smart_objnode;
- for (smart_objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head(); smart_objnode; smart_objnode = smart_objnode->Next()) {
- SmartGameObj * obj = smart_objnode->Data();
- if ( obj->Get_Player_Data() == OwnerBackup ) {
- Owner = obj;
- Debug_Say(( "Found C4 owner\n" ));
- }
- }
- if ( Get_Owner() == NULL ) {
- OwnerBackup = NULL;
- Defuse();
- Debug_Say(( "Didn't find C4 owner\n" ));
- }
- }
- }
- /*
- **
- */
- #define C4_LIMIT 30
- void C4GameObj::Maintain_C4_Limit( int player_type )
- {
- if ( !CombatManager::I_Am_Server() || IS_MISSION ) {
- return;
- }
- SLNode<BaseGameObj> *objnode;
- C4GameObj * oldest_c4 = NULL;
- int count = 0;
- for ( objnode = GameObjManager::Get_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
- PhysicalGameObj * phys = objnode->Data()->As_PhysicalGameObj();
- if ( phys ) {
- C4GameObj * c4 = phys->As_C4GameObj();
- if ( c4 &&
- c4->Get_Player_Type() == player_type &&
- c4->AmmoDefinition &&
- (int)c4->AmmoDefinition->AmmoType != (int)AmmoDefinitionClass::AMMO_TYPE_C4_TIMED ) {
- count++;
- if ( (oldest_c4 == NULL) || (c4->Age > oldest_c4->Age) ) {
- oldest_c4 = c4;
- }
- }
- }
- }
- if ( count > C4_LIMIT && oldest_c4 != NULL ) {
- oldest_c4->Defuse();
- }
- }
|