doom3-bfg/base/script/weapon_handgrenade.script
2022-08-27 13:19:00 +02:00

267 lines
5.8 KiB
Text

/***********************************************************************
weapon_handgrenade.script
***********************************************************************/
#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
object weapon_handgrenade : weapon_base {
float spread;
float fuse_start;
string skin_nade;
string skin_nade_invis;
string skin_nonade;
string skin_nonade_invis;
entity projectile;
boolean show_grenade;
void init();
void Lower();
void Raise();
void Idle();
void Fire();
void EnterCinematic();
void ExitCinematic();
void WeaponStolen();
void OwnerDied();
void ExplodeInHand();
// called by the game
void UpdateSkin();
// used by anim frame commands
void GrenadeNade();
void GrenadeNoNade();
};
void weapon_handgrenade::init() {
spread = getFloatKey( "spread" );
skin_nade = getKey( "skin_nade" );
skin_nade_invis = getKey( "skin_nade_invis" );
skin_nonade = getKey( "skin_nonade" );
skin_nonade_invis = getKey( "skin_nonade_invis" );
GrenadeNade();
weaponState( "Raise", 0 );
}
void weapon_handgrenade::Raise() {
if ( !ammoAvailable() ) {
weaponHolstered();
nextWeapon();
return;
}
weaponRising();
playAnim( ANIMCHANNEL_ALL, "raise" );
waitUntil( animDone( ANIMCHANNEL_ALL, HANDGRENADE_RAISE_TO_IDLE ) );
weaponState( "Idle", HANDGRENADE_RAISE_TO_IDLE );
}
void weapon_handgrenade::Lower() {
weaponLowering();
playAnim( ANIMCHANNEL_ALL, "putaway" );
waitUntil( animDone( ANIMCHANNEL_ALL, 0 ) );
weaponHolstered();
waitUntil( WEAPON_RAISEWEAPON );
weaponState( "Raise", 0 );
}
void weapon_handgrenade::Idle() {
weaponReady();
playCycle( ANIMCHANNEL_ALL, "idle" );
while( 1 ) {
if ( WEAPON_LOWERWEAPON ) {
weaponState( "Lower", HANDGRENADE_IDLE_TO_LOWER );
}
if ( WEAPON_ATTACK ) {
weaponState( "Fire", HANDGRENADE_IDLE_TO_FIRE );
}
waitFrame();
}
}
void weapon_handgrenade::Fire() {
float fuse_end;
float current_time;
float time_held;
float power;
boolean exploded;
projectile = createProjectile();
if ( projectile ) {
projectile.startSound( "snd_throw", SND_CHANNEL_BODY, true );
}
playAnim( ANIMCHANNEL_ALL, "throw_start" );
current_time = sys.getTime();
fuse_start = current_time;
fuse_end = current_time + HANDGRENADE_FUSE;
while( current_time < fuse_end ) {
if ( ( current_time > fuse_start + HANDGRENADE_MINRELEASETIME ) && !WEAPON_ATTACK ) {
break;
}
waitFrame();
current_time = sys.getTime();
}
time_held = current_time - fuse_start;
power = time_held + HANDGRENADE_MINPOWER;
if ( power > HANDGRENADE_MAXPOWER ) {
power = HANDGRENADE_MAXPOWER;
}
if ( time_held < HANDGRENADE_QUICKTHROWTIME ) {
playAnim( ANIMCHANNEL_ALL, "throw_quick" );
sys.wait( HANDGRENADE_QUICKTHROWLAUNCH );
exploded = false;
} else if ( time_held < HANDGRENADE_FUSE ) {
playAnim( ANIMCHANNEL_ALL, "throw" );
sys.wait( HANDGRENADE_NORMALTHROWLAUNCH );
exploded = false;
} else {
// no anim. grenade just blows up
ExplodeInHand();
exploded = true;
}
if ( !exploded ) {
GrenadeNoNade();
current_time = sys.getTime();
if ( projectile ) {
projectile.show();
projectile.unbind();
launchProjectiles( HANDGRENADE_NUMPROJECTILES, spread, current_time - fuse_start, power, 1.0 );
projectile = $null_entity;
}
waitUntil( animDone( ANIMCHANNEL_ALL, HANDGRENADE_FIRE_TO_IDLE ) );
}
if ( !ammoAvailable() ) {
weaponHolstered();
nextWeapon();
} else {
GrenadeNade();
weaponState( "Idle", HANDGRENADE_FIRE_TO_IDLE );
}
}
void weapon_handgrenade::EnterCinematic() {
if ( projectile ) {
projectile.remove();
projectile = $null_entity;
}
weaponState( "Idle", 0 );
}
void weapon_handgrenade::ExitCinematic() {
if ( !ammoAvailable() ) {
weaponHolstered();
nextWeapon();
} else {
GrenadeNade();
weaponState( "Idle", 0 );
}
}
void weapon_handgrenade::GrenadeNade() {
show_grenade = true;
UpdateSkin();
}
void weapon_handgrenade::GrenadeNoNade() {
show_grenade = false;
UpdateSkin();
}
void weapon_handgrenade::UpdateSkin() {
if ( !show_grenade ) {
if ( isInvisible() ) {
setSkin( skin_nonade_invis );
} else {
setSkin( skin_nonade );
}
} else {
if ( isInvisible() ) {
setSkin( skin_nade_invis );
} else {
setSkin( skin_nade );
}
}
}
void weapon_handgrenade::WeaponStolen() {
if ( projectile ) {
projectile.remove();
projectile = $null_entity;
}
}
void weapon_handgrenade::OwnerDied() {
float time_held;
if ( projectile ) {
time_held = sys.getTime() - fuse_start;
projectile.show();
projectile.unbind();
// allow grenade to drop
launchProjectiles( HANDGRENADE_NUMPROJECTILES, spread, time_held, 0, 1.0 );
projectile = $null_entity;
}
}
void weapon_handgrenade::ExplodeInHand() {
string entname;
entity explosion;
vector forward;
vector angles;
entity owner;
if ( projectile ) {
projectile.remove();
projectile = $null_entity;
}
owner = getOwner();
GrenadeNoNade();
startSound( "snd_explode", SND_CHANNEL_ANY, false );
if ( !sys.isClient() ) {
useAmmo( HANDGRENADE_NUMPROJECTILES );
angles = owner.getViewAngles();
forward = sys.angToForward( angles );
entname = getKey( "def_explode_inhand" );
explosion = sys.spawn( entname );
explosion.setOrigin( getOrigin() + forward * 16 );
explosion.setShaderParm( SHADERPARM_TIMEOFFSET, -sys.getTime() );
delayRemove( explosion, 2 );
// this should kill us
sys.radiusDamage( getOrigin(), self, owner, $null_entity, getKey( "def_damage_inhand" ), 1.0 );
}
}