//======== (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(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(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(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; }