331 lines
11 KiB
C
331 lines
11 KiB
C
|
/*
|
||
|
** 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/weapons.h $*
|
||
|
* *
|
||
|
* $Author:: Byon_g $*
|
||
|
* *
|
||
|
* $Modtime:: 3/25/02 2:08p $*
|
||
|
* *
|
||
|
* $Revision:: 108 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#ifndef WEAPONS_H
|
||
|
#define WEAPONS_H
|
||
|
|
||
|
#ifndef ALWAYS_H
|
||
|
#include "always.h"
|
||
|
#endif
|
||
|
|
||
|
#ifndef GAMEOBJREF_H
|
||
|
#include "gameobjref.h"
|
||
|
#endif
|
||
|
|
||
|
#ifndef MATRIX3D_H
|
||
|
#include "matrix3d.h"
|
||
|
#endif
|
||
|
|
||
|
#ifndef WEAPONMANAGER_H
|
||
|
#include "weaponmanager.h"
|
||
|
#endif
|
||
|
|
||
|
#ifndef SIMPLEVEC_H
|
||
|
#include "simplevec.h"
|
||
|
#endif
|
||
|
|
||
|
class BitStreamClass;
|
||
|
class ChunkSaveClass;
|
||
|
class ChunkLoadClass;
|
||
|
class RenderObjClass;
|
||
|
class ArmedGameObj;
|
||
|
class ParticleEmitterClass;
|
||
|
class AudibleSoundClass;
|
||
|
class PhysicalGameObj;
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
typedef enum {
|
||
|
WEAPON_HOLD_STYLE_C4 = 0,
|
||
|
WEAPON_HOLD_STYLE_NOT_USED,
|
||
|
WEAPON_HOLD_STYLE_AT_SHOULDER, // 2
|
||
|
WEAPON_HOLD_STYLE_AT_HIP,
|
||
|
WEAPON_HOLD_STYLE_LAUNCHER,
|
||
|
WEAPON_HOLD_STYLE_HANDGUN,
|
||
|
WEAPON_HOLD_STYLE_BEACON,
|
||
|
WEAPON_HOLD_STYLE_EMPTY_HANDS,
|
||
|
WEAPON_HOLD_STYLE_AT_CHEST,
|
||
|
WEAPON_HOLD_STYLE_HANDS_DOWN,
|
||
|
NUM_WEAPON_HOLD_STYLES
|
||
|
} WeaponHoldStyleType;
|
||
|
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
typedef enum {
|
||
|
WEAPON_MODEL_UPDATE_WILL_BE_NEEDED,
|
||
|
WEAPON_MODEL_UPDATE_IS_NEEDED,
|
||
|
WEAPON_MODEL_UPDATE_NOT_NEEDED,
|
||
|
} WeaponModelUpdateState;
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
typedef enum {
|
||
|
WEAPON_ANIM_NOT_FIRING,
|
||
|
WEAPON_ANIM_FIRING_0,
|
||
|
WEAPON_ANIM_FIRING_1
|
||
|
} WeaponAnimState;
|
||
|
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
class MuzzleFlashClass {
|
||
|
|
||
|
public:
|
||
|
MuzzleFlashClass( void );
|
||
|
~MuzzleFlashClass( void );
|
||
|
|
||
|
void Init( RenderObjClass * robj );
|
||
|
|
||
|
void Update( bool flashA0, bool flashA1 );
|
||
|
|
||
|
private:
|
||
|
|
||
|
int MuzzleA0Bone;
|
||
|
int MuzzleA1Bone;
|
||
|
float Rotation;
|
||
|
RenderObjClass * Model;
|
||
|
|
||
|
bool LastFlashA0;
|
||
|
bool LastFlashA1;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
*/
|
||
|
class WeaponClass {
|
||
|
|
||
|
public:
|
||
|
WeaponClass( const WeaponDefinitionClass *weapon_def = NULL );
|
||
|
~WeaponClass( void );
|
||
|
|
||
|
void Init( const WeaponDefinitionClass *weapon_def );
|
||
|
|
||
|
bool Save( ChunkSaveClass & csave );
|
||
|
bool Load( ChunkLoadClass & cload );
|
||
|
|
||
|
void Set_Model( RenderObjClass *model );
|
||
|
void Set_Owner( ArmedGameObj *owner );
|
||
|
ArmedGameObj *Get_Owner( void ) { return (ArmedGameObj *)Owner.Get_Ptr(); }
|
||
|
|
||
|
enum {
|
||
|
MUZZLE_PRIMARY_0,
|
||
|
MUZZLE_PRIMARY_1,
|
||
|
MUZZLE_SECONDARY_0,
|
||
|
MUZZLE_SECONDARY_1,
|
||
|
};
|
||
|
|
||
|
void Select( void );
|
||
|
void Deselect( void );
|
||
|
|
||
|
void Update( void );
|
||
|
|
||
|
bool Is_Muzzle_Clear( void );
|
||
|
void Compute_Bullet_Start_Point(const Matrix3D & muzzle,Vector3 * set_start_point);
|
||
|
|
||
|
void Next_C4_Detonation_Mode( void ); // Take the weapon to the next state (for C4)
|
||
|
|
||
|
const WeaponDefinitionClass *Get_Definition( void ) { return Definition; }
|
||
|
const char * Get_Name( void ) { return Definition->Get_Name(); }
|
||
|
int Get_ID( void ) { return Definition->Get_ID(); }
|
||
|
const char * Get_HUD_Icon_Texture_Name( void ) { return Definition->HUDIconTextureName; }
|
||
|
const char * Get_Model_Name( void ) { return Definition->Model; }
|
||
|
const char * Get_Back_Model_Name( void ){ return Definition->BackModel; }
|
||
|
const char * Get_Anim_Name( void ) { return (NextAnimState != WEAPON_ANIM_NOT_FIRING) ? Definition->FireAnim : Definition->IdleAnim; }
|
||
|
int Get_Style( void ) { return Definition->Style; }
|
||
|
float Get_Key_Number( void ) { return Definition->KeyNumber; }
|
||
|
bool Get_Can_Snipe( void ) { return Definition->CanSnipe; }
|
||
|
float Get_Rating( void ) { return Definition->Rating; }
|
||
|
float Get_Effective_Range( void ){ return PrimaryAmmoDefinition->EffectiveRange; }
|
||
|
float Get_Primary_Fire_Rate( void ){ return PrimaryAmmoDefinition->RateOfFire; }
|
||
|
|
||
|
const char * Get_First_Person_Model_Name( void ) const { return Definition->FirstPersonModel; }
|
||
|
const Vector3& Get_First_Person_Model_Offset( void ) const { return Definition->FirstPersonOffset; }
|
||
|
|
||
|
float Get_Recoil_Time( void ) { return Definition->RecoilTime; }
|
||
|
float Get_Recoil_Scale( void ) { return Definition->RecoilScale; }
|
||
|
|
||
|
// =========== Ammo
|
||
|
void Set_Total_Rounds( int num );
|
||
|
int Get_Total_Rounds( void );
|
||
|
void Add_Rounds( int num );
|
||
|
void Set_Clip_Rounds( int rounds ) { ClipRounds = rounds; }
|
||
|
int Get_Clip_Rounds( void ) { return ClipRounds; }
|
||
|
void Set_Inventory_Rounds( int rounds ) { InventoryRounds = rounds; }
|
||
|
int Get_Inventory_Rounds( void ) { return InventoryRounds; }
|
||
|
void Do_Reload( void );
|
||
|
void Decrement_Rounds( int rounds = 1 );
|
||
|
bool Is_Ammo_Maxed( void );
|
||
|
bool Is_Loaded( void ) { return (ClipRounds != 0); }
|
||
|
bool Is_Reload_OK( void );
|
||
|
bool Is_Reload_Needed( void ) { return !Is_Loaded() && Is_Reload_OK(); }
|
||
|
float Get_Range( void );
|
||
|
|
||
|
bool Is_Model_Update_Needed( void ) { return (UpdateModel == WEAPON_MODEL_UPDATE_IS_NEEDED); }
|
||
|
void Reset_Model_Update( void ) { UpdateModel = WEAPON_MODEL_UPDATE_NOT_NEEDED; CurrentAnimState = (WeaponAnimState)-1; }
|
||
|
bool Is_Anim_Update_Needed( void ) { return ( NextAnimState != CurrentAnimState ); }
|
||
|
void Reset_Anim_Update( void ) { CurrentAnimState = NextAnimState; }
|
||
|
WeaponAnimState Get_Anim_State( void ) { return CurrentAnimState; }
|
||
|
|
||
|
int Get_Total_Rounds_Fired( void ) { return TotalRoundsFired; }
|
||
|
|
||
|
void Display_Targeting( void );
|
||
|
|
||
|
void Set_Target( const Vector3 &target) { Target = target; }
|
||
|
const Vector3 &Get_Target( void ) { return Target; }
|
||
|
|
||
|
void Set_Target_Object( PhysicalGameObj * obj );
|
||
|
PhysicalGameObj * Get_Target_Object( PhysicalGameObj * obj );
|
||
|
|
||
|
/*
|
||
|
** Weapons States
|
||
|
*/
|
||
|
typedef enum {
|
||
|
STATE_IDLE,
|
||
|
STATE_READY,
|
||
|
STATE_CHARGE,
|
||
|
STATE_FIRE_PRIMARY,
|
||
|
STATE_FIRE_SECONDARY,
|
||
|
STATE_RELOAD,
|
||
|
STATE_START_SWITCH,
|
||
|
STATE_END_SWITCH,
|
||
|
// NUM_STATES,
|
||
|
} WeaponStateType;
|
||
|
|
||
|
WeaponStateType Get_State( void ) { return State; }
|
||
|
bool Is_Firing( void ) { return DidFire; }
|
||
|
bool Is_Reloading( void ) { return (State == STATE_RELOAD); }
|
||
|
bool Is_Switching( void ) { return (State == STATE_START_SWITCH) || (State == STATE_END_SWITCH); }
|
||
|
void Force_Reload( void );
|
||
|
|
||
|
// Trigger State
|
||
|
void Set_Safety( bool saftey ) { SafetySet = saftey; }
|
||
|
bool Is_Safety_Set( void ) { return SafetySet; }
|
||
|
void Set_Primary_Triggered( bool triggered );
|
||
|
void Set_Secondary_Triggered( bool triggered );
|
||
|
bool Is_Triggered( void ) { return IsSecondaryTriggered || IsPrimaryTriggered; }
|
||
|
|
||
|
void Init_Muzzle_Flash( RenderObjClass * robj ) { MuzzleFlash.Init( robj ); }
|
||
|
void Update_Muzzle_Flash( bool flashA0, bool flashA1 ) { MuzzleFlash.Update( flashA0, flashA1 ); }
|
||
|
|
||
|
bool Does_Weapon_Exist( void ) { return WeaponExists; }
|
||
|
void Set_Weapon_Exists( bool exists ) { WeaponExists = exists; }
|
||
|
|
||
|
PhysicalGameObj * Cast_Weapon( const Vector3 & target );
|
||
|
bool Cast_Weapon_Down_Muzzle( Vector3 & hit_pos );
|
||
|
|
||
|
void Make_Shell_Eject( const Matrix3D & tm );
|
||
|
|
||
|
//
|
||
|
// Sound support
|
||
|
//
|
||
|
void Stop_Firing_Sound( void );
|
||
|
|
||
|
private:
|
||
|
|
||
|
void Fire_C4( const AmmoDefinitionClass *ammo_def );
|
||
|
bool Fire_Beacon( const AmmoDefinitionClass *ammo_def );
|
||
|
void Fire_Bullet( const AmmoDefinitionClass *ammo_def, bool primary );
|
||
|
|
||
|
// Weapon Info
|
||
|
const WeaponDefinitionClass *Definition;
|
||
|
GameObjReference Owner; // who gets credit for this weapon's kills?
|
||
|
RenderObjClass *Model;
|
||
|
int C4DetonationMode;
|
||
|
|
||
|
// Ammo Info
|
||
|
const AmmoDefinitionClass *PrimaryAmmoDefinition;
|
||
|
const AmmoDefinitionClass *SecondaryAmmoDefinition;
|
||
|
safe_int ClipRounds;
|
||
|
safe_int InventoryRounds; // -1 for unlimited
|
||
|
safe_float BurstDelayTimer;
|
||
|
safe_int BurstCount;
|
||
|
float BulletBumpTime;
|
||
|
bool WeaponExists; // allows us to have ammo with no weapon
|
||
|
|
||
|
// Weapon States
|
||
|
WeaponStateType State; // The state of the weapon
|
||
|
float StateTimer; // in seconds. Used for switching, reloading, and idle
|
||
|
bool DidFire;
|
||
|
|
||
|
bool LastFrameIsPrimaryTriggered; // is the Trigger pulled
|
||
|
bool LastFrameIsSecondaryTriggered; // is the Trigger pulled
|
||
|
bool IsPrimaryTriggered; // is the Trigger pulled
|
||
|
bool IsSecondaryTriggered; // is the Trigger pulled
|
||
|
int TotalRoundsFired;
|
||
|
bool SafetySet;
|
||
|
bool LockTriggers;
|
||
|
float EmptySoundTimer;
|
||
|
|
||
|
// Weapon Looks
|
||
|
WeaponAnimState NextAnimState; // Which anim should we be on
|
||
|
WeaponAnimState CurrentAnimState; // Which anim are we on
|
||
|
WeaponModelUpdateState UpdateModel; // Does the weapon Model need to be updated
|
||
|
|
||
|
Vector3 Target;
|
||
|
GameObjReference TargetObject;
|
||
|
|
||
|
// Continuous Muzzle Effects (flames)
|
||
|
SimpleVecClass<ParticleEmitterClass *> ContinuousEmitters;
|
||
|
AudibleSoundClass * ContinuousSound;
|
||
|
|
||
|
AudibleSoundClass * FiringSound;
|
||
|
int FiringSoundDefID;
|
||
|
|
||
|
// Functions
|
||
|
const Matrix3D & Get_Muzzle( int index = MUZZLE_PRIMARY_0 );
|
||
|
void Do_Fire( bool primary );
|
||
|
|
||
|
// Weapon State
|
||
|
void Set_State( WeaponStateType new_state );
|
||
|
void Update_State( float dtime );
|
||
|
void Do_Firing_Effects( void );
|
||
|
void Do_Continuous_Effects( bool enable );
|
||
|
|
||
|
// Muzzle Flash
|
||
|
MuzzleFlashClass MuzzleFlash;
|
||
|
|
||
|
void Ignore_Owner( void );
|
||
|
void Unignore_Owner( void );
|
||
|
|
||
|
};
|
||
|
|
||
|
#endif // WEAPONS_H
|