mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-15 23:21:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
398
Code/Combat/samsite.cpp
Normal file
398
Code/Combat/samsite.cpp
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
** 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/samsite.cpp $*
|
||||
* *
|
||||
* $Author:: Tom_s $*
|
||||
* *
|
||||
* $Modtime:: 9/17/01 4:18p $*
|
||||
* *
|
||||
* $Revision:: 36 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "samsite.h"
|
||||
#include "decophys.h"
|
||||
#include "combat.h"
|
||||
#include "animcontrol.h"
|
||||
#include "wwpacket.h"
|
||||
#include "debug.h"
|
||||
#include "gameobjmanager.h"
|
||||
#include "vehicle.h"
|
||||
#include "persistfactory.h"
|
||||
#include "combatchunkid.h"
|
||||
#include "simpledefinitionfactory.h"
|
||||
#include "wwhack.h"
|
||||
#include "wwprofile.h"
|
||||
|
||||
|
||||
/*
|
||||
** SAMSiteGameObjDef
|
||||
*/
|
||||
DECLARE_FORCE_LINK( SAMSite )
|
||||
|
||||
SimplePersistFactoryClass<SAMSiteGameObjDef, CHUNKID_GAME_OBJECT_DEF_SAMSITE> _SAMSiteGameObjDefPersistFactory;
|
||||
|
||||
DECLARE_DEFINITION_FACTORY(SAMSiteGameObjDef, CLASSID_GAME_OBJECT_DEF_SAMSITE, "SAMSite") _SAMSiteGameObjDefDefFactory;
|
||||
|
||||
SAMSiteGameObjDef::SAMSiteGameObjDef( void )
|
||||
{
|
||||
MODEL_DEF_PARAM( SAMSiteGameObjDef, PhysDefID, "DecorationPhysDef" );
|
||||
}
|
||||
|
||||
uint32 SAMSiteGameObjDef::Get_Class_ID (void) const
|
||||
{
|
||||
return CLASSID_GAME_OBJECT_DEF_SAMSITE;
|
||||
}
|
||||
|
||||
PersistClass * SAMSiteGameObjDef::Create( void ) const
|
||||
{
|
||||
SAMSiteGameObj * obj = new SAMSiteGameObj;
|
||||
obj->Init( *this );
|
||||
return obj;
|
||||
}
|
||||
|
||||
enum {
|
||||
CHUNKID_DEF_PARENT = 930991800,
|
||||
};
|
||||
|
||||
bool SAMSiteGameObjDef::Save( ChunkSaveClass & csave )
|
||||
{
|
||||
csave.Begin_Chunk( CHUNKID_DEF_PARENT );
|
||||
SmartGameObjDef::Save( csave );
|
||||
csave.End_Chunk();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SAMSiteGameObjDef::Load( ChunkLoadClass &cload )
|
||||
{
|
||||
while (cload.Open_Chunk()) {
|
||||
switch(cload.Cur_Chunk_ID()) {
|
||||
|
||||
case CHUNKID_DEF_PARENT:
|
||||
SmartGameObjDef::Load( cload );
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug_Say(( "Unrecognized SimpleDef chunkID\n" ));
|
||||
break;
|
||||
|
||||
}
|
||||
cload.Close_Chunk();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const PersistFactoryClass & SAMSiteGameObjDef::Get_Factory (void) const
|
||||
{
|
||||
return _SAMSiteGameObjDefPersistFactory;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**
|
||||
*/
|
||||
SimplePersistFactoryClass<SAMSiteGameObj, CHUNKID_GAME_OBJECT_SAMSITE> _SAMSiteGameObjPersistFactory;
|
||||
|
||||
const PersistFactoryClass & SAMSiteGameObj::Get_Factory (void) const
|
||||
{
|
||||
return _SAMSiteGameObjPersistFactory;
|
||||
}
|
||||
|
||||
|
||||
typedef enum {
|
||||
SAMSITE_STATE_DOWN,
|
||||
SAMSITE_STATE_UP,
|
||||
SAMSITE_STATE_RISING,
|
||||
SAMSITE_STATE_DROPPING,
|
||||
};
|
||||
|
||||
/*
|
||||
** SAMSiteGameObject
|
||||
*/
|
||||
SAMSiteGameObj::SAMSiteGameObj() :
|
||||
TurretBone( -1 ),
|
||||
BarrelBone( -1 ),
|
||||
State( SAMSITE_STATE_DOWN )
|
||||
{
|
||||
}
|
||||
|
||||
SAMSiteGameObj::~SAMSiteGameObj()
|
||||
{
|
||||
if ( Peek_Model() ) {
|
||||
if ( TurretBone != -1 ) {
|
||||
if ( Peek_Model()->Is_Bone_Captured( TurretBone ) ) {
|
||||
Peek_Model()->Release_Bone( TurretBone );
|
||||
TurretBone = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( BarrelBone != -1 ) {
|
||||
if ( Peek_Model()->Is_Bone_Captured( BarrelBone ) ) {
|
||||
Peek_Model()->Release_Bone( BarrelBone );
|
||||
BarrelBone = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
*/
|
||||
void SAMSiteGameObj::Init( void )
|
||||
{
|
||||
Init( Get_Definition() );
|
||||
}
|
||||
|
||||
void SAMSiteGameObj::Init( const SAMSiteGameObjDef & definition )
|
||||
{
|
||||
SmartGameObj::Init( definition );
|
||||
}
|
||||
|
||||
const SAMSiteGameObjDef & SAMSiteGameObj::Get_Definition( void ) const
|
||||
{
|
||||
return (const SAMSiteGameObjDef &)BaseGameObj::Get_Definition();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** SAMSiteGameObj Save and Load
|
||||
*/
|
||||
enum {
|
||||
CHUNKID_PARENT = 922991750,
|
||||
CHUNKID_VARIABLES,
|
||||
XXXCHUNKID_SAM_TIMER,
|
||||
XXXCHUNKID_ANIM_CONTROL,
|
||||
|
||||
XXXMICROCHUNKID_PHYSOBJ = 1,
|
||||
MICROCHUNKID_STATE,
|
||||
MICROCHUNKID_TIMER,
|
||||
};
|
||||
|
||||
bool SAMSiteGameObj::Save( ChunkSaveClass & csave )
|
||||
{
|
||||
csave.Begin_Chunk( CHUNKID_PARENT );
|
||||
SmartGameObj::Save( csave );
|
||||
csave.End_Chunk();
|
||||
|
||||
csave.Begin_Chunk( CHUNKID_VARIABLES );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STATE, State );
|
||||
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TIMER, Timer );
|
||||
csave.End_Chunk();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SAMSiteGameObj::Load( ChunkLoadClass &cload )
|
||||
{
|
||||
while (cload.Open_Chunk()) {
|
||||
switch(cload.Cur_Chunk_ID()) {
|
||||
|
||||
case CHUNKID_PARENT:
|
||||
SmartGameObj::Load( cload );
|
||||
break;
|
||||
|
||||
case CHUNKID_VARIABLES:
|
||||
{
|
||||
while (cload.Open_Micro_Chunk()) {
|
||||
switch(cload.Cur_Micro_Chunk_ID()) {
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_STATE, State );
|
||||
READ_MICRO_CHUNK( cload, MICROCHUNKID_TIMER, Timer );
|
||||
default:
|
||||
Debug_Say(( "Unrecognized SimpleGameObj Variable chunkID\n" ));
|
||||
break;
|
||||
}
|
||||
cload.Close_Micro_Chunk();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Debug_Say(( "Unrecognized SimpleGameObj chunkID\n" ));
|
||||
break;
|
||||
|
||||
}
|
||||
cload.Close_Chunk();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
*/
|
||||
void SAMSiteGameObj::Import_Frequent( BitStreamClass & packet )
|
||||
{
|
||||
WWASSERT(CombatManager::I_Am_Only_Client());
|
||||
|
||||
SmartGameObj::Import_Frequent( packet );
|
||||
WWASSERT(packet.Is_Flushed());
|
||||
}
|
||||
|
||||
void SAMSiteGameObj::Export_Frequent( BitStreamClass & packet )
|
||||
{
|
||||
SmartGameObj::Export_Frequent( packet );
|
||||
}
|
||||
|
||||
void SAMSiteGameObj::Update_Turret( float weapon_turn, float weapon_tilt )
|
||||
{
|
||||
if ( TurretBone == -1 ) {
|
||||
TurretBone = Peek_Model()->Get_Bone_Index( "turret" );
|
||||
if ( TurretBone != -1 ) {
|
||||
Peek_Model()->Capture_Bone( TurretBone );
|
||||
if ( !Peek_Model()->Is_Bone_Captured( TurretBone ) ) {
|
||||
Debug_Say(( "SAMSiteGameObj : Turret Bone not captured\n" ));
|
||||
TurretBone = -1;
|
||||
}
|
||||
} else {
|
||||
Debug_Say(( "SAMSiteGameObj : Turret Bone not found\n" ));
|
||||
}
|
||||
}
|
||||
|
||||
if ( BarrelBone == -1 ) {
|
||||
BarrelBone = Peek_Model()->Get_Bone_Index( "barrel" );
|
||||
if ( BarrelBone != -1 ) {
|
||||
Peek_Model()->Capture_Bone( BarrelBone );
|
||||
if ( !Peek_Model()->Is_Bone_Captured( BarrelBone ) ) {
|
||||
BarrelBone = -1;
|
||||
Debug_Say(( "Barrel Bone not captured\n" ));
|
||||
}
|
||||
|
||||
} else {
|
||||
Debug_Say(( "Barrel Bone not found\n" ));
|
||||
}
|
||||
}
|
||||
|
||||
if ( TurretBone != -1 ) {
|
||||
|
||||
Matrix3D facing(1);
|
||||
facing.Rotate_Z( weapon_turn );
|
||||
|
||||
if ( BarrelBone == -1 ) { // if no barrel bone
|
||||
facing.Rotate_Y( -weapon_tilt ); // neg rotate y tilts up
|
||||
}
|
||||
|
||||
Peek_Model()->Control_Bone( TurretBone, facing );
|
||||
}
|
||||
|
||||
if ( BarrelBone != -1 ) {
|
||||
Matrix3D facing(1);
|
||||
facing.Rotate_Y( -weapon_tilt ); // neg rotate y tilts up
|
||||
Peek_Model()->Control_Bone( BarrelBone, facing );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool SAMSiteGameObj::Set_Targeting( const Vector3 & target_pos, bool do_tilt )
|
||||
{
|
||||
// Should add slow turning
|
||||
SmartGameObj::Set_Targeting( target_pos );
|
||||
|
||||
Vector3 muzzle_pos = Peek_Model()->Get_Bone_Transform( "muzzle" ).Get_Translation();
|
||||
Matrix3D tm;
|
||||
tm.Obj_Look_At( muzzle_pos, target_pos, 0 );
|
||||
|
||||
float weapon_tilt = -tm.Get_Y_Rotation();
|
||||
tm.Rotate_Y( weapon_tilt );
|
||||
float weapon_turn = tm.Get_Z_Rotation();
|
||||
|
||||
if ( do_tilt == false ) {
|
||||
weapon_tilt = 0;
|
||||
}
|
||||
|
||||
Update_Turret( weapon_turn, weapon_tilt );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SAMSiteGameObj::Generate_Control( void )
|
||||
{
|
||||
if ( State == SAMSITE_STATE_UP ) {
|
||||
SmartGameObj::Generate_Control();
|
||||
}
|
||||
}
|
||||
|
||||
static char * _profile_name = "SAMSite Think";
|
||||
void SAMSiteGameObj::Think( void )
|
||||
{
|
||||
SmartGameObj *target = NULL;
|
||||
{ WWPROFILE( _profile_name );
|
||||
|
||||
// Find Nearest Emeny
|
||||
Vector3 my_pos;
|
||||
Get_Position( &my_pos );
|
||||
SLNode<SmartGameObj> *node;
|
||||
for ( node = GameObjManager::Get_Smart_Game_Obj_List()->Head(); node; node = node->Next()) {
|
||||
VehicleGameObj *obj = node->Data()->As_VehicleGameObj();
|
||||
if ( !obj || !obj->Is_Aircraft() ) continue;
|
||||
Vector3 vehicle_pos;
|
||||
obj->Get_Position( &vehicle_pos );
|
||||
vehicle_pos -= my_pos;
|
||||
target = obj;
|
||||
// Debug_Say(( "Vehicle is %f away\n", distance ));
|
||||
}
|
||||
if ( target ) {
|
||||
ActionParamsStruct parameters;
|
||||
parameters.Priority = 100;
|
||||
parameters.AttackObject = target;
|
||||
parameters.AttackRange = 40;
|
||||
parameters.MoveLocation = my_pos;
|
||||
parameters.MoveArrivedDistance = 10000;
|
||||
Get_Action()->Attack( parameters );
|
||||
} else {
|
||||
Get_Action()->Reset( 100 );
|
||||
}
|
||||
}
|
||||
SmartGameObj::Think();
|
||||
{ WWPROFILE( _profile_name );
|
||||
|
||||
if ( State == SAMSITE_STATE_DOWN ) {
|
||||
if ( target ) {
|
||||
Set_Animation( "B_samsiteL1.M_samrise" );
|
||||
Get_Anim_Control()->Set_Mode( ANIM_MODE_ONCE, 0 );
|
||||
State = SAMSITE_STATE_RISING;
|
||||
}
|
||||
} else if ( State == SAMSITE_STATE_UP ) {
|
||||
Timer -= TimeManager::Get_Frame_Seconds();
|
||||
if ( Timer <= 0 ) {
|
||||
Set_Animation( "B_samsitel1.M_samdrop" );
|
||||
Get_Anim_Control()->Set_Mode( ANIM_MODE_ONCE, 0 );
|
||||
State = SAMSITE_STATE_DROPPING;
|
||||
}
|
||||
} else {
|
||||
// If rising of dropping, check for completion, then set timer and state
|
||||
if( Get_Anim_Control()->Is_Complete() ) {
|
||||
State = ( State == SAMSITE_STATE_RISING ) ? SAMSITE_STATE_UP : SAMSITE_STATE_DOWN;
|
||||
Timer = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user