Files
DoomRTX/neo/doom3/game/weapons/Weapon_handgrenade.cpp
2026-05-23 20:50:12 -07:00

382 lines
7.1 KiB
C++

// Weapon_handgrenade.cpp
//
#pragma hdrstop
#include "precompiled.h"
#include "../Game_local.h"
#define HANDGRENADE_MINRELEASETIME 0.05
#define HANDGRENADE_FUSE 3
#define HANDGRENADE_QUICKTHROWTIME .2
#define HANDGRENADE_MINPOWER 1.5
#define HANDGRENADE_MAXPOWER 6
#define HANDGRENADE_QUICKTHROWLAUNCH 0.55
#define HANDGRENADE_NORMALTHROWLAUNCH 0.3
#define HANDGRENADE_NUMPROJECTILES 1
// blend times
#define HANDGRENADE_IDLE_TO_LOWER 4
#define HANDGRENADE_IDLE_TO_FIRE 4
#define HANDGRENADE_RAISE_TO_IDLE 4
#define HANDGRENADE_FIRE_TO_IDLE 4
/*
===============
rvmWeaponHandgrenade::Init
===============
*/
void rvmWeaponHandgrenade::Init( idWeapon* weapon )
{
rvmWeaponObject::Init( weapon );
projectile = NULL;
spread = owner->GetFloatKey( "spread" );
skin_nade = owner->GetKey( "skin_nade" );
skin_nade_invis = owner->GetKey( "skin_nade_invis" );
skin_nonade = owner->GetKey( "skin_nonade" );
skin_nonade_invis = owner->GetKey( "skin_nonade_invis" );
GrenadeNade();
}
/*
===============
rvmWeaponHandgrenade::GrenadeNade
===============
*/
void rvmWeaponHandgrenade::GrenadeNade( void )
{
show_grenade = true;
UpdateSkin();
}
/*
===============
rvmWeaponHandgrenade::GrenadeNoNade
===============
*/
void rvmWeaponHandgrenade::GrenadeNoNade( void )
{
show_grenade = false;
UpdateSkin();
}
/*
===============
rvmWeaponHandgrenade::GrenadeNoNade
===============
*/
void rvmWeaponHandgrenade::UpdateSkin()
{
if( !show_grenade )
{
if( owner->Event_IsInvisible() )
{
owner->Event_SetSkin( skin_nonade_invis );
}
else
{
owner->Event_SetSkin( skin_nonade );
}
}
else
{
if( owner->Event_IsInvisible() )
{
owner->Event_SetSkin( skin_nade_invis );
}
else
{
owner->Event_SetSkin( skin_nade );
}
}
}
/*
===============
rvmWeaponHandgrenade::Raise
===============
*/
stateResult_t rvmWeaponHandgrenade::Raise( stateParms_t* parms )
{
enum RisingState
{
RISING_NOTSET = 0,
RISING_WAIT
};
switch( parms->stage )
{
case RISING_NOTSET:
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "raise", false );
parms->stage = RISING_WAIT;
return SRESULT_WAIT;
case RISING_WAIT:
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, HANDGRENADE_RAISE_TO_IDLE ) )
{
return SRESULT_DONE;
}
return SRESULT_WAIT;
}
return SRESULT_ERROR;
}
/*
===============
rvmWeaponHandgrenade::Lower
===============
*/
stateResult_t rvmWeaponHandgrenade::Lower( stateParms_t* parms )
{
enum LoweringState
{
LOWERING_NOTSET = 0,
LOWERING_WAIT
};
switch( parms->stage )
{
case LOWERING_NOTSET:
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "putaway", false );
parms->stage = LOWERING_WAIT;
return SRESULT_WAIT;
case LOWERING_WAIT:
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, 0 ) )
{
SetState( "Holstered" );
return SRESULT_DONE;
}
return SRESULT_WAIT;
}
return SRESULT_ERROR;
}
/*
===============
rvmWeaponHandgrenade::Idle
===============
*/
stateResult_t rvmWeaponHandgrenade::Idle( stateParms_t* parms )
{
enum IdleState
{
IDLE_NOTSET = 0,
IDLE_WAIT
};
switch( parms->stage )
{
case IDLE_NOTSET:
owner->Event_WeaponReady();
owner->Event_PlayCycle( ANIMCHANNEL_ALL, "idle" );
parms->stage = IDLE_WAIT;
return SRESULT_WAIT;
case IDLE_WAIT:
// Do nothing.
return SRESULT_DONE;
}
return SRESULT_ERROR;
}
/*
===============
rvmWeaponHandgrenade::OwnerDied
===============
*/
void rvmWeaponHandgrenade::OwnerDied( void )
{
float time_held;
if( projectile )
{
time_held = gameLocal.SysScriptTime() - fuse_start;
projectile->Show();
projectile->Unbind();
// allow grenade to drop
owner->Event_LaunchProjectiles( HANDGRENADE_NUMPROJECTILES, spread, time_held, 0, 1.0 );
projectile = NULL;
}
}
/*
===============
rvmWeaponHandgrenade::Fire
===============
*/
stateResult_t rvmWeaponHandgrenade::Fire( stateParms_t* parms )
{
if( parms->stage == 0 )
{
projectile = ( idProjectile* )owner->CreateProjectile();
if( projectile )
{
projectile->Event_StartSound( "snd_throw", SND_CHANNEL_BODY, true );
}
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "throw_start", false );
current_time = gameLocal.SysScriptTime();
fuse_start = current_time;
fuse_end = current_time + HANDGRENADE_FUSE;
parms->stage = 1;
return SRESULT_WAIT;
}
if( parms->stage == 1 )
{
if( current_time < fuse_end )
{
if( ( current_time > fuse_start + HANDGRENADE_MINRELEASETIME ) )
{
parms->stage = 2;
return SRESULT_WAIT;
}
current_time = gameLocal.SysScriptTime();
return SRESULT_WAIT;
}
parms->stage = 2;
return SRESULT_WAIT;
}
if( parms->stage == 2 )
{
time_held = current_time - fuse_start;
power = time_held + HANDGRENADE_MINPOWER;
if( power > HANDGRENADE_MAXPOWER )
{
power = HANDGRENADE_MAXPOWER;
}
if( time_held < HANDGRENADE_QUICKTHROWTIME )
{
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "throw_quick", false );
parms->Wait( HANDGRENADE_QUICKTHROWLAUNCH );
exploded = false;
}
else if( time_held < HANDGRENADE_FUSE )
{
owner->Event_PlayAnim( ANIMCHANNEL_ALL, "throw", false );
parms->Wait( HANDGRENADE_NORMALTHROWLAUNCH );
exploded = false;
}
else
{
// no anim. grenade just blows up
ExplodeInHand();
exploded = true;
}
parms->stage = 3;
return SRESULT_WAIT;
}
if( parms->stage == 3 )
{
if( !exploded )
{
GrenadeNoNade();
current_time = gameLocal.SysScriptTime();
if( projectile )
{
projectile->Show();
projectile->Unbind();
owner->Event_LaunchProjectiles( HANDGRENADE_NUMPROJECTILES, spread, current_time - fuse_start, power, 1.0 );
projectile = NULL;
}
parms->stage = 4;
return SRESULT_WAIT;
}
parms->stage = 5;
return SRESULT_WAIT;
}
if( parms->stage == 4 )
{
if( owner->Event_AnimDone( ANIMCHANNEL_ALL, HANDGRENADE_FIRE_TO_IDLE ) )
{
parms->stage = 5;
return SRESULT_WAIT;
}
return SRESULT_WAIT;
}
if( !owner->AmmoAvailable() )
{
stateThread.Clear();
stateThread.SetState( "Holstered" );
owner->GetOwner()->NextWeapon();
}
else
{
GrenadeNade();
}
return SRESULT_DONE;
}
/*
===============
rvmWeaponHandgrenade::Reload
===============
*/
stateResult_t rvmWeaponHandgrenade::Reload( stateParms_t* parms )
{
return SRESULT_DONE;
}
/*
===============
rvmWeaponHandgrenade::ExplodeInHand
===============
*/
void rvmWeaponHandgrenade::ExplodeInHand()
{
idStr entname;
idEntity* explosion;
idVec3 forward;
idAngles angles;
idPlayer* owner;
if( projectile )
{
projectile->Event_Remove();
projectile = NULL;
}
owner = this->owner->GetOwner();
GrenadeNoNade();
this->owner->Event_StartSound( "snd_explode", SND_CHANNEL_ANY, false );
//if( !common->IsClient() )
{
this->owner->Event_UseAmmo( HANDGRENADE_NUMPROJECTILES );
angles = owner->viewAngles;
forward = angles.ToForward();
entname = this->owner->GetKey( "def_explode_inhand" );
explosion = gameLocal.Spawn( entname );
explosion->SetOrigin( this->owner->GetOrigin() + forward * 16 );
explosion->SetShaderParm( SHADERPARM_TIMEOFFSET, -gameLocal.SysScriptTime() );
gameLocal.DelayRemoveEntity( explosion, 2 );
// this should kill us
gameLocal.RadiusDamage( this->owner->GetOrigin(), this->owner, owner, NULL, NULL, this->owner->GetKey( "def_damage_inhand" ), 1.0f );
}
}