weapons update

- add pistol binary trigger aka pistol script and attack queueing
- add gorge heal spray +movement
- lerk flap +movement update
- fix for onos attack release bugs with +movement
This commit is contained in:
pierow 2024-02-04 04:05:28 -05:00
parent a024343cb0
commit ceb814f4f6
11 changed files with 183 additions and 61 deletions

View file

@ -387,9 +387,9 @@ void WeaponsResource::UserCmd_MovementOn()
wID = AVH_ABILITY_LEAP; wID = AVH_ABILITY_LEAP;
break; break;
//TODO: Make healspray work with attack2 //TODO: Make healspray work with attack2
//case AVH_USER3_ALIEN_PLAYER2: case AVH_USER3_ALIEN_PLAYER2:
// wID = AVH_WEAPON_HEALINGSPRAY; wID = AVH_WEAPON_HEALINGSPRAY;
// break; break;
case AVH_USER3_ALIEN_PLAYER3: case AVH_USER3_ALIEN_PLAYER3:
lerkFlap = true; lerkFlap = true;
break; break;
@ -404,7 +404,24 @@ void WeaponsResource::UserCmd_MovementOn()
return; return;
} }
if (wID > -1) if (wID == AVH_WEAPON_HEALINGSPRAY)
{
WEAPON* healWeapon = this->GetWeapon(AVH_WEAPON_HEALINGSPRAY);
WEAPON* currentWeapon = this->GetWeapon(gHUD.GetCurrentWeaponID());
if (healWeapon != NULL && currentWeapon != NULL)
{
//if (healWeapon != currentWeapon)
//{
healSprayLastWeapon = currentWeapon;
//}
ServerCmd(healWeapon->szName);
g_weaponselect = healWeapon->iId;
IN_Attack2Down();
}
}
else if (wID > -1)
{ {
// Fetch the needed movement weapon // Fetch the needed movement weapon
WEAPON *p = this->GetWeapon(wID); WEAPON *p = this->GetWeapon(wID);
@ -427,6 +444,22 @@ void WeaponsResource::UserCmd_MovementOff()
// Ensure that we're not activating any weapons when selected // Ensure that we're not activating any weapons when selected
IN_Attack2Up(); IN_Attack2Up();
IN_ReloadUp(); IN_ReloadUp();
if (gViewPort)
{
if (gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER2)
{
WEAPON* healWeapon = this->GetWeapon(AVH_WEAPON_HEALINGSPRAY);
if (healWeapon != NULL && healSprayLastWeapon != NULL)
{
//if (healsprayLastWeapon != healWeapon)
//{
ServerCmd(healSprayLastWeapon->szName);
g_weaponselect = healSprayLastWeapon->iId;
//}
}
}
}
} }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -73,6 +73,7 @@ private:
WEAPON rgWeapons[MAX_WEAPONS]; // current weapon state WEAPON rgWeapons[MAX_WEAPONS]; // current weapon state
WEAPON* rgSlots[MAX_WEAPON_SLOTS][MAX_WEAPON_POSITIONS]; // current weapon slot map WEAPON* rgSlots[MAX_WEAPON_SLOTS][MAX_WEAPON_POSITIONS]; // current weapon slot map
WEAPON* lastWeapon; // client-side lastinv WEAPON* lastWeapon; // client-side lastinv
WEAPON* healSprayLastWeapon;
int riAmmo[MAX_AMMO_TYPES]; // current ammo counts int riAmmo[MAX_AMMO_TYPES]; // current ammo counts
int iOldWeaponBits; int iOldWeaponBits;

View file

@ -525,63 +525,80 @@ void CBasePlayerWeapon::ItemPostFrame( void )
} }
} }
if ( (m_pPlayer->pev->button & IN_ATTACK) && !(m_pPlayer->pev->button & IN_ATTACK2)) if ((m_pPlayer->pev->button & IN_ATTACK || this->m_bAttackQueued) && (!(m_pPlayer->pev->button & IN_ATTACK2) || gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER3))
{ {
if ((m_fInSpecialReload == 1 || m_fInSpecialReload == 2) && m_iClip != 0) if (GetCanUseWeapon())
{
m_fInSpecialReload = 3;
Reload();
}
else if (GetCanUseWeapon() && (m_flNextPrimaryAttack <= 0.0))
{ {
if ( (m_iClip == 0 && ii.pszAmmo1) || if ((m_fInSpecialReload == 1 || m_fInSpecialReload == 2) && m_iClip != 0)
(ii.iMaxClip == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] ) )
{
m_fFireOnEmpty = TRUE;
}
if ((gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER1)
&& (gHUD.GetCurrentWeaponID() == AVH_ABILITY_LEAP)
&& (this->m_flLastAnimationPlayed + (float)BALANCE_VAR(kLeapROF) <= gpGlobals->time))
{ {
// : 0001151 predict energy too m_fInSpecialReload = 3;
AvHAlienWeapon* theWeapon = dynamic_cast<AvHAlienWeapon *>(g_pWpns[AVH_ABILITY_LEAP]); Reload();
if ( theWeapon && theWeapon->IsUseable() ) { }
float theVolumeScalar = 1.0f; else if (m_flNextPrimaryAttack <= 0.0)
cl_entity_t *player = gEngfuncs.GetLocalPlayer(); {
int theSilenceLevel = AvHGetAlienUpgradeLevel(player->curstate.iuser4, MASK_UPGRADE_6); if ( (m_iClip == 0 && ii.pszAmmo1) ||
switch(theSilenceLevel) (ii.iMaxClip == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] ) )
{ {
case 1: m_fFireOnEmpty = TRUE;
theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel1Volume); }
break;
case 2:
theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel2Volume); if ((gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER1)
break; && (gHUD.GetCurrentWeaponID() == AVH_ABILITY_LEAP)
case 3: && (this->m_flLastAnimationPlayed + (float)BALANCE_VAR(kLeapROF) <= gpGlobals->time))
theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel3Volume); {
break; // : 0001151 predict energy too
} AvHAlienWeapon* theWeapon = dynamic_cast<AvHAlienWeapon *>(g_pWpns[AVH_ABILITY_LEAP]);
HUD_PlaySound( kLeapSound, theVolumeScalar); if ( theWeapon && theWeapon->IsUseable() ) {
AvHMUDeductAlienEnergy(m_pPlayer->pev->fuser3, theWeapon->GetEnergyForAttack() ); float theVolumeScalar = 1.0f;
gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 2); cl_entity_t *player = gEngfuncs.GetLocalPlayer();
this->m_flLastAnimationPlayed = gpGlobals->time; int theSilenceLevel = AvHGetAlienUpgradeLevel(player->curstate.iuser4, MASK_UPGRADE_6);
} switch(theSilenceLevel)
{
case 1:
theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel1Volume);
break;
case 2:
theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel2Volume);
break;
case 3:
theVolumeScalar = (float)BALANCE_VAR(kSilenceLevel3Volume);
break;
}
HUD_PlaySound( kLeapSound, theVolumeScalar);
AvHMUDeductAlienEnergy(m_pPlayer->pev->fuser3, theWeapon->GetEnergyForAttack() );
gEngfuncs.pEventAPI->EV_WeaponAnimation(3, 2);
this->m_flLastAnimationPlayed = gpGlobals->time;
}
}
//#ifdef AVH_CLIENT
//if((m_iClip == 0) && ?
//#endif
PrimaryAttack();
//return;
}
else
{
QueueAttack();
} }
//#ifdef AVH_CLIENT
//if((m_iClip == 0) && ?
//#endif
PrimaryAttack();
//return;
} }
} }
// +movement: Rewritten to allow us to use +attack2 for movement abilities // +movement: Rewritten to allow us to use +attack2 for movement abilities
else if ((m_pPlayer->pev->button & IN_ATTACK2) && (gHUD.GetIsAlien())) else if ((m_pPlayer->pev->button & IN_ATTACK2) && (gHUD.GetIsAlien()))
{ {
AvHUser3 theUser3 = gHUD.GetHUDUser3();
//m_flNextSecondaryAttack //m_flNextSecondaryAttack
// Find out what kind of special movement we are using, and execute the animation for it // Find out what kind of special movement we are using, and execute the animation for it
if (this->PrevAttack2Status == false)
if (theUser3 == AVH_USER3_ALIEN_PLAYER2)
{
if (GetCanUseWeapon() && m_flNextPrimaryAttack <= 0.0)
{
SecondaryAttack();
}
}
else if (this->PrevAttack2Status == false)
{ {
bool enabled=false; bool enabled=false;
// : 0001151 predict energy too // : 0001151 predict energy too
@ -589,7 +606,7 @@ void CBasePlayerWeapon::ItemPostFrame( void )
if ( theWeapon ) if ( theWeapon )
enabled=theWeapon->IsUseable(); enabled=theWeapon->IsUseable();
switch (gHUD.GetHUDUser3()) switch (theUser3)
{ {
case AVH_USER3_ALIEN_PLAYER1: case AVH_USER3_ALIEN_PLAYER1:
@ -644,8 +661,7 @@ void CBasePlayerWeapon::ItemPostFrame( void )
} }
} }
if ((gHUD.GetHUDUser3() == AVH_USER3_ALIEN_PLAYER1) if ((theUser3 == AVH_USER3_ALIEN_PLAYER1) && (this->m_flLastAnimationPlayed + BALANCE_VAR(kLeapROF) < gpGlobals->time))
&& (this->m_flLastAnimationPlayed + BALANCE_VAR(kLeapROF) < gpGlobals->time))
this->PrevAttack2Status = false; this->PrevAttack2Status = false;
else else
this->PrevAttack2Status = true; this->PrevAttack2Status = true;

View file

@ -61,6 +61,7 @@ extern "C"
#include "mod/AvHScrollHandler.h" #include "mod/AvHScrollHandler.h"
#include "mod/AvHCommanderModeHandler.h" #include "mod/AvHCommanderModeHandler.h"
#include "util/Mat3.h" #include "util/Mat3.h"
#include "mod/AvHBasePlayerWeaponConstants.h"
#include "engine/APIProxy.h" #include "engine/APIProxy.h"
#include "Exports.h" #include "Exports.h"
@ -145,6 +146,7 @@ cvar_t *senslock;
cvar_t *cl_chatbeep; cvar_t *cl_chatbeep;
cvar_t *cl_mutemenu; cvar_t *cl_mutemenu;
cvar_t *cl_weaponcfgs; cvar_t *cl_weaponcfgs;
cvar_t *cl_pistoltrigger;
/* /*
=============================================================================== ===============================================================================
@ -808,7 +810,7 @@ void IN_AttackUp(void)
in_cancel = 0; in_cancel = 0;
// Attack2up only for onos so it can end +attack onos charges. Attack2up for all causes blink and leap to cancel if you release attack while blinking or leaping. // Attack2up only for onos so it can end +attack onos charges. Attack2up for all causes blink and leap to cancel if you release attack while blinking or leaping.
if (g_iUser3 == AVH_USER3_ALIEN_PLAYER5) if (gHUD.GetCurrentWeaponID() == AVH_ABILITY_CHARGE)
{ {
IN_Attack2Up(); IN_Attack2Up();
} }
@ -824,6 +826,32 @@ void IN_AttackUpForced(void)
KeyUpForced( &in_attack ); KeyUpForced( &in_attack );
} }
void IN_AttackHandlerDown(void)
{
if (gHUD.GetCurrentWeaponID() == AVH_WEAPON_PISTOL && cl_pistoltrigger && cl_pistoltrigger->value)
{
IN_AttackDown();
IN_AttackUp();
}
else
{
IN_AttackDown();
}
}
void IN_AttackHandlerUp(void)
{
if (gHUD.GetCurrentWeaponID() == AVH_WEAPON_PISTOL && cl_pistoltrigger && cl_pistoltrigger->value)
{
IN_AttackDown();
IN_AttackUp();
}
else
{
IN_AttackUp();
}
}
// Special handling // Special handling
void IN_Cancel(void) void IN_Cancel(void)
{ {
@ -1602,8 +1630,8 @@ void InitInput (void)
gEngfuncs.pfnAddCommand ("-moveright", IN_MoverightUp); gEngfuncs.pfnAddCommand ("-moveright", IN_MoverightUp);
gEngfuncs.pfnAddCommand ("+speed", IN_SpeedDown); gEngfuncs.pfnAddCommand ("+speed", IN_SpeedDown);
gEngfuncs.pfnAddCommand ("-speed", IN_SpeedUp); gEngfuncs.pfnAddCommand ("-speed", IN_SpeedUp);
gEngfuncs.pfnAddCommand ("+attack", IN_AttackDown); gEngfuncs.pfnAddCommand ("+attack", IN_AttackHandlerDown);
gEngfuncs.pfnAddCommand ("-attack", IN_AttackUp); gEngfuncs.pfnAddCommand ("-attack", IN_AttackHandlerUp);
//gEngfuncs.pfnAddCommand ("+movement", IN_Attack2Down); //gEngfuncs.pfnAddCommand ("+movement", IN_Attack2Down);
//gEngfuncs.pfnAddCommand ("-movement", IN_Attack2Up); //gEngfuncs.pfnAddCommand ("-movement", IN_Attack2Up);
gEngfuncs.pfnAddCommand ("+use", IN_UseDown); gEngfuncs.pfnAddCommand ("+use", IN_UseDown);
@ -1687,6 +1715,7 @@ void InitInput (void)
cl_chatbeep = gEngfuncs.pfnRegisterVariable ("cl_chatbeep", "1", FCVAR_ARCHIVE); cl_chatbeep = gEngfuncs.pfnRegisterVariable ("cl_chatbeep", "1", FCVAR_ARCHIVE);
cl_mutemenu = gEngfuncs.pfnRegisterVariable ("cl_mutemenu", "3", FCVAR_ARCHIVE); cl_mutemenu = gEngfuncs.pfnRegisterVariable ("cl_mutemenu", "3", FCVAR_ARCHIVE);
cl_weaponcfgs = gEngfuncs.pfnRegisterVariable ("cl_weaponcfgs", "1", FCVAR_ARCHIVE); cl_weaponcfgs = gEngfuncs.pfnRegisterVariable ("cl_weaponcfgs", "1", FCVAR_ARCHIVE);
cl_pistoltrigger = gEngfuncs.pfnRegisterVariable ("cl_pistoltrigger", "1", FCVAR_ARCHIVE);
// Initialize third person camera controls. // Initialize third person camera controls.
CAM_Init(); CAM_Init();

View file

@ -949,7 +949,8 @@ BOOL CanAttack( float attack_time, float curtime, BOOL isPredicted )
void CBasePlayerWeapon::ItemPostFrame( void ) void CBasePlayerWeapon::ItemPostFrame( void )
{ {
bool theAttackPressed = (m_pPlayer->pev->button & IN_ATTACK) && !(m_pPlayer->pev->button & IN_ATTACK2); // Block attacks during +movement except for lerk.
bool theAttackPressed = (m_pPlayer->pev->button & IN_ATTACK) && (!(m_pPlayer->pev->button & IN_ATTACK2) || m_pPlayer->pev->iuser3 == AVH_USER3_ALIEN_PLAYER3);
bool theWeaponPrimes = (this->GetWeaponPrimeTime() > 0.0f); bool theWeaponPrimes = (this->GetWeaponPrimeTime() > 0.0f);
bool theWeaponIsPriming = this->GetIsWeaponPriming(); bool theWeaponIsPriming = this->GetIsWeaponPriming();
@ -988,7 +989,7 @@ void CBasePlayerWeapon::ItemPostFrame( void )
else else
*/ */
if ( theAttackPressed && m_pPlayer->GetCanUseWeapon()) if ( (theAttackPressed || m_bAttackQueued) && m_pPlayer->GetCanUseWeapon())
{ {
if ((m_fInSpecialReload == 1 || m_fInSpecialReload == 2) && m_iClip != 0) if ((m_fInSpecialReload == 1 || m_fInSpecialReload == 2) && m_iClip != 0)
{ {
@ -1005,6 +1006,20 @@ void CBasePlayerWeapon::ItemPostFrame( void )
m_pPlayer->TabulateAmmo(); m_pPlayer->TabulateAmmo();
PrimaryAttack(); PrimaryAttack();
} }
else
{
QueueAttack();
}
}
else if (m_pPlayer->pev->button & IN_ATTACK2)
{
if (m_pPlayer->pev->iuser3 == AVH_USER3_ALIEN_PLAYER2 && m_pPlayer->GetCanUseWeapon())
{
if (CanAttack(m_flNextPrimaryAttack, gpGlobals->time, UseDecrement()))
{
SecondaryAttack();
}
}
} }
else if ( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload ) else if ( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload )
{ {

View file

@ -354,6 +354,7 @@ public:
virtual void ItemPostFrame( void ); // called each frame by the player PostThink virtual void ItemPostFrame( void ); // called each frame by the player PostThink
// called by CBasePlayerWeapons ItemPostFrame() // called by CBasePlayerWeapons ItemPostFrame()
virtual void PrimaryAttack( void ) { return; } // do "+ATTACK" virtual void PrimaryAttack( void ) { return; } // do "+ATTACK"
virtual void QueueAttack(void) { return; } // queue an attack
virtual void SecondaryAttack( void ) { return; } // do "+ATTACK2" virtual void SecondaryAttack( void ) { return; } // do "+ATTACK2"
virtual void Reload( void ) { return; } // do "+RELOAD" virtual void Reload( void ) { return; } // do "+RELOAD"
virtual void WeaponIdle( void ) { return; } // called when no buttons pressed virtual void WeaponIdle( void ) { return; } // called when no buttons pressed
@ -384,7 +385,8 @@ public:
int m_iDefaultAmmo;// how much ammo you get when you pick up this weapon as placed by a level designer. int m_iDefaultAmmo;// how much ammo you get when you pick up this weapon as placed by a level designer.
bool PrevAttack2Status; // HACK: For +movement weapon animations bool PrevAttack2Status; // HACK: For +movement weapon animations
float m_flLastAnimationPlayed; float m_flLastAnimationPlayed;
bool m_bAttackQueued;
}; };

View file

@ -425,6 +425,8 @@ public:
virtual int iItemSlot(void); virtual int iItemSlot(void);
virtual void Precache(void); virtual void Precache(void);
virtual void SecondaryAttack();
virtual void Spawn(); virtual void Spawn();

View file

@ -675,6 +675,8 @@ void AvHBasePlayerWeapon::Holster( int skiplocal)
#ifdef AVH_SERVER #ifdef AVH_SERVER
this->mInOverwatch = false; this->mInOverwatch = false;
#endif #endif
this->m_bAttackQueued = false;
} }
float AvHBasePlayerWeapon::GetTimePassedThisTick() const float AvHBasePlayerWeapon::GetTimePassedThisTick() const

View file

@ -137,6 +137,11 @@ void AvHHealingSpray::Precache()
this->mEvent = PRECACHE_EVENT(1, kHealingSprayEventName); this->mEvent = PRECACHE_EVENT(1, kHealingSprayEventName);
} }
// Use secondary attack to call primary attack so client predicted ghost spit attacks don't occur on the first frame of +movement use, as the weapon also switches that frame.
void AvHHealingSpray::SecondaryAttack(void)
{
AvHHealingSpray::PrimaryAttack();
}
void AvHHealingSpray::Spawn() void AvHHealingSpray::Spawn()
{ {

View file

@ -228,10 +228,14 @@ public:
virtual int GetReloadAnimation() const; virtual int GetReloadAnimation() const;
virtual int GetShootAnimation() const; virtual int GetShootAnimation() const;
virtual int iItemSlot(void);
virtual int iItemSlot(void);
virtual void Precache(void); virtual void Precache(void);
virtual void PrimaryAttack();
virtual void QueueAttack(void);
virtual void Spawn(); virtual void Spawn();

View file

@ -174,6 +174,19 @@ void AvHPistol::Precache()
this->mEvent = PRECACHE_EVENT(1, kHGEventName); this->mEvent = PRECACHE_EVENT(1, kHGEventName);
} }
void AvHPistol::PrimaryAttack()
{
this->m_bAttackQueued = false;
AvHMarineWeapon::PrimaryAttack();
}
void AvHPistol::QueueAttack(void)
{
if (!this->mAttackButtonDownLastFrame)
{
this->m_bAttackQueued = true;
}
}
void AvHPistol::Spawn() void AvHPistol::Spawn()
{ {