summaryrefslogtreecommitdiff
path: root/game/client/tf/c_tf_halloween.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/c_tf_halloween.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/client/tf/c_tf_halloween.cpp')
-rw-r--r--game/client/tf/c_tf_halloween.cpp416
1 files changed, 416 insertions, 0 deletions
diff --git a/game/client/tf/c_tf_halloween.cpp b/game/client/tf/c_tf_halloween.cpp
new file mode 100644
index 0000000..42884d6
--- /dev/null
+++ b/game/client/tf/c_tf_halloween.cpp
@@ -0,0 +1,416 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+#include "cbase.h"
+
+#include "c_tf_player.h"
+#include "collisionutils.h"
+#include "econ_item_inventory.h"
+#include "iclientmode.h"
+#include "tf_gcmessages.h"
+#include "tf_gamerules.h"
+#include "econ_notifications.h"
+#include "rtime.h"
+#include "achievementmgr.h"
+#include "baseachievement.h"
+#include "achievements_tf.h"
+#include "gc_clientsystem.h"
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+EHalloweenMap GetHalloweenMap()
+{
+ if ( FStrEq( engine->GetLevelName(), "maps/cp_manor_event.bsp" ) )
+ return kHalloweenMap_MannManor;
+
+ if ( FStrEq( engine->GetLevelName(), "maps/koth_viaduct_event.bsp" ) )
+ return kHalloweenMap_Viaduct;
+
+ if ( FStrEq( engine->GetLevelName(), "maps/koth_lakeside_event.bsp" ) )
+ return kHalloweenMap_Lakeside;
+
+ if ( FStrEq( engine->GetLevelName(), "maps/plr_hightower_event.bsp" ) )
+ return kHalloweenMap_Hightower;
+
+ return kHalloweenMapCount;
+}
+
+
+//-----------------------------------------------------------------------------
+// Created when the GC decides to give out an item.
+// A player must intersect the item to claim it.
+//-----------------------------------------------------------------------------
+#define HALLOWEEN_ITEM_TIME_TO_READY 10.0f
+class C_HalloweenItemPickup : public CBaseAnimating
+{
+ DECLARE_CLASS( C_HalloweenItemPickup, CBaseAnimating );
+public:
+ C_HalloweenItemPickup()
+ : m_bReadyForPickup( false )
+ , m_bClaimed( false )
+ , m_flTimeToReady( 0.0f )
+ {
+ AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
+ }
+
+ virtual ~C_HalloweenItemPickup()
+ {
+ }
+
+ bool Initialize()
+ {
+ const char *pszModelName = "models/props_halloween/halloween_gift.mdl";
+ SetModelName( AllocPooledString( pszModelName ) );
+
+ if ( InitializeAsClientEntity( STRING(GetModelName()), RENDER_GROUP_OPAQUE_ENTITY ) == false )
+ return false;
+
+ const model_t *mod = GetModel();
+ if ( mod )
+ {
+ Vector mins, maxs;
+ modelinfo->GetModelBounds( mod, mins, maxs );
+ SetCollisionBounds( mins, maxs );
+ }
+
+ Spawn();
+
+ // initialize as translucent
+ float alpha = 0.0f;
+ SetRenderMode( kRenderTransTexture );
+ SetRenderColorA( alpha * 256 );
+ m_flTimeToReady = gpGlobals->realtime + HALLOWEEN_ITEM_TIME_TO_READY;
+
+ UpdatePartitionListEntry();
+
+ SetBlocksLOS( false ); // this should be a small object
+
+ // Set up shadows; do it here so that objects can change shadowcasting state
+ CreateShadow();
+
+ UpdateVisibility();
+
+ SetNextClientThink( CLIENT_THINK_ALWAYS );
+
+ return true;
+ }
+
+ virtual void Spawn()
+ {
+ Precache();
+ BaseClass::Spawn();
+ SetSolid( SOLID_NONE );
+ AddSolidFlags( FSOLID_NOT_SOLID );
+ SetMoveType( MOVETYPE_NONE );
+ }
+
+ virtual void ClientThink()
+ {
+ if ( m_bReadyForPickup )
+ {
+ ClientThink_Active();
+ return;
+ }
+
+ float flTimeDelta = m_flTimeToReady - gpGlobals->realtime;
+ if ( flTimeDelta < 0 )
+ {
+ m_bReadyForPickup = true;
+ ParticleProp()->Create( "halloween_pickup_active", PATTACH_ABSORIGIN_FOLLOW );
+ SetRenderMode( kRenderNormal );
+ }
+ else
+ {
+ float alpha = 0.75f * ( ( HALLOWEEN_ITEM_TIME_TO_READY - flTimeDelta ) / HALLOWEEN_ITEM_TIME_TO_READY );
+ SetRenderColorA( alpha * 256 );
+ }
+ }
+
+ void ClientThink_Active( void )
+ {
+ Vector vWorldMins = WorldAlignMins();
+ Vector vWorldMaxs = WorldAlignMaxs();
+ Vector vBoxMin1 = GetAbsOrigin() + vWorldMins;
+ Vector vBoxMax1 = GetAbsOrigin() + vWorldMaxs;
+
+ float flBestDistance2 = 0.0f;
+ CSteamID bestSteamID;
+ bool bBestHasNoclip = false;
+
+#define CLIENT_HALLOWEEN_LOGIC_ENABLE_LOCAL_PLAYER_ONLY 1
+
+#if !CLIENT_HALLOWEEN_LOGIC_ENABLE_LOCAL_PLAYER_ONLY
+ for( int iPlayerIndex = 1 ; iPlayerIndex <= MAX_PLAYERS; iPlayerIndex++ )
+ {
+ C_TFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( iPlayerIndex ) );
+#else
+ do
+ {
+ C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
+#endif
+ CSteamID steamID;
+ if ( pPlayer == NULL || pPlayer->IsBot() == true || pPlayer->GetSteamID( &steamID ) == false ||
+ ( pPlayer->GetTeamNumber() != TF_TEAM_RED && pPlayer->GetTeamNumber() != TF_TEAM_BLUE ) ||
+ pPlayer->IsAlive() == false ||
+ pPlayer->GetObserverMode() != OBS_MODE_NONE )
+ {
+ continue;
+ }
+
+ Vector vPlayerMins = pPlayer->GetAbsOrigin() + pPlayer->WorldAlignMins();
+ Vector vPlayerMaxs = pPlayer->GetAbsOrigin() + pPlayer->WorldAlignMaxs();
+ bool bIntersecting = IsBoxIntersectingBox( vBoxMin1, vBoxMax1, vPlayerMins, vPlayerMaxs );
+ float flDistance2 = ( pPlayer->GetAbsOrigin(), GetAbsOrigin() ).LengthSqr();
+ if ( bIntersecting && ( bestSteamID.GetAccountID() == 0 || flDistance2 < flBestDistance2 ) )
+ {
+ bestSteamID = steamID;
+ bBestHasNoclip = pPlayer->GetMoveType() == MOVETYPE_NOCLIP;
+ flBestDistance2 = flDistance2;
+ }
+ }
+#if CLIENT_HALLOWEEN_LOGIC_ENABLE_LOCAL_PLAYER_ONLY
+ while ( false );
+#endif
+
+ if ( bestSteamID.GetAccountID() != 0 )
+ {
+ GCSDK::CProtoBufMsg<CMsgGC_Halloween_GrantItem> msg( k_EMsgGC_Halloween_GrantItem );
+ msg.Body().set_recipient_account_id( bestSteamID.GetAccountID() );
+ msg.Body().set_level_id( GetHalloweenMap() );
+ msg.Body().set_flagged( bBestHasNoclip );
+ GCClientSystem()->BSendMessage( msg );
+ OnClaimed( true );
+ return;
+ }
+
+ SetNextClientThink( gpGlobals->curtime + 0.33f );
+ }
+
+ void OnClaimed( bool bPlayAudio )
+ {
+ if ( m_bClaimed )
+ return;
+
+ m_bClaimed = true;
+ // stop thinking and remove sparkle...
+ ParticleProp()->StopParticlesNamed( "halloween_pickup_active", true );
+ SetNextClientThink( CLIENT_THINK_NEVER );
+ // throw up bday confetti
+ DispatchParticleEffect( "halloween_gift_pickup", GetAbsOrigin(), vec3_angle );
+
+ if ( bPlayAudio )
+ {
+ C_BaseEntity::EmitSound( "Game.HappyBirthday" );
+ }
+ SetRenderMode( kRenderNone );
+ UpdateVisibility();
+ }
+
+ bool m_bReadyForPickup;
+ bool m_bClaimed;
+ float m_flTimeToReady;
+};
+
+LINK_ENTITY_TO_CLASS( tf_halloween_item_pickup, C_HalloweenItemPickup );
+PRECACHE_REGISTER( tf_halloween_item_pickup );
+
+static EHANDLE gHalloweenPickup;
+
+#ifdef _DEBUG
+CON_COMMAND( cl_halloween_test_cheating, "Test cheating the halloween pickup" )
+{
+ GCSDK::CProtoBufMsg< CMsgGC_Halloween_GrantItem > msg( k_EMsgGC_Halloween_GrantItem );
+ msg.Body().set_recipient_account_id( steamapicontext->SteamUser()->GetSteamID().GetAccountID() );
+ GCClientSystem()->BSendMessage( msg );
+}
+
+CON_COMMAND( cl_halloween_test_spawn_pickup, "Test spawning the pickup item" )
+{
+ C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+ if ( pLocalPlayer == NULL )
+ return;
+
+ // Now create the pickup item
+ C_HalloweenItemPickup *pEntity = new C_HalloweenItemPickup();
+ if ( !pEntity )
+ return;
+
+ Vector vecTargetPoint;
+ trace_t tr;
+ Vector forward;
+ pLocalPlayer->EyeVectors( &forward );
+ UTIL_TraceLine( pLocalPlayer->EyePosition(),
+ pLocalPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_NPCSOLID,
+ pLocalPlayer, COLLISION_GROUP_NONE, &tr );
+
+ if ( tr.fraction != 1.0 )
+ {
+ vecTargetPoint = tr.endpos;
+ }
+
+ pEntity->SetAbsOrigin( vecTargetPoint );
+ if ( !pEntity->Initialize() )
+ {
+ pEntity->Release();
+ }
+ else
+ {
+ if ( gHalloweenPickup.Get() )
+ gHalloweenPickup->Release();
+ gHalloweenPickup = pEntity;
+ }
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// GC has decided to drop a Halloween item
+//-----------------------------------------------------------------------------
+//class CGCHalloween_ReservedItem : public GCSDK::CGCClientJob
+//{
+//public:
+// CGCHalloween_ReservedItem( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
+//
+// virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
+// {
+// GCSDK::CProtoBufMsg<CMsgGC_Halloween_ReservedItem> msg( pNetPacket );
+//
+// // Figure out which level we're on so we know how to handle notifications, etc.
+// EHalloweenMap eMap = GetHalloweenMap();
+// if ( eMap == kHalloweenMapCount )
+// return true;
+//
+// // Sanity-check the message contents from the GC.
+// if ( msg.Body().x_size() != msg.Body().y_size() || msg.Body().y_size() != msg.Body().z_size() )
+// return true;
+//
+// if ( msg.Body().x_size() <= eMap )
+// return true;
+//
+// // Don't spawn gifts during startup.
+// if ( TFGameRules() == NULL
+// || TFGameRules()->State_Get() != GR_STATE_RND_RUNNING
+// || TFGameRules()->InSetup()
+// || TFGameRules()->IsInWaitingForPlayers()
+// || TFGameRules()->ArePlayersInHell() ) // Dont spawn gifts if players are in 2013 Hell
+// return true;
+//
+// C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
+// if ( pLocalPlayer == NULL )
+// return true;
+//
+// // If we don't already know about this gift pickup, create one.
+// if ( gHalloweenPickup.Get() == NULL )
+// {
+// // Now create the pickup item
+// C_HalloweenItemPickup *pEntity = new C_HalloweenItemPickup();
+// if ( !pEntity )
+// return true;
+//
+// Vector position( msg.Body().x( eMap ), msg.Body().y( eMap ), msg.Body().z( eMap ) );
+// pEntity->SetAbsOrigin( position );
+// if ( !pEntity->Initialize() )
+// {
+// pEntity->Release();
+// }
+// else
+// {
+// gHalloweenPickup = pEntity;
+// }
+// }
+//
+// // Regardless of whether we created a new gift or whether this was a new notification about an old gift,
+// // display a UI notification for the user.
+// CEconNotification *pNotification = new CEconNotification();
+// pNotification->SetText( "#TF_HalloweenItem_Reserved" );
+// pNotification->SetLifetime( 15.0f );
+// pNotification->SetSoundFilename( "ui/halloween_loot_spawn.wav" );
+// NotificationQueue_Add( pNotification );
+//
+// return true;
+// }
+//};
+//GC_REG_JOB( GCSDK::CGCClient, CGCHalloween_ReservedItem, "CGCHalloween_ReservedItem", k_EMsgGC_Halloween_ReservedItem, GCSDK::k_EServerTypeGCClient );
+
+//-----------------------------------------------------------------------------
+// GC gave out the Halloween item to a player
+//-----------------------------------------------------------------------------
+//class CGCHalloween_GrantedItemResponse : public GCSDK::CGCClientJob
+//{
+//public:
+// CGCHalloween_GrantedItemResponse( GCSDK::CGCClient *pClient ) : GCSDK::CGCClientJob( pClient ) {}
+//
+// virtual bool BYieldingRunGCJob( GCSDK::IMsgNetPacket *pNetPacket )
+// {
+// GCSDK::CProtoBufMsg<CMsgGC_Halloween_GrantItemResponse> msg( pNetPacket );
+//
+// // which Steam universe are we in?
+// EUniverse eUniverse = steamapicontext && steamapicontext->SteamUtils()
+// ? steamapicontext->SteamUtils()->GetConnectedUniverse()
+// : k_EUniverseInvalid;
+//
+// CSteamID steamIDRecipient( msg.Body().recipient_account_id(), eUniverse, k_EAccountTypeIndividual );
+// bool bIsValidRecipient = steamIDRecipient.IsValid();
+//
+// if ( gHalloweenPickup.Get() != NULL )
+// {
+// assert_cast<C_HalloweenItemPickup *>( gHalloweenPickup.Get() )->OnClaimed( bIsValidRecipient );
+// gHalloweenPickup->Release();
+// gHalloweenPickup = NULL;
+// }
+//
+// // don't do any work if we're not on a Halloween map
+// EHalloweenMap eMap = GetHalloweenMap();
+// if ( eMap == kHalloweenMapCount )
+// return true;
+//
+// // add alert
+// const char* pPlayerName = InventoryManager()->PersonaName_Get( steamIDRecipient.GetAccountID() );
+// wchar_t wszPlayerName[MAX_PLAYER_NAME_LENGTH] = L"";
+// if ( pPlayerName != NULL && FStrEq( pPlayerName, "" ) == false )
+// {
+// g_pVGuiLocalize->ConvertANSIToUnicode( pPlayerName, wszPlayerName, sizeof(wszPlayerName) );
+// }
+// CEconNotification *pNotification = new CEconNotification();
+// pNotification->SetLifetime( 15.0f );
+//
+// if ( bIsValidRecipient )
+// {
+// pNotification->SetText( "#TF_HalloweenItem_Granted" );
+// pNotification->AddStringToken( "recipient", wszPlayerName );
+// pNotification->SetSteamID( steamIDRecipient );
+// pNotification->SetSoundFilename( "ui/halloween_loot_found.wav" );
+// }
+// else
+// {
+// pNotification->SetText( "#TF_HalloweenItem_GrantPickupFail" );
+// // pNotification->SetSoundFilename( "coach/coach_student_died.wav" );
+// }
+//
+// NotificationQueue_Add( pNotification );
+//
+// // is this the local player? award the achievement...
+// if ( steamapicontext && steamapicontext->SteamUser() )
+// {
+// CSteamID localSteamID = steamapicontext->SteamUser()->GetSteamID();
+// if ( steamIDRecipient == localSteamID )
+// {
+// g_AchievementMgrTF.OnAchievementEvent( ACHIEVEMENT_TF_HALLOWEEN_COLLECT_GOODY_BAG );
+// }
+// }
+//
+// return true;
+// }
+//};
+//GC_REG_JOB( GCSDK::CGCClient, CGCHalloween_GrantedItemResponse, "CGCHalloween_GrantedItemResponse", k_EMsgGC_Halloween_GrantItemResponse, GCSDK::k_EServerTypeGCClient );
+
+
+//-----------------------------------------------------------------------------
+
+void CL_Halloween_LevelShutdown()
+{
+ gHalloweenPickup = NULL;
+}