This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Combat/samsite.cpp

399 lines
10 KiB
C++
Raw Permalink Normal View History

/*
** 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;
}
}
}
}