NS/main/source/mod/AvHStomp.cpp
pierow 68b7278072 weapon animation fixes
- Fixed animation issues with pistol binary trigger and moved the binary triggering to client code
- Fixed reload animation not always playing
- Fixed numerous incorrect or broken alien weapon animations on every class
- Added transitional animation out of gorge building
2024-04-17 22:41:10 -04:00

368 lines
8.7 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: AvHStomp.cpp $
// $Date: $
//
//-------------------------------------------------------------------------------
// $Log: $
//===============================================================================
#include "AvHAlienWeapons.h"
#include "AvHPlayer.h"
#include "AvHConstants.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 "AvHAlienWeaponConstants.h"
#include "AvHPlayerUpgrade.h"
#ifdef AVH_SERVER
#include "AvHGamerules.h"
#include "AvHServerUtil.h"
#endif
#include "AvHParticleConstants.h"
#include "AvHHulls.h"
#include "AvHSharedUtil.h"
LINK_ENTITY_TO_CLASS(kwStomp, AvHStomp);
#ifdef AVH_SERVER
LINK_ENTITY_TO_CLASS(kwStompProjectile, AvHStompProjectile);
AvHStompProjectile::AvHStompProjectile()
{
}
void AvHStompProjectile::Precache(void)
{
CBaseEntity::Precache();
}
void AvHStompProjectile::Spawn(void)
{
this->Precache();
CBaseEntity::Spawn();
this->pev->movetype = MOVETYPE_NOCLIP;
this->pev->classname = MAKE_STRING(kwsStompProjectile);
SET_MODEL(ENT(this->pev), kStompProjectileModel);
this->pev->solid = SOLID_TRIGGER;
if(!GetGameRules()->GetDrawInvisibleEntities())
{
this->pev->effects = EF_NODRAW;
}
else
{
this->pev->frame = 0;
this->pev->scale = 1.0;
this->pev->rendermode = kRenderTransAdd;
this->pev->renderamt = kStompModelRenderAmount;
}
const int kBoxWidth = 50;
UTIL_SetSize(this->pev, Vector(-kBoxWidth, -kBoxWidth, -kBoxWidth), Vector(kBoxWidth, kBoxWidth, kBoxWidth));
// UTIL_SetSize(this->pev, Vector( 0, 0, 0), Vector(0, 0, 0));
SetTouch(&AvHStompProjectile::StompTouch);
SetThink(&CBaseEntity::SUB_Remove);
this->pev->nextthink = gpGlobals->time + kStompProjectileLifetime;
this->mStunTime = 0.0f;
}
void AvHStompProjectile::SetStunTime(float inStunTime)
{
this->mStunTime = inStunTime;
}
void AvHStompProjectile::StompTouch(CBaseEntity* inOther)
{
if(!AvHSUGetIsExternalClassName(STRING(inOther->pev->classname)))
{
// Stop when it hits the world
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(inOther);
if(thePlayer)
{
if(thePlayer->GetCanBeAffectedByEnemies() && (thePlayer->GetTeam() != this->pev->team))
{
// Stun them if they're not stunned already, to prevent perpetual stunning
if(!thePlayer->GetIsStunned() && !GetHasUpgrade(thePlayer->pev->iuser4, MASK_TOPDOWN))
{
// Don't stun jetpackers
if(!GetHasUpgrade(thePlayer->pev->iuser4, MASK_UPGRADE_7)) //&& !(thePlayer->pev->flags & FL_ONGROUND)))
{
// Do a traceline to make sure the world isn't blocking it (StompTouch doesn't seem to be called for CWorld collisions)
TraceResult theTraceResult;
UTIL_TraceLine(this->mSpawnLocation, inOther->pev->origin, ignore_monsters, ignore_glass, NULL, &theTraceResult);
if(theTraceResult.flFraction == 1.0f)
{
if(thePlayer->SetIsStunned(true, this->mStunTime))
{
// Play effect at player's feet
Vector theMinSize, theMaxSize;
thePlayer->GetSize(theMinSize, theMaxSize);
vec3_t theOrigin = thePlayer->pev->origin;
theOrigin.z += theMinSize.z;
AvHSUPlayParticleEvent(kpsStompEffect, inOther->edict(), theOrigin);
}
}
else
{
CBaseEntity* theEntityHit = CBaseEntity::Instance(ENT(theTraceResult.pHit));
}
}
}
}
}
}
}
#endif
BOOL AvHStomp::CanHolster(void)
{
return true;
}
void AvHStomp::Init()
{
this->mRange = BALANCE_VAR(kStompRadius);
}
// Only allow it to be triggered when on the ground
BOOL AvHStomp::IsUseable(void)
{
BOOL theSuccess = AvHAlienWeapon::IsUseable();
if(theSuccess)
{
if(!this->m_pPlayer || !FBitSet(this->m_pPlayer->pev->flags, FL_ONGROUND))
{
theSuccess = false;
}
}
return theSuccess;
}
int AvHStomp::GetBarrelLength() const
{
return kStompBarrelLength;
}
float AvHStomp::GetRateOfFire() const
{
return BALANCE_VAR(kStompROF);
}
int AvHStomp::GetDeployAnimation() const
{
// Look at most recently used weapon and see if we can transition from it
int theDeployAnimation = 7;
AvHWeaponID thePreviousID = this->GetPreviousWeaponID();
switch(thePreviousID)
{
case AVH_WEAPON_CLAWS:
theDeployAnimation = 7;
break;
case AVH_ABILITY_CHARGE:
theDeployAnimation = 11;
break;
case AVH_WEAPON_DEVOUR:
theDeployAnimation = 20;
break;
}
return theDeployAnimation;
}
float AvHStomp::GetDeployTime() const
{
return .6f;
}
void AvHStomp::GetEventAngles(Vector& outAngles) const
{
//this->GetStompVelocity(outAngles);
AvHAlienWeapon::GetEventAngles(outAngles);
}
void AvHStomp::GetEventOrigin(Vector& outOrigin) const
{
this->GetStompOrigin(outOrigin);
}
bool AvHStomp::GetFiresUnderwater() const
{
return false;
}
int AvHStomp::GetIdleAnimation() const
{
return 3;
}
bool AvHStomp::GetIsDroppable() const
{
return false;
}
int AvHStomp::GetShootAnimation() const
{
return 24;
}
void AvHStomp::FireProjectiles(void)
{
#ifdef AVH_SERVER
// Search for relevant enemy players in range (only on ground?)
// CBaseEntity* theEntity = NULL;
// while((theEntity = UTIL_FindEntityInSphere(theEntity, this->pev->origin, this->mRange)) != NULL)
// {
// AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(theEntity);
// if(thePlayer && (thePlayer != this->m_pPlayer))
// {
// if(thePlayer->GetIsRelevant() && (thePlayer->GetTeam() != this->m_pPlayer->pev->team))
// {
// // Stun them if they're not stunned already, to prevent perpetual stunning
// if(!thePlayer->GetIsStunned() && !GetHasUpgrade(thePlayer->pev->iuser4, MASK_TOPDOWN))
// {
// // Don't stun flying jetpackers
// if(!(GetHasUpgrade(thePlayer->pev->iuser4, MASK_UPGRADE_7) && !(thePlayer->pev->flags & FL_ONGROUND)))
// {
// thePlayer->SetIsStunned(true, BALANCE_VAR(kStompTime));
// }
// }
// }
// }
// }
// Create stomp projectile that flies forward, stunning enemies it touches
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(this->m_pPlayer);
ASSERT(thePlayer);
AvHStompProjectile* theStomp = GetClassPtr((AvHStompProjectile*)NULL );
theStomp->Spawn();
this->GetStompOrigin(theStomp->pev->origin);
UTIL_SetOrigin(theStomp->pev, theStomp->pev->origin);
// Save starting point
VectorCopy(theStomp->pev->origin, theStomp->mSpawnLocation);
this->GetStompVelocity(theStomp->pev->velocity);
// Set owner
theStomp->pev->owner = ENT(this->m_pPlayer->pev);
// Set Stomp's team :)
theStomp->pev->team = this->m_pPlayer->pev->team;
// Set stun time
float theStunTime = BALANCE_VAR(kStompTime);
if(AvHSHUGetIsWeaponFocusable(AvHWeaponID(this->m_iId)))
{
theStunTime *= AvHPlayerUpgrade::GetFocusDamageUpgrade(this->m_pPlayer->pev->iuser4);
}
theStomp->SetStunTime(theStunTime);
// Play view shake here
float theShakeAmplitude = 100;
float theShakeFrequency = 100;
float theShakeDuration = 1.0f;
float theShakeRadius = 700;
UTIL_ScreenShake(this->pev->origin, theShakeAmplitude, theShakeFrequency, theShakeDuration, this->mRange);
#endif
}
void AvHStomp::GetStompOrigin(Vector& outOrigin) const
{
VectorCopy(this->m_pPlayer->pev->origin, outOrigin);
#ifdef AVH_SERVER
float theZOffset = this->m_pPlayer->pev->mins.z;
outOrigin.z += theZOffset;
#endif
}
void AvHStomp::GetStompVelocity(Vector& outVelocity) const
{
// Send shockwave in direction player is looking, but always make it go kStompProjectilVelocity
UTIL_MakeVectors(this->m_pPlayer->pev->v_angle);
// Zero out z velocity so it stays on the ground
Vector theAim = gpGlobals->v_forward;
theAim.z = 0;
VectorNormalize(theAim);
VectorScale(theAim, kStompProjectileVelocity, outVelocity);
}
char* AvHStomp::GetViewModel() const
{
return kLevel5ViewModel;
}
void AvHStomp::Precache()
{
AvHAlienWeapon::Precache();
PRECACHE_UNMODIFIED_SOUND(kStompFireSound);
PRECACHE_UNMODIFIED_MODEL(kStompProjectileModel);
this->mEvent = PRECACHE_EVENT(1, kStompShootEventName);
}
void AvHStomp::Spawn()
{
AvHAlienWeapon::Spawn();
Precache();
this->m_iId = AVH_WEAPON_STOMP;
// Set our class name
this->pev->classname = MAKE_STRING(kwsStomp);
SET_MODEL(ENT(this->pev), kNullModel);
FallInit();// get ready to fall down.
}
bool AvHStomp::UsesAmmo(void) const
{
return false;
}