mirror of
https://github.com/ENSL/NS.git
synced 2024-11-25 05:51:11 +00:00
485 lines
12 KiB
C++
485 lines
12 KiB
C++
//======== (C) Copyright 2002 Charles G. Cleveland All rights reserved. =========
|
|
//
|
|
// The copyright to the contents herein is the property of Charles G. Cleveland.
|
|
// The contents may be used and/or copied only with the written permission of
|
|
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
|
|
// the agreement/contract under which the contents have been supplied.
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $Workfile: AvHGrenadeGun.cpp $
|
|
// $Date: 2002/11/22 21:28:16 $
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
// $Log: AvHGrenadeGun.cpp,v $
|
|
// Revision 1.17 2002/11/22 21:28:16 Flayra
|
|
// - mp_consistency changes
|
|
//
|
|
// Revision 1.16 2002/10/16 20:53:09 Flayra
|
|
// - Removed weapon upgrade sounds
|
|
//
|
|
// Revision 1.15 2002/10/03 18:46:26 Flayra
|
|
// - Added heavy view model
|
|
//
|
|
// Revision 1.14 2002/07/24 19:09:16 Flayra
|
|
// - Linux issues
|
|
//
|
|
// Revision 1.13 2002/07/24 18:45:41 Flayra
|
|
// - Linux and scripting changes
|
|
//
|
|
// Revision 1.12 2002/06/25 17:50:59 Flayra
|
|
// - Reworking for correct player animations and new enable/disable state, new view model artwork, alien weapon refactoring
|
|
//
|
|
// Revision 1.11 2002/06/03 16:37:56 Flayra
|
|
// - Added different deploy times (this should be refactored a bit more), refactored grenades
|
|
//
|
|
// Revision 1.10 2002/05/28 17:44:58 Flayra
|
|
// - Tweak weapon deploy volume, as Valve's sounds weren't normalized
|
|
//
|
|
// Revision 1.9 2002/05/23 02:33:42 Flayra
|
|
// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
|
|
//
|
|
//===============================================================================
|
|
#include "AvHPlayer.h"
|
|
|
|
#ifdef AVH_CLIENT
|
|
#include "cl_dll/eventscripts.h"
|
|
#include "cl_dll/in_defs.h"
|
|
#include "cl_dll/wrect.h"
|
|
#include "cl_dll/cl_dll.h"
|
|
#endif
|
|
|
|
#include "../common/hldm.h"
|
|
#include "../common/event_api.h"
|
|
#include "../common/event_args.h"
|
|
#include "../common/vector_util.h"
|
|
#include "AvHMarineWeapons.h"
|
|
#include "AvHMarineWeaponConstants.h"
|
|
#include "AvHServerUtil.h"
|
|
|
|
LINK_ENTITY_TO_CLASS(kwGrenadeGun, AvHGrenadeGun);
|
|
void V_PunchAxis( int axis, float punch );
|
|
|
|
const int kSpecialReloadNone = 0;
|
|
const int kSpecialReloadGotoReload = 1;
|
|
const int kSpecialReloadAddGren = 2;
|
|
const int kSpecialReloadCloseGG = 3;
|
|
const float kEndReloadAnimationTime = 2.43f;
|
|
|
|
void AvHGrenadeGun::Init()
|
|
{
|
|
this->mRange = kGGRange;
|
|
this->mDamage = BALANCE_VAR(kGrenadeDamage);
|
|
this->m_fInSpecialReload = kSpecialReloadNone;
|
|
}
|
|
|
|
int AvHGrenadeGun::GetBarrelLength() const
|
|
{
|
|
return kGGBarrelLength;
|
|
}
|
|
|
|
float AvHGrenadeGun::GetRateOfFire() const
|
|
{
|
|
return BALANCE_VAR(kGGROF);
|
|
}
|
|
|
|
int AvHGrenadeGun::GetDeployAnimation() const
|
|
{
|
|
int theAnimation = -1;
|
|
|
|
int theShotsInClip = this->GetShotsInClip();
|
|
|
|
switch(theShotsInClip)
|
|
{
|
|
case 4:
|
|
case 0:
|
|
theAnimation = 13;
|
|
break;
|
|
case 3:
|
|
theAnimation = 14;
|
|
break;
|
|
case 2:
|
|
theAnimation = 15;
|
|
break;
|
|
case 1:
|
|
theAnimation = 16;
|
|
break;
|
|
}
|
|
|
|
return theAnimation;
|
|
}
|
|
|
|
char* AvHGrenadeGun::GetDeploySound() const
|
|
{
|
|
return kGGDeploySound;
|
|
}
|
|
|
|
float AvHGrenadeGun::GetReloadTime(void) const
|
|
{
|
|
int theShotsToLoad = BALANCE_VAR(kGGMaxClip) - this->GetShotsInClip();
|
|
|
|
float theBaseReloadTime = BALANCE_VAR(kGrenadeLauncherBaseReloadTime);
|
|
float theGrenadeReloadTime = BALANCE_VAR(kGrenadeLauncherGrenadeReloadTime);
|
|
float theEndReloadTime = BALANCE_VAR(kGrenadeLauncherEndReloadTime);
|
|
|
|
return theBaseReloadTime + theShotsToLoad*theGrenadeReloadTime + theEndReloadTime;
|
|
}
|
|
|
|
bool AvHGrenadeGun::GetHasMuzzleFlash() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void AvHGrenadeGun::GetEventOrigin(Vector& outOrigin) const
|
|
{
|
|
Vector theGunPosition = this->m_pPlayer->GetGunPosition();
|
|
VectorCopy(theGunPosition, outOrigin);
|
|
}
|
|
|
|
void AvHGrenadeGun::GetEventAngles(Vector& outAngles) const
|
|
{
|
|
float theGrenadeForce = BALANCE_VAR(kGrenadeForce);
|
|
|
|
Vector theAiming = this->m_pPlayer->GetAutoaimVector(AUTOAIM_5DEGREES);
|
|
|
|
Vector theVelocity = theAiming*theGrenadeForce + this->m_pPlayer->pev->velocity;
|
|
|
|
VectorCopy(theVelocity, outAngles);
|
|
}
|
|
|
|
char* AvHGrenadeGun::GetHeavyViewModel() const
|
|
{
|
|
return kGGHVVModel;
|
|
}
|
|
|
|
int AvHGrenadeGun::GetIdleAnimation() const
|
|
{
|
|
int theAnimation = -1;
|
|
|
|
int theShotsInClip = this->GetShotsInClip();
|
|
|
|
switch(theShotsInClip)
|
|
{
|
|
case 0:
|
|
case 4:
|
|
theAnimation = 0;
|
|
break;
|
|
|
|
case 1:
|
|
theAnimation = 3;
|
|
break;
|
|
|
|
case 2:
|
|
theAnimation = 2;
|
|
break;
|
|
|
|
case 3:
|
|
theAnimation = 1;
|
|
break;
|
|
}
|
|
|
|
return theAnimation;
|
|
}
|
|
|
|
char* AvHGrenadeGun::GetPlayerModel() const
|
|
{
|
|
return kGGPModel;
|
|
}
|
|
|
|
int AvHGrenadeGun::GetReloadAnimation() const
|
|
{
|
|
int theAnimation = -1;
|
|
|
|
int ShotsEmpty = this->GetClipSize() - this->GetShotsInClip();
|
|
|
|
int Shotsleft = this->m_pPlayer->m_rgAmmo[this->m_iPrimaryAmmoType];
|
|
|
|
int ShotsToReload = min(ShotsEmpty, Shotsleft);
|
|
|
|
switch(ShotsToReload)
|
|
{
|
|
case 4:
|
|
theAnimation = 7;
|
|
break;
|
|
|
|
case 3:
|
|
theAnimation = 6;
|
|
break;
|
|
|
|
case 2:
|
|
theAnimation = 5;
|
|
break;
|
|
|
|
case 1:
|
|
theAnimation = 4;
|
|
break;
|
|
}
|
|
|
|
return theAnimation;
|
|
}
|
|
|
|
int AvHGrenadeGun::GetEmptyShootAnimation() const
|
|
{
|
|
return 12;
|
|
}
|
|
|
|
int AvHGrenadeGun::GetShootAnimation() const
|
|
{
|
|
int theAnimation = -1;
|
|
|
|
int theShotsInClip = this->GetShotsInClip();
|
|
|
|
switch(theShotsInClip)
|
|
{
|
|
case 4:
|
|
theAnimation = 8;
|
|
break;
|
|
case 3:
|
|
theAnimation = 9;
|
|
break;
|
|
case 2:
|
|
theAnimation = 10;
|
|
break;
|
|
case 1:
|
|
theAnimation = 11;
|
|
break;
|
|
case 0:
|
|
theAnimation = 12;
|
|
break;
|
|
}
|
|
|
|
return theAnimation;
|
|
}
|
|
|
|
int AvHGrenadeGun::GetEndAnimation() const
|
|
{
|
|
int theAnimation = -1;
|
|
|
|
int theShotsInClip = this->GetShotsInClip();
|
|
|
|
switch (theShotsInClip)
|
|
{
|
|
case 1:
|
|
theAnimation = 17;
|
|
break;
|
|
|
|
case 2:
|
|
case 3:
|
|
theAnimation = 18;
|
|
break;
|
|
}
|
|
|
|
return theAnimation;
|
|
}
|
|
|
|
char* AvHGrenadeGun::GetViewModel() const
|
|
{
|
|
return kGGVModel;
|
|
}
|
|
|
|
char* AvHGrenadeGun::GetWorldModel() const
|
|
{
|
|
return kGGWModel;
|
|
}
|
|
|
|
void AvHGrenadeGun::FireProjectiles(void)
|
|
{
|
|
#ifdef AVH_SERVER
|
|
|
|
Vector theOrigin;
|
|
this->GetEventOrigin(theOrigin);
|
|
|
|
// Grenade gun uses velocity here instead of angles, assumes angles are the player angles (for both the server grenade and the client temp entity)
|
|
Vector theVelocity;
|
|
this->GetEventAngles(theVelocity);
|
|
|
|
// How to handle this? Only generate entity on server, but we should do SOMETHING on the client, no?
|
|
CGrenade* theGrenade = AvHSUShootServerGrenade(this->m_pPlayer->pev, theOrigin, theVelocity, BALANCE_VAR(kGrenDetonateTime), false);
|
|
ASSERT(theGrenade);
|
|
theGrenade->pev->dmg = this->mDamage;
|
|
|
|
#endif
|
|
}
|
|
|
|
void AvHGrenadeGun::Precache()
|
|
{
|
|
AvHMarineWeapon::Precache();
|
|
|
|
PRECACHE_UNMODIFIED_MODEL(kGGEjectModel);
|
|
PRECACHE_UNMODIFIED_MODEL(kGGAmmoModel);
|
|
|
|
PRECACHE_UNMODIFIED_SOUND(kGrenadeBounceSound1);
|
|
PRECACHE_UNMODIFIED_SOUND(kGrenadeBounceSound2);
|
|
PRECACHE_UNMODIFIED_SOUND(kGrenadeBounceSound3);
|
|
|
|
PRECACHE_UNMODIFIED_SOUND(kGGFireSound1);
|
|
|
|
PRECACHE_UNMODIFIED_SOUND(kGGReloadSound);
|
|
|
|
this->mEvent = PRECACHE_EVENT(1, kGGEventName);
|
|
}
|
|
|
|
void AvHGrenadeGun::DeductCostForShot(void)
|
|
{
|
|
AvHMarineWeapon::DeductCostForShot();
|
|
|
|
// Stop reload if we were in the middle of one
|
|
if (this->m_fInSpecialReload != kSpecialReloadNone)
|
|
{
|
|
this->m_fInSpecialReload = kSpecialReloadNone;
|
|
}
|
|
}
|
|
|
|
int AvHGrenadeGun::DefaultReload(int iClipSize, int iAnim, float fDelay)
|
|
{
|
|
// Needed to prevet super fast default reload
|
|
return FALSE;
|
|
}
|
|
|
|
void AvHGrenadeGun::Holster(int skiplocal)
|
|
{
|
|
AvHMarineWeapon::Holster(skiplocal);
|
|
|
|
// Cancel any reload in progress.
|
|
this->m_fInSpecialReload = kSpecialReloadNone;
|
|
}
|
|
|
|
void AvHGrenadeGun::Reload(void)
|
|
{
|
|
int theClipSize = this->GetClipSize();
|
|
|
|
if ((this->m_pPlayer->m_rgAmmo[this->m_iPrimaryAmmoType] > 0) && (m_iClip < theClipSize))
|
|
{
|
|
if (this->m_fInSpecialReload == kSpecialReloadCloseGG)
|
|
{
|
|
this->SendWeaponAnim(this->GetEndAnimation());
|
|
//Timings here made to match animations as well as reload length of the previous reload version. Numbers are seconds*2 because they get decremented twice in NS.
|
|
this->m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + kEndReloadAnimationTime;
|
|
this->m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + kEndReloadAnimationTime;
|
|
this->m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + kEndReloadAnimationTime;
|
|
//this->m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + kEndReloadAnimationTime;
|
|
|
|
this->m_pPlayer->SetAnimation(PLAYER_RELOAD_END);
|
|
this->m_fInSpecialReload = kSpecialReloadNone;
|
|
}
|
|
else if (this->m_fInSpecialReload == kSpecialReloadAddGren)
|
|
{
|
|
// Add to grenade count at specified time in the middle of reload to sync with animation and sound.
|
|
if (m_flTimeWeaponIdle <= UTIL_WeaponTimeBase())
|
|
{
|
|
// Add them to the clip
|
|
this->m_iClip += 1;
|
|
this->m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 1;
|
|
|
|
if (this->m_iClip < theClipSize && (this->m_pPlayer->m_rgAmmo[this->m_iPrimaryAmmoType] != 0))
|
|
{
|
|
this->m_fInSpecialReload = kSpecialReloadGotoReload;
|
|
}
|
|
else
|
|
{
|
|
this->m_fInSpecialReload = kSpecialReloadNone;
|
|
|
|
this->m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + kEndReloadAnimationTime;
|
|
this->m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + kEndReloadAnimationTime;
|
|
this->m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + kEndReloadAnimationTime;
|
|
|
|
this->m_pPlayer->SetAnimation(PLAYER_RELOAD_END);
|
|
}
|
|
}
|
|
}
|
|
// don't reload until recoil is done
|
|
else if (this->m_flNextPrimaryAttack <= UTIL_WeaponTimeBase())
|
|
{
|
|
if (this->m_fInSpecialReload == kSpecialReloadNone)
|
|
{
|
|
// Start reload
|
|
this->m_fInSpecialReload = kSpecialReloadGotoReload;
|
|
|
|
this->SendWeaponAnim(this->GetReloadAnimation());
|
|
|
|
const float theGotoReloadAnimationTime = 1.1f;
|
|
|
|
this->m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + theGotoReloadAnimationTime;
|
|
this->m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + theGotoReloadAnimationTime;
|
|
this->m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + theGotoReloadAnimationTime;
|
|
|
|
//this->m_pPlayer->SetAnimation(PLAYER_RELOAD);
|
|
this->m_pPlayer->SetAnimation(PLAYER_RELOAD_START);
|
|
}
|
|
else if (this->m_fInSpecialReload == kSpecialReloadGotoReload)
|
|
{
|
|
if (m_flTimeWeaponIdle <= UTIL_WeaponTimeBase())
|
|
{
|
|
this->m_fInSpecialReload = kSpecialReloadAddGren;
|
|
|
|
const float theGrenReloadTime = 2.4f;
|
|
|
|
this->m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + theGrenReloadTime;
|
|
this->m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + theGrenReloadTime;
|
|
this->m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + theGrenReloadTime;
|
|
|
|
this->m_pPlayer->SetAnimation(PLAYER_RELOAD_INSERT);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->m_fInSpecialReload = kSpecialReloadNone;
|
|
}
|
|
}
|
|
|
|
void AvHGrenadeGun::WeaponIdle(void)
|
|
{
|
|
// : 0000484 - ensures that all idle weapons can fire the empty sound
|
|
ResetEmptySound();
|
|
if (this->m_flTimeWeaponIdle < UTIL_WeaponTimeBase())
|
|
{
|
|
if ((this->m_iClip == 0) && (this->m_fInSpecialReload == kSpecialReloadNone) && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
|
|
{
|
|
this->Reload();
|
|
}
|
|
else if (this->m_fInSpecialReload != kSpecialReloadNone)
|
|
{
|
|
if ((m_iClip != this->GetClipSize()) && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
|
|
{
|
|
this->Reload();
|
|
}
|
|
else
|
|
{
|
|
// reload debounce has timed out
|
|
this->m_fInSpecialReload = kSpecialReloadNone;
|
|
//ALERT(at_console, "specreset time:%g idle:%g primary:%g specrel:%d\n", gpGlobals->time, this->m_flTimeWeaponIdle, this->m_flNextPrimaryAttack, m_fInSpecialReload);
|
|
this->SendWeaponAnim(this->GetEndAnimation());
|
|
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + kEndReloadAnimationTime;
|
|
this->m_pPlayer->SetAnimation(PLAYER_RELOAD_END);
|
|
}
|
|
}
|
|
//else
|
|
//{
|
|
// Hack to prevent idle animation from playing mid-reload. Not sure how to fix this right, but all this special reloading is happening server-side, client doesn't know about it
|
|
//if (m_iClip == this->GetClipSize())
|
|
//{
|
|
// AvHMarineWeapon::WeaponIdle();
|
|
//}
|
|
//}
|
|
}
|
|
}
|
|
|
|
void AvHGrenadeGun::Spawn()
|
|
{
|
|
AvHMarineWeapon::Spawn();
|
|
|
|
Precache();
|
|
|
|
this->m_iId = AVH_WEAPON_GRENADE_GUN;
|
|
m_iDefaultAmmo = BALANCE_VAR(kGGMaxClip);
|
|
|
|
// Set our class name
|
|
this->pev->classname = MAKE_STRING(kwsGrenadeGun);
|
|
|
|
SET_MODEL(ENT(this->pev), kGGWModel);
|
|
|
|
FallInit();// get ready to fall down.
|
|
}
|