mirror of
https://github.com/ENSL/NS.git
synced 2024-11-27 06:42:54 +00:00
501fa5ab18
* The client build preview now respects func_nobuild, fixing situations where the client thought it could build somewhere, but nothing would appear when clicking.
2464 lines
56 KiB
C++
2464 lines
56 KiB
C++
//======== (C) Copyright 2001 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: AvHEntities.cpp$
|
|
// $Date: 2002/11/22 21:26:25 $
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
// $Log: AvHEntities.cpp,v $
|
|
// Revision 1.44 2002/11/22 21:26:25 Flayra
|
|
// - mp_consistency changes
|
|
// - Fixes to allow NULL owner
|
|
//
|
|
// Revision 1.43 2002/11/12 02:23:22 Flayra
|
|
// - Removed ancient egg
|
|
//
|
|
// Revision 1.42 2002/11/03 04:47:56 Flayra
|
|
// - Moved constants into .dll out of .cfg
|
|
//
|
|
// Revision 1.41 2002/10/20 21:10:14 Flayra
|
|
// - Optimizations
|
|
//
|
|
// Revision 1.40 2002/10/18 22:19:01 Flayra
|
|
// - Fixed bug where resources were still getting destroyed
|
|
//
|
|
// Revision 1.39 2002/10/16 00:53:16 Flayra
|
|
// - Play marine tower harvesting sound louder so it can be heard
|
|
//
|
|
// Revision 1.38 2002/10/03 18:42:31 Flayra
|
|
// - func_resources now are destroyed if a resource tower is destroyed
|
|
//
|
|
// Revision 1.37 2002/09/23 22:12:31 Flayra
|
|
// - Resource towers give 3 points to team in general
|
|
//
|
|
// Revision 1.36 2002/08/16 02:34:23 Flayra
|
|
// - Webs no longer affect friendlies in tourny mode
|
|
//
|
|
// Revision 1.35 2002/07/24 18:45:41 Flayra
|
|
// - Linux and scripting changes
|
|
//
|
|
// Revision 1.34 2002/07/23 17:01:33 Flayra
|
|
// - Updated resource model, removed old junk
|
|
//
|
|
// Revision 1.33 2002/07/10 14:40:04 Flayra
|
|
// - Fixed bug where .mp3s weren't being processed client-side
|
|
//
|
|
// Revision 1.32 2002/07/08 16:55:35 Flayra
|
|
// - Added max ensnare, can't remember why I'm tagging team starts, changed resources functions to floats (for proper handicapping)
|
|
//
|
|
// Revision 1.31 2002/07/01 21:26:41 Flayra
|
|
// - Toned down resource tower sounds (moved to CHAN_BODY to cut down on multiples playing)
|
|
//
|
|
// Revision 1.30 2002/06/25 17:54:20 Flayra
|
|
// - New info_location entity, make resource tower sounds very quiet
|
|
//
|
|
// Revision 1.29 2002/06/10 19:52:31 Flayra
|
|
// - Marked non-visible entities as nodraw, fixes visible entities problems!
|
|
//
|
|
// Revision 1.28 2002/05/28 17:37:01 Flayra
|
|
// - Track number of web strands to enforce limit, reworking of webs in general, removed duplicate code for AvHResourceTower
|
|
//
|
|
// Revision 1.27 2002/05/23 02:33:41 Flayra
|
|
// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
|
|
//
|
|
//===============================================================================
|
|
#include "AvHEntities.h"
|
|
#include "../dlls/player.h"
|
|
#include "../dlls/gamerules.h"
|
|
#include "../dlls/explode.h"
|
|
#include "../dlls/soundent.h"
|
|
#include "../dlls/weapons.h"
|
|
#include "../dlls/cpushable.h"
|
|
#include "AvHPlayerUpgrade.h"
|
|
#include "AvHServerUtil.h"
|
|
#include "AvHGamerules.h"
|
|
#include "AvHMarineEquipmentConstants.h"
|
|
#include "AvHAlienEquipmentConstants.h"
|
|
#include "AvHServerVariables.h"
|
|
#include "AvHPlayer.h"
|
|
#include "AvHTitles.h"
|
|
#include "AvHSoundListManager.h"
|
|
#include "AvHParticleTemplateServer.h"
|
|
#include "AvHParticleConstants.h"
|
|
#include "AvHParticleSystemEntity.h"
|
|
#include "AvHSharedUtil.h"
|
|
#include "AvHHulls.h"
|
|
#include "../engine/studio.h"
|
|
#include "AvHBaseBuildable.h"
|
|
#include "AvHScriptManager.h"
|
|
#include "../dlls/animation.h"
|
|
#include "../util/MathUtil.h"
|
|
|
|
extern DLL_GLOBAL CGameRules* g_pGameRules;
|
|
BOOL IsSpawnPointValid( CBaseEntity *pPlayer, CBaseEntity *pSpot );
|
|
|
|
LINK_ENTITY_TO_CLASS( keSpectate, AvHSpectateEntity );
|
|
LINK_ENTITY_TO_CLASS( keJoinTeam, AvHJoinTeamEntity );
|
|
//LINK_ENTITY_TO_CLASS( keLeaveGame, AvHLeaveGameEntity );
|
|
LINK_ENTITY_TO_CLASS( keTeamStart, AvHTeamStartEntity );
|
|
LINK_ENTITY_TO_CLASS( keAutoAssign, AvHAutoAssignEntity );
|
|
LINK_ENTITY_TO_CLASS( keMapInfo, AvHMapInfo );
|
|
LINK_ENTITY_TO_CLASS( keGameplay, AvHGameplay );
|
|
|
|
LINK_ENTITY_TO_CLASS( keSeethrough, AvHSeeThrough);
|
|
LINK_ENTITY_TO_CLASS( keSeethroughDoor, AvHSeeThroughDoor);
|
|
|
|
//LINK_ENTITY_TO_CLASS( keWaypoint, AvHWaypoint);
|
|
LINK_ENTITY_TO_CLASS( keNoBuild, AvHNoBuild);
|
|
LINK_ENTITY_TO_CLASS( keFuncResource, AvHFuncResource);
|
|
|
|
LINK_ENTITY_TO_CLASS( keGamma, AvHGamma );
|
|
|
|
LINK_ENTITY_TO_CLASS( keMP3Audio, AvHMP3Audio);
|
|
|
|
LINK_ENTITY_TO_CLASS( keTriggerPresence, TriggerPresence);
|
|
LINK_ENTITY_TO_CLASS( keTriggerRandom, AvHTriggerRandom );
|
|
LINK_ENTITY_TO_CLASS( keTriggerScript, AvHTriggerScript);
|
|
|
|
//LINK_ENTITY_TO_CLASS( keTeamEgg, AvHEgg );
|
|
LINK_ENTITY_TO_CLASS( keTeamWebStrand, AvHWebStrand );
|
|
|
|
LINK_ENTITY_TO_CLASS( keFog, AvHFog);
|
|
|
|
LINK_ENTITY_TO_CLASS(kwResourceTower, AvHResourceTower);
|
|
|
|
LINK_ENTITY_TO_CLASS(keInfoLocation, AvHInfoLocation);
|
|
|
|
// Dummy initializer
|
|
StringList AvHMP3Audio::sSoundList;
|
|
|
|
extern AvHSoundListManager gSoundListManager;
|
|
extern AvHParticleTemplateListServer gParticleTemplateList;
|
|
const float kFallThinkInterval = .1f;
|
|
|
|
AvHBaseEntity::AvHBaseEntity()
|
|
{
|
|
//this->mTeam = TEAM_IND;
|
|
}
|
|
|
|
AvHTeamNumber AvHBaseEntity::GetTeamNumber() const
|
|
{
|
|
//return this->mTeam;
|
|
return (AvHTeamNumber)this->pev->team;
|
|
}
|
|
|
|
void AvHBaseEntity::FallThink(void)
|
|
{
|
|
this->pev->nextthink = gpGlobals->time + kFallThinkInterval;
|
|
|
|
if(this->pev->flags & FL_ONGROUND)
|
|
{
|
|
// clatter if we have an owner (i.e., dropped by someone)
|
|
// don't clatter if the gun is waiting to respawn (if it's waiting, it is invisible!)
|
|
//if ( !FNullEnt( this->pev->owner ) )
|
|
//{
|
|
// int pitch = 95 + RANDOM_LONG(0,29);
|
|
// EMIT_SOUND_DYN(ENT(this->pev), CHAN_VOICE, "items/weapondrop1.wav", 1, ATTN_NORM, 0, pitch);
|
|
//}
|
|
|
|
// lie flat
|
|
this->pev->angles.x = 0;
|
|
this->pev->angles.z = 0;
|
|
|
|
UTIL_SetOrigin( pev, pev->origin );// link into world.
|
|
}
|
|
}
|
|
|
|
void AvHBaseEntity::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
if(FStrEq(pkvd->szKeyName, "teamchoice"))
|
|
{
|
|
//this->mTeam = (AvHTeamNumber)(atoi(pkvd->szValue));
|
|
this->pev->team = (AvHTeamNumber)(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
CBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void AvHBaseEntity::NotifyUpgrade(AvHUpgradeMask inUpgradeMask)
|
|
{
|
|
}
|
|
|
|
AvHClientCommandEntity::AvHClientCommandEntity()
|
|
{
|
|
}
|
|
|
|
void AvHClientCommandEntity::ClientCommandTouch( CBaseEntity *pOther )
|
|
{
|
|
// If incoming entity is a player
|
|
CBasePlayer* theBasePlayer = dynamic_cast<CBasePlayer*>(pOther);
|
|
if(theBasePlayer)
|
|
{
|
|
// execute client command for that player
|
|
g_pGameRules->ClientCommand(theBasePlayer, this->GetClientCommand());
|
|
}
|
|
}
|
|
|
|
void AvHClientCommandEntity::Spawn(void)
|
|
{
|
|
pev->movetype = MOVETYPE_NONE;
|
|
pev->solid = SOLID_TRIGGER;
|
|
pev->iuser3 = AVH_USER3_CLIENT_COMMAND;
|
|
|
|
SET_MODEL( ENT(pev), STRING(pev->model) );
|
|
this->pev->effects = EF_NODRAW;
|
|
|
|
SetTouch(&AvHClientCommandEntity::ClientCommandTouch);
|
|
}
|
|
|
|
const char* AvHJoinTeamEntity::GetClientCommand()
|
|
{
|
|
const char* theCommand = "";
|
|
|
|
AvHTeamNumber theTeamNumber = this->GetTeamNumber();
|
|
switch(theTeamNumber)
|
|
{
|
|
case TEAM_ONE:
|
|
theCommand = kcJoinTeamOne;
|
|
break;
|
|
case TEAM_TWO:
|
|
theCommand = kcJoinTeamTwo;
|
|
break;
|
|
case TEAM_THREE:
|
|
theCommand = kcJoinTeamThree;
|
|
break;
|
|
case TEAM_FOUR:
|
|
theCommand = kcJoinTeamFour;
|
|
break;
|
|
}
|
|
|
|
return theCommand;
|
|
}
|
|
|
|
void AvHTeamStartEntity::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
AvHBaseEntity::KeyValue(pkvd);
|
|
}
|
|
|
|
void AvHTeamStartEntity::Spawn(void)
|
|
{
|
|
AvHBaseEntity::Spawn();
|
|
|
|
this->pev->effects |= EF_NODRAW;
|
|
|
|
// Mark with special iuser3
|
|
AvHUser3 theUser3 = AVH_USER3_SPAWN_READYROOM;
|
|
|
|
AvHTeamNumber theTeamNumber = this->GetTeamNumber();
|
|
if( theTeamNumber == GetGameRules()->GetTeamA()->GetTeamNumber() )
|
|
{
|
|
theUser3 = AVH_USER3_SPAWN_TEAMA;
|
|
}
|
|
else if( theTeamNumber == GetGameRules()->GetTeamB()->GetTeamNumber() )
|
|
{
|
|
theUser3 = AVH_USER3_SPAWN_TEAMB;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(false);
|
|
}
|
|
|
|
this->pev->iuser3 = theUser3;
|
|
}
|
|
|
|
|
|
|
|
//void AvHBuildableAnimating::BuildUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
|
//{
|
|
// // Check teams to see if right person is using it
|
|
// if(this->pev->team == pActivator->pev->team)
|
|
// {
|
|
// if(!this->GetIsBuilt())
|
|
// {
|
|
// if(AvHSUPlayerCanBuild(pActivator->pev))
|
|
// {
|
|
// this->mTimeLastUsed = gpGlobals->time;
|
|
//
|
|
// if(RANDOM_LONG(0, 4) == 0)
|
|
// {
|
|
// // Set health, taking into account upgrade
|
|
// this->SetNormalizedBuildPercentage(this->GetNormalizedBuildPercentage() + 1.0f);
|
|
// this->pev->health = this->GetMinHitPoints() + (this->GetNormalizedBuildPercentage())*(this->GetMaxHitPoints() - this->GetMinHitPoints());
|
|
// //this->pev->armorvalue = this->mMaxArmor;
|
|
// this->pev->rendermode = kRenderTransTexture;
|
|
// this->pev->renderamt = (this->pev->health/this->GetMaxHitPoints())*255;
|
|
// }
|
|
//
|
|
// //this->PlayBuildSound();
|
|
// AvHSUPlayRandomConstructionEffect(this);
|
|
//
|
|
// if(this->GetIsBuilt())
|
|
// {
|
|
// this->SetConstructionComplete();
|
|
// }
|
|
//
|
|
// AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(pActivator);
|
|
// if(thePlayer && !this->GetIsBuilt())
|
|
// {
|
|
// thePlayer->TriggerProgressBar(this->entindex(), 1);
|
|
// //this->pev->fuser1 = this->GetNormalizedBuildPercentage()*kNormalizationNetworkFactor;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//}
|
|
//
|
|
//int AvHBuildableAnimating::GetMinHitPoints() const
|
|
//{
|
|
// return .5f*this->GetMaxHitPoints();
|
|
//}
|
|
//
|
|
//int AvHBuildableAnimating::GetMaxHitPoints() const
|
|
//{
|
|
// return 200;
|
|
//}
|
|
//
|
|
//bool AvHBuildableAnimating::GetIsBuilt() const
|
|
//{
|
|
// return (this->GetNormalizedBuildPercentage() >= 1.0f);
|
|
//}
|
|
//
|
|
//void AvHBuildableAnimating::SetIsBuilt()
|
|
//{
|
|
// this->SetNormalizedBuildPercentage(1.0f);
|
|
//}
|
|
//
|
|
//float AvHBuildableAnimating::GetNormalizedBuildPercentage() const
|
|
//{
|
|
// return this->pev->fuser1/kNormalizationNetworkFactor;
|
|
//}
|
|
//
|
|
//void AvHBuildableAnimating::SetNormalizedBuildPercentage(float inPercentage)
|
|
//{
|
|
// this->pev->fuser1 = inPercentage*kNormalizationNetworkFactor;
|
|
//}
|
|
//
|
|
//
|
|
//void AvHBuildableAnimating::Spawn(void)
|
|
//{
|
|
// CBaseAnimating::Spawn();
|
|
//
|
|
// SetUse(BuildUse);
|
|
//
|
|
// this->pev->iuser3 = AVH_USER3_BUILDABLE;
|
|
// this->pev->fuser1 = 0.0f;
|
|
// this->mTimeLastUsed = -1;
|
|
//}
|
|
|
|
|
|
//// Build site entities
|
|
//AvHResource::AvHResource(AvHTechID inTechID, AvHMessageID inMessageID, char* inClassName, int inHealth, AvHSelectableUser4 inUser4) : mThinkInterval(.1f)
|
|
//{
|
|
// this->mBuildRange = 0.0f;
|
|
// this->mResourceRating = 0;
|
|
// this->mHasResource = false;
|
|
// this->mStartAlreadyBuilt = false;
|
|
// this->mValidTeams = 0;
|
|
// this->mBuildSoundPlaying = false;
|
|
// this->mTimeLastContributed = -1;
|
|
//}
|
|
//
|
|
//int AvHResource::BloodColor( void )
|
|
//{
|
|
// return DONT_BLEED;
|
|
//}
|
|
//
|
|
//float AvHResource::GetBuildRange(void) const
|
|
//{
|
|
// return this->mBuildRange;
|
|
//}
|
|
//
|
|
//bool AvHResource::GetIsActive(void) const
|
|
//{
|
|
// return this->GetIsBuilt() && (this->pev->health > 0);
|
|
//}
|
|
//
|
|
//float AvHResource::GetTimeLastContributed()
|
|
//{
|
|
// return this->mTimeLastContributed;
|
|
//}
|
|
//
|
|
//void AvHResource::SetTimeLastContributed(float inTime)
|
|
//{
|
|
// this->mTimeLastContributed = inTime;
|
|
//}
|
|
//
|
|
//void AvHResource::Killed( entvars_t *pevAttacker, int iGib )
|
|
//{
|
|
// // lots of smoke
|
|
// MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
|
|
// WRITE_BYTE( TE_SMOKE );
|
|
// WRITE_COORD( RANDOM_FLOAT( pev->absmin.x, pev->absmax.x ) );
|
|
// WRITE_COORD( RANDOM_FLOAT( pev->absmin.y, pev->absmax.y ) );
|
|
// WRITE_COORD( pev->origin.z );
|
|
// WRITE_SHORT( g_sModelIndexSmoke );
|
|
// WRITE_BYTE( 25 ); // scale * 10
|
|
// WRITE_BYTE( 10 ); // framerate
|
|
// MESSAGE_END();
|
|
//
|
|
// if (pev->dmgtime + RANDOM_FLOAT( 0, 5 ) > gpGlobals->time)
|
|
// {
|
|
// Vector vecSrc = Vector( (float)RANDOM_FLOAT( pev->absmin.x, pev->absmax.x ), (float)RANDOM_FLOAT( pev->absmin.y, pev->absmax.y ), (float)0 );
|
|
// vecSrc = vecSrc + Vector( (float)0, (float)0, (float)RANDOM_FLOAT( pev->origin.z, pev->absmax.z ) );
|
|
//
|
|
// UTIL_Sparks( vecSrc );
|
|
// }
|
|
//
|
|
// CBaseAnimating::Killed(pevAttacker, iGib);
|
|
//}
|
|
//
|
|
//
|
|
////void AvHResource::LoopSound(void) const
|
|
////{
|
|
//// //UTIL_EmitAmbientSound( ENT(this->pev), pev->origin, kResourceHum, 100.0f, ATTN_NORM, SND_SPAWNING, RANDOM_LONG( 50, 100 ));
|
|
//// UTIL_EmitAmbientSound( ENT(this->pev), pev->origin, kResourceHum, 1, 1.25, SND_SPAWNING, 100);
|
|
////}
|
|
//
|
|
//int AvHResource::ObjectCaps( void )
|
|
//{
|
|
// return FCAP_CONTINUOUS_USE;
|
|
//}
|
|
//
|
|
////void AvHResource::PlayBuildSound(void)
|
|
////{
|
|
//// if(!this->mBuildSoundPlaying)
|
|
//// {
|
|
//// UTIL_EmitAmbientSound( ENT(this->pev), this->pev->origin, kResourceBuildSound, 100.0f, ATTN_NORM, 0, RANDOM_LONG( 50, 100 ));
|
|
//// this->mBuildSoundPlaying = true;
|
|
//// }
|
|
////}
|
|
////
|
|
////void AvHResource::StopBuildSound(void)
|
|
////{
|
|
//// if(this->mBuildSoundPlaying)
|
|
//// {
|
|
//// UTIL_EmitAmbientSound(ENT(this->pev), this->pev->origin, kResourceBuildSound, 0, 0, SND_STOP, 0);
|
|
//// this->mBuildSoundPlaying = false;
|
|
//// }
|
|
////}
|
|
//
|
|
//void AvHResource::Precache( void )
|
|
//{
|
|
// CBaseAnimating::Precache();
|
|
//
|
|
// //PRECACHE_SOUND(kResourceHum);
|
|
// //PRECACHE_SOUND(kResourceBuildSound);
|
|
//
|
|
// if(pev->model)
|
|
// {
|
|
// PRECACHE_MODEL( (char *)STRING(pev->model) );
|
|
// }
|
|
//}
|
|
//
|
|
//void AvHResource::ResourceThink(void)
|
|
//{
|
|
//// if((gpGlobals->time - this->mTimeLastUsed > .2f) && this->mBuildSoundPlaying)
|
|
//// {
|
|
//// this->StopBuildSound();
|
|
//// }
|
|
// pev->nextthink = gpGlobals->time + this->mThinkInterval;
|
|
//}
|
|
//
|
|
//void AvHResource::ResourceTouch( CBaseEntity *pOther )
|
|
//{
|
|
//}
|
|
//
|
|
////void AvHResource::ResourceUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
|
////{
|
|
////}
|
|
//
|
|
//void AvHResource::SetConstructionComplete()
|
|
//{
|
|
// //SetUse(NULL);
|
|
// this->SetIsBuilt();
|
|
// //this->LoopSound();
|
|
// this->pev->health = this->GetMaxHitPoints();
|
|
// this->pev->rendermode = kRenderNormal;
|
|
// this->pev->renderamt = 0;
|
|
// this->pev->takedamage = 1;
|
|
// pev->solid = SOLID_SLIDEBOX;
|
|
//
|
|
// this->mTimeLastContributed = gpGlobals->time;
|
|
//}
|
|
//
|
|
//void AvHResource::Spawn(void)
|
|
//{
|
|
// this->Precache();
|
|
//
|
|
// pev->classname = MAKE_STRING(kAvHResourceClassName);
|
|
//
|
|
// pev->movetype = MOVETYPE_FLY;
|
|
//
|
|
// SET_MODEL( ENT(pev), STRING(pev->model) );
|
|
//
|
|
// if(this->mStartAlreadyBuilt)
|
|
// {
|
|
// this->SetIsBuilt();
|
|
// this->pev->health = this->GetMaxHitPoints();
|
|
// this->pev->rendermode = kRenderNormal;
|
|
// SetUse(NULL);
|
|
// //this->LoopSound();
|
|
// this->pev->solid = SOLID_SLIDEBOX;
|
|
// }
|
|
// else
|
|
// {
|
|
// this->pev->fuser1 = 0;
|
|
// this->pev->rendermode = kRenderTransTexture;
|
|
// this->pev->solid = SOLID_NOT;
|
|
// this->pev->health = this->GetMinHitPoints();
|
|
// //SetTouch(ResourceTouch);
|
|
// //SetUse(ResourceUse);
|
|
// }
|
|
//
|
|
// SetThink(ResourceThink);
|
|
// pev->nextthink = gpGlobals->time + this->mThinkInterval;
|
|
//
|
|
// this->mTimeLastContributed = gpGlobals->time;
|
|
//}
|
|
//
|
|
//int AvHResource::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
|
//{
|
|
// int theReturnCode = 0;
|
|
//
|
|
// if (pev->takedamage )
|
|
// {
|
|
// // Resources have armor too, get protection from upgrades
|
|
// float theNewDamage = AvHSUCalculateDamageLessArmor(this->pev, flDamage, bitsDamageType, GetGameRules()->IsMultiplayer());
|
|
// theReturnCode = CBaseAnimating::TakeDamage(pevInflictor, pevAttacker, theNewDamage, bitsDamageType);
|
|
//
|
|
//// pev->health -= theNewDamage;
|
|
//// if (pev->health <= 0)
|
|
//// {
|
|
//// pev->health = 0;
|
|
//// pev->takedamage = DAMAGE_NO;
|
|
//// pev->dmgtime = gpGlobals->time;
|
|
////
|
|
//// ClearBits (pev->flags, FL_MONSTER); // why are they set in the first place???
|
|
////
|
|
//// SetUse(NULL);
|
|
////
|
|
//// // SetThink?
|
|
////
|
|
//// //SUB_UseTargets( this, USE_ON, 0 ); // wake up others
|
|
//// }
|
|
// }
|
|
//
|
|
// return theReturnCode;
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AvHSeeThrough::AvHSeeThrough()
|
|
{
|
|
this->mCommanderAlpha = 0;
|
|
this->mPlayerAlpha = 255;
|
|
}
|
|
|
|
void AvHSeeThrough::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
if(FStrEq(pkvd->szKeyName, "commanderAlpha") || FStrEq(pkvd->szKeyName, "seeThroughAlpha"))
|
|
{
|
|
int theAlpha = atoi(pkvd->szValue);
|
|
this->mCommanderAlpha = min(max(0, theAlpha), 255);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if(FStrEq(pkvd->szKeyName, "playerAlpha"))
|
|
{
|
|
int theAlpha = atoi(pkvd->szValue);
|
|
this->mPlayerAlpha = min(max(0, theAlpha), 255);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
CBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void AvHSeeThrough::Spawn()
|
|
{
|
|
this->Precache();
|
|
CBaseEntity::Spawn();
|
|
|
|
this->pev->solid = SOLID_BSP;
|
|
this->pev->movetype = MOVETYPE_PUSH;
|
|
SET_MODEL( ENT(pev), STRING(pev->model) );
|
|
|
|
this->pev->classname = MAKE_STRING(kesSeethrough);
|
|
|
|
this->pev->iuser3 = AVH_USER3_ALPHA;
|
|
this->pev->fuser1 = this->mCommanderAlpha;
|
|
this->pev->fuser2 = this->mPlayerAlpha;
|
|
}
|
|
|
|
|
|
|
|
AvHSeeThroughDoor::AvHSeeThroughDoor()
|
|
{
|
|
this->mCommanderAlpha = 0;
|
|
this->mPlayerAlpha = 255;
|
|
}
|
|
|
|
void AvHSeeThroughDoor::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
// For backwards compatibility with old AvHSeeThrough
|
|
if(FStrEq(pkvd->szKeyName, "commanderAlpha") || FStrEq(pkvd->szKeyName, "seeThroughAlpha"))
|
|
{
|
|
int theAlpha = atoi(pkvd->szValue);
|
|
this->mCommanderAlpha = min(max(0, theAlpha), 255);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if(FStrEq(pkvd->szKeyName, "playerAlpha"))
|
|
{
|
|
int theAlpha = atoi(pkvd->szValue);
|
|
this->mPlayerAlpha = min(max(0, theAlpha), 255);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
CBaseDoor::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
|
|
void AvHSeeThroughDoor::Spawn()
|
|
{
|
|
this->Precache();
|
|
CBaseDoor::Spawn();
|
|
|
|
this->pev->solid = SOLID_BSP;
|
|
this->pev->movetype = MOVETYPE_PUSH;
|
|
SET_MODEL( ENT(pev), STRING(pev->model) );
|
|
|
|
this->pev->classname = MAKE_STRING(kesSeethroughDoor);
|
|
|
|
this->pev->iuser3 = AVH_USER3_ALPHA;
|
|
this->pev->fuser1 = this->mCommanderAlpha;
|
|
this->pev->fuser2 = this->mPlayerAlpha;
|
|
}
|
|
|
|
|
|
|
|
AvHNoBuild::AvHNoBuild()
|
|
{
|
|
}
|
|
|
|
void AvHNoBuild::KeyValue(KeyValueData* pkvd)
|
|
{
|
|
AvHBaseEntity::KeyValue(pkvd);
|
|
}
|
|
|
|
void AvHNoBuild::Spawn()
|
|
{
|
|
this->Precache();
|
|
AvHBaseEntity::Spawn();
|
|
|
|
this->pev->solid = SOLID_BSP;
|
|
this->pev->movetype = MOVETYPE_PUSH;
|
|
|
|
//this->pev->solid = SOLID_TRIGGER;
|
|
//this->pev->movetype = MOVETYPE_NONE;
|
|
|
|
SET_MODEL( ENT(pev), STRING(pev->model) );
|
|
|
|
this->pev->classname = MAKE_STRING(kesNoBuild);
|
|
this->pev->iuser3 = AVH_USER3_NOBUILD;
|
|
|
|
this->pev->rendermode = kRenderTransAdd;
|
|
this->pev->renderamt = 0;
|
|
//this->pev->effects = EF_NODRAW;
|
|
}
|
|
|
|
|
|
|
|
AvHMP3Audio::AvHMP3Audio()
|
|
{
|
|
this->mUseState = false;
|
|
this->mSoundVolume = 255;
|
|
this->mLooping = false;
|
|
}
|
|
|
|
int AvHMP3Audio::GetFadeDistance() const
|
|
{
|
|
return this->mFadeDistance;
|
|
}
|
|
|
|
void AvHMP3Audio::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
if(FStrEq(pkvd->szKeyName, "soundname"))
|
|
{
|
|
this->mSoundName = pkvd->szValue;
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "soundvolume"))
|
|
{
|
|
this->mSoundVolume = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "fadedistance"))
|
|
{
|
|
this->mFadeDistance = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
AvHBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void AvHMP3Audio::Precache()
|
|
{
|
|
CBaseEntity::Precache();
|
|
PRECACHE_UNMODIFIED_MODEL(kNullModel);
|
|
}
|
|
|
|
void AvHMP3Audio::Spawn()
|
|
{
|
|
Precache();
|
|
|
|
AvHBaseEntity::Spawn();
|
|
|
|
// Set spawn flags
|
|
if(this->pev->spawnflags & 1)
|
|
{
|
|
// Don't fade sound with position, treat as HUD sound
|
|
this->mFadeDistance = 0;
|
|
}
|
|
if(this->pev->spawnflags & 2)
|
|
{
|
|
this->mLooping = true;
|
|
}
|
|
if(this->pev->spawnflags & 4)
|
|
{
|
|
this->pev->iuser3 = AVH_USER3_AUDIO_ON;
|
|
}
|
|
else
|
|
{
|
|
this->pev->iuser3 = AVH_USER3_AUDIO_OFF;
|
|
}
|
|
|
|
// Set model
|
|
pev->classname = MAKE_STRING(kesMP3Audio);
|
|
|
|
this->pev->solid = SOLID_NOT;
|
|
this->pev->movetype = MOVETYPE_NONE;
|
|
|
|
//this->pev->effects |= EF_NODRAW;
|
|
|
|
//SET_MODEL(ENT(pev), STRING(pev->model));
|
|
SET_MODEL(ENT(this->pev), kNullModel);
|
|
UTIL_SetOrigin(pev, pev->origin);
|
|
|
|
// Set use so it can be toggled on and off like a switch, not used by the player
|
|
SetUse(&AvHMP3Audio::SpecialSoundUse);
|
|
|
|
// Add sound name to global registry (relative path without mod directory).
|
|
// This is pushing back duplicates. Do we care? If SoundList changes to a hash, this could break.
|
|
int theListSize = sSoundList.size();
|
|
sSoundList.push_back(this->mSoundName);
|
|
theListSize = sSoundList.size();
|
|
|
|
// The sound index is the position in this list (assume we're adding to end)
|
|
int theSoundIndexOffset = sSoundList.size() - 1;
|
|
|
|
// Set up variables
|
|
ASSERT(theSoundIndexOffset >= 0);
|
|
ASSERT(theSoundIndexOffset < 256);
|
|
int theValue = (theSoundIndexOffset << 8);
|
|
|
|
int theEntIndex = this->entindex();
|
|
theValue |= (theEntIndex << 16);
|
|
ASSERT(theEntIndex == (theValue >> 16));
|
|
this->pev->fuser1 = theValue;
|
|
//memcpy(&this->pev->fuser1, &theValue, sizeof(float));
|
|
int theConvertedFuser1 = (int)(this->pev->fuser1);
|
|
//int theConvertedFuser1 = 0;
|
|
//memcpy(&theConvertedFuser1, &this->pev->fuser1, sizeof(float));
|
|
ASSERT(theConvertedFuser1 == theValue);
|
|
this->pev->fuser2 = gpGlobals->time;
|
|
|
|
// Mash all these little ints into iuser4 (fade distance is max of 16-bits)
|
|
theValue = this->mFadeDistance;
|
|
theValue |= (this->mSoundVolume << 16);
|
|
theValue |= (this->pev->spawnflags << 24);
|
|
this->pev->iuser4 = theValue;
|
|
}
|
|
|
|
void AvHMP3Audio::ClearSoundNameList()
|
|
{
|
|
sSoundList.clear();
|
|
}
|
|
|
|
const StringList& AvHMP3Audio::GetSoundNameList()
|
|
{
|
|
return sSoundList;
|
|
}
|
|
|
|
|
|
void AvHMP3Audio::SpecialSoundUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
|
{
|
|
bool theOldUseState = this->mUseState;
|
|
|
|
// Can't toggle it once it's been welded
|
|
switch(useType)
|
|
{
|
|
case USE_OFF:
|
|
this->mUseState = false;
|
|
break;
|
|
|
|
case USE_ON:
|
|
this->mUseState = true;
|
|
break;
|
|
|
|
case USE_SET:
|
|
// Handle this?
|
|
break;
|
|
|
|
case USE_TOGGLE:
|
|
this->mUseState = !this->mUseState;
|
|
break;
|
|
}
|
|
|
|
// Just turned on or off?
|
|
if(theOldUseState != this->mUseState)
|
|
{
|
|
// Update time of action
|
|
this->pev->fuser2 = gpGlobals->time;
|
|
|
|
// Update type of action
|
|
if(this->mUseState)
|
|
{
|
|
this->pev->iuser3 = AVH_USER3_AUDIO_ON;
|
|
}
|
|
else
|
|
{
|
|
this->pev->iuser3 = AVH_USER3_AUDIO_OFF;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
AvHMapInfo::AvHMapInfo()
|
|
{
|
|
this->mMapExtents.ResetMapExtents();
|
|
}
|
|
|
|
const AvHMapExtents& AvHMapInfo::GetMapExtents() const
|
|
{
|
|
return this->mMapExtents;
|
|
}
|
|
|
|
void AvHMapInfo::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
if (FStrEq(pkvd->szKeyName, "viewheight"))
|
|
{
|
|
this->mMapExtents.SetMaxViewHeight(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if (FStrEq(pkvd->szKeyName, "minviewheight"))
|
|
{
|
|
this->mMapExtents.SetMinViewHeight(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if (FStrEq(pkvd->szKeyName, "minx"))
|
|
{
|
|
this->mMapExtents.SetMinMapX(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if (FStrEq(pkvd->szKeyName, "miny"))
|
|
{
|
|
this->mMapExtents.SetMinMapY(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if (FStrEq(pkvd->szKeyName, "maxx"))
|
|
{
|
|
this->mMapExtents.SetMaxMapX(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if (FStrEq(pkvd->szKeyName, "maxy"))
|
|
{
|
|
this->mMapExtents.SetMaxMapY(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if (FStrEq(pkvd->szKeyName, "culldistance"))
|
|
{
|
|
this->mMapExtents.SetTopDownCullDistance(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
AvHBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void AvHMapInfo::Spawn()
|
|
{
|
|
AvHBaseEntity::Spawn();
|
|
|
|
this->pev->classname = MAKE_STRING(kwsMapInfoClassName);
|
|
this->pev->solid = SOLID_NOT;
|
|
this->pev->movetype = MOVETYPE_NONE;
|
|
this->pev->effects = EF_NODRAW;
|
|
|
|
// Did mapper check "don't draw background" flag?
|
|
if(pev->spawnflags & 1)
|
|
{
|
|
this->mMapExtents.SetDrawMapBG(false);
|
|
}
|
|
}
|
|
|
|
AvHGameplay::AvHGameplay()
|
|
{
|
|
this->mTeamAType = AVH_CLASS_TYPE_UNDEFINED;
|
|
this->mTeamBType = AVH_CLASS_TYPE_UNDEFINED;
|
|
|
|
this->mInitialHives = 1;
|
|
}
|
|
|
|
AvHClassType AvHGameplay::GetTeamAType() const
|
|
{
|
|
return this->mTeamAType;
|
|
}
|
|
|
|
AvHClassType AvHGameplay::GetTeamBType() const
|
|
{
|
|
return this->mTeamBType;
|
|
}
|
|
|
|
int AvHGameplay::GetInitialHives() const
|
|
{
|
|
return this->mInitialHives;
|
|
}
|
|
|
|
int AvHGameplay::GetInitialAlienPoints() const
|
|
{
|
|
return BALANCE_VAR(kNumInitialAlienPoints);
|
|
}
|
|
|
|
int AvHGameplay::GetInitialMarinePoints() const
|
|
{
|
|
return BALANCE_VAR(kNumInitialMarinePoints);
|
|
}
|
|
|
|
int AvHGameplay::GetAlienRespawnCost() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int AvHGameplay::GetMarineRespawnCost() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Not used currently
|
|
int AvHGameplay::GetAlienRespawnTime() const
|
|
{
|
|
float theTimeToRespawn = BALANCE_VAR(kAlienRespawnTime);
|
|
|
|
if(GetGameRules()->GetIsTesting() || GetGameRules()->GetCheatsEnabled())
|
|
{
|
|
theTimeToRespawn = 2.0f;
|
|
}
|
|
|
|
return theTimeToRespawn;
|
|
}
|
|
|
|
int AvHGameplay::GetTowerInjectionTime() const
|
|
{
|
|
return BALANCE_VAR(kFuncResourceInjectionTime);
|
|
}
|
|
|
|
int AvHGameplay::GetTowerInjectionAmount() const
|
|
{
|
|
return BALANCE_VAR(kFuncResourceInjectionAmount);
|
|
}
|
|
|
|
|
|
void AvHGameplay::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
if (FStrEq(pkvd->szKeyName, "teamone"))
|
|
{
|
|
this->mTeamAType = (AvHClassType)(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
if (FStrEq(pkvd->szKeyName, "teamtwo"))
|
|
{
|
|
this->mTeamBType = (AvHClassType)(atoi(pkvd->szValue));
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
AvHBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void AvHGameplay::Reset()
|
|
{
|
|
// This should have all the correct defaults (same as ns.fgd)
|
|
this->mTeamAType = AVH_CLASS_TYPE_MARINE;
|
|
this->mTeamBType = AVH_CLASS_TYPE_ALIEN;
|
|
|
|
this->mInitialHives = 1;
|
|
}
|
|
|
|
// Should we even do this?
|
|
void AvHGameplay::Spawn()
|
|
{
|
|
AvHBaseEntity::Spawn();
|
|
|
|
this->pev->classname = MAKE_STRING(kwsGameplayClassName);
|
|
this->pev->solid = SOLID_NOT;
|
|
this->pev->movetype = MOVETYPE_NONE;
|
|
this->pev->effects = EF_NODRAW;
|
|
}
|
|
|
|
|
|
|
|
AvHGamma::AvHGamma()
|
|
{
|
|
this->mGammaScalar = 1.0f;
|
|
}
|
|
|
|
void AvHGamma::KeyValue(KeyValueData* pkvd)
|
|
{
|
|
if(FStrEq(pkvd->szKeyName, "desiredgamma"))
|
|
{
|
|
this->mGammaScalar = atof(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
AvHBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
float AvHGamma::GetGamma() const
|
|
{
|
|
return this->mGammaScalar;
|
|
}
|
|
|
|
|
|
void AvHGamma::Spawn()
|
|
{
|
|
AvHBaseEntity::Spawn();
|
|
this->pev->classname = MAKE_STRING(kwsGammaClassName);
|
|
this->pev->effects = EF_NODRAW;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//AvHEgg::AvHEgg()
|
|
//{
|
|
//}
|
|
//
|
|
//void AvHEgg::EggThink(void)
|
|
//{
|
|
// // If we're not touching any
|
|
// //FallThink();
|
|
// this->pev->nextthink = gpGlobals->time + kFallThinkInterval;
|
|
//
|
|
// if(this->pev->flags & FL_ONGROUND)
|
|
// {
|
|
// // lie flat
|
|
// this->pev->angles.x = 0;
|
|
// this->pev->angles.z = 0;
|
|
//
|
|
// this->pev->solid = SOLID_BBOX;
|
|
// this->pev->movetype = MOVETYPE_TOSS;
|
|
//
|
|
// // Now it's big enough to block
|
|
// this->pev->takedamage = DAMAGE_YES;
|
|
//
|
|
// Vector theFinalPos = this->pev->origin;
|
|
// //theFinalPos.z += 50;
|
|
//
|
|
// UTIL_SetSize(this->pev, Vector( -32, -32, -50), Vector(32, 32, 64) );
|
|
// UTIL_SetOrigin(this->pev, theFinalPos);// link into world.
|
|
// SetThink (NULL);
|
|
//
|
|
// // Start animating
|
|
// this->pev->sequence = 0;
|
|
// this->pev->frame = 0;
|
|
// //ResetSequenceInfo();
|
|
// //AvHSUSetCollisionBoxFromSequence(this->pev);
|
|
// }
|
|
//}
|
|
//
|
|
//void AvHEgg::Hatch()
|
|
//{
|
|
//}
|
|
//
|
|
//void AvHEgg::Killed( entvars_t *pevAttacker, int iGib )
|
|
//{
|
|
// AvHSUExplodeEntity(this, matFlesh);
|
|
//
|
|
// EMIT_SOUND(ENT(this->pev), CHAN_AUTO, kEggDestroyedSound, 1.0, ATTN_IDLE);
|
|
//
|
|
// //AvHBaseEntity::Killed(pevAttacker, iGib);
|
|
// //CBaseAnimating::Killed(pevAttacker, iGib);
|
|
// CBaseEntity::Killed(pevAttacker, iGib);
|
|
//}
|
|
//
|
|
//void AvHEgg::Precache(void)
|
|
//{
|
|
// PRECACHE_SOUND(kEggDestroyedSound);
|
|
// PRECACHE_MODEL(kEggModel);
|
|
//}
|
|
//
|
|
//void AvHEgg::Spawn()
|
|
//{
|
|
// this->Precache( );
|
|
//
|
|
// this->pev->solid = SOLID_BBOX;
|
|
// this->pev->movetype = MOVETYPE_TOSS;
|
|
// //this->pev->flags &= ~FL_ONGROUND;
|
|
// //this->pev->velocity = Vector(0, 0, 8);
|
|
//
|
|
// SET_MODEL( ENT(this->pev), kEggModel);
|
|
// UTIL_SetOrigin(pev, pev->origin); // set size and link into world
|
|
//
|
|
// DROP_TO_FLOOR(ENT(pev));
|
|
//
|
|
// this->pev->classname = MAKE_STRING(kwsEggClassName);
|
|
// this->pev->health = AvHPlayerUpgrade::GetMaxHealth(0, ROLE_GESTATING);
|
|
// this->pev->max_health = pev->health;
|
|
// this->pev->takedamage = DAMAGE_YES;
|
|
// //this->pev->view_ofs = Vector(0,0,22);
|
|
//
|
|
// this->pev->sequence = 0;
|
|
// this->pev->frame = 0;
|
|
// ResetSequenceInfo();
|
|
// AvHSUSetCollisionBoxFromSequence(this->pev);
|
|
//}
|
|
//
|
|
//void AvHEgg::SpawnPlayer()
|
|
//{
|
|
// // Bring origin up a bit, so when the player spawns he won't be stuck in the ground
|
|
// this->pev->origin.z += 50;
|
|
//
|
|
// AvHSUExplodeEntity(this, matFlesh);
|
|
//
|
|
// SetThink(SUB_Remove);
|
|
//
|
|
// this->pev->nextthink = gpGlobals->time + .3f;
|
|
//}
|
|
//
|
|
//int AvHEgg::TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType )
|
|
//{
|
|
// //return CBaseAnimating::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
|
// return CBaseEntity::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
|
|
//}
|
|
|
|
|
|
const float kTriggerPresenceThinkInterval = .05f;
|
|
|
|
TriggerPresence::TriggerPresence()
|
|
{
|
|
this->mEnabled = true;
|
|
this->mPresence = false;
|
|
this->mPlayersDontActivate = false;
|
|
this->mMonstersDontActivate = false;
|
|
this->mPushablesDontActivate = false;
|
|
this->mTeamAOnly = false;
|
|
this->mTeamBOnly = false;
|
|
|
|
this->mTimeOfLastTouch = -1;
|
|
this->mTimeBeforeLeave = .5f;
|
|
this->mMomentaryOpenTime = 1.0f;
|
|
this->mMomentaryCloseTime = 1.0f;
|
|
}
|
|
|
|
void TriggerPresence::KeyValue(KeyValueData* pkvd)
|
|
{
|
|
pkvd->fHandled = FALSE;
|
|
|
|
if(FStrEq(pkvd->szKeyName, "master"))
|
|
{
|
|
this->mMaster = pkvd->szValue;
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "targetenter"))
|
|
{
|
|
this->mTargetEnter = pkvd->szValue;
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "targetleave"))
|
|
{
|
|
this->mTargetLeave = pkvd->szValue;
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "momentarytarget"))
|
|
{
|
|
this->mMomentaryTarget = pkvd->szValue;
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "timebeforeleave"))
|
|
{
|
|
this->mTimeBeforeLeave = max(atof(pkvd->szValue), (double)0.0f);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "momentaryopentime"))
|
|
{
|
|
this->mMomentaryOpenTime = max(atof(pkvd->szValue), (double)0.01f);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "momentaryclosetime"))
|
|
{
|
|
this->mMomentaryCloseTime = max(atof(pkvd->szValue), (double)0.01f);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "spawnflags"))
|
|
{
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
CBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void TriggerPresence::Precache(void)
|
|
{
|
|
}
|
|
|
|
//void TriggerPresence::ResetEntity(void)
|
|
//{
|
|
// Not sure if this should be here or not...think
|
|
//this->mTimeOfLastTouch = -1;
|
|
//this->SetPresence(false);
|
|
//this->mEnabled = false;
|
|
//}
|
|
|
|
void TriggerPresence::SetPresence(bool inPresence)
|
|
{
|
|
// If we current have presence and inPresence is false
|
|
if(this->mPresence && !inPresence)
|
|
{
|
|
// fire mTargetLeave
|
|
FireTargets(this->mTargetLeave.c_str(), this, this, USE_TOGGLE, 0.0f);
|
|
}
|
|
// else if we don't have presence and inPresence is true
|
|
else if(!this->mPresence && inPresence)
|
|
{
|
|
// fire mTargetEnter
|
|
if(this->mTargetEnter != "")
|
|
{
|
|
FireTargets(this->mTargetEnter.c_str(), this, this, USE_TOGGLE, 0.0f);
|
|
}
|
|
}
|
|
|
|
// Set mPresence to inPresence
|
|
this->mPresence = inPresence;
|
|
}
|
|
|
|
void TriggerPresence::Spawn(void)
|
|
{
|
|
this->Precache();
|
|
|
|
CBaseEntity::Spawn();
|
|
|
|
// Spawn code
|
|
this->SetTouch(&TriggerPresence::TriggerTouch);
|
|
|
|
this->pev->movetype = MOVETYPE_NONE;
|
|
this->pev->solid = SOLID_TRIGGER;
|
|
|
|
SET_MODEL(ENT(pev), STRING(pev->model));
|
|
this->pev->effects = EF_NODRAW;
|
|
|
|
// Set spawn flags
|
|
if(this->pev->spawnflags & 1)
|
|
{
|
|
this->mPlayersDontActivate = true;
|
|
}
|
|
if(this->pev->spawnflags & 2)
|
|
{
|
|
this->mMonstersDontActivate = true;
|
|
}
|
|
if(this->pev->spawnflags & 4)
|
|
{
|
|
this->mPushablesDontActivate = true;
|
|
}
|
|
if(this->pev->spawnflags & 8)
|
|
{
|
|
this->mTeamAOnly = true;
|
|
}
|
|
if(this->pev->spawnflags & 16)
|
|
{
|
|
this->mTeamBOnly = true;
|
|
}
|
|
|
|
// Don't start enabled if a master was specified
|
|
if(this->mMaster != "")
|
|
{
|
|
this->mEnabled = false;
|
|
}
|
|
|
|
SetThink(&TriggerPresence::TriggerThink);
|
|
this->pev->nextthink = gpGlobals->time + kTriggerPresenceThinkInterval;
|
|
}
|
|
|
|
void TriggerPresence::TriggerThink()
|
|
{
|
|
if(this->mEnabled)
|
|
{
|
|
// If we have presence and haven't received a touch for a certain amount of time
|
|
if(this->mPresence)
|
|
{
|
|
if(gpGlobals->time > this->mTimeOfLastTouch + this->mTimeBeforeLeave)
|
|
{
|
|
this->SetPresence(false);
|
|
}
|
|
}
|
|
|
|
// Keep firing momentary target if presence detected
|
|
if(this->mMomentaryTarget != "")
|
|
{
|
|
// Update the value if we're opening or closing
|
|
float theDifference = this->mPresence ? kTriggerPresenceThinkInterval/this->mMomentaryOpenTime : -kTriggerPresenceThinkInterval/this->mMomentaryCloseTime;
|
|
this->mMomentaryValue += theDifference;
|
|
this->mMomentaryValue = min(max(this->mMomentaryValue, 0.0f), 1.0f);
|
|
|
|
//float theAmount = RANDOM_FLOAT(0, 1);
|
|
FireTargets(this->mMomentaryTarget.c_str(), this, this, USE_SET, this->mMomentaryValue);
|
|
}
|
|
}
|
|
|
|
this->pev->nextthink = gpGlobals->time + kTriggerPresenceThinkInterval;
|
|
}
|
|
|
|
void TriggerPresence::TriggerTouch(CBaseEntity *pOther)
|
|
{
|
|
if(this->mEnabled)
|
|
{
|
|
// If players activate and is player
|
|
CBasePlayer* thePlayer = dynamic_cast<CBasePlayer*>(pOther);
|
|
CBaseMonster* theMonster = dynamic_cast<CBaseMonster*>(pOther);
|
|
CPushable* thePushable = dynamic_cast<CPushable*>(pOther);
|
|
|
|
bool theTriggerFires = true;
|
|
|
|
if(thePlayer && this->mPlayersDontActivate)
|
|
{
|
|
theTriggerFires = false;
|
|
}
|
|
if(theMonster && this->mMonstersDontActivate)
|
|
{
|
|
theTriggerFires = false;
|
|
}
|
|
if(thePushable && this->mPushablesDontActivate)
|
|
{
|
|
theTriggerFires = false;
|
|
}
|
|
if(this->mTeamAOnly && (pOther->pev->team != GetGameRules()->GetTeamA()->GetTeamNumber()))
|
|
{
|
|
theTriggerFires = false;
|
|
}
|
|
if(this->mTeamBOnly && (pOther->pev->team != GetGameRules()->GetTeamB()->GetTeamNumber()))
|
|
{
|
|
theTriggerFires = false;
|
|
}
|
|
|
|
//if(thePlayer)
|
|
//{
|
|
// ClientPrint(thePlayer->pev, HUD_PRINTCONSOLE, "Player touch\n");
|
|
//}
|
|
|
|
if(theTriggerFires)
|
|
{
|
|
this->SetPresence(true);
|
|
this->mTimeOfLastTouch = gpGlobals->time;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TriggerPresence::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE inUseType, float inValue)
|
|
{
|
|
switch(inUseType)
|
|
{
|
|
case USE_OFF:
|
|
this->mEnabled = false;
|
|
break;
|
|
case USE_ON:
|
|
this->mEnabled = true;
|
|
break;
|
|
case USE_SET:
|
|
this->mEnabled = (bool)inValue;
|
|
break;
|
|
case USE_TOGGLE:
|
|
this->mEnabled = !this->mEnabled;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
AvHTriggerRandom::AvHTriggerRandom()
|
|
{
|
|
this->mMinFireTime = 0;
|
|
this->mMaxFireTime = 1;
|
|
this->mWaitBeforeReset = 3;
|
|
|
|
this->mStartOn = false;
|
|
this->mToggle = false;
|
|
this->mRemoveOnFire = false;
|
|
|
|
this->mFiredAtLeastOnce = false;
|
|
this->mToggleableAndOn = false;
|
|
this->mTimeOfLastActivation = -1;
|
|
this->mTimeOfLastTrigger = -1;
|
|
}
|
|
|
|
|
|
void AvHTriggerRandom::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
pkvd->fHandled = FALSE;
|
|
|
|
if (FStrEq(pkvd->szKeyName, "minfiretime"))
|
|
{
|
|
this->mMinFireTime = atof( pkvd->szValue );
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "maxfiretime"))
|
|
{
|
|
this->mMaxFireTime = atof(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "wait"))
|
|
{
|
|
this->mWaitBeforeReset = atoi(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "spawnflags"))
|
|
{
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "balancedtarget"))
|
|
{
|
|
this->mBalancedTarget = pkvd->szValue;
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Else it's a target name, add it as a target
|
|
this->mTargetList.push_back(pkvd->szKeyName);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
|
|
void AvHTriggerRandom::ResetEntity()
|
|
{
|
|
this->mFiredAtLeastOnce = false;
|
|
this->mTimeOfLastActivation = -1;
|
|
this->mTimeOfLastTrigger = -1;
|
|
this->mToggleableAndOn = false;
|
|
|
|
// Fire first if necessary
|
|
if(this->mStartOn)
|
|
{
|
|
this->Use(NULL, NULL, USE_TOGGLE, 0.0f);
|
|
}
|
|
}
|
|
|
|
void AvHTriggerRandom::SetNextTrigger()
|
|
{
|
|
float theRandomTime = RANDOM_FLOAT(this->mMinFireTime, this->mMaxFireTime);
|
|
this->pev->nextthink = gpGlobals->time + theRandomTime;
|
|
this->mTimeOfLastTrigger = this->pev->nextthink;
|
|
}
|
|
|
|
|
|
void AvHTriggerRandom::Spawn(void)
|
|
{
|
|
this->Precache();
|
|
|
|
this->pev->classname = MAKE_STRING(kesTriggerRandom);
|
|
this->pev->effects = EF_NODRAW;
|
|
|
|
// Start on
|
|
if(pev->spawnflags & 1)
|
|
{
|
|
this->mStartOn = true;
|
|
}
|
|
// Toggle
|
|
if(pev->spawnflags & 2)
|
|
{
|
|
this->mToggle = true;
|
|
}
|
|
// Remove on fire
|
|
if(pev->spawnflags & 4)
|
|
{
|
|
this->mRemoveOnFire = true;
|
|
}
|
|
|
|
if(this->mTargetList.size() == 0)
|
|
{
|
|
ALERT(at_warning, "No targets found in trigger_random (%s)", STRING(this->pev->targetname));
|
|
}
|
|
}
|
|
|
|
void AvHTriggerRandom::TriggerTargetThink(void)
|
|
{
|
|
// Pick random target in list
|
|
int theNumTargetsToChooseFrom = this->mTargetList.size();
|
|
if(theNumTargetsToChooseFrom > 0)
|
|
{
|
|
// Fire targets with this entity name
|
|
string theTargetName;
|
|
|
|
if(GetGameRules()->GetIsTournamentMode() && (this->mBalancedTarget != ""))
|
|
{
|
|
theTargetName = this->mBalancedTarget;
|
|
}
|
|
else
|
|
{
|
|
int theRandomIndex = RANDOM_LONG(0, theNumTargetsToChooseFrom - 1);
|
|
theTargetName = this->mTargetList[theRandomIndex];
|
|
}
|
|
|
|
FireTargets(theTargetName.c_str(), NULL, NULL, USE_TOGGLE, 0.0f);
|
|
|
|
if(this->mToggleableAndOn)
|
|
{
|
|
this->SetNextTrigger();
|
|
}
|
|
else
|
|
{
|
|
// Set think to NULL
|
|
SetThink(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHTriggerRandom::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
|
|
{
|
|
// Don't activate if it's a one shot trigger
|
|
if(!this->mRemoveOnFire || (!this->mFiredAtLeastOnce && (this->mTimeOfLastActivation == -1)))
|
|
{
|
|
// If haven't been triggered yet, or is toggleable
|
|
if(!this->mFiredAtLeastOnce || this->mToggle)
|
|
{
|
|
// Don't trigger faster than wait time
|
|
float theCurrentTime = gpGlobals->time;
|
|
if((this->mTimeOfLastActivation == -1) || theCurrentTime >= (this->mTimeOfLastActivation + this->mWaitBeforeReset))
|
|
{
|
|
// Pick random time between min and max for think
|
|
SetThink(&AvHTriggerRandom::TriggerTargetThink);
|
|
this->SetNextTrigger();
|
|
this->mTimeOfLastActivation = theCurrentTime;
|
|
|
|
if(this->mToggle)
|
|
{
|
|
this->mToggleableAndOn = !this->mToggleableAndOn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
AvHTriggerScript::AvHTriggerScript()
|
|
{
|
|
this->mStartOn = false;
|
|
this->mTriggered = false;
|
|
}
|
|
|
|
void AvHTriggerScript::KeyValue(KeyValueData* pkvd)
|
|
{
|
|
if(FStrEq(pkvd->szKeyName, "scriptname"))
|
|
{
|
|
const char* theCStrLevelName = STRING(gpGlobals->mapname);
|
|
if(theCStrLevelName && !FStrEq(theCStrLevelName, ""))
|
|
{
|
|
string theLevelName = theCStrLevelName;
|
|
this->mScriptName = AvHSHUBuildExecutableScriptName(string(pkvd->szValue), theLevelName);
|
|
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CBaseEntity::KeyValue(pkvd);
|
|
}
|
|
|
|
}
|
|
|
|
void AvHTriggerScript::ResetEntity()
|
|
{
|
|
if(this->mStartOn)
|
|
{
|
|
this->Trigger();
|
|
}
|
|
}
|
|
|
|
void AvHTriggerScript::Spawn()
|
|
{
|
|
this->Precache();
|
|
|
|
this->pev->classname = MAKE_STRING(kesTriggerScript);
|
|
|
|
// Start on
|
|
if(this->pev->spawnflags & 1)
|
|
{
|
|
this->mStartOn = true;
|
|
}
|
|
}
|
|
|
|
void AvHTriggerScript::Trigger()
|
|
{
|
|
AvHScriptManager::Instance()->RunScript(this->mScriptName);
|
|
}
|
|
|
|
|
|
void AvHTriggerScript::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE inUseType, float inValue)
|
|
{
|
|
bool theNewState = false;
|
|
|
|
switch(inUseType)
|
|
{
|
|
case USE_OFF:
|
|
theNewState = false;
|
|
break;
|
|
case USE_ON:
|
|
theNewState = true;
|
|
break;
|
|
case USE_SET:
|
|
theNewState = (bool)inValue;
|
|
break;
|
|
case USE_TOGGLE:
|
|
theNewState = !this->mTriggered;
|
|
break;
|
|
}
|
|
|
|
// Trigger if necessary
|
|
if((this->mTriggered != theNewState) && theNewState)
|
|
{
|
|
this->Trigger();
|
|
}
|
|
|
|
// Update triggered state
|
|
this->mTriggered = theNewState;
|
|
}
|
|
|
|
|
|
AvHWebStrand::AvHWebStrand() : mSolid(false)
|
|
{
|
|
}
|
|
|
|
void AvHWebStrand::Break()
|
|
{
|
|
EMIT_SOUND(ENT(this->pev), CHAN_AUTO, kWebStrandBreakSound, 1.0, ATTN_IDLE);
|
|
UTIL_Remove(this);
|
|
SetThink(NULL);
|
|
|
|
// Decrement number of strands
|
|
AvHTeam* theTeam = GetGameRules()->GetTeam((AvHTeamNumber)this->pev->team);
|
|
ASSERT(theTeam);
|
|
theTeam->SetNumWebStrands(theTeam->GetNumWebStrands() - 1);
|
|
}
|
|
|
|
void AvHWebStrand::Killed(entvars_t *pevAttacker, int iGib)
|
|
{
|
|
this->Break();
|
|
|
|
CBeam::Killed(pevAttacker, iGib);
|
|
}
|
|
|
|
void AvHWebStrand::Precache(void)
|
|
{
|
|
// Precache web strand sprite
|
|
PRECACHE_UNMODIFIED_MODEL(kWebStrandSprite);
|
|
PRECACHE_UNMODIFIED_SOUND(kWebStrandBreakSound);
|
|
PRECACHE_UNMODIFIED_SOUND(kWebStrandHardenSound);
|
|
PRECACHE_UNMODIFIED_SOUND(kWebStrandFormSound);
|
|
}
|
|
|
|
void AvHWebStrand::Setup(const Vector& inPointOne, const Vector& inPointTwo)
|
|
{
|
|
// Create a new entity with CBeam private data
|
|
this->BeamInit(kWebStrandSprite, 40); //kWebStrandWidth);
|
|
|
|
this->PointsInit(inPointOne, inPointTwo);
|
|
this->SetColor( 255, 255, 255 );
|
|
this->SetScrollRate( 0 );
|
|
this->SetFrame(0);
|
|
//this->SetBrightness( 64 );
|
|
this->SetBrightness( 16 );
|
|
|
|
this->pev->classname = MAKE_STRING(kesTeamWebStrand);
|
|
this->pev->rendermode = kRenderNormal;
|
|
}
|
|
|
|
void AvHWebStrand::Spawn(void)
|
|
{
|
|
this->Precache();
|
|
|
|
CBeam::Spawn();
|
|
|
|
// Spawn code
|
|
this->SetTouch(NULL);
|
|
this->pev->solid = SOLID_NOT;
|
|
this->pev->health = kWebHitPoints;
|
|
this->pev->takedamage = DAMAGE_YES;
|
|
this->mSolid=false;
|
|
this->mHardenTime = gpGlobals->time + BALANCE_VAR(kWebWarmupTime);
|
|
this->pev->nextthink = gpGlobals->time + kWebThinkInterval;
|
|
SetThink(&AvHWebStrand::StrandThink);
|
|
|
|
this->RelinkBeam();
|
|
|
|
EMIT_SOUND(ENT(this->pev), CHAN_AUTO, kWebStrandFormSound, 1.0, ATTN_IDLE);
|
|
|
|
}
|
|
|
|
void AvHWebStrand::StrandThink()
|
|
{
|
|
TraceResult Hit;
|
|
|
|
Vector StartTrace = this->GetStartPos();
|
|
Vector EndTrace = this->GetEndPos();
|
|
|
|
UTIL_TraceLine(StartTrace, EndTrace, dont_ignore_monsters, nullptr, &Hit);
|
|
|
|
if (!FNullEnt(Hit.pHit))
|
|
{
|
|
edict_t* webbedEdict = Hit.pHit;
|
|
AvHPlayer* theWebbedPlayer = dynamic_cast<AvHPlayer*>(CBaseEntity::Instance(webbedEdict));
|
|
|
|
if (theWebbedPlayer)
|
|
{
|
|
StrandTouch(theWebbedPlayer);
|
|
}
|
|
}
|
|
|
|
if (!this->mSolid)
|
|
{
|
|
if (gpGlobals->time >= this->mHardenTime)
|
|
{
|
|
EMIT_SOUND(ENT(this->pev), CHAN_AUTO, kWebStrandHardenSound, 1.0, ATTN_IDLE);
|
|
this->SetBrightness(32);
|
|
this->SetColor(255, 255, 255);
|
|
this->SetFrame(1);
|
|
this->mSolid = true;
|
|
}
|
|
}
|
|
|
|
this->pev->nextthink = gpGlobals->time + kWebThinkInterval;
|
|
|
|
}
|
|
void AvHWebStrand::StrandExpire()
|
|
{
|
|
this->Break();
|
|
}
|
|
|
|
|
|
void AvHWebStrand::StrandTouch( CBaseEntity *pOther )
|
|
{
|
|
// Webs can never break on friendlies
|
|
//if(GetGameRules()->CanEntityDoDamageTo(this, pOther))
|
|
if (pOther->pev->team != this->pev->team)
|
|
{
|
|
if ( this->mSolid ) {
|
|
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(pOther);
|
|
if(thePlayer && thePlayer->GetCanBeAffectedByEnemies())
|
|
{
|
|
// Break web and ensnare player if possible (players can't be too webbed)
|
|
if(thePlayer->SetEnsnareState(true))
|
|
{
|
|
this->Break();
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
this->Break();
|
|
}
|
|
}
|
|
}
|
|
|
|
int AvHWebStrand::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
|
|
{
|
|
float theDamage = 0;
|
|
|
|
//if(bitsDamageType == DMG_SLASH)
|
|
//{
|
|
theDamage = flDamage;
|
|
//}
|
|
|
|
if(!pevAttacker)
|
|
{
|
|
pevAttacker = pevInflictor;
|
|
}
|
|
|
|
if(!pevInflictor)
|
|
{
|
|
pevInflictor = pevAttacker;
|
|
}
|
|
|
|
return CBeam::TakeDamage(pevInflictor, pevAttacker, theDamage, bitsDamageType);
|
|
}
|
|
|
|
|
|
|
|
const float kResourceThinkInterval = 1.0f;
|
|
|
|
AvHFuncResource::AvHFuncResource()
|
|
{
|
|
this->mParticleSystemIndex = -1;
|
|
this->mOccupied = false;
|
|
this->mLastTimeDrawnUpon = -1;
|
|
}
|
|
|
|
void AvHFuncResource::DeleteParticleSystem()
|
|
{
|
|
int theParticleSystemIndex = this->GetParticleSystemIndex();
|
|
if(theParticleSystemIndex != -1)
|
|
{
|
|
AvHParticleSystemEntity* theParticleSystemEntity = NULL;
|
|
if(AvHSUGetEntityFromIndex(theParticleSystemIndex, theParticleSystemEntity))
|
|
{
|
|
ASSERT(theParticleSystemEntity);
|
|
|
|
UTIL_Remove(theParticleSystemEntity);
|
|
this->mParticleSystemIndex = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//int AvHFuncResource::ObjectCaps(void)
|
|
//{
|
|
// return FCAP_CONTINUOUS_USE;
|
|
//}
|
|
|
|
void AvHFuncResource::DrawUse(CBaseEntity* inActivator, CBaseEntity* inCaller, USE_TYPE useType, float value)
|
|
{
|
|
// If nozzle is unoccupied
|
|
if(!this->mOccupied)
|
|
{
|
|
// Check if gorge is using nozzle
|
|
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(inActivator);
|
|
if(thePlayer && thePlayer->GetIsRelevant() && (thePlayer->GetUser3() == AVH_USER3_ALIEN_PLAYER2))
|
|
{
|
|
// Check interval. It slows down as the gorge becomes full. Automatically allows multiple gorges feeding off the same node to balance out (guy with less will hog node, then they should ping back and forth).
|
|
float thePlayerResources = thePlayer->GetResources();
|
|
float theDrawMinInterval = BALANCE_VAR(kDrawMinInterval);
|
|
float theDrawMaxInterval = BALANCE_VAR(kDrawMaxInterval);
|
|
float theDrawInterval = theDrawMinInterval + (theDrawMaxInterval - theDrawMinInterval)*(thePlayerResources/kMaxAlienResources);
|
|
if((this->mLastTimeDrawnUpon == -1) || (gpGlobals->time > (this->mLastTimeDrawnUpon + theDrawInterval)))
|
|
{
|
|
// Give gorge some resources
|
|
float theDrawAmount = BALANCE_VAR(kDrawAmount);
|
|
thePlayer->SetResources(thePlayer->GetResources() + theDrawAmount);
|
|
|
|
// Play animation
|
|
thePlayer->PlayerConstructUse();
|
|
|
|
// Play sound
|
|
AvHSUPlayRandomConstructionEffect(thePlayer, this);
|
|
|
|
// Remember this
|
|
this->mLastTimeDrawnUpon = gpGlobals->time;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHFuncResource::TurnOffParticleSystem()
|
|
{
|
|
int theParticleSystemIndex = this->GetParticleSystemIndex();
|
|
if(theParticleSystemIndex != -1)
|
|
{
|
|
AvHParticleSystemEntity* theParticleSystemEntity = NULL;
|
|
if(AvHSUGetEntityFromIndex(theParticleSystemIndex, theParticleSystemEntity))
|
|
{
|
|
ASSERT(theParticleSystemEntity);
|
|
theParticleSystemEntity->SetUseState(USE_OFF);
|
|
|
|
//UTIL_Remove(theParticleSystemEntity);
|
|
//this->mParticleSystemIndex = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHFuncResource::TurnOnParticleSystem()
|
|
{
|
|
int theParticleSystemIndex = this->GetParticleSystemIndex();
|
|
if(theParticleSystemIndex == -1)
|
|
{
|
|
uint32 theTemplateIndex;
|
|
if(gParticleTemplateList.GetTemplateIndexWithName(kpsResourceEmission, theTemplateIndex))
|
|
{
|
|
edict_t *pent;
|
|
AvHParticleSystemEntity* thePSEntity;
|
|
|
|
pent = CREATE_NAMED_ENTITY(MAKE_STRING(kesParticles));
|
|
if ( FNullEnt( pent ) )
|
|
{
|
|
ALERT ( at_console, "NULL Ent in Create!\n" );
|
|
ASSERT(false);
|
|
}
|
|
|
|
thePSEntity = dynamic_cast<AvHParticleSystemEntity*>(CBaseEntity::Instance(pent));
|
|
ASSERT(thePSEntity);
|
|
thePSEntity->SetTemplateIndex(theTemplateIndex);
|
|
|
|
Vector thePosition;
|
|
thePosition.x = (this->pev->absmax.x + this->pev->absmin.x)/2.0f;
|
|
thePosition.y = (this->pev->absmax.y + this->pev->absmin.y)/2.0f;
|
|
thePosition.z = (this->pev->absmax.z + this->pev->absmin.z)/2.0f;
|
|
|
|
thePSEntity->pev->origin = thePosition;
|
|
thePSEntity->pev->angles = this->pev->angles;
|
|
|
|
DispatchSpawn(thePSEntity->edict());
|
|
|
|
this->mParticleSystemIndex = thePSEntity->entindex();
|
|
}
|
|
}
|
|
|
|
if(theParticleSystemIndex != -1)
|
|
{
|
|
AvHParticleSystemEntity* theParticleSystemEntity = NULL;
|
|
if(AvHSUGetEntityFromIndex(theParticleSystemIndex, theParticleSystemEntity))
|
|
{
|
|
ASSERT(theParticleSystemEntity);
|
|
theParticleSystemEntity->SetUseState(USE_ON);
|
|
|
|
//UTIL_Remove(theParticleSystemEntity);
|
|
//this->mParticleSystemIndex = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AvHFuncResource::FuncResourceThink()
|
|
{
|
|
// If we don't have a resource tower, and we haven't created a particle system
|
|
if(!this->mOccupied)
|
|
{
|
|
this->TurnOnParticleSystem();
|
|
}
|
|
|
|
//SetUse(&AvHFuncResource::DrawUse);
|
|
|
|
this->pev->nextthink = gpGlobals->time + kResourceThinkInterval;
|
|
}
|
|
|
|
bool AvHFuncResource::GetIsActive() const
|
|
{
|
|
return this->mActive;
|
|
}
|
|
|
|
|
|
bool AvHFuncResource::GetIsOccupied() const
|
|
{
|
|
return this->mOccupied;
|
|
}
|
|
|
|
int AvHFuncResource::GetParticleSystemIndex() const
|
|
{
|
|
return this->mParticleSystemIndex;
|
|
}
|
|
|
|
void AvHFuncResource::KeyValue( KeyValueData* pkvd )
|
|
{
|
|
if (FStrEq(pkvd->szKeyName, "targetOnBuild"))
|
|
{
|
|
this->mTargetOnBuild = pkvd->szValue;
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else if (FStrEq(pkvd->szKeyName, "targetOnDestroy"))
|
|
{
|
|
this->mTargetOnDestroy = pkvd->szValue;
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
CBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void AvHFuncResource::Precache()
|
|
{
|
|
CBaseAnimating::Precache();
|
|
PRECACHE_UNMODIFIED_MODEL((char*)STRING(this->pev->model));
|
|
}
|
|
|
|
void AvHFuncResource::ResetEntity()
|
|
{
|
|
// Set user3 in case it was removed when resource was destroyed
|
|
this->pev->iuser3 = AVH_USER3_FUNC_RESOURCE;
|
|
|
|
// Reset our properties back to original unharvested settings
|
|
this->mOccupied = false;
|
|
this->DeleteParticleSystem();
|
|
|
|
this->mLastTimeDrawnUpon = -1;
|
|
}
|
|
|
|
void AvHFuncResource::Spawn()
|
|
{
|
|
this->Precache();
|
|
|
|
this->pev->solid = SOLID_BBOX;
|
|
this->pev->movetype = MOVETYPE_TOSS;
|
|
|
|
SET_MODEL(ENT(this->pev), STRING(this->pev->model));
|
|
// set size and link into world
|
|
// UTIL_SetOrigin(pev, pev->origin);
|
|
|
|
// DROP_TO_FLOOR(ENT(pev));
|
|
|
|
//this->pev->solid = SOLID_TRIGGER;
|
|
|
|
this->pev->classname = MAKE_STRING(kesFuncResource);
|
|
|
|
// Set health greater then 0 so it seems "alive" (won't be needed when buildings can be selected, allows research to continue)
|
|
this->pev->health = 1;
|
|
this->pev->max_health = pev->health;
|
|
this->pev->takedamage = DAMAGE_NO;
|
|
|
|
// For some reason, drop before setting size
|
|
DROP_TO_FLOOR(ENT(pev));
|
|
|
|
UTIL_SetOrigin(this->pev, this->pev->origin);
|
|
UTIL_SetSize(this->pev, kFuncResourceMinSize, kFuncResourceMaxSize);
|
|
|
|
this->pev->iuser3 = AVH_USER3_FUNC_RESOURCE;
|
|
|
|
SetUpgradeMask(&this->pev->iuser4, MASK_SELECTABLE);
|
|
|
|
SetThink(&AvHFuncResource::FuncResourceThink);
|
|
this->pev->nextthink = gpGlobals->time + kResourceThinkInterval;
|
|
}
|
|
|
|
void AvHFuncResource::TriggerOccupy()
|
|
{
|
|
this->mOccupied = true;
|
|
}
|
|
|
|
void AvHFuncResource::TriggerBuild()
|
|
{
|
|
this->mActive = true;
|
|
if(this->mTargetOnBuild != "")
|
|
{
|
|
FireTargets(this->mTargetOnBuild.c_str(), NULL, NULL, USE_TOGGLE, 0.0f);
|
|
}
|
|
|
|
this->TurnOffParticleSystem();
|
|
}
|
|
|
|
void AvHFuncResource::TriggerDestroy()
|
|
{
|
|
this->mActive = false;
|
|
this->mOccupied = false;
|
|
|
|
if(this->mTargetOnDestroy != "")
|
|
{
|
|
FireTargets(this->mTargetOnDestroy.c_str(), NULL, NULL, USE_TOGGLE, 0.0f);
|
|
}
|
|
}
|
|
|
|
|
|
AvHFog::AvHFog()
|
|
{
|
|
this->mFogColor[0] = this->mFogColor[1] = this->mFogColor[2] = 255;
|
|
this->mFogStart = 0;
|
|
this->mFogEnd = 1000;
|
|
this->mFogExpireTime = 1.0f;
|
|
}
|
|
|
|
void AvHFog::KeyValue(KeyValueData* pkvd)
|
|
{
|
|
if(FStrEq(pkvd->szKeyName, "fogcolor"))
|
|
{
|
|
if(sscanf(pkvd->szValue, "%d %d %d", this->mFogColor + 0, this->mFogColor + 1, this->mFogColor + 2) == 3)
|
|
{
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "fogstart"))
|
|
{
|
|
if(sscanf(pkvd->szValue, "%f", &this->mFogStart) == 1)
|
|
{
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "fogend"))
|
|
{
|
|
if(sscanf(pkvd->szValue, "%f", &this->mFogEnd) == 1)
|
|
{
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(pkvd->szKeyName, "fogexpire"))
|
|
{
|
|
if(sscanf(pkvd->szValue, "%f", &this->mFogExpireTime) == 1)
|
|
{
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void AvHFog::FogTouch(CBaseEntity* inEntity)
|
|
{
|
|
AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(inEntity);
|
|
if(thePlayer)
|
|
{
|
|
thePlayer->TriggerFog(this->entindex(), this->mFogExpireTime);
|
|
}
|
|
}
|
|
|
|
void AvHFog::GetFogColor(int& outRed, int& outGreen, int& outBlue) const
|
|
{
|
|
outRed = this->mFogColor[0];
|
|
outGreen = this->mFogColor[1];
|
|
outBlue = this->mFogColor[2];
|
|
}
|
|
|
|
float AvHFog::GetFogEnd() const
|
|
{
|
|
return this->mFogEnd;
|
|
}
|
|
|
|
float AvHFog::GetFogStart() const
|
|
{
|
|
return this->mFogStart;
|
|
}
|
|
|
|
void AvHFog::Spawn()
|
|
{
|
|
this->Precache();
|
|
|
|
// Don't show model but still allow triggering of it
|
|
CBaseEntity::Spawn();
|
|
|
|
this->pev->movetype = MOVETYPE_NONE;
|
|
this->pev->solid = SOLID_TRIGGER;
|
|
|
|
SET_MODEL(ENT(pev), STRING(pev->model));
|
|
this->pev->effects = EF_NODRAW;
|
|
|
|
// Set touch
|
|
SetTouch(&AvHFog::FogTouch);
|
|
}
|
|
|
|
|
|
|
|
AvHResourceTower::AvHResourceTower() : AvHBaseBuildable(TECH_NULL, BUILD_RESOURCES, kwsResourceTower, AVH_USER3_RESTOWER)
|
|
{
|
|
this->mResourceEntityIndex = -1;
|
|
this->mTechLevel = 1;
|
|
this->mTimeLastContributed = -1;
|
|
this->mTimeOfLastSound = -1;
|
|
this->mActivateTime = 0;
|
|
}
|
|
|
|
AvHResourceTower::AvHResourceTower(AvHTechID inTechID, AvHMessageID inMessageID, char* inClassName, int inUser4) : AvHBaseBuildable(inTechID, inMessageID, inClassName, inUser4)
|
|
{
|
|
this->mResourceEntityIndex = -1;
|
|
this->mTechLevel = 1;
|
|
}
|
|
|
|
int AvHResourceTower::GetSequenceForBoundingBox() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
// Called at end of deploy animation
|
|
void AvHResourceTower::ActivateThink()
|
|
{
|
|
// Set regular think, but don't start for a little bit
|
|
SetThink(&AvHResourceTower::ResourceTowerThink);
|
|
this->pev->nextthink = gpGlobals->time + 4.0f;
|
|
this->mTimeOfLastSound = -1;
|
|
this->mScannedForFuncResource = false;
|
|
}
|
|
|
|
float AvHResourceTower::GetTimeLastContributed()
|
|
{
|
|
return this->mTimeLastContributed;
|
|
}
|
|
|
|
char* AvHResourceTower::GetActiveSoundList() const
|
|
{
|
|
return kResourceTowerSoundList;
|
|
}
|
|
|
|
int AvHResourceTower::GetPointValue() const
|
|
{
|
|
return BALANCE_VAR(kScoringResourceTowerValue);
|
|
}
|
|
|
|
void AvHResourceTower::SetTimeLastContributed(float inTime)
|
|
{
|
|
this->mTimeLastContributed = inTime;
|
|
}
|
|
|
|
int AvHResourceTower::GetIdleAnimation() const
|
|
{
|
|
int theIdleAnimation = -1;
|
|
|
|
if(this->GetIsBuilt())
|
|
{
|
|
theIdleAnimation = this->GetActiveAnimation();
|
|
}
|
|
|
|
return theIdleAnimation;
|
|
}
|
|
|
|
void AvHResourceTower::ResourceTowerThink(void)
|
|
{
|
|
if(this->GetIsBuilt())
|
|
{
|
|
// Check if
|
|
if((this->mTimeOfLastSound == -1) || ((gpGlobals->time - this->mTimeOfLastSound) > kResourceTowerMinSoundInterval))
|
|
{
|
|
if(RANDOM_LONG(0, 3) == 1)
|
|
{
|
|
char* theSoundList = this->GetActiveSoundList();
|
|
if(theSoundList)
|
|
{
|
|
gSoundListManager.PlaySoundInList(theSoundList, this, CHAN_BODY, .2f);
|
|
this->mTimeOfLastSound = gpGlobals->time;
|
|
}
|
|
}
|
|
}
|
|
|
|
AvHFuncResource* theFuncResource= this->GetHostResource();
|
|
if(theFuncResource)
|
|
{
|
|
theFuncResource->TriggerBuild();
|
|
}
|
|
|
|
AvHBaseBuildable::AnimateThink();
|
|
}
|
|
|
|
this->pev->nextthink = gpGlobals->time + .05f;
|
|
}
|
|
|
|
AvHFuncResource* AvHResourceTower::GetHostResource() const
|
|
{
|
|
AvHFuncResource* theFuncResource = NULL;
|
|
|
|
if(this->mResourceEntityIndex > 0)
|
|
{
|
|
// Look up func_resource
|
|
edict_t* theEdict = g_engfuncs.pfnPEntityOfEntIndex(this->mResourceEntityIndex);
|
|
if(!theEdict->free)
|
|
{
|
|
CBaseEntity* theEntity = CBaseEntity::Instance(theEdict);
|
|
if(theEntity)
|
|
{
|
|
theFuncResource = dynamic_cast<AvHFuncResource*>(theEntity);
|
|
}
|
|
}
|
|
}
|
|
|
|
return theFuncResource;
|
|
}
|
|
|
|
bool AvHResourceTower::GetIsActive() const
|
|
{
|
|
bool theIsActive = false;
|
|
|
|
if(this->GetIsBuilt() && this->pev && !GetHasUpgrade(this->pev->iuser4, MASK_RECYCLING))
|
|
{
|
|
theIsActive = true;
|
|
}
|
|
|
|
return theIsActive;
|
|
}
|
|
|
|
|
|
int AvHResourceTower::GetMaxHitPoints() const
|
|
{
|
|
return 200;
|
|
}
|
|
|
|
int AvHResourceTower::GetResourceEntityIndex() const
|
|
{
|
|
return this->mResourceEntityIndex;
|
|
}
|
|
|
|
int AvHResourceTower::GetTechLevel() const
|
|
{
|
|
return this->mTechLevel;
|
|
}
|
|
|
|
void AvHResourceTower::Killed(entvars_t* pevAttacker, int iGib)
|
|
{
|
|
AvHBaseBuildable::Killed(pevAttacker, iGib);
|
|
|
|
// Look up AvHFuncResource and tell it to reset
|
|
AvHFuncResource* theHostResource = this->GetHostResource();
|
|
if(theHostResource)
|
|
{
|
|
theHostResource->TriggerDestroy();
|
|
}
|
|
|
|
// Play death sequence
|
|
this->PlayAnimationAtIndex(this->GetKilledAnimation());
|
|
}
|
|
|
|
void AvHResourceTower::Precache(void)
|
|
{
|
|
AvHBaseBuildable::Precache();
|
|
|
|
//PRECACHE_SOUND(this->GetHarvestSound());
|
|
PRECACHE_UNMODIFIED_SOUND(this->GetDeploySound());
|
|
PRECACHE_UNMODIFIED_MODEL(this->GetModelName());
|
|
}
|
|
|
|
void AvHResourceTower::SetActivateTime(int inTime)
|
|
{
|
|
this->mActivateTime = inTime;
|
|
}
|
|
|
|
void AvHResourceTower::SetHasBeenBuilt()
|
|
{
|
|
AvHBuildable::SetHasBeenBuilt();
|
|
|
|
// Set time for end of animation
|
|
SetThink(&AvHResourceTower::ActivateThink);
|
|
//this->pev->nextthink = gpGlobals->time + 8.0f;
|
|
|
|
this->mTimeLastContributed = this->pev->nextthink = (gpGlobals->time + this->mActivateTime);
|
|
}
|
|
|
|
void AvHResourceTower::Spawn()
|
|
{
|
|
AvHBaseBuildable::Spawn();
|
|
|
|
this->mTimeLastContributed = gpGlobals->time;
|
|
|
|
this->mActivateTime = BALANCE_VAR(kResourceTowerActivateTime);
|
|
|
|
//Claim ourselves a func_resource immediately and set it occupied
|
|
if(!this->mScannedForFuncResource && (this->mResourceEntityIndex <= 0))
|
|
{
|
|
float theNearestDistance = 10000000;
|
|
int theFuncResourceID = -1;
|
|
|
|
// Find nearest unoccupied func_resource and set the building's resource id
|
|
FOR_ALL_ENTITIES(kesFuncResource, AvHFuncResource*)
|
|
if(!theEntity->GetIsOccupied())
|
|
{
|
|
float theDistance = VectorDistance(theEntity->pev->origin, this->pev->origin);
|
|
if(theDistance < theNearestDistance)
|
|
{
|
|
theNearestDistance = theDistance;
|
|
theFuncResourceID = theEntity->entindex();
|
|
}
|
|
}
|
|
END_FOR_ALL_ENTITIES(kesFuncResource)
|
|
|
|
if(theFuncResourceID != -1)
|
|
{
|
|
this->mResourceEntityIndex = theFuncResourceID;
|
|
|
|
AvHFuncResource* theFuncResource= this->GetHostResource();
|
|
if(theFuncResource)
|
|
{
|
|
theFuncResource->TriggerOccupy();
|
|
}
|
|
}
|
|
|
|
this->mScannedForFuncResource = true;
|
|
}
|
|
}
|
|
|
|
void AvHResourceTower::Upgrade()
|
|
{
|
|
AvHFuncResource* theFuncResource = this->GetHostResource();
|
|
|
|
// Increment our tech level
|
|
this->mTechLevel++;
|
|
}
|
|
|
|
char* AvHResourceTower::GetClassName() const
|
|
{
|
|
return kwsResourceTower;
|
|
}
|
|
|
|
//char* AvHResourceTower::GetHarvestSound() const
|
|
//{
|
|
// return kResourceTowerHarvestSound;
|
|
//}
|
|
|
|
char* AvHResourceTower::GetDeploySound() const
|
|
{
|
|
return kResourceTowerDeploySound;
|
|
}
|
|
|
|
char* AvHResourceTower::GetModelName() const
|
|
{
|
|
return kResourceTowerModel;
|
|
}
|
|
|
|
|
|
void AvHInfoLocation::KeyValue(KeyValueData* pkvd)
|
|
{
|
|
// Look for name
|
|
if(FStrEq(pkvd->szKeyName, "locationname"))
|
|
{
|
|
if(pkvd->szValue != "")
|
|
{
|
|
this->mLocationName = string(pkvd->szValue);
|
|
pkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CBaseEntity::KeyValue(pkvd);
|
|
}
|
|
}
|
|
|
|
void AvHInfoLocation::Spawn()
|
|
{
|
|
// If we have a valid name
|
|
if(this->mLocationName != "")
|
|
{
|
|
// Set model, size, hook into world
|
|
SET_MODEL(ENT(this->pev), STRING(this->pev->model));
|
|
this->pev->movetype = MOVETYPE_NONE;
|
|
this->pev->solid = SOLID_NOT;
|
|
UTIL_SetOrigin(this->pev, this->pev->origin);
|
|
|
|
// Set as nodraw
|
|
this->pev->effects |= EF_NODRAW;
|
|
|
|
// Compute min and max
|
|
this->mMaxExtent = this->pev->maxs;
|
|
this->mMinExtent = this->pev->mins;
|
|
}
|
|
else
|
|
{
|
|
// Mark for removal
|
|
UTIL_Remove(this);
|
|
}
|
|
}
|
|
|
|
void AvHInfoLocation::UpdateOnRemove(void)
|
|
{
|
|
int a = 0;
|
|
}
|
|
|