diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/tfc/tfc_gamerules.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/shared/tfc/tfc_gamerules.cpp')
| -rw-r--r-- | game/shared/tfc/tfc_gamerules.cpp | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/game/shared/tfc/tfc_gamerules.cpp b/game/shared/tfc/tfc_gamerules.cpp new file mode 100644 index 0000000..20e208d --- /dev/null +++ b/game/shared/tfc/tfc_gamerules.cpp @@ -0,0 +1,422 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The TF Game rules +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "tfc_gamerules.h" +#include "ammodef.h" +#include "KeyValues.h" +#include "weapon_tfcbase.h" + + +#ifdef CLIENT_DLL + + #include "c_tfc_player.h" + +#else + + #include "voice_gamemgr.h" + #include "team.h" + #include "tfc_bot_temp.h" + #include "tfc_player.h" + #include "tfc_timer.h" + #include "tfc_team.h" + +#endif + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +#ifndef CLIENT_DLL +LINK_ENTITY_TO_CLASS(info_player_terrorist, CPointEntity); +LINK_ENTITY_TO_CLASS(info_player_counterterrorist,CPointEntity); +#endif + +REGISTER_GAMERULES_CLASS( CTFCGameRules ); + + +BEGIN_NETWORK_TABLE_NOBASE( CTFCGameRules, DT_TFCGameRules ) +END_NETWORK_TABLE() + + +LINK_ENTITY_TO_CLASS( tfc_gamerules, CTFCGameRulesProxy ); +IMPLEMENT_NETWORKCLASS_ALIASED( TFCGameRulesProxy, DT_TFCGameRulesProxy ) + + +#ifdef CLIENT_DLL + void RecvProxy_TFCGameRules( const RecvProp *pProp, void **pOut, void *pData, int objectID ) + { + CTFCGameRules *pRules = TFCGameRules(); + Assert( pRules ); + *pOut = pRules; + } + + BEGIN_RECV_TABLE( CTFCGameRulesProxy, DT_TFCGameRulesProxy ) + RecvPropDataTable( "tfc_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_TFCGameRules ), RecvProxy_TFCGameRules ) + END_RECV_TABLE() +#else + void *SendProxy_TFCGameRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) + { + CTFCGameRules *pRules = TFCGameRules(); + Assert( pRules ); + pRecipients->SetAllRecipients(); + return pRules; + } + + BEGIN_SEND_TABLE( CTFCGameRulesProxy, DT_TFCGameRulesProxy ) + SendPropDataTable( "tfc_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_TFCGameRules ), SendProxy_TFCGameRules ) + END_SEND_TABLE() +#endif + + +ConVar mp_fadetoblack( + "mp_fadetoblack", + "0", + FCVAR_REPLICATED, + "fade a player's screen to black when he dies" ); + + +// (We clamp ammo ourselves elsewhere). +ConVar ammo_max( "ammo_max", "5000", FCVAR_REPLICATED ); + + +CTFCGameRules::CTFCGameRules() +{ + CTF_Map = true; + +#ifdef GAME_DLL + // Create the team managers + for ( int i = 0; i < ARRAYSIZE( teamnames ); i++ ) + { + CTeam *pTeam = static_cast<CTeam*>(CreateEntityByName( "tfc_team_manager" )); + pTeam->Init( teamnames[i], i ); + + g_Teams.AddToTail( pTeam ); + } +#endif +} + + +#ifdef CLIENT_DLL + + +#else + + + int cease_fire; + int no_cease_fire_text; + + + // --------------------------------------------------------------------------------------------------- // + // Voice helper + // --------------------------------------------------------------------------------------------------- // + + class CVoiceGameMgrHelper : public IVoiceGameMgrHelper + { + public: + virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker ) + { + // Dead players can only be heard by other dead team mates + if ( pTalker->IsAlive() == false ) + { + if ( pListener->IsAlive() == false ) + return ( pListener->InSameTeam( pTalker ) ); + + return false; + } + + return ( pListener->InSameTeam( pTalker ) ); + } + }; + CVoiceGameMgrHelper g_VoiceGameMgrHelper; + IVoiceGameMgrHelper *g_pVoiceGameMgrHelper = &g_VoiceGameMgrHelper; + + + + // --------------------------------------------------------------------------------------------------- // + // Globals. + // --------------------------------------------------------------------------------------------------- // + + // NOTE: the indices here must match TEAM_TERRORIST, TEAM_CT, TEAM_SPECTATOR, etc. + char *sTeamNames[] = + { + "Unassigned", + "Spectator", + "Terrorist", + "Counter-Terrorist" + }; + + + // --------------------------------------------------------------------------------------------------- // + // Global helper functions. + // --------------------------------------------------------------------------------------------------- // + + // World.cpp calls this but we don't use it in TFC. + void InitBodyQue() + { + } + + //----------------------------------------------------------------------------- + // Purpose: + //----------------------------------------------------------------------------- + CTFCGameRules::~CTFCGameRules() + { + // Note, don't delete each team since they are in the gEntList and will + // automatically be deleted from there, instead. + g_Teams.Purge(); + } + + //----------------------------------------------------------------------------- + // Purpose: TF2 Specific Client Commands + // Input : + // Output : + //----------------------------------------------------------------------------- + bool CTFCGameRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) + { + CTFCPlayer *pPlayer = ToTFCPlayer( pEdict ); + + if( pPlayer->ClientCommand( args ) ) + return true; + + return BaseClass::ClientCommand( pEdict, args ); + } + + //----------------------------------------------------------------------------- + // Purpose: Player has just spawned. Equip them. + //----------------------------------------------------------------------------- + + void CTFCGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore ) + { + RadiusDamage( info, vecSrcIn, flRadius, iClassIgnore, false ); + } + + // Add the ability to ignore the world trace + void CTFCGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld ) + { + CBaseEntity *pEntity = NULL; + trace_t tr; + float flAdjustedDamage, falloff; + Vector vecSpot; + Vector vecToTarget; + Vector vecEndPos; + + Vector vecSrc = vecSrcIn; + + if ( flRadius ) + falloff = info.GetDamage() / flRadius; + else + falloff = 1.0; + + int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false; + + vecSrc.z += 1;// in case grenade is lying on the ground + + // iterate on all entities in the vicinity. + for ( CEntitySphereQuery sphere( vecSrc, flRadius ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() ) + { + if ( pEntity->m_takedamage != DAMAGE_NO ) + { + // UNDONE: this should check a damage mask, not an ignore + if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) + {// houndeyes don't hurt other houndeyes with their attack + continue; + } + + // blast's don't tavel into or out of water + if (bInWater && pEntity->GetWaterLevel() == 0) + continue; + if (!bInWater && pEntity->GetWaterLevel() == 3) + continue; + + // radius damage can only be blocked by the world + vecSpot = pEntity->BodyTarget( vecSrc ); + + + + bool bHit = false; + + if( bIgnoreWorld ) + { + vecEndPos = vecSpot; + bHit = true; + } + else + { + UTIL_TraceLine( vecSrc, vecSpot, MASK_SOLID_BRUSHONLY, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); + + if (tr.startsolid) + { + // if we're stuck inside them, fixup the position and distance + tr.endpos = vecSrc; + tr.fraction = 0.0; + } + + vecEndPos = tr.endpos; + + if( tr.fraction == 1.0 || tr.m_pEnt == pEntity ) + { + bHit = true; + } + } + + if ( bHit ) + { + // the explosion can 'see' this entity, so hurt them! + //vecToTarget = ( vecSrc - vecEndPos ); + vecToTarget = ( vecEndPos - vecSrc ); + + // decrease damage for an ent that's farther from the bomb. + flAdjustedDamage = vecToTarget.Length() * falloff; + flAdjustedDamage = info.GetDamage() - flAdjustedDamage; + + if ( flAdjustedDamage > 0 ) + { + CTakeDamageInfo adjustedInfo = info; + adjustedInfo.SetDamage( flAdjustedDamage ); + + Vector dir = vecToTarget; + VectorNormalize( dir ); + + // If we don't have a damage force, manufacture one + if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin ) + { + CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc, 1.5 /* explosion scale! */ ); + } + else + { + // Assume the force passed in is the maximum force. Decay it based on falloff. + float flForce = adjustedInfo.GetDamageForce().Length() * falloff; + adjustedInfo.SetDamageForce( dir * flForce ); + adjustedInfo.SetDamagePosition( vecSrc ); + } + + pEntity->TakeDamage( adjustedInfo ); + + // Now hit all triggers along the way that respond to damage... + pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, vecEndPos, dir ); + } + } + } + } + } + + void CTFCGameRules::Think() + { + Timer_UpdateAll(); + + BaseClass::Think(); + } + + const char *CTFCGameRules::GetChatPrefix( bool bTeamOnly, CBasePlayer *pPlayer ) + { + return "(chat prefix)"; + } + + + bool CTFCGameRules::IsInPreMatch() const + { + // TFCTODO return (cb_prematch_time > gpGlobals->time) + return false; + } + + float CTFCGameRules::GetPreMatchEndTime() const + { + //TFCTODO: implement this. + return gpGlobals->curtime; + } + + void CTFCGameRules::TFCGoToIntermission() + { + // TFCTODO: implement this. + Assert( false ); + } + + +#endif + + +bool CTFCGameRules::ShouldCollide( int collisionGroup0, int collisionGroup1 ) +{ + if ( collisionGroup0 > collisionGroup1 ) + { + // swap so that lowest is always first + swap(collisionGroup0,collisionGroup1); + } + + //Don't stand on COLLISION_GROUP_WEAPONs + if( collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT && + collisionGroup1 == COLLISION_GROUP_WEAPON ) + { + return false; + } + + if ( collisionGroup0 == COLLISION_GROUP_PLAYER ) + { + // Players don't collide with objects or other players + if ( collisionGroup1 == COLLISION_GROUP_PLAYER ) + return false; + } + + if ( collisionGroup1 == COLLISION_GROUP_PLAYER_MOVEMENT ) + { + // This is only for probing, so it better not be on both sides!!! + Assert( collisionGroup0 != COLLISION_GROUP_PLAYER_MOVEMENT ); + + // No collide with players any more + // Nor with objects or grenades + switch ( collisionGroup0 ) + { + default: + break; + case COLLISION_GROUP_PLAYER: + return false; + } + } + + return BaseClass::ShouldCollide( collisionGroup0, collisionGroup1 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Init CS ammo definitions +//----------------------------------------------------------------------------- + +// shared ammo definition +// JAY: Trying to make a more physical bullet response +#define BULLET_MASS_GRAINS_TO_LB(grains) (0.002285*(grains)/16.0f) +#define BULLET_MASS_GRAINS_TO_KG(grains) lbs2kg(BULLET_MASS_GRAINS_TO_LB(grains)) + +// exaggerate all of the forces, but use real numbers to keep them consistent +#define BULLET_IMPULSE_EXAGGERATION 1 + +// convert a velocity in ft/sec and a mass in grains to an impulse in kg in/s +#define BULLET_IMPULSE(grains, ftpersec) ((ftpersec)*12*BULLET_MASS_GRAINS_TO_KG(grains)*BULLET_IMPULSE_EXAGGERATION) + + +CAmmoDef* GetAmmoDef() +{ + static CAmmoDef def; + static bool bInitted = false; + + if ( !bInitted ) + { + bInitted = true; + + // Start at 1 here and skip the dummy ammo type to make CAmmoDef use the same indices + // as our #defines. + for ( int i=1; i < TFC_NUM_AMMO_TYPES; i++ ) + { + def.AddAmmoType( g_AmmoTypeNames[i], DMG_BULLET, TRACER_LINE, 0, 0, "ammo_max", 2400, 10, 14 ); + Assert( def.Index( g_AmmoTypeNames[i] ) == i ); + } + } + + return &def; +} + + |