mirror of
https://github.com/unknownworlds/NS.git
synced 2024-11-22 20:51:36 +00:00
60007652a3
git-svn-id: https://unknownworlds.svn.cloudforge.com/ns1@21 67975925-1194-0748-b3d5-c16f83f1a3a1
363 lines
9.1 KiB
C++
363 lines
9.1 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 "mod/AvHAlienWeapons.h"
|
|
#include "mod/AvHPlayer.h"
|
|
#include "mod/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 "mod/AvHAlienWeaponConstants.h"
|
|
#include "mod/AvHPlayerUpgrade.h"
|
|
|
|
#ifdef AVH_SERVER
|
|
#include "mod/AvHGamerules.h"
|
|
#include "mod/AvHServerUtil.h"
|
|
#endif
|
|
|
|
#include "mod/AvHParticleConstants.h"
|
|
#include "mod/AvHHulls.h"
|
|
#include "mod/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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|