mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-09-01 15:09:19 +00:00
upload "kind" alien swarm
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
#include "cbase.h"
|
||||
#include "asw_bone_merge.h"
|
||||
#include "c_asw_weapon.h"
|
||||
#include "bone_setup.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Alien Swarm weapons use custom bone merge cache so they can pitch the guns up slightly
|
||||
void C_ASW_Weapon::CalcBoneMerge( CStudioHdr *hdr, int boneMask, CBoneBitList &boneComputed )
|
||||
{
|
||||
// For EF_BONEMERGE entities, copy the bone matrices for any bones that have matching names.
|
||||
bool boneMerge = IsEffectActive(EF_BONEMERGE);
|
||||
if ( boneMerge || m_pBoneMergeCache )
|
||||
{
|
||||
if ( boneMerge )
|
||||
{
|
||||
if ( !m_pBoneMergeCache )
|
||||
{
|
||||
m_pBoneMergeCache = new CASW_Bone_Merge_Cache;
|
||||
m_pBoneMergeCache->Init( this );
|
||||
}
|
||||
CASW_Bone_Merge_Cache *pASWBoneMergeCache = static_cast<CASW_Bone_Merge_Cache*>( m_pBoneMergeCache );
|
||||
pASWBoneMergeCache->MergeMatchingBones( boneMask, boneComputed, ShouldAlignWeaponToLaserPointer(), m_vecLaserPointerDirection );
|
||||
|
||||
int iAttachment = GetMuzzleAttachment();
|
||||
if ( iAttachment > 0 && m_pLaserPointerEffect )
|
||||
{
|
||||
Vector vecOrigin;
|
||||
QAngle angWeapon;
|
||||
GetAttachment( iAttachment, vecOrigin, angWeapon );
|
||||
m_pLaserPointerEffect->SetControlPoint( 1, vecOrigin );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete m_pBoneMergeCache;
|
||||
m_pBoneMergeCache = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConVar asw_weapon_pitch( "asw_weapon_pitch", "12", FCVAR_NONE );
|
||||
|
||||
|
||||
CASW_Bone_Merge_Cache::CASW_Bone_Merge_Cache()
|
||||
{
|
||||
m_nRightHandBoneID = -1;
|
||||
}
|
||||
|
||||
// apply custom pitch to bone merge
|
||||
void CASW_Bone_Merge_Cache::MergeMatchingBones( int boneMask, CBoneBitList &boneComputed, bool bOverrideDirection, const Vector &vecDir )
|
||||
{
|
||||
UpdateCache();
|
||||
|
||||
// If this is set, then all the other cache data is set.
|
||||
if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
|
||||
return;
|
||||
|
||||
// Have the entity we're following setup its bones.
|
||||
m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
|
||||
|
||||
matrix3x4_t matPitchUp;
|
||||
AngleMatrix( QAngle( asw_weapon_pitch.GetFloat(), 0, 0 ), matPitchUp );
|
||||
|
||||
// Now copy the bone matrices.
|
||||
for ( int i=0; i < m_MergedBones.Count(); i++ )
|
||||
{
|
||||
int iOwnerBone = m_MergedBones[i].m_iMyBone;
|
||||
int iParentBone = m_MergedBones[i].m_iParentBone;
|
||||
|
||||
// Only update bones reference by the bone mask.
|
||||
if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
|
||||
continue;
|
||||
|
||||
if ( bOverrideDirection && m_nRightHandBoneID == -1 ) // only want to change direction of the right hand bone, cache its index here
|
||||
{
|
||||
mstudiobone_t *pOwnerBones = m_pOwnerHdr->pBone( 0 );
|
||||
for ( int k = 0; k < m_pOwnerHdr->numbones(); k++ )
|
||||
{
|
||||
if ( !Q_stricmp( pOwnerBones[k].pszName(), "ValveBiped.Bip01_R_Hand" ) )
|
||||
{
|
||||
m_nRightHandBoneID = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bOverrideDirection && i == m_nRightHandBoneID )
|
||||
{
|
||||
matrix3x4_t matParentBoneToWorld;
|
||||
m_pFollow->GetBoneTransform( iParentBone, matParentBoneToWorld );
|
||||
MatrixSetColumn( vec3_origin, 3, matParentBoneToWorld ); // remove translation
|
||||
|
||||
matrix3x4_t matParentBoneToWorldInv;
|
||||
MatrixInvert( matParentBoneToWorld, matParentBoneToWorldInv );
|
||||
|
||||
QAngle angAiming;
|
||||
VectorAngles( vecDir, Vector( 0, 0, -1 ), angAiming );
|
||||
matrix3x4_t matAimDirection;
|
||||
AngleMatrix( angAiming, matAimDirection );
|
||||
MatrixSetColumn( vec3_origin, 3, matAimDirection ); // remove translation
|
||||
|
||||
matrix3x4_t matCorrection;
|
||||
ConcatTransforms( matParentBoneToWorldInv, matAimDirection, matCorrection );
|
||||
|
||||
ConcatTransforms( m_pFollow->GetBone( iParentBone ), matCorrection, m_pOwner->GetBoneForWrite( iOwnerBone ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ConcatTransforms( m_pFollow->GetBone( iParentBone ), matPitchUp, m_pOwner->GetBoneForWrite( iOwnerBone ) );
|
||||
}
|
||||
|
||||
boneComputed.Set( i );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef _INCLUDED_ASW_BONE_MERGE_H
|
||||
#define _INCLUDED_ASW_BONE_MERGE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "bone_merge_cache.h"
|
||||
|
||||
class CASW_Bone_Merge_Cache : public CBoneMergeCache
|
||||
{
|
||||
public:
|
||||
typedef CBoneMergeCache BaseClass;
|
||||
|
||||
CASW_Bone_Merge_Cache();
|
||||
|
||||
// This copies the transform from all bones in the followed entity that have
|
||||
// names that match our bones.
|
||||
virtual void MergeMatchingBones( int boneMask, CBoneBitList &boneComputed, bool bOverrideDirection, const Vector &vecDir );
|
||||
|
||||
int m_nRightHandBoneID;
|
||||
};
|
||||
|
||||
#endif //_INCLUDED_ASW_BONE_MERGE_H
|
||||
@@ -0,0 +1,893 @@
|
||||
#include "cbase.h"
|
||||
#include "asw_briefing.h"
|
||||
#include "c_asw_game_resource.h"
|
||||
#include "c_asw_marine_resource.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "asw_equipment_list.h"
|
||||
#include "asw_marine_profile.h"
|
||||
#include "asw_weapon_parse.h"
|
||||
#include <vgui/ILocalize.h>
|
||||
#include "c_playerresource.h"
|
||||
#include "asw_gamerules.h"
|
||||
#include "c_asw_campaign_save.h"
|
||||
#define CASW_Equip_Req C_ASW_Equip_Req
|
||||
#include "asw_equip_req.h"
|
||||
#include "voice_status.h"
|
||||
#include "asw_campaign_info.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern ConVar asw_ignore_need_two_player_requirement;
|
||||
|
||||
CASW_Briefing* g_pBriefing = NULL;
|
||||
|
||||
IBriefing* Briefing()
|
||||
{
|
||||
if ( !g_pBriefing )
|
||||
{
|
||||
// could return different briefings here to support briefing outside of a map
|
||||
g_pBriefing = new CASW_Briefing();
|
||||
}
|
||||
return g_pBriefing;
|
||||
}
|
||||
|
||||
CASW_Briefing::CASW_Briefing()
|
||||
{
|
||||
m_nLastLobbySlotMappingFrame = -1;
|
||||
m_flLastSelectionChatterTime = 0.0f;
|
||||
}
|
||||
|
||||
CASW_Briefing::~CASW_Briefing()
|
||||
{
|
||||
if ( g_pBriefing == this )
|
||||
{
|
||||
g_pBriefing = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Briefing::UpdateLobbySlotMapping()
|
||||
{
|
||||
if ( m_nLastLobbySlotMappingFrame == gpGlobals->framecount ) // don't update twice in one frame
|
||||
return;
|
||||
|
||||
m_nLastLobbySlotMappingFrame = gpGlobals->framecount;
|
||||
|
||||
if ( !ASWGameResource() )
|
||||
return;
|
||||
|
||||
C_ASW_Player *pLocalPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pLocalPlayer )
|
||||
return;
|
||||
|
||||
if ( IsOfflineGame() )
|
||||
{
|
||||
// just map marine resources to slots directly
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources() && i < NUM_BRIEFING_LOBBY_SLOTS; i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR )
|
||||
{
|
||||
if ( i == 0 )
|
||||
{
|
||||
m_LobbySlotMapping[ i ].m_nPlayerEntIndex = pLocalPlayer->entindex();
|
||||
m_LobbySlotMapping[ i ].m_hPlayer = pLocalPlayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LobbySlotMapping[ i ].m_nPlayerEntIndex = -1;
|
||||
m_LobbySlotMapping[ i ].m_hPlayer = NULL;
|
||||
}
|
||||
m_LobbySlotMapping[ i ].m_nMarineResourceIndex = -1;
|
||||
m_LobbySlotMapping[ i ].m_hMR = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_LobbySlotMapping[ i ].m_nPlayerEntIndex = pLocalPlayer->entindex();
|
||||
m_LobbySlotMapping[ i ].m_hPlayer = pLocalPlayer;
|
||||
m_LobbySlotMapping[ i ].m_nMarineResourceIndex = i;
|
||||
m_LobbySlotMapping[ i ].m_hMR = pMR;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// lobby slot 0 is always reserved for the local player
|
||||
m_LobbySlotMapping[ 0 ].m_nPlayerEntIndex = pLocalPlayer->entindex();
|
||||
m_LobbySlotMapping[ 0 ].m_hPlayer = pLocalPlayer;
|
||||
m_LobbySlotMapping[ 0 ].m_nMarineResourceIndex = -1;
|
||||
m_LobbySlotMapping[ 0 ].m_hMR = NULL;
|
||||
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR || pMR->GetCommander() != pLocalPlayer )
|
||||
continue;
|
||||
|
||||
m_LobbySlotMapping[ 0 ].m_nMarineResourceIndex = i;
|
||||
m_LobbySlotMapping[ 0 ].m_hMR = pMR;
|
||||
break;
|
||||
}
|
||||
|
||||
int nSlot = 1;
|
||||
|
||||
// if the player has any other marines selected, they come first
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR || pMR->GetCommander() != pLocalPlayer )
|
||||
continue;
|
||||
|
||||
bool bAlreadyInList = false;
|
||||
for ( int k = 0; k < nSlot; k++ )
|
||||
{
|
||||
if ( pMR == m_LobbySlotMapping[ k ].m_hMR.Get() )
|
||||
{
|
||||
bAlreadyInList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bAlreadyInList )
|
||||
continue;
|
||||
|
||||
m_LobbySlotMapping[ nSlot ].m_nPlayerEntIndex = pLocalPlayer->entindex();
|
||||
m_LobbySlotMapping[ nSlot ].m_hPlayer = pLocalPlayer;
|
||||
m_LobbySlotMapping[ nSlot ].m_hMR = pMR;
|
||||
m_LobbySlotMapping[ nSlot ].m_nMarineResourceIndex = i;
|
||||
|
||||
nSlot++;
|
||||
if ( nSlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( nSlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return;
|
||||
|
||||
// now add marines for other players in order
|
||||
for( int iClient = 1; iClient < MAX_PLAYERS; iClient++ )
|
||||
{
|
||||
if ( !g_PR->IsConnected( iClient ) )
|
||||
continue;
|
||||
|
||||
if ( iClient == pLocalPlayer->entindex() )
|
||||
continue;
|
||||
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR || pMR->m_iCommanderIndex != iClient )
|
||||
continue;
|
||||
|
||||
bool bAlreadyInList = false;
|
||||
for ( int k = 0; k < nSlot; k++ )
|
||||
{
|
||||
if ( pMR == m_LobbySlotMapping[ k ].m_hMR.Get() )
|
||||
{
|
||||
bAlreadyInList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bAlreadyInList )
|
||||
continue;
|
||||
|
||||
m_LobbySlotMapping[ nSlot ].m_nPlayerEntIndex = iClient;
|
||||
m_LobbySlotMapping[ nSlot ].m_hPlayer = static_cast<C_ASW_Player*>( UTIL_PlayerByIndex( iClient ) );
|
||||
m_LobbySlotMapping[ nSlot ].m_hMR = pMR;
|
||||
m_LobbySlotMapping[ nSlot ].m_nMarineResourceIndex = i;
|
||||
|
||||
nSlot++;
|
||||
if ( nSlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( nSlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return;
|
||||
|
||||
// now add any players who don't have any marines
|
||||
for( int iClient = 1; iClient < MAX_PLAYERS; iClient++ )
|
||||
{
|
||||
if ( !g_PR->IsConnected( iClient ) )
|
||||
continue;
|
||||
|
||||
if ( iClient == pLocalPlayer->entindex() )
|
||||
continue;
|
||||
|
||||
int nMarines = 0;
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR || pMR->m_iCommanderIndex != iClient )
|
||||
continue;
|
||||
|
||||
nMarines++;
|
||||
}
|
||||
|
||||
if ( nMarines == 0)
|
||||
{
|
||||
m_LobbySlotMapping[ nSlot ].m_nPlayerEntIndex = iClient;
|
||||
m_LobbySlotMapping[ nSlot ].m_hPlayer = static_cast<C_ASW_Player*>( UTIL_PlayerByIndex( iClient ) );
|
||||
m_LobbySlotMapping[ nSlot ].m_hMR = NULL;
|
||||
m_LobbySlotMapping[ nSlot ].m_nMarineResourceIndex = -1;
|
||||
|
||||
nSlot++;
|
||||
if ( nSlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( int k = nSlot; k < NUM_BRIEFING_LOBBY_SLOTS; k++ )
|
||||
{
|
||||
m_LobbySlotMapping[ k ].m_nPlayerEntIndex = -1;
|
||||
m_LobbySlotMapping[ k ].m_hPlayer = NULL;
|
||||
m_LobbySlotMapping[ k ].m_hMR = NULL;
|
||||
m_LobbySlotMapping[ k ].m_nMarineResourceIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int CASW_Briefing::LobbySlotToMarineResourceIndex( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return -1;
|
||||
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
return m_LobbySlotMapping[ nLobbySlot ].m_nMarineResourceIndex;
|
||||
}
|
||||
|
||||
const char* CASW_Briefing::GetLeaderName()
|
||||
{
|
||||
if ( !ASWGameResource() )
|
||||
return "";
|
||||
|
||||
C_ASW_Player *pLeader = ASWGameResource()->GetLeader();
|
||||
if ( !pLeader )
|
||||
return "";
|
||||
|
||||
return pLeader->GetPlayerName();
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsLocalPlayerLeader()
|
||||
{
|
||||
if ( !ASWGameResource() )
|
||||
return false;
|
||||
|
||||
C_ASW_Player *pLeader = ASWGameResource()->GetLeader();
|
||||
if ( !pLeader )
|
||||
return false;
|
||||
|
||||
return pLeader == C_ASW_Player::GetLocalASWPlayer();
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsLobbySlotOccupied( int nLobbySlot )
|
||||
{
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
return m_LobbySlotMapping[ nLobbySlot ].m_nPlayerEntIndex != -1;
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsLobbySlotLocal( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot == 0 || IsOfflineGame() ) // first slot is always the local player
|
||||
return true;
|
||||
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
if ( !pMR )
|
||||
return false;
|
||||
|
||||
return pMR->GetCommander() && ( pMR->GetCommander() == C_ASW_Player::GetLocalASWPlayer() );
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsLobbySlotBot( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS || !IsLobbySlotOccupied( nLobbySlot ) )
|
||||
return false;
|
||||
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
|
||||
bool bHuman = ( pMR == NULL );
|
||||
|
||||
if ( pMR )
|
||||
{
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
C_ASW_Marine_Resource *pFirstMR = pPlayer ? ASWGameResource()->GetFirstMarineResourceForPlayer( pPlayer ) : NULL;
|
||||
|
||||
if ( pFirstMR == pMR )
|
||||
{
|
||||
bHuman = true;
|
||||
}
|
||||
}
|
||||
return !bHuman;
|
||||
}
|
||||
|
||||
wchar_t* CASW_Briefing::GetMarineOrPlayerName( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS || !IsLobbySlotOccupied( nLobbySlot ) )
|
||||
return L"";
|
||||
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
|
||||
bool bUsePlayerName = ( pMR == NULL );
|
||||
|
||||
if ( pMR )
|
||||
{
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
C_ASW_Marine_Resource *pFirstMR = pPlayer ? ASWGameResource()->GetFirstMarineResourceForPlayer( pPlayer ) : NULL;
|
||||
|
||||
if ( pFirstMR == pMR )
|
||||
{
|
||||
bUsePlayerName = true;
|
||||
}
|
||||
}
|
||||
else if ( !bUsePlayerName )
|
||||
{
|
||||
// no marine and no player name to use, return blank
|
||||
return L"";
|
||||
}
|
||||
|
||||
|
||||
static wchar_t wszMarineNameResult[ 32 ];
|
||||
|
||||
// if it's their first marine, show the commander name instead
|
||||
if ( bUsePlayerName )
|
||||
{
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return L"";
|
||||
|
||||
const char *pszPlayerName = pPlayer->GetPlayerName();
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pszPlayerName ? pszPlayerName : "", wszMarineNameResult, sizeof( wszMarineNameResult ) );
|
||||
return wszMarineNameResult;
|
||||
}
|
||||
|
||||
pMR->GetDisplayName( wszMarineNameResult, sizeof( wszMarineNameResult ) );
|
||||
return wszMarineNameResult;
|
||||
}
|
||||
|
||||
wchar_t* CASW_Briefing::GetMarineName( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS || !IsLobbySlotOccupied( nLobbySlot ) )
|
||||
return L"";
|
||||
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
if ( !pMR )
|
||||
return L"";
|
||||
|
||||
static wchar_t wszMarineNameResult[ 32 ];
|
||||
|
||||
pMR->GetDisplayName( wszMarineNameResult, sizeof( wszMarineNameResult ) );
|
||||
return wszMarineNameResult;
|
||||
}
|
||||
|
||||
const char* CASW_Briefing::GetPlayerNameForMarineProfile( int nProfileIndex )
|
||||
{
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR )
|
||||
continue;
|
||||
|
||||
if ( pMR->GetProfileIndex() == nProfileIndex )
|
||||
{
|
||||
C_ASW_Player *pPlayer = pMR->GetCommander();
|
||||
if ( pPlayer )
|
||||
{
|
||||
return pPlayer->GetPlayerName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
#if !defined(NO_STEAM)
|
||||
CSteamID CASW_Briefing::GetCommanderSteamID( int nLobbySlot )
|
||||
{
|
||||
CSteamID invalid_result;
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return invalid_result;
|
||||
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return invalid_result;
|
||||
|
||||
int iIndex = pPlayer->entindex();
|
||||
player_info_t pi;
|
||||
if ( engine->GetPlayerInfo(iIndex, &pi) )
|
||||
{
|
||||
if ( pi.friendsID )
|
||||
{
|
||||
CSteamID steamIDForPlayer( pi.friendsID, 1, steamapicontext->SteamUtils()->GetConnectedUniverse(), k_EAccountTypeIndividual );
|
||||
return steamIDForPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
return invalid_result;
|
||||
}
|
||||
#endif
|
||||
|
||||
int CASW_Briefing::GetCommanderLevel( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return -1;
|
||||
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return -1;
|
||||
|
||||
return pPlayer->GetLevel();
|
||||
}
|
||||
|
||||
int CASW_Briefing::GetCommanderXP( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return -1;
|
||||
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return -1;
|
||||
|
||||
return pPlayer->GetExperience();
|
||||
}
|
||||
|
||||
int CASW_Briefing::GetCommanderPromotion( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return -1;
|
||||
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return -1;
|
||||
|
||||
return pPlayer->GetPromotion();
|
||||
}
|
||||
|
||||
ASW_Marine_Class CASW_Briefing::GetMarineClass( int nLobbySlot )
|
||||
{
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
if ( !pMR || !pMR->GetProfile() )
|
||||
return MARINE_CLASS_UNDEFINED;
|
||||
|
||||
return pMR->GetProfile()->GetMarineClass();
|
||||
}
|
||||
|
||||
CASW_Marine_Profile *CASW_Briefing::GetMarineProfile( int nLobbySlot )
|
||||
{
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
if ( !pMR )
|
||||
return NULL;
|
||||
|
||||
return pMR->GetProfile();
|
||||
}
|
||||
|
||||
CASW_Marine_Profile *CASW_Briefing::GetMarineProfileByProfileIndex( int nProfileIndex )
|
||||
{
|
||||
if ( !MarineProfileList() )
|
||||
return NULL;
|
||||
|
||||
return MarineProfileList()->GetProfile( nProfileIndex );
|
||||
}
|
||||
|
||||
int CASW_Briefing::GetProfileSelectedWeapon( int nProfileIndex, int nWeaponSlot )
|
||||
{
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR )
|
||||
continue;
|
||||
|
||||
if ( pMR->GetProfileIndex() == nProfileIndex )
|
||||
{
|
||||
return pMR->m_iWeaponsInSlots[ nWeaponSlot ];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CASW_Briefing::GetMarineSelectedWeapon( int nLobbySlot, int nWeaponSlot )
|
||||
{
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
if ( !pMR || nWeaponSlot < 0 || nWeaponSlot >= ASW_NUM_INVENTORY_SLOTS )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pMR->m_iWeaponsInSlots[ nWeaponSlot ];
|
||||
}
|
||||
|
||||
const char* CASW_Briefing::GetMarineWeaponClass( int nLobbySlot, int nWeaponSlot )
|
||||
{
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
if ( !pMR || nWeaponSlot < 0 || nWeaponSlot >= ASW_NUM_INVENTORY_SLOTS || !ASWEquipmentList() )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
CASW_EquipItem *pItem = ASWEquipmentList()->GetItemForSlot( nWeaponSlot, pMR->m_iWeaponsInSlots[ nWeaponSlot ] );
|
||||
if ( !pItem )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return STRING( pItem->m_EquipClass );
|
||||
}
|
||||
|
||||
int CASW_Briefing::GetCommanderReady( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return -1;
|
||||
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return true;
|
||||
|
||||
return ASWGameResource()->IsPlayerReady( pPlayer );
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsLeader( int nLobbySlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS )
|
||||
return -1;
|
||||
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return true;
|
||||
|
||||
return ( pPlayer == ASWGameResource()->GetLeader() );
|
||||
}
|
||||
|
||||
int CASW_Briefing::GetMarineSkillPoints( int nLobbySlot, int nSkillSlot )
|
||||
{
|
||||
if ( nLobbySlot < 0 || nLobbySlot >= NUM_BRIEFING_LOBBY_SLOTS || !ASWGameResource() )
|
||||
return -1;
|
||||
|
||||
int nMarineResourceIndex = LobbySlotToMarineResourceIndex( nLobbySlot );
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource() ? ASWGameResource()->GetMarineResource( nMarineResourceIndex ) : NULL;
|
||||
if ( !pMR )
|
||||
return -1;
|
||||
|
||||
return GetProfileSkillPoints( pMR->GetProfileIndex(), nSkillSlot );
|
||||
|
||||
}
|
||||
int CASW_Briefing::GetProfileSkillPoints( int nProfileIndex, int nSkillSlot )
|
||||
{
|
||||
if ( !ASWGameResource() )
|
||||
return -1;
|
||||
|
||||
return ASWGameResource()->GetMarineSkill( nProfileIndex, nSkillSlot );
|
||||
}
|
||||
|
||||
void CASW_Briefing::AutoSelectFullSquadForSingleplayer( int nFirstSelectedProfileIndex )
|
||||
{
|
||||
if ( !MarineProfileList() )
|
||||
return;
|
||||
|
||||
CASW_Marine_Profile* pFirstSelectedProfile = MarineProfileList()->GetProfile( nFirstSelectedProfileIndex );
|
||||
if ( !pFirstSelectedProfile )
|
||||
return;
|
||||
|
||||
ASW_Marine_Class nMarineClasses[]=
|
||||
{
|
||||
MARINE_CLASS_NCO,
|
||||
MARINE_CLASS_SPECIAL_WEAPONS,
|
||||
MARINE_CLASS_MEDIC,
|
||||
MARINE_CLASS_TECH
|
||||
};
|
||||
|
||||
// select one of each class
|
||||
for ( int i = 0; i < NELEMS( nMarineClasses ); i++ )
|
||||
{
|
||||
if ( nMarineClasses[ i ] == pFirstSelectedProfile->GetMarineClass() )
|
||||
continue;
|
||||
|
||||
CASW_Marine_Profile* pProfile = NULL;
|
||||
for ( int p = 0; p < MarineProfileList()->m_NumProfiles; p++ )
|
||||
{
|
||||
pProfile = MarineProfileList()->GetProfile( p );
|
||||
if ( pProfile && pProfile->GetMarineClass() == nMarineClasses[i] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !pProfile )
|
||||
continue;
|
||||
|
||||
SelectMarine( 0, pProfile->m_ProfileIndex, -1 );
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Briefing::SelectMarine( int nOrder, int nProfileIndex, int nPreferredLobbySlot )
|
||||
{
|
||||
// for now, just select him
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
if ( IsOfflineGame() )
|
||||
{
|
||||
pPlayer->RosterSelectMarineForSlot( nProfileIndex, nPreferredLobbySlot );
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer->RosterSelectSingleMarine( nProfileIndex );
|
||||
}
|
||||
|
||||
if ( gpGlobals->curtime - m_flLastSelectionChatterTime < 1.0f )
|
||||
return;
|
||||
|
||||
CASW_Marine_Profile *pProfile = Briefing()->GetMarineProfileByProfileIndex( nProfileIndex );
|
||||
if ( pProfile )
|
||||
{
|
||||
char szSelectionSound[ CHATTER_STRING_SIZE ];
|
||||
V_snprintf( szSelectionSound, sizeof( szSelectionSound ), "%s%d", pProfile->m_Chatter[ CHATTER_SELECTION ], RandomInt( 0, pProfile->m_iChatterCount[ CHATTER_SELECTION ] - 1 ) );
|
||||
|
||||
CSoundParameters params;
|
||||
if ( C_BaseEntity::GetParametersForSound( szSelectionSound, params, NULL ) )
|
||||
{
|
||||
EmitSound_t playparams( params );
|
||||
playparams.m_nChannel = CHAN_STATIC;
|
||||
playparams.m_bEmitCloseCaption = false;
|
||||
|
||||
CLocalPlayerFilter filter;
|
||||
C_BaseEntity::EmitSound( filter, -1, playparams );
|
||||
|
||||
m_flLastSelectionChatterTime = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsWeaponUnlocked( const char *szWeaponClass )
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return true;
|
||||
|
||||
return pPlayer->IsWeaponUnlocked( szWeaponClass );
|
||||
}
|
||||
|
||||
void CASW_Briefing::SelectWeapon( int nProfileIndex, int nInventorySlot, int nEquipIndex )
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR )
|
||||
continue;
|
||||
|
||||
if ( pMR->GetProfileIndex() == nProfileIndex )
|
||||
{
|
||||
int nMarineResourceIndex = ASWGameResource()->GetIndexFor( pMR );
|
||||
pPlayer->LoadoutSelectEquip( nMarineResourceIndex, nInventorySlot, nEquipIndex );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Briefing::ToggleLocalPlayerReady()
|
||||
{
|
||||
engine->ClientCmd("cl_ready");
|
||||
}
|
||||
|
||||
bool CASW_Briefing::CheckMissionRequirements()
|
||||
{
|
||||
if ( ASWGameRules() && ASWGameRules()->GetGameState() < ASW_GS_DEBRIEF && ASWGameResource() )
|
||||
{
|
||||
if ( ASWGameRules()->m_bMissionRequiresTech )
|
||||
{
|
||||
bool bTech = false;
|
||||
for (int i=0;i<ASWGameResource()->GetMaxMarineResources();i++)
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource(i);
|
||||
if (pMR && pMR->GetProfile() && pMR->GetProfile()->CanHack())
|
||||
bTech = true;
|
||||
}
|
||||
if (!bTech)
|
||||
{
|
||||
// have the server print a message about needing a tech, so all can see
|
||||
engine->ClientCmd("cl_needtech");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
C_ASW_Equip_Req* pReq = C_ASW_Equip_Req::FindEquipReq();
|
||||
if (pReq)
|
||||
{
|
||||
if (pReq && !pReq->AreRequirementsMet())
|
||||
{
|
||||
// have the server print a message about needing equip, so all can see
|
||||
engine->ClientCmd("cl_needequip");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( !ASWGameResource()->AtLeastOneMarine() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ASWGameResource() && !asw_ignore_need_two_player_requirement.GetBool() )
|
||||
{
|
||||
CASW_Campaign_Info *pCampaign = ASWGameRules()->GetCampaignInfo();
|
||||
|
||||
char mapname[64];
|
||||
V_FileBase( engine->GetLevelName(), mapname, sizeof( mapname ) );
|
||||
|
||||
if ( pCampaign && pCampaign->GetMissionByMapName( mapname ) )
|
||||
{
|
||||
bool bNeedsMoreThanOneMarine = pCampaign->GetMissionByMapName( mapname )->m_bNeedsMoreThanOneMarine;
|
||||
if ( bNeedsMoreThanOneMarine )
|
||||
{
|
||||
// how many marines do we have?
|
||||
int numMarines = 0;
|
||||
for (int i=0;i<ASWGameResource()->GetMaxMarineResources();i++)
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource(i);
|
||||
if ( pMR && pMR->GetProfileIndex() >= 0 )
|
||||
numMarines++;
|
||||
}
|
||||
|
||||
if ( numMarines < 2 )
|
||||
{
|
||||
engine->ClientCmd("cl_needtwoplayers");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CASW_Briefing::AreOtherPlayersReady()
|
||||
{
|
||||
if ( !ASWGameResource() )
|
||||
return false;
|
||||
|
||||
C_ASW_Player *pLeader = ASWGameResource()->GetLeader();
|
||||
if ( !pLeader )
|
||||
return false;
|
||||
|
||||
return ASWGameResource()->AreAllOtherPlayersReady( pLeader->entindex() );
|
||||
}
|
||||
|
||||
void CASW_Briefing::StartMission()
|
||||
{
|
||||
engine->ClientCmd("cl_start");
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsProfileSelectedBySomeoneElse( int nProfileIndex )
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR )
|
||||
continue;
|
||||
|
||||
if ( pMR->GetProfileIndex() == nProfileIndex )
|
||||
{
|
||||
return ( pMR->GetCommander() != pPlayer );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsProfileSelected( int nProfileIndex )
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < ASWGameResource()->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource( i );
|
||||
if ( !pMR )
|
||||
continue;
|
||||
|
||||
if ( pMR->GetProfileIndex() == nProfileIndex )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int CASW_Briefing::GetMaxPlayers()
|
||||
{
|
||||
return gpGlobals->maxClients;
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsOfflineGame()
|
||||
{
|
||||
if ( !ASWGameResource() )
|
||||
return true;
|
||||
|
||||
return ASWGameResource()->IsOfflineGame();
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsCampaignGame()
|
||||
{
|
||||
return ASWGameResource() && ASWGameResource()->IsCampaignGame();
|
||||
}
|
||||
|
||||
bool CASW_Briefing::UsingFixedSkillPoints()
|
||||
{
|
||||
if ( !IsCampaignGame() || !ASWGameRules() || !ASWGameRules()->GetCampaignSave() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ASWGameRules()->GetCampaignSave()->UsingFixedSkillPoints();
|
||||
}
|
||||
|
||||
void CASW_Briefing::SetChangingWeaponSlot( int nWeaponSlot )
|
||||
{
|
||||
engine->ClientCmd( VarArgs( "cl_editing_slot %d", nWeaponSlot ) );
|
||||
}
|
||||
|
||||
int CASW_Briefing::GetChangingWeaponSlot( int nLobbySlot )
|
||||
{
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return 0;
|
||||
|
||||
return pPlayer->m_nChangingSlot.Get();
|
||||
}
|
||||
|
||||
bool CASW_Briefing::IsCommanderSpeaking( int nLobbySlot )
|
||||
{
|
||||
if ( gpGlobals->maxClients <= 1 )
|
||||
return false;
|
||||
|
||||
UpdateLobbySlotMapping();
|
||||
|
||||
C_ASW_Player *pPlayer = m_LobbySlotMapping[ nLobbySlot ].m_hPlayer.Get();
|
||||
if ( !pPlayer )
|
||||
return false;
|
||||
|
||||
CVoiceStatus *pVoiceMgr = GetClientVoiceMgr();
|
||||
if ( !pVoiceMgr )
|
||||
return false;
|
||||
|
||||
int index = pPlayer->entindex();
|
||||
bool bTalking = false;
|
||||
if ( pPlayer == C_ASW_Player::GetLocalASWPlayer() )
|
||||
{
|
||||
bTalking = pVoiceMgr->IsLocalPlayerSpeakingAboveThreshold( FirstValidSplitScreenSlot() );
|
||||
}
|
||||
else
|
||||
{
|
||||
bTalking = pVoiceMgr->IsPlayerSpeaking( index );
|
||||
}
|
||||
return bTalking;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#ifndef _INCLUDED_ASW_BRIEFING_H
|
||||
#define _INCLUDED_ASW_BRIEFING_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "ibriefing.h"
|
||||
|
||||
class C_ASW_Player;
|
||||
class C_ASW_Marine_Resource;
|
||||
|
||||
struct LobbySlotMapping_t
|
||||
{
|
||||
int m_nPlayerEntIndex;
|
||||
CHandle<C_ASW_Player> m_hPlayer;
|
||||
CHandle<C_ASW_Marine_Resource> m_hMR;
|
||||
int m_nMarineResourceIndex;
|
||||
};
|
||||
|
||||
class CASW_Briefing : public IBriefing
|
||||
{
|
||||
public:
|
||||
CASW_Briefing();
|
||||
~CASW_Briefing();
|
||||
|
||||
virtual const char* GetLeaderName();
|
||||
|
||||
virtual bool IsLocalPlayerLeader();
|
||||
virtual void ToggleLocalPlayerReady();
|
||||
virtual bool CheckMissionRequirements(); // do we have all the required classes/equips to start the mission?
|
||||
virtual bool AreOtherPlayersReady(); // is everyone except the leader ready?
|
||||
virtual void StartMission();
|
||||
virtual bool IsLobbySlotOccupied( int nLobbySlot );
|
||||
virtual bool IsLobbySlotLocal( int nLobbySlot );
|
||||
virtual bool IsLobbySlotBot( int nLobbySlot );
|
||||
virtual wchar_t* GetMarineOrPlayerName( int nLobbySlot );
|
||||
virtual wchar_t* GetMarineName( int nLobbySlot ); // always returns the marine's profile name
|
||||
virtual const char* GetPlayerNameForMarineProfile( int nProfileIndex );
|
||||
virtual int GetCommanderLevel( int nLobbySlot );
|
||||
virtual int GetCommanderXP( int nLobbySlot );
|
||||
virtual int GetCommanderPromotion( int nLobbySlot );
|
||||
#if !defined(NO_STEAM)
|
||||
CSteamID GetCommanderSteamID( int nLobbySlot );
|
||||
#endif
|
||||
virtual ASW_Marine_Class GetMarineClass( int nLobbySlot );
|
||||
virtual CASW_Marine_Profile *GetMarineProfile( int nLobbySlot );
|
||||
virtual CASW_Marine_Profile *GetMarineProfileByProfileIndex( int nProfileIndex );
|
||||
virtual int GetProfileSelectedWeapon( int nProfileIndex, int nWeaponSlot );
|
||||
virtual int GetMarineSelectedWeapon( int nLobbySlot, int nWeaponSlot );
|
||||
virtual const char* GetMarineWeaponClass( int nLobbySlot, int nWeaponSlot );
|
||||
virtual int GetCommanderReady( int nLobbySlot );
|
||||
virtual bool IsLeader( int nLobbySlot );
|
||||
virtual int GetMarineSkillPoints( int nLobbySlot, int nSkillSlot );
|
||||
virtual int GetProfileSkillPoints( int nProfileIndex, int nSkillSlot );
|
||||
virtual bool IsWeaponUnlocked( const char *szWeaponClass );
|
||||
virtual bool IsProfileSelectedBySomeoneElse( int nProfileIndex );
|
||||
virtual bool IsProfileSelected( int nProfileIndex );
|
||||
virtual int GetMaxPlayers();
|
||||
virtual bool IsOfflineGame();
|
||||
virtual bool IsCampaignGame();
|
||||
virtual bool UsingFixedSkillPoints();
|
||||
virtual void SetChangingWeaponSlot( int nWeaponSlot );
|
||||
virtual int GetChangingWeaponSlot( int nLobbySlot );
|
||||
virtual bool IsCommanderSpeaking( int nLobbySlot );
|
||||
|
||||
virtual void SelectMarine( int nOrder, int nProfileIndex, int nPreferredLobbySlot );
|
||||
virtual void SelectWeapon( int nProfileIndex, int nInventorySlot, int nEquipIndex );
|
||||
virtual void AutoSelectFullSquadForSingleplayer( int nFirstSelectedProfileIndex );
|
||||
|
||||
virtual void ResetLastChatterTime() { m_flLastSelectionChatterTime = 0.0f; }
|
||||
|
||||
int LobbySlotToMarineResourceIndex( int nLobbySlot );
|
||||
void UpdateLobbySlotMapping();
|
||||
|
||||
int m_nLastLobbySlotMappingFrame;
|
||||
LobbySlotMapping_t m_LobbySlotMapping[ NUM_BRIEFING_LOBBY_SLOTS ];
|
||||
|
||||
float m_flLastSelectionChatterTime;
|
||||
};
|
||||
|
||||
IBriefing *Briefing();
|
||||
|
||||
#endif // _INCLUDED_ASW_BRIEFING_H
|
||||
@@ -0,0 +1,36 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose : Singleton manager for color correction on the client
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include "asw_client_entities.h"
|
||||
#include "c_asw_camera_volume.h"
|
||||
#include "c_asw_snow_volume.h"
|
||||
#include "c_asw_scanner_noise.h"
|
||||
|
||||
static CASW_Client_Entities s_ASW_Client_Entities;
|
||||
|
||||
CASW_Client_Entities::CASW_Client_Entities()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CASW_Client_Entities::LevelInitPostEntity()
|
||||
{
|
||||
//C_ASW_Camera_Volume::RecreateAll();
|
||||
C_ASW_Snow_Volume::RecreateAll();
|
||||
//C_Sprite::RecreateAll();
|
||||
C_ASW_Scanner_Noise::RecreateAll();
|
||||
}
|
||||
|
||||
void CASW_Client_Entities::LevelShutdownPreEntity()
|
||||
{
|
||||
//C_ASW_Camera_Volume::DestroyAll();
|
||||
C_ASW_Snow_Volume::DestroyAll();
|
||||
//C_Sprite::DestroyAll();
|
||||
C_ASW_Scanner_Noise::DestroyAll();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose : Manages creating clientside entities
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef _INCLUDED_ASW_CLIENT_ENTITIES_H
|
||||
#define _INCLUDED_ASW_CLIENT_ENTITIES_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "igamesystem.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Manages creating clientside entities
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class CASW_Client_Entities : public CAutoGameSystem
|
||||
{
|
||||
// Inherited from IGameSystemPerFrame
|
||||
public:
|
||||
virtual char const *Name() { return "Infested clientside entities"; }
|
||||
|
||||
// Other public methods
|
||||
public:
|
||||
CASW_Client_Entities();
|
||||
virtual void LevelInitPostEntity();
|
||||
virtual void LevelShutdownPreEntity();
|
||||
};
|
||||
|
||||
|
||||
#endif // _INCLUDED_ASW_CLIENT_ENTITIES_H
|
||||
@@ -0,0 +1,44 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Game-specific impact effect hooks
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "fx_impact.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Handle weapon impacts
|
||||
//-----------------------------------------------------------------------------
|
||||
void ImpactCallback( const CEffectData &data )
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vecOrigin, vecStart, vecShotDir;
|
||||
int iMaterial, iDamageType, iHitbox;
|
||||
short nSurfaceProp;
|
||||
|
||||
C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox );
|
||||
|
||||
if ( !pEntity )
|
||||
return;
|
||||
|
||||
// If we hit, perform our custom effects and play the sound
|
||||
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) )
|
||||
{
|
||||
// Check for custom effects based on the Decal index
|
||||
PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 1.0 );
|
||||
|
||||
//Play a ricochet sound some of the time
|
||||
if( random->RandomInt(1,10) <= 3 && (iDamageType == DMG_BULLET) )
|
||||
{
|
||||
CLocalPlayerFilter filter;
|
||||
C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, "Bounce.Shrapnel", &vecOrigin );
|
||||
}
|
||||
}
|
||||
|
||||
PlayImpactSound( pEntity, tr, vecOrigin, nSurfaceProp );
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( Impact, ImpactCallback );
|
||||
@@ -0,0 +1,524 @@
|
||||
#include "cbase.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "c_asw_camera_volume.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "asw_gamerules.h"
|
||||
#include "asw_input.h"
|
||||
#include "missionchooser/iasw_random_missions.h"
|
||||
#include "holdout_resupply_frame.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Marine Camera ConVars.
|
||||
ConVar asw_cam_marine_pitch( "asw_cam_marine_pitch", "60", FCVAR_CHEAT, "Marine Camera: pitch." );
|
||||
ConVar asw_cam_marine_pitch_rate( "asw_cam_marine_pitch_rate", "1000", FCVAR_CHEAT ); // asw setting
|
||||
ConVar asw_cam_marine_yaw( "asw_cam_marine_yaw", "90", FCVAR_CHEAT, "Marine Camera: yaw." );
|
||||
ConVar asw_cam_marine_dist( "asw_cam_marine_dist", "412", FCVAR_CHEAT, "Marine Camera: Distance from marine." );
|
||||
ConVar asw_cam_marine_dist_rate( "asw_cam_marine_dist_rate", "50", FCVAR_CHEAT, "Marine Camera: Distance from marine." );
|
||||
|
||||
ConVar asw_cam_marine_dist_death( "asw_cam_marine_dist_death", "200", FCVAR_CHEAT, "Marine Camera: Distance from marine as he dies." );
|
||||
ConVar asw_cam_marine_pitch_death( "asw_cam_marine_pitch_death", "50", FCVAR_CHEAT, "Marine Camera: pitch when he dies." );
|
||||
ConVar asw_cam_marine_yaw_death_rate( "asw_cam_marine_yaw_death_rate", "35.0", FCVAR_CHEAT, "Marine Camera: yaw rotate rate when he dies." );
|
||||
ConVar asw_cam_marine_shift_z_death( "asw_cam_marine_shift_z_death", "-30.0", FCVAR_CHEAT, "Marine Camera: Shift camera vertically when he dies." );
|
||||
|
||||
ConVar asw_cam_marine_shift_ratex( "asw_cam_marine_shift_ratex", "1000", FCVAR_CHEAT, "Marine Camera: How far the camera pans east/west as you move the mouse." );
|
||||
ConVar asw_cam_marine_shift_ratey( "asw_cam_marine_shift_ratey", "650", FCVAR_CHEAT, "Marine Camera: How far the camera pans north as you move the mouse." );
|
||||
ConVar asw_cam_marine_shift_ratey_south( "asw_cam_marine_shift_ratey_south", "2000", FCVAR_CHEAT, "Marine Camera: How far the camera pans south as you move the mouse." );
|
||||
ConVar asw_cam_marine_shift_maxx( "asw_cam_marine_shift_maxx", "300", FCVAR_CHEAT, "Marine Camera: How far the camera pans east/west as you move the mouse." );
|
||||
ConVar asw_cam_marine_shift_maxy( "asw_cam_marine_shift_maxy", "200", FCVAR_CHEAT, "Marine Camera: How far the camera pans north as you move the mouse." );
|
||||
ConVar asw_cam_marine_shift_maxy_south( "asw_cam_marine_shift_maxy_south", "380", FCVAR_CHEAT, "Marine Camera: How far the camera pans south as you move the mouse." );
|
||||
ConVar asw_cam_marine_shift_deadspace( "asw_cam_marine_shift_deadspace", "64", FCVAR_CHEAT, "Marine Camera: Deadspace around the marine before camera shifting starts." );
|
||||
ConVar asw_cam_marine_blend( "asw_cam_marine_blend", "1", FCVAR_CHEAT, "Marine Camera: Whether camera should blend Z movement changes.");
|
||||
|
||||
ConVar asw_cam_marine_test( "asw_cam_marine_test", "1", FCVAR_CHEAT, "Camera Test." );
|
||||
ConVar asw_cam_marine_sphere_min( "asw_cam_marine_sphere_min", "32", FCVAR_CHEAT, "Test" );
|
||||
ConVar asw_cam_marine_sphere_max( "asw_cam_marine_sphere_max", "400", FCVAR_CHEAT, "Test" );
|
||||
|
||||
ConVar asw_cam_marine_spring_vel_max( "asw_cam_marine_spring_vel_max", "35.0", FCVAR_CHEAT, "Camera max velocity." );
|
||||
ConVar asw_cam_marine_spring_const( "asw_cam_marine_spring_const", "0.75", FCVAR_CHEAT, "Camera spring constant." );
|
||||
ConVar asw_cam_marine_spring_dampening( "asw_cam_marine_spring_dampening", "3.0", FCVAR_CHEAT, "Camera spring dampening." );
|
||||
|
||||
ConVar asw_cam_marine_yshift_static( "asw_cam_marine_yshift_static", "75.0f", FCVAR_CHEAT, "Camera y-shift value." );
|
||||
|
||||
ConVar asw_cam_marine_shift_enable( "asw_cam_marine_shift_enable", "1", FCVAR_CHEAT, "Camera shifting enable/disable." );
|
||||
|
||||
// Vehicle Camera ConVars.
|
||||
ConVar asw_vehicle_cam_height( "asw_vehicle_cam_height", "0", FCVAR_CHEAT );
|
||||
ConVar asw_vehicle_cam_pitch( "asw_vehicle_cam_pitch", "45", FCVAR_CHEAT );
|
||||
ConVar asw_vehicle_cam_dist( "asw_vehicle_cam_dist", "412", FCVAR_CHEAT );
|
||||
|
||||
// ASWTODO - allow thirdperson but cheat protect first person
|
||||
//static ConCommand thirdperson( "thirdperson", ::CAM_ToThirdPerson, "Switch to thirdperson camera." );
|
||||
//static ConCommand firstperson( "firstperson", ::CAM_ToFirstPerson, "Switch to firstperson camera.", FCVAR_CHEAT );
|
||||
|
||||
extern kbutton_t in_zoom;
|
||||
extern ConVar asw_hide_local_marine;
|
||||
extern ConVar cam_command;
|
||||
extern ConVar sv_cheats;
|
||||
extern ConVar joy_pan_camera;
|
||||
|
||||
#define DIST 2
|
||||
|
||||
// Camera height distances!
|
||||
float s_flCameraHeights[ASW_TILETYPE_COUNT] =
|
||||
{
|
||||
500.0f, // Unknown
|
||||
600.0f, // Outdoor1
|
||||
800.0f, // Outdoor2
|
||||
550.0f, // Arena1
|
||||
650.0f, // Arena2
|
||||
750.0f, // Arena3
|
||||
450.0f, // Room1
|
||||
550.0f, // Room2
|
||||
300.0f, // Corridor1
|
||||
400.0f, // Corridor1
|
||||
250.0f // Vents
|
||||
};
|
||||
|
||||
float s_flCameraHeights55[ASW_TILETYPE_COUNT] =
|
||||
{
|
||||
900.0f, // Unknown
|
||||
1080.0f, // Outdoor1
|
||||
1440.0f, // Outdoor2
|
||||
990.0f, // Arena1
|
||||
1170.0f, // Arena2
|
||||
1350.0f, // Arena3
|
||||
810.0f, // Room1
|
||||
990.0f, // Room2
|
||||
540.0f, // Corridor1
|
||||
720.0f, // Corridor1
|
||||
450.0f // Vents
|
||||
};
|
||||
|
||||
|
||||
// Panning to much when pulled further out
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Alien Swarm camera pitch.
|
||||
//-----------------------------------------------------------------------------
|
||||
float CASWInput::ASW_GetCameraPitch( const float *pfDeathCamInterp /*= NULL*/ )
|
||||
{
|
||||
// Get the given pitch.
|
||||
float flPitch = asw_cam_marine_pitch.GetFloat();
|
||||
|
||||
float fDeathCamInterp;
|
||||
if ( pfDeathCamInterp )
|
||||
{
|
||||
fDeathCamInterp = *pfDeathCamInterp;
|
||||
}
|
||||
else
|
||||
{
|
||||
fDeathCamInterp = ( ASWGameRules() ? ASWGameRules()->GetMarineDeathCamInterp() : 0.0f );
|
||||
}
|
||||
|
||||
if ( fDeathCamInterp > 0.0f )
|
||||
{
|
||||
flPitch = ( 1.0f - fDeathCamInterp ) * flPitch + fDeathCamInterp * asw_cam_marine_pitch_death.GetFloat();
|
||||
}
|
||||
|
||||
// Check to see if we are in a camera volume.
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer && pPlayer->GetMarine())
|
||||
{
|
||||
float fCameraVolumePitch = C_ASW_Camera_Volume::IsPointInCameraVolume( pPlayer->GetMarine()->GetAbsOrigin() );
|
||||
if ( fCameraVolumePitch != -1 )
|
||||
{
|
||||
flPitch = fCameraVolumePitch;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_fCurrentCameraPitch != flPitch )
|
||||
{
|
||||
float flDelta = MIN( 0.2f, gpGlobals->frametime );
|
||||
m_fCurrentCameraPitch = ASW_ClampYaw( asw_cam_marine_pitch_rate.GetFloat(), m_fCurrentCameraPitch, flPitch, flDelta );
|
||||
}
|
||||
|
||||
return m_fCurrentCameraPitch;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Alien Swarm camera yaw.
|
||||
//-----------------------------------------------------------------------------
|
||||
float CASWInput::ASW_GetCameraYaw( const float *pfDeathCamInterp /*= NULL*/ )
|
||||
{
|
||||
float fDeathCamInterp;
|
||||
if ( pfDeathCamInterp )
|
||||
{
|
||||
fDeathCamInterp = *pfDeathCamInterp;
|
||||
}
|
||||
else
|
||||
{
|
||||
fDeathCamInterp = ( ASWGameRules() ? ASWGameRules()->GetMarineDeathCamInterp() : 0.0f );
|
||||
}
|
||||
|
||||
if ( fDeathCamInterp > 0.0f )
|
||||
{
|
||||
float fRotate = gpGlobals->curtime * asw_cam_marine_yaw_death_rate.GetFloat() + ASWGameRules()->m_fDeathCamYawAngleOffset;
|
||||
float fFullRotations = static_cast< int >( fRotate / 360.0f );
|
||||
fRotate -= fFullRotations * 360.0f;
|
||||
|
||||
fRotate = AngleNormalize( fRotate );
|
||||
|
||||
return ( 1.0f - fDeathCamInterp ) * asw_cam_marine_yaw.GetFloat() + fDeathCamInterp * ( asw_cam_marine_yaw.GetFloat() + fRotate );
|
||||
}
|
||||
|
||||
return asw_cam_marine_yaw.GetFloat();
|
||||
}
|
||||
|
||||
|
||||
extern ConVar fov_desired;
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Alien Swarm camera distance.
|
||||
//-----------------------------------------------------------------------------
|
||||
float CASWInput::ASW_GetCameraDist( const float *pfDeathCamInterp /*= NULL*/ )
|
||||
{
|
||||
#ifdef VARIABLE_CAMERA
|
||||
// Are we using a valid FOV, if not use the default distance.
|
||||
float flFOV = fov_desired.GetFloat();
|
||||
if ( !( flFOV == 75.0f || flFOV == 50.0f ) )
|
||||
return asw_cam_marine_dist.GetFloat();
|
||||
|
||||
// Do we have a missionchooser, if not use the default distance.
|
||||
if ( !missionchooser || !missionchooser->RandomMissions() )
|
||||
return asw_cam_marine_dist.GetFloat();
|
||||
|
||||
// Do we have a valid player and marine, if not use the default distance.
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer || !pPlayer->GetMarine() )
|
||||
return asw_cam_marine_dist.GetFloat();
|
||||
|
||||
// Do we have a valid room, if not use the default distance.
|
||||
IASW_Room_Details *pRoom = missionchooser->RandomMissions()->GetRoomDetails( pPlayer->GetMarine()->GetAbsOrigin() );
|
||||
if ( !pRoom )
|
||||
return asw_cam_marine_dist.GetFloat();
|
||||
|
||||
// Get the desired distance for the room.
|
||||
float flDesiredDist = s_flCameraHeights[pRoom->GetTileType()];
|
||||
if ( flFOV == 50 )
|
||||
{
|
||||
flDesiredDist = s_flCameraHeights55[pRoom->GetTileType()];
|
||||
}
|
||||
|
||||
float flCameraDelta = fabs( m_flCurrentCameraDist - flDesiredDist );
|
||||
// Check against a tolerance so we don't oscillate forever.
|
||||
if ( flCameraDelta > 0.2f )
|
||||
{
|
||||
// Get frametime = delta time
|
||||
float flFrameTime = gpGlobals->frametime;
|
||||
|
||||
float flAccel = fabs( flDesiredDist - m_flCurrentCameraDist ) * asw_cam_marine_spring_const.GetFloat();
|
||||
float flZDampening = asw_cam_marine_spring_dampening.GetFloat() * m_vecCameraVelocity.z;
|
||||
flAccel -= flZDampening;
|
||||
float flZVelocity = flAccel * flFrameTime;
|
||||
m_vecCameraVelocity.z += flZVelocity;
|
||||
m_vecCameraVelocity.z = clamp( m_vecCameraVelocity.z, 0.1f, asw_cam_marine_spring_vel_max.GetFloat() );
|
||||
if ( m_flCurrentCameraDist < flDesiredDist )
|
||||
{
|
||||
m_flCurrentCameraDist += m_vecCameraVelocity.z * flFrameTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flCurrentCameraDist -= m_vecCameraVelocity.z * flFrameTime;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecCameraVelocity.z = 0.0f;
|
||||
m_flCurrentCameraDist = flDesiredDist;
|
||||
}
|
||||
|
||||
return m_flCurrentCameraDist;
|
||||
#else
|
||||
float fDeathCamInterp;
|
||||
if ( pfDeathCamInterp )
|
||||
{
|
||||
fDeathCamInterp = *pfDeathCamInterp;
|
||||
}
|
||||
else
|
||||
{
|
||||
fDeathCamInterp = ( ASWGameRules() ? ASWGameRules()->GetMarineDeathCamInterp() : 0.0f );
|
||||
}
|
||||
|
||||
if ( fDeathCamInterp > 0.0f )
|
||||
{
|
||||
return ( 1.0f - fDeathCamInterp ) * asw_cam_marine_dist.GetFloat() + fDeathCamInterp * asw_cam_marine_dist_death.GetFloat();
|
||||
}
|
||||
|
||||
return asw_cam_marine_dist.GetFloat();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
extern void UpdateOrderArrow();
|
||||
|
||||
void CASWInput::CAM_Think( void )
|
||||
{
|
||||
Assert( engine->IsLocalPlayerResolvable() );
|
||||
|
||||
UpdateOrderArrow(); // update the arrow direction if we're in the middle of ordering a marine (see in_main.cpp)
|
||||
|
||||
switch( GetPerUser().m_nCamCommand )
|
||||
{
|
||||
case CAM_COMMAND_TOTHIRDPERSON:
|
||||
CAM_ToThirdPerson();
|
||||
break;
|
||||
|
||||
case CAM_COMMAND_TOFIRSTPERSON:
|
||||
CAM_ToFirstPerson();
|
||||
break;
|
||||
|
||||
case CAM_COMMAND_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !GetPerUser().m_fCameraInThirdPerson )
|
||||
return;
|
||||
|
||||
GetPerUser().m_vecCameraOffset[ PITCH ] = ASW_GetCameraPitch();
|
||||
GetPerUser().m_vecCameraOffset[ YAW ] = ASW_GetCameraYaw();
|
||||
GetPerUser().m_vecCameraOffset[ DIST ] = 0;
|
||||
}
|
||||
|
||||
void CASWInput::CAM_ToThirdPerson(void)
|
||||
{
|
||||
asw_hide_local_marine.SetValue(0);
|
||||
CInput::CAM_ToThirdPerson();
|
||||
}
|
||||
|
||||
void CASWInput::CAM_ToFirstPerson(void)
|
||||
{
|
||||
asw_hide_local_marine.SetValue(1);
|
||||
CInput::CAM_ToFirstPerson();
|
||||
}
|
||||
|
||||
extern int g_asw_iPlayerListOpen;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASWInput::CalculateCameraShift( C_ASW_Player *pPlayer, float flDeltaX, float flDeltaY, float &flShiftX, float &flShiftY )
|
||||
{
|
||||
// Init.
|
||||
flShiftX = 0.0f;
|
||||
flShiftY = 0.0f;
|
||||
|
||||
if ( !asw_cam_marine_shift_enable.GetBool() )
|
||||
return;
|
||||
|
||||
if ( m_bCameraFixed || Holdout_Resupply_Frame::HasResupplyFrameOpen() || g_asw_iPlayerListOpen > 0 || ( pPlayer && pPlayer->GetSpectatingMarine() ) )
|
||||
{
|
||||
m_fShiftFraction = Approach( 0.0f, m_fShiftFraction, gpGlobals->frametime );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fShiftFraction = Approach( 1.0f, m_fShiftFraction, gpGlobals->frametime );
|
||||
}
|
||||
|
||||
if ( ASWGameRules() )
|
||||
{
|
||||
m_fShiftFraction = m_fShiftFraction * ( 1.0f - ASWGameRules()->GetMarineDeathCamInterp() );
|
||||
}
|
||||
|
||||
flShiftX = flDeltaX * asw_cam_marine_shift_maxx.GetFloat() * m_fShiftFraction;
|
||||
float camshifty = (flDeltaY < 0) ? asw_cam_marine_shift_maxy.GetFloat() : asw_cam_marine_shift_maxy_south.GetFloat();
|
||||
flShiftY = flDeltaY * camshifty * m_fShiftFraction;
|
||||
|
||||
|
||||
return;
|
||||
|
||||
// Calculate the shift, spherically, based on the cursor distance from the player.
|
||||
float flDistance = FastSqrt( flDeltaX * flDeltaX + flDeltaY * flDeltaY );
|
||||
if ( flDistance > asw_cam_marine_sphere_min.GetFloat() )
|
||||
{
|
||||
flDistance -= asw_cam_marine_sphere_min.GetFloat();
|
||||
|
||||
float flRatio = 1.0f;
|
||||
if ( m_flCurrentCameraDist < asw_cam_marine_dist.GetFloat() )
|
||||
{
|
||||
flRatio = ( m_flCurrentCameraDist / asw_cam_marine_dist.GetFloat() ) * 0.8f;
|
||||
}
|
||||
|
||||
float flTemp = flDistance / ( asw_cam_marine_sphere_max.GetFloat() * flRatio );
|
||||
flTemp = clamp( flTemp, 0.0f, 1.0f );
|
||||
|
||||
float flAngle = atan2( (float)flDeltaY, (float)flDeltaX );
|
||||
flShiftX = cos( flAngle ) * flTemp * ( asw_cam_marine_shift_maxx.GetFloat() * flRatio );
|
||||
if ( flDeltaY < 0 )
|
||||
{
|
||||
flShiftY = sin( flAngle ) * flTemp * ( asw_cam_marine_shift_maxy.GetFloat() * flRatio );
|
||||
}
|
||||
else
|
||||
{
|
||||
flShiftY = sin( flAngle ) * flTemp * ( asw_cam_marine_shift_maxy_south.GetFloat() * flRatio );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASWInput::SmoothCamera( C_ASW_Player *pPlayer, Vector &vecCameraLocation )
|
||||
{
|
||||
// Override smoothing enabled.
|
||||
if ( !asw_cam_marine_blend.GetBool() )
|
||||
return;
|
||||
|
||||
// Apply smoothing from the previous position if we did change marine
|
||||
if ( !pPlayer->SmoothMarineChangeCamera( vecCameraLocation ) )
|
||||
{
|
||||
// Apply Z smoothing to the camera if we didn't change marine.
|
||||
pPlayer->SmoothCameraZ( vecCameraLocation );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASWInput::ASW_GetCameraLocation( C_ASW_Player *pPlayer, Vector &vecCameraLocation, QAngle &angCamera, int &nMouseX, int &nMouseY, bool bApplySmoothing )
|
||||
{
|
||||
// Verify data.
|
||||
Assert( pPlayer != NULL );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
Assert( ASWInput() != NULL );
|
||||
if ( !ASWInput() )
|
||||
return;
|
||||
|
||||
// If we've already calculated the camera position on this frame, then just return the previous result.
|
||||
// if ( pPlayer->m_nLastCameraFrame == gpGlobals->framecount )
|
||||
// {
|
||||
// vecCameraLocation = pPlayer->m_vecLastCameraPosition;
|
||||
// angCamera = pPlayer->m_angLastCamera;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Get the current camera position.
|
||||
vecCameraLocation = pPlayer->EyePosition();
|
||||
|
||||
// Get the camera angles and calculate the camera view directions.
|
||||
Vector vecCameraDirection;
|
||||
::input->CAM_GetCameraOffset( vecCameraDirection );
|
||||
|
||||
angCamera[PITCH] = vecCameraDirection[PITCH];
|
||||
angCamera[YAW] = vecCameraDirection[YAW];
|
||||
angCamera[ROLL] = 0;
|
||||
|
||||
Vector vecCamForward, vecCamRight, vecCamUp;
|
||||
AngleVectors( angCamera, &vecCamForward, &vecCamRight, &vecCamUp );
|
||||
|
||||
// Get the window center.
|
||||
int nCenterX, nCenterY;
|
||||
ASWInput()->ASW_GetWindowCenter( nCenterX, nCenterY );
|
||||
|
||||
// Get the position change.
|
||||
int nUnclampedX, nUnclampedY;
|
||||
ASWInput()->GetSimulatedFullscreenMousePos( &nMouseX, &nMouseY, &nUnclampedX, &nUnclampedY );
|
||||
|
||||
// Calculate the movement delta - only needed for mouse control or controller with pan enabled.
|
||||
int nDeltaX = 0;
|
||||
int nDeltaY = 0;
|
||||
if ( !ASWInput()->ControllerModeActive() || joy_pan_camera.GetBool() )
|
||||
{
|
||||
nDeltaX = nMouseX - nCenterX;
|
||||
nDeltaY = nMouseY - nCenterY;
|
||||
|
||||
// Calculate the camera shift and move the camera.
|
||||
float flShiftX, flShiftY;
|
||||
CalculateCameraShift( pPlayer, (float) nDeltaX / ( nCenterX * 2.0f ), (float) nDeltaY / ( nCenterY * 2.0f ), flShiftX, flShiftY );
|
||||
|
||||
VectorMA( vecCameraLocation, flShiftX, vecCamRight, vecCameraLocation );
|
||||
vecCamUp.z = 0; // don't want the camera changing z
|
||||
vecCamUp.NormalizeInPlace();
|
||||
VectorMA( vecCameraLocation, -flShiftY, vecCamUp, vecCameraLocation );
|
||||
}
|
||||
|
||||
bool bDeathcam = ASWGameRules() && ( ASWGameRules()->GetMarineDeathCamInterp() > 0.0f );
|
||||
|
||||
// Smooth the camera movement.
|
||||
if ( bApplySmoothing && !bDeathcam )
|
||||
{
|
||||
SmoothCamera( pPlayer, vecCameraLocation );
|
||||
pPlayer->m_vecLastCameraPosition = vecCameraLocation;
|
||||
}
|
||||
|
||||
// Update the player camera data.
|
||||
pPlayer->m_nLastCameraFrame = gpGlobals->framecount;
|
||||
pPlayer->m_angLastCamera = angCamera;
|
||||
|
||||
// Do we still need this???
|
||||
pPlayer->m_hLastMarine = pPlayer->GetMarine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============================
|
||||
CAM_StartMouseMove
|
||||
|
||||
==============================
|
||||
*/
|
||||
void CASWInput::CAM_StartMouseMove(void)
|
||||
{
|
||||
GetPerUser().m_fCameraMovingWithMouse=false;
|
||||
GetPerUser().m_fCameraInterceptingMouse=false;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================
|
||||
CAM_StartDistance
|
||||
|
||||
routines to start the process of moving the cam in or out
|
||||
using the mouse
|
||||
==============================
|
||||
*/
|
||||
void CASWInput::CAM_StartDistance(void)
|
||||
{
|
||||
// asw
|
||||
GetPerUser().m_fCameraDistanceMove=false;
|
||||
GetPerUser().m_fCameraMovingWithMouse=false;
|
||||
GetPerUser().m_fCameraInterceptingMouse=false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================
|
||||
Init_Camera
|
||||
|
||||
==============================
|
||||
*/
|
||||
void CASWInput::Init_Camera( void )
|
||||
{
|
||||
for ( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; ++i )
|
||||
{
|
||||
m_PerUser[ i ].m_fCameraInThirdPerson = true;
|
||||
m_PerUser[ i ].m_CameraIsOrthographic = false;
|
||||
// TODO: make this part of the per user data
|
||||
m_fCurrentCameraPitch = false;
|
||||
m_flCurrentCameraDist = asw_cam_marine_dist.GetFloat();
|
||||
m_vecCameraVelocity.Init();
|
||||
|
||||
m_fShiftFraction = 1.0f;
|
||||
m_bCameraFixed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// asw - sets us up for moving the camera around in demos
|
||||
void ASWDemoCamera_f()
|
||||
{
|
||||
if (!engine->IsPlayingDemo())
|
||||
return;
|
||||
|
||||
engine->ClientCmd("firstperson");
|
||||
engine->ClientCmd("asw_hl2_camera 1");
|
||||
engine->ClientCmd("asw_controls 0");
|
||||
}
|
||||
ConCommand asw_demo_camera("asw_demo_camera", ASWDemoCamera_f);
|
||||
@@ -0,0 +1,710 @@
|
||||
#include "cbase.h"
|
||||
#include "asw_input.h"
|
||||
#include "iasw_client_vehicle.h" // asw
|
||||
#include "iasw_client_aim_target.h" // asw
|
||||
#include "c_asw_player.h" // asw
|
||||
#include "c_asw_marine.h" // asw
|
||||
#include "c_asw_marine_resource.h" // asw
|
||||
#include "c_asw_game_resource.h" // asw
|
||||
#include "c_asw_weapon.h"
|
||||
#include "controller_focus.h"
|
||||
#include "inputsystem/ButtonCode.h"
|
||||
#include "kbutton.h"
|
||||
#include "c_asw_order_arrow.h"
|
||||
#include "vgui/asw_vgui_info_message.h"
|
||||
#include "hltvcamera.h"
|
||||
#include "iclientmode.h"
|
||||
#include "prediction.h"
|
||||
#include "checksum_md5.h"
|
||||
#include "in_buttons.h"
|
||||
#include "holdout_resupply_frame.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern ConVar asw_controls; // asw, whether to use swarm controls or not
|
||||
ConVar joy_pan_camera("joy_pan_camera", "0", FCVAR_ARCHIVE);
|
||||
ConVar asw_ground_secondary("asw_ground_secondary", "1", FCVAR_NONE, "Set to 1 to make marines aim grenades at the floor instead of firing them straight");
|
||||
|
||||
|
||||
static kbutton_t in_holdorder;
|
||||
|
||||
// JOYPAD ADDED
|
||||
|
||||
// ===========
|
||||
// IN_Joystick_Advanced_f
|
||||
// ===========
|
||||
void IN_Joystick_Advanced_f (void)
|
||||
{
|
||||
::input->Joystick_Advanced( false );
|
||||
#ifdef INFESTED_DLL // asw - make sure our vgui joypad focus panel knows which buttons we're using for up/down/left/right
|
||||
ASW_UpdateControllerCodes();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern ConVar sv_noclipduringpause;
|
||||
extern ConVar in_forceuser;
|
||||
extern int in_impulse[ MAX_SPLITSCREEN_PLAYERS ];
|
||||
extern kbutton_t in_attack;
|
||||
extern kbutton_t in_attack2;
|
||||
|
||||
static float s_fMarineDownTime = 0;
|
||||
static int s_iMarineOrderingStartX = 0;
|
||||
static int s_iMarineOrderingStartY = 0;
|
||||
static Vector s_vecMarineOrderPos = vec3_origin;
|
||||
CHandle<C_ASW_Marine> s_hOrderTarget = NULL;
|
||||
ConVar asw_mouse_order_dist("asw_mouse_order_dist", "100", 0, "Minimum distance squared needed to move the cursor while holding down a marine number to order that marine to face that direction");
|
||||
|
||||
void GetVGUICursorPos( int& x, int& y );
|
||||
void SetVGUICursorPos( int x, int y );
|
||||
|
||||
void SelectMarineDown(int iMarine)
|
||||
{
|
||||
// number ordering disabled for now
|
||||
/*
|
||||
if (s_fMarineDownTime == 0)
|
||||
{
|
||||
s_fMarineDownTime = gpGlobals->curtime;
|
||||
s_iMarineOrdering = iMarine;
|
||||
GetVGUICursorPos(s_iMarineOrderingStartX, s_iMarineOrderingStartY);
|
||||
int x, y;
|
||||
engine->GetScreenSize( x, y );
|
||||
x = x >> 1;
|
||||
y = y >> 1;
|
||||
|
||||
float mx, my;
|
||||
mx = s_iMarineOrderingStartX - x;
|
||||
my = s_iMarineOrderingStartY - y;
|
||||
float mx_ratio =((float) mx) / ((float) x);
|
||||
float my_ratio =((float) my) / ((float) y);
|
||||
HUDTraceToWorld(-mx_ratio * 0.5f, -my_ratio * 0.5f, s_vecMarineOrderPos); // store the spot we'll send a marine to
|
||||
}
|
||||
*/
|
||||
|
||||
// if we change marines, clear any marine ordering we're about to give
|
||||
if (s_hOrderTarget.Get())
|
||||
{
|
||||
s_hOrderTarget = NULL;
|
||||
ASWInput()->ASW_SetOrderingMarine(0);
|
||||
}
|
||||
// send marine switch command
|
||||
char buffer[64];
|
||||
Q_snprintf(buffer, sizeof(buffer), "cl_switchm %d", iMarine+1);
|
||||
engine->ServerCmd(buffer);
|
||||
}
|
||||
|
||||
void SelectMarineUp(int iMarine)
|
||||
{
|
||||
// number ordering disabled for now
|
||||
/*
|
||||
// check for
|
||||
if (s_iMarineOrdering == iMarine)
|
||||
{
|
||||
// find how much the mouse has moved
|
||||
int cx, cy;
|
||||
GetVGUICursorPos(cx, cy);
|
||||
int dx = cx - s_iMarineOrderingStartX;
|
||||
int dy = cy - s_iMarineOrderingStartY;
|
||||
float dist_sqr = dx * dx + dy * dy;
|
||||
s_iMarineOrdering = 0;
|
||||
s_fMarineDownTime = 0;
|
||||
float fScreenScale = ScreenWidth() / 1024.0f;
|
||||
int iMinPixels = asw_mouse_order_dist.GetFloat() * fScreenScale;
|
||||
if (dist_sqr > iMinPixels)
|
||||
{
|
||||
// order that marine to face this way
|
||||
Vector vecOrderDir(dx, dy, 0);
|
||||
float fYaw = -UTIL_VecToYaw(vecOrderDir);
|
||||
char buffer[64];
|
||||
|
||||
Q_snprintf(buffer, sizeof(buffer), "cl_marineface %d %f %d %d %d", iMarine, fYaw,
|
||||
int(s_vecMarineOrderPos.x), int(s_vecMarineOrderPos.y), int(s_vecMarineOrderPos.z));
|
||||
//Msg("Sending command %s\n", buffer);
|
||||
engine->ClientCmd(buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// otherwise send the normal marine switch
|
||||
char buffer[64];
|
||||
Q_snprintf(buffer, sizeof(buffer), "cl_switchm %d", iMarine+1);
|
||||
//Msg("Sending command %s\n", buffer);
|
||||
engine->ClientCmd(buffer);
|
||||
*/
|
||||
}
|
||||
|
||||
void IN_SelectMarine1Down(void) { SelectMarineDown(0); }
|
||||
void IN_SelectMarine1Up(void) { SelectMarineUp(0); }
|
||||
void IN_SelectMarine2Down(void) { SelectMarineDown(1); }
|
||||
void IN_SelectMarine2Up(void) { SelectMarineUp(1); }
|
||||
void IN_SelectMarine3Down(void) { SelectMarineDown(2); }
|
||||
void IN_SelectMarine3Up(void) { SelectMarineUp(2); }
|
||||
void IN_SelectMarine4Down(void) { SelectMarineDown(3); }
|
||||
void IN_SelectMarine4Up(void) { SelectMarineUp(3); }
|
||||
void IN_SelectMarine5Down(void) { SelectMarineDown(4); }
|
||||
void IN_SelectMarine5Up(void) { SelectMarineUp(4); }
|
||||
void IN_SelectMarine6Down(void) { SelectMarineDown(5); }
|
||||
void IN_SelectMarine6Up(void) { SelectMarineUp(5); }
|
||||
void IN_SelectMarine7Down(void) { SelectMarineDown(6); }
|
||||
void IN_SelectMarine7Up(void) { SelectMarineUp(6); }
|
||||
void IN_SelectMarine8Down(void) { SelectMarineDown(7); }
|
||||
void IN_SelectMarine8Up(void) { SelectMarineUp(7); }
|
||||
// ordering marines to hold a specific position/direction
|
||||
void IN_HoldOrderDown()
|
||||
{
|
||||
KeyDown(&in_holdorder, NULL);
|
||||
// if we don't have a marine to order, find one
|
||||
if (s_hOrderTarget.Get() == NULL)
|
||||
{
|
||||
GetVGUICursorPos(s_iMarineOrderingStartX, s_iMarineOrderingStartY);
|
||||
int x, y;
|
||||
engine->GetScreenSize( x, y );
|
||||
x = x >> 1;
|
||||
y = y >> 1;
|
||||
|
||||
float mx, my;
|
||||
mx = s_iMarineOrderingStartX - x;
|
||||
my = s_iMarineOrderingStartY - y;
|
||||
float mx_ratio =((float) mx) / ((float) x);
|
||||
float my_ratio =((float) my) / ((float) y);
|
||||
HUDTraceToWorld(-mx_ratio * 0.5f, -my_ratio * 0.5f, s_vecMarineOrderPos); // store the spot we'll send a marine to
|
||||
|
||||
// find the marine nearest s_vecMarineOrderPos, biased against marines already holding a spot
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
// get the marine we're ordering
|
||||
C_ASW_Marine *pTarget = pPlayer->FindMarineToHoldOrder(s_vecMarineOrderPos);
|
||||
if (pTarget && pTarget->GetHealth() > 0)
|
||||
{
|
||||
s_hOrderTarget = pTarget;
|
||||
ASWInput()->ASW_SetOrderingMarine(pTarget->entindex());
|
||||
}
|
||||
}
|
||||
C_ASW_Game_Resource *pGameResource = ASWGameResource();
|
||||
if (pGameResource && pGameResource->GetNumMarines(pPlayer, true) > 2) // if we only have 2 marines selected, we can just fall through here and start ordering
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_fMarineDownTime == 0)
|
||||
{
|
||||
s_fMarineDownTime = gpGlobals->curtime;
|
||||
GetVGUICursorPos(s_iMarineOrderingStartX, s_iMarineOrderingStartY);
|
||||
int x, y;
|
||||
engine->GetScreenSize( x, y );
|
||||
x = x >> 1;
|
||||
y = y >> 1;
|
||||
|
||||
float mx, my;
|
||||
mx = s_iMarineOrderingStartX - x;
|
||||
my = s_iMarineOrderingStartY - y;
|
||||
float mx_ratio =((float) mx) / ((float) x);
|
||||
float my_ratio =((float) my) / ((float) y);
|
||||
HUDTraceToWorld(-mx_ratio * 0.5f, -my_ratio * 0.5f, s_vecMarineOrderPos, true); // store the spot we'll send a marine to
|
||||
|
||||
// find the marine nearest s_vecMarineOrderPos, biased against marines already holding a spot
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
C_ASW_Marine *pTarget = s_hOrderTarget.Get();
|
||||
if (pTarget && pTarget->GetHealth() > 0)
|
||||
{
|
||||
s_hOrderTarget = pTarget;
|
||||
// position this marine's arrow here
|
||||
if (pTarget->m_hOrderArrow.Get())
|
||||
{
|
||||
// work out yaw to my marine
|
||||
C_ASW_Marine *pMyMarine = pPlayer->GetMarine();
|
||||
float fYaw = 0;
|
||||
if (pMyMarine)
|
||||
{
|
||||
Vector diff = s_vecMarineOrderPos - pMyMarine->GetAbsOrigin();
|
||||
diff.z = 0;
|
||||
fYaw = UTIL_VecToYaw(diff);
|
||||
}
|
||||
pTarget->m_hOrderArrow->SetAbsOrigin(s_vecMarineOrderPos);
|
||||
pTarget->m_hOrderArrow->RemoveEffects(EF_NODRAW);
|
||||
pTarget->m_hOrderArrow->RefreshArrow();
|
||||
QAngle arrow_yaw(0, fYaw, 0);
|
||||
pTarget->m_hOrderArrow->SetAbsAngles(arrow_yaw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IN_HoldOrderUp()
|
||||
{
|
||||
// if we don't have a marine to order yet, skip
|
||||
if (s_hOrderTarget.Get() == NULL || s_fMarineDownTime == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KeyUp(&in_holdorder, NULL);
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pPlayer )
|
||||
{
|
||||
// find how much the mouse has moved
|
||||
int cx, cy;
|
||||
GetVGUICursorPos(cx, cy);
|
||||
int dx = cx - s_iMarineOrderingStartX;
|
||||
int dy = cy - s_iMarineOrderingStartY;
|
||||
float dist_sqr = dx * dx + dy * dy;
|
||||
s_fMarineDownTime = 0;
|
||||
float fScreenScale = ScreenWidth() / 1024.0f;
|
||||
int iMinPixels = asw_mouse_order_dist.GetFloat() * fScreenScale;
|
||||
float fYaw = 0;
|
||||
if (dist_sqr > iMinPixels)
|
||||
{
|
||||
// order that marine to face this way
|
||||
Vector vecOrderDir(dx, dy, 0);
|
||||
fYaw = -UTIL_VecToYaw(vecOrderDir);
|
||||
}
|
||||
else if ( pPlayer->GetMarine() )
|
||||
{
|
||||
// otherwise order the marine to face away from current marine
|
||||
Vector diff = s_vecMarineOrderPos - pPlayer->GetMarine()->GetAbsOrigin();
|
||||
diff.z = 0;
|
||||
fYaw = UTIL_VecToYaw(diff);
|
||||
}
|
||||
char buffer[64];
|
||||
Q_snprintf(buffer, sizeof(buffer), "cl_marineface %d %f %d %d %d", ASWInput()->ASW_GetOrderingMarine(), fYaw,
|
||||
int(s_vecMarineOrderPos.x), int(s_vecMarineOrderPos.y), int(s_vecMarineOrderPos.z));
|
||||
|
||||
engine->ClientCmd(buffer);
|
||||
s_hOrderTarget = NULL;
|
||||
ASWInput()->ASW_SetOrderingMarine(0);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOrderArrow()
|
||||
{
|
||||
if (!(in_holdorder.GetPerUser().state & 1))
|
||||
return;
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (!pPlayer || !pPlayer->GetMarine() || s_hOrderTarget.Get() == NULL || s_fMarineDownTime == 0)
|
||||
return;
|
||||
// find how much the mouse has moved
|
||||
int cx, cy;
|
||||
GetVGUICursorPos(cx, cy);
|
||||
int dx = cx - s_iMarineOrderingStartX;
|
||||
int dy = cy - s_iMarineOrderingStartY;
|
||||
float dist_sqr = dx * dx + dy * dy;
|
||||
|
||||
float fScreenScale = ScreenWidth() / 1024.0f;
|
||||
int iMinPixels = asw_mouse_order_dist.GetFloat() * fScreenScale;
|
||||
float fYaw = 0;
|
||||
if (dist_sqr > iMinPixels)
|
||||
{
|
||||
// order that marine to face this way
|
||||
Vector vecOrderDir(dx, dy, 0);
|
||||
fYaw = -UTIL_VecToYaw(vecOrderDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise order the marine to face away from current marine
|
||||
Vector diff = s_vecMarineOrderPos - pPlayer->GetMarine()->GetAbsOrigin();
|
||||
diff.z = 0;
|
||||
fYaw = UTIL_VecToYaw(diff);
|
||||
}
|
||||
|
||||
if (s_hOrderTarget->m_hOrderArrow.Get())
|
||||
{
|
||||
QAngle arrow_yaw(0, fYaw, 0);
|
||||
s_hOrderTarget->m_hOrderArrow->SetAbsAngles(arrow_yaw);
|
||||
s_hOrderTarget->m_hOrderArrow->RefreshArrow();
|
||||
}
|
||||
}
|
||||
|
||||
// order marine nearest the cursor to follow
|
||||
|
||||
void asw_OrderMarinesFollowf()
|
||||
{
|
||||
// if we order nearby marines, clear any specific marine ordering we're about to give
|
||||
if (s_hOrderTarget.Get())
|
||||
{
|
||||
s_hOrderTarget = NULL;
|
||||
ASWInput()->ASW_SetOrderingMarine(0);
|
||||
}
|
||||
// send follow order
|
||||
engine->ClientCmd("cl_orderfollow");
|
||||
}
|
||||
ConCommand OrderMarinesFollow( "asw_OrderMarinesFollow", asw_OrderMarinesFollowf, "Orders nearest marine to follow", 0);
|
||||
|
||||
void asw_OrderMarinesHoldf()
|
||||
{
|
||||
// if we order nearby marines, clear any specific marine ordering we're about to give
|
||||
if (s_hOrderTarget.Get())
|
||||
{
|
||||
s_hOrderTarget = NULL;
|
||||
ASWInput()->ASW_SetOrderingMarine(0);
|
||||
}
|
||||
// send follow order
|
||||
engine->ClientCmd("cl_orderhold");
|
||||
}
|
||||
ConCommand OrderMarinesHold( "asw_OrderMarinesHold", asw_OrderMarinesHoldf, "Orders nearby marines to hold position", 0);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
KeyEvent
|
||||
|
||||
Return 1 to allow engine to process the key, otherwise, act on it as needed
|
||||
============
|
||||
*/
|
||||
int CASWInput::KeyEvent( int down, ButtonCode_t code, const char *pszCurrentBinding )
|
||||
{
|
||||
// JOYPAD ADDED
|
||||
// asw - grab joypad presses here
|
||||
if ( code >= JOYSTICK_FIRST && code <= KEY_XSTICK2_UP && GetControllerFocus() )
|
||||
{
|
||||
if (down != 0)
|
||||
{
|
||||
if ( GetControllerFocus()->OnControllerButtonPressed( code ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( GetControllerFocus()->OnControllerButtonReleased( code ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// notify ingame VGUI panels of mouse clicks
|
||||
if ( code == MOUSE_LEFT )
|
||||
{
|
||||
if ( g_IngamePanelManager.SendMouseClick( false, down ? true : false ) )
|
||||
return false;
|
||||
}
|
||||
else if ( code == MOUSE_RIGHT )
|
||||
{
|
||||
if ( g_IngamePanelManager.SendMouseClick( true, down ? true : false ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// use key: if we have any info messages up, close them and leave as that's our keypress used
|
||||
if (down && pszCurrentBinding && Q_strcmp( pszCurrentBinding, "+use" ) == 0 && CASW_VGUI_Info_Message::CloseInfoMessage())
|
||||
return false;
|
||||
|
||||
return CInput::KeyEvent( down, code, pszCurrentBinding );
|
||||
}
|
||||
|
||||
void CASWInput::ExtraMouseSample( float frametime, bool active )
|
||||
{
|
||||
ASSERT_LOCAL_PLAYER_RESOLVABLE();
|
||||
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
|
||||
|
||||
static CUserCmd dummy[ MAX_SPLITSCREEN_PLAYERS ];
|
||||
CUserCmd *cmd = &dummy[ nSlot ];
|
||||
|
||||
cmd->Reset();
|
||||
|
||||
|
||||
QAngle viewangles;
|
||||
|
||||
if ( active )
|
||||
{
|
||||
// Determine view angles
|
||||
AdjustAngles ( nSlot, frametime );
|
||||
|
||||
|
||||
// asw - is this needed?
|
||||
// Retreive view angles from engine ( could have been changed in AdjustAngles above )
|
||||
engine->GetViewAngles( viewangles );
|
||||
// Use new view angles if alive, otherwise user last angles we stored off.
|
||||
VectorCopy( viewangles, cmd->viewangles );
|
||||
VectorCopy( viewangles, GetPerUser().m_angPreviousViewAngles );
|
||||
|
||||
// Determine sideways movement
|
||||
ComputeSideMove( nSlot, cmd );
|
||||
|
||||
// Determine vertical movement
|
||||
ComputeUpwardMove( nSlot, cmd );
|
||||
|
||||
// Determine forward movement
|
||||
ComputeForwardMove( nSlot, cmd );
|
||||
|
||||
// Scale based on holding speed key or having too fast of a velocity based on client maximum
|
||||
// speed.
|
||||
ScaleMovements( cmd );
|
||||
|
||||
// Allow mice and other controllers to add their inputs
|
||||
ControllerMove( nSlot, frametime, cmd );
|
||||
}
|
||||
|
||||
// Retreive view angles from engine ( could have been set in IN_AdjustAngles above )
|
||||
engine->GetViewAngles( viewangles );
|
||||
|
||||
// Set button and flag bits, don't blow away state
|
||||
cmd->buttons = GetButtonBits( false );
|
||||
|
||||
// Use new view angles if alive, otherwise user last angles we stored off.
|
||||
VectorCopy( viewangles, cmd->viewangles );
|
||||
VectorCopy( viewangles, GetPerUser().m_angPreviousViewAngles );
|
||||
|
||||
// Let the move manager override anything it wants to.
|
||||
if ( GetClientMode()->CreateMove( frametime, cmd ) )
|
||||
{
|
||||
// Get current view angles after the client mode tweaks with it
|
||||
engine->SetViewAngles( cmd->viewangles );
|
||||
prediction->SetLocalViewAngles( cmd->viewangles );
|
||||
}
|
||||
}
|
||||
|
||||
void CASWInput::CreateMove( int sequence_number, float input_sample_frametime, bool active )
|
||||
{
|
||||
ASSERT_LOCAL_PLAYER_RESOLVABLE();
|
||||
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
|
||||
|
||||
CUserCmd *cmd = &GetPerUser(nSlot).m_pCommands[ sequence_number % MULTIPLAYER_BACKUP];
|
||||
CVerifiedUserCmd *pVerified = &GetPerUser(nSlot).m_pVerifiedCommands[ sequence_number % MULTIPLAYER_BACKUP];
|
||||
|
||||
cmd->Reset();
|
||||
|
||||
cmd->command_number = sequence_number;
|
||||
cmd->tick_count = gpGlobals->tickcount;
|
||||
|
||||
QAngle viewangles;
|
||||
|
||||
if ( active || sv_noclipduringpause.GetInt() )
|
||||
{
|
||||
if ( engine->GetActiveSplitScreenPlayerSlot() == in_forceuser.GetInt() )
|
||||
{
|
||||
// Determine view angles
|
||||
AdjustAngles ( nSlot, input_sample_frametime );
|
||||
|
||||
|
||||
// asw - is this needed?
|
||||
// Retreive view angles from engine ( could have been changed in AdjustAngles above )
|
||||
engine->GetViewAngles( viewangles );
|
||||
// Use new view angles if alive, otherwise user last angles we stored off.
|
||||
VectorCopy( viewangles, cmd->viewangles );
|
||||
VectorCopy( viewangles, GetPerUser( nSlot ).m_angPreviousViewAngles );
|
||||
|
||||
// Determine sideways movement
|
||||
ComputeSideMove( nSlot, cmd );
|
||||
|
||||
// Determine vertical movement
|
||||
ComputeUpwardMove( nSlot, cmd );
|
||||
|
||||
// Determine forward movement
|
||||
ComputeForwardMove( nSlot, cmd );
|
||||
|
||||
// Scale based on holding speed key or having too fast of a velocity based on client maximum
|
||||
// speed.
|
||||
ScaleMovements( cmd );
|
||||
|
||||
if ( CASW_VGUI_Info_Message::HasInfoMessageOpen() || Holdout_Resupply_Frame::HasResupplyFrameOpen() )
|
||||
{
|
||||
cmd->forwardmove = 0;
|
||||
cmd->sidemove = 0;
|
||||
cmd->upmove = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow mice and other controllers to add their inputs
|
||||
ControllerMove( nSlot, input_sample_frametime, cmd );
|
||||
}
|
||||
|
||||
// Retreive view angles from engine ( could have been set in IN_AdjustAngles above )
|
||||
engine->GetViewAngles( viewangles );
|
||||
|
||||
cmd->impulse = in_impulse[ nSlot ];
|
||||
in_impulse[ nSlot ] = 0;
|
||||
|
||||
// Latch and clear weapon selection
|
||||
if ( GetPerUser().m_hSelectedWeapon != NULL )
|
||||
{
|
||||
C_BaseCombatWeapon *weapon = GetPerUser().m_hSelectedWeapon;
|
||||
|
||||
cmd->weaponselect = weapon->entindex();
|
||||
|
||||
// Always clear weapon selection
|
||||
GetPerUser().m_hSelectedWeapon = NULL;
|
||||
}
|
||||
|
||||
// store the currently selected marine in the weapon subtype
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
C_ASW_Marine* pMarine = pPlayer->GetMarine();
|
||||
if ( ASWGameResource() && pPlayer && pMarine && pPlayer->GetMarine()->GetMarineResource() )
|
||||
{
|
||||
cmd->weaponsubtype = ASWGameResource()->GetMarineResourceIndex( pMarine->GetMarineResource() );
|
||||
|
||||
// get light at the current marine
|
||||
//Vector pos = pPlayer->GetMarine()->GetAbsOrigin() + Vector(0, 0, 40);
|
||||
//Vector col = engine->GetLightForPoint( pos, true );
|
||||
//cmd->light_level = (byte) clamp( ( 255.0f * ( col.x + col.y + col.z ) ) / 3.0f, 0.0f, 254.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->weaponsubtype = 0;
|
||||
//cmd->light_level = 255;
|
||||
}
|
||||
|
||||
// Set button and flag bits
|
||||
cmd->buttons = GetButtonBits( true );
|
||||
|
||||
// Using joystick?
|
||||
if ( in_joystick.GetInt() )
|
||||
{
|
||||
if ( cmd->forwardmove > 0 )
|
||||
{
|
||||
cmd->buttons |= IN_FORWARD;
|
||||
}
|
||||
else if ( cmd->forwardmove < 0 )
|
||||
{
|
||||
cmd->buttons |= IN_BACK;
|
||||
}
|
||||
}
|
||||
|
||||
// asw - alter view angles for this move if it's one where we're firing off a ground grenade
|
||||
if ( asw_ground_secondary.GetBool() && cmd->buttons & IN_ATTACK2 )
|
||||
{
|
||||
ASW_AdjustViewAngleForGroundShooting(viewangles);
|
||||
}
|
||||
|
||||
// Use new view angles if alive, otherwise user last angles we stored off.
|
||||
VectorCopy( viewangles, cmd->viewangles );
|
||||
VectorCopy( viewangles, GetPerUser().m_angPreviousViewAngles );
|
||||
|
||||
// Let the move manager override anything it wants to.
|
||||
if ( GetClientMode()->CreateMove( input_sample_frametime, cmd ) )
|
||||
{
|
||||
// Get current view angles after the client mode tweaks with it
|
||||
engine->SetViewAngles( cmd->viewangles );
|
||||
}
|
||||
|
||||
GetPerUser().m_flLastForwardMove = cmd->forwardmove;
|
||||
|
||||
cmd->random_seed = MD5_PseudoRandom( sequence_number ) & 0x7fffffff;
|
||||
|
||||
HLTVCamera()->CreateMove( cmd );
|
||||
|
||||
if ( pPlayer )
|
||||
{
|
||||
cmd->crosshairtrace = ASWInput()->GetCrosshairTracePos();
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->crosshairtrace = vec3_origin;
|
||||
}
|
||||
cmd->crosshair_entity = GetHighlightEntity() ? GetHighlightEntity()->entindex() : 0;
|
||||
|
||||
cmd->forced_action = pMarine ? pMarine->GetForcedActionRequest() : 0;
|
||||
cmd->sync_kill_ent = 0;
|
||||
|
||||
C_ASW_Weapon *pWeapon = pMarine ? pMarine->GetActiveASWWeapon() : NULL;
|
||||
if ( pWeapon )
|
||||
{
|
||||
pWeapon->CheckSyncKill( cmd->forced_action, cmd->sync_kill_ent );
|
||||
}
|
||||
|
||||
pVerified->m_cmd = *cmd;
|
||||
pVerified->m_crc = cmd->GetChecksum();
|
||||
}
|
||||
|
||||
// asw
|
||||
|
||||
bool CASWInput::ASWWriteVehicleMessage( bf_write *buf )
|
||||
{
|
||||
int startbit = buf->GetNumBitsWritten();
|
||||
|
||||
if (!PlayerDriving())
|
||||
return false;
|
||||
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (!pPlayer || !pPlayer->GetMarine() || !pPlayer->GetMarine()->GetClientsideVehicle())
|
||||
return false;
|
||||
|
||||
C_BaseAnimating *pAnimating = dynamic_cast<C_BaseAnimating*>(pPlayer->GetMarine()->GetClientsideVehicle()->GetEntity());
|
||||
if (!pAnimating)
|
||||
return false;
|
||||
|
||||
// = static_cast<C_BaseAnimating*>(s_pCVehicle->GetVehicleEnt());
|
||||
buf->WriteBitVec3Coord(pAnimating->GetAbsOrigin());
|
||||
buf->WriteBitAngles(pAnimating->GetAbsAngles());
|
||||
//todo: velocity?
|
||||
|
||||
// poseparams
|
||||
//Msg(" Client params: ");
|
||||
for (int i=0;i<12;i++)
|
||||
{
|
||||
buf->WriteBitFloat(pAnimating->GetPoseParameterRaw(i));
|
||||
//Msg("%f ", pAnimating->GetPoseParameter(i));
|
||||
}
|
||||
//Msg("\n");
|
||||
|
||||
if ( buf->IsOverflowed() )
|
||||
{
|
||||
int endbit = buf->GetNumBitsWritten();
|
||||
|
||||
Msg( "WARNING! ASW Vehicle packet buffer overflow, last cmd was %i bits long\n",
|
||||
endbit - startbit );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CASWInput::GetButtonBits( bool bResetState )
|
||||
{
|
||||
int bits = CInput::GetButtonBits( bResetState );
|
||||
|
||||
// if player is pressing their melee key, do a simple check for contact
|
||||
/*
|
||||
if ( bits & MELEE_BUTTON )
|
||||
{
|
||||
C_ASW_Marine *pMarine = C_ASW_Marine::GetLocalMarine();
|
||||
if ( pMarine && !pMarine->m_bMeleeMadeContact && pMarine->GetCurrentMeleeAttack() )
|
||||
{
|
||||
if ( !asw_melee_require_contact.GetBool() || pMarine->GetCurrentMeleeAttack()->CheckContact( pMarine ) )
|
||||
{
|
||||
bits |= IN_MELEE_CONTACT;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return bits;
|
||||
}
|
||||
|
||||
static ConCommand startselectmarine1("+selectmarine1", IN_SelectMarine1Down);
|
||||
static ConCommand endselectmarine1("-selectmarine1", IN_SelectMarine1Up);
|
||||
static ConCommand startselectmarine2("+selectmarine2", IN_SelectMarine2Down);
|
||||
static ConCommand endselectmarine2("-selectmarine2", IN_SelectMarine2Up);
|
||||
static ConCommand startselectmarine3("+selectmarine3", IN_SelectMarine3Down);
|
||||
static ConCommand endselectmarine3("-selectmarine3", IN_SelectMarine3Up);
|
||||
static ConCommand startselectmarine4("+selectmarine4", IN_SelectMarine4Down);
|
||||
static ConCommand endselectmarine4("-selectmarine4", IN_SelectMarine4Up);
|
||||
static ConCommand startselectmarine5("+selectmarine5", IN_SelectMarine5Down);
|
||||
static ConCommand endselectmarine5("-selectmarine5", IN_SelectMarine5Up);
|
||||
static ConCommand startselectmarine6("+selectmarine6", IN_SelectMarine6Down);
|
||||
static ConCommand endselectmarine6("-selectmarine6", IN_SelectMarine6Up);
|
||||
static ConCommand startselectmarine7("+selectmarine7", IN_SelectMarine7Down);
|
||||
static ConCommand endselectmarine7("-selectmarine7", IN_SelectMarine7Up);
|
||||
static ConCommand startselectmarine8("+selectmarine8", IN_SelectMarine8Down);
|
||||
static ConCommand endselectmarine8("-selectmarine8", IN_SelectMarine8Up);
|
||||
static ConCommand startholdorder("+holdorder", IN_HoldOrderDown);
|
||||
static ConCommand endholdorder("-holdorder", IN_HoldOrderUp);
|
||||
|
||||
void CASWInput::Init_All( void )
|
||||
{
|
||||
CInput::Init_All();
|
||||
m_iOrderingMarine = 0;
|
||||
|
||||
if ( IsX360() )
|
||||
{
|
||||
EngageControllerMode();
|
||||
}
|
||||
}
|
||||
|
||||
// was used by joypad to stop turning the marine when firing
|
||||
bool CASWInput::IsAttacking( void )
|
||||
{
|
||||
return (( in_attack.GetPerUser().state & 1 ) || ( in_attack2.GetPerUser().state & 1 ));
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
#include "cbase.h"
|
||||
#include "asw_input.h"
|
||||
#include "vgui/asw_vgui_ingame_panel.h"
|
||||
#include "asw_hud_crosshair.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_weapon.h"
|
||||
#include "c_asw_pickup.h"
|
||||
#include "kbutton.h"
|
||||
#include "cdll_int.h"
|
||||
#include "vgui/isurface.h"
|
||||
#include "iasw_client_aim_target.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern ConVar asw_controls; // asw: whether to use swarm mouse controls or not
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: make sure cursor isn't reset to 0 by the accumulation
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASWInput::ActivateMouse (void)
|
||||
{
|
||||
if ( m_fMouseInitialized )
|
||||
{
|
||||
// asw store mouse pos
|
||||
int current_posx, current_posy;
|
||||
GetMousePos(current_posx, current_posy);
|
||||
|
||||
CInput::ActivateMouse();
|
||||
|
||||
// asw - move it back to original position
|
||||
SetMousePos(current_posx, current_posy);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Don't allow recentering the mouse
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASWInput::ResetMouse( void )
|
||||
{
|
||||
int x, y;
|
||||
HACK_GETLOCALPLAYER_GUARD( "Mouse behavior is tied to a specific player's status - splitscreen player would depend on which player (if any) is using mouse control" );
|
||||
if (MarineControllingTurret() || !asw_controls.GetBool())
|
||||
{
|
||||
GetWindowCenter( x, y );
|
||||
SetMousePos( x, y );
|
||||
}
|
||||
else
|
||||
{
|
||||
GetMousePos( x, y ); // asw instead of GetWindowCenter, so mouse doesn't move
|
||||
SetMousePos( x, y );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: AccumulateMouse - asw: stop mouse from being moved back to the centre of the screen
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASWInput::AccumulateMouse( int nSlot )
|
||||
{
|
||||
// asw store mouse pos
|
||||
int current_posx, current_posy;
|
||||
GetMousePos(current_posx, current_posy);
|
||||
|
||||
CInput::AccumulateMouse( nSlot );
|
||||
|
||||
// asw - move it back to original position
|
||||
SetMousePos(current_posx, current_posy);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: ApplyMouse -- applies mouse deltas to CUserCmd
|
||||
// Input : viewangles -
|
||||
// *cmd -
|
||||
// mouse_x -
|
||||
// mouse_y -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASWInput::ApplyMouse( int nSlot, QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y )
|
||||
{
|
||||
int current_posx, current_posy;
|
||||
GetMousePos(current_posx, current_posy);
|
||||
|
||||
|
||||
if ( ASWInput()->ControllerModeActive() )
|
||||
return;
|
||||
|
||||
if ( asw_controls.GetBool() && !MarineControllingTurret() )
|
||||
{
|
||||
TurnTowardMouse( viewangles, cmd );
|
||||
|
||||
// Re-center the mouse.
|
||||
|
||||
// force the mouse to the center, so there's room to move
|
||||
ResetMouse();
|
||||
SetMousePos( current_posx, current_posy ); // asw - swarm wants it unmoved (have to reset to stop buttons locking)
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( MarineControllingTurret() )
|
||||
{
|
||||
// accelerate up the mouse intertia
|
||||
static float mouse_x_accumulated = 0;
|
||||
static float mouse_y_accumulated = 0;
|
||||
|
||||
// decay it
|
||||
mouse_x_accumulated *= 0.95f;
|
||||
mouse_y_accumulated *= 0.95f;
|
||||
|
||||
mouse_x_accumulated += mouse_x * 0.04f;
|
||||
mouse_y_accumulated += mouse_y * 0.04f;
|
||||
|
||||
// clamp it
|
||||
mouse_x_accumulated = clamp(mouse_x_accumulated, -500.0f,500.0f);
|
||||
mouse_y_accumulated = clamp(mouse_y_accumulated, -500.0f,500.0f);
|
||||
|
||||
// move with our inertia style
|
||||
mouse_x = mouse_x_accumulated;
|
||||
mouse_y = mouse_y_accumulated;
|
||||
}
|
||||
CInput::ApplyMouse( nSlot, viewangles, cmd, mouse_x, mouse_y );
|
||||
|
||||
// force the mouse to the center, so there's room to move
|
||||
ResetMouse();
|
||||
}
|
||||
}
|
||||
|
||||
void CASWInput::GetFullscreenMousePos( int *mx, int *my, int *unclampedx /*=NULL*/, int *unclampedy /*=NULL*/ )
|
||||
{
|
||||
Assert( mx );
|
||||
Assert( my );
|
||||
|
||||
int x, y;
|
||||
GetWindowCenter( x, y );
|
||||
|
||||
int current_posx, current_posy;
|
||||
|
||||
GetMousePos(current_posx, current_posy);
|
||||
|
||||
current_posx -= x;
|
||||
current_posy -= y;
|
||||
|
||||
// Now need to add back in mid point of viewport
|
||||
int w, h;
|
||||
vgui::surface()->GetScreenSize( w, h );
|
||||
current_posx += w / 2;
|
||||
current_posy += h / 2;
|
||||
|
||||
if ( unclampedx )
|
||||
{
|
||||
*unclampedx = current_posx;
|
||||
}
|
||||
|
||||
if ( unclampedy )
|
||||
{
|
||||
*unclampedy = current_posy;
|
||||
}
|
||||
|
||||
// Clamp
|
||||
current_posx = MAX( 0, current_posx );
|
||||
current_posx = MIN( ScreenWidth(), current_posx );
|
||||
|
||||
current_posy = MAX( 0, current_posy );
|
||||
current_posy = MIN( ScreenHeight(), current_posy );
|
||||
|
||||
*mx = current_posx;
|
||||
*my = current_posy;
|
||||
}
|
||||
|
||||
void CASWInput::SetMouseOverEntity( C_BaseEntity* pEnt )
|
||||
{
|
||||
// highlight the next entity
|
||||
m_hMouseOverEntity = pEnt;
|
||||
|
||||
//m_MouseOverGlowObject.SetEntity( pEnt );
|
||||
|
||||
if ( !pEnt )
|
||||
return;
|
||||
|
||||
C_ASW_Marine *pOtherMarine = C_ASW_Marine::AsMarine( pEnt );
|
||||
if ( pOtherMarine )
|
||||
return;
|
||||
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
C_ASW_Marine *pMarine = pPlayer ? pPlayer->GetMarine() : NULL;
|
||||
if ( !pMarine )
|
||||
return;
|
||||
|
||||
IASW_Client_Aim_Target* pAimEnt = dynamic_cast<IASW_Client_Aim_Target*>( pEnt );
|
||||
if ( pAimEnt )
|
||||
{
|
||||
// check we have LOS to the target
|
||||
CTraceFilterLOS traceFilter( pMarine, COLLISION_GROUP_NONE );
|
||||
trace_t tr2;
|
||||
Vector vecWeaponPos = pMarine->GetRenderOrigin() + Vector( 0,0, ASW_MARINE_GUN_OFFSET_Z );
|
||||
UTIL_TraceLine( vecWeaponPos, pAimEnt->GetAimTargetRadiusPos( vecWeaponPos ), MASK_OPAQUE, &traceFilter, &tr2 );
|
||||
//C_BaseEntity *pEnt = pAimEnt->GetEntity();
|
||||
//bool bHasLOS = (!tr2.startsolid && (tr2.fraction >= 1.0 || tr2.m_pEnt == pEnt));
|
||||
// we can't shoot it, so skip it
|
||||
// if ( bHasLOS )
|
||||
// {
|
||||
// m_MouseOverGlowObject.SetRenderFlags( true, true );
|
||||
// m_MouseOverGlowObject.SetColor( Vector( 0.65f, 0.45f, 0.15f ) );
|
||||
// m_MouseOverGlowObject.SetAlpha( 0.875f );
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// m_MouseOverGlowObject.SetRenderFlags( true, true );
|
||||
// m_MouseOverGlowObject.SetColor( Vector( 0.4f, 0.35f, 0.3f ) );
|
||||
// m_MouseOverGlowObject.SetAlpha( 0.8f );
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CASWInput::SetHighlightEntity( C_BaseEntity* pEnt, bool bGlow )
|
||||
{
|
||||
// if we're currently highlighting something, stop
|
||||
if ( m_hHighlightEntity.Get() )
|
||||
{
|
||||
C_BaseAnimating *pAnimating = dynamic_cast<C_BaseAnimating*>( m_hHighlightEntity.Get() );
|
||||
if (pAnimating)
|
||||
{
|
||||
// ASWTODO - put this back in when we have a material proxy that supports lighting a specific marine
|
||||
//pAnimating->SetHighlight(false);
|
||||
}
|
||||
}
|
||||
// highlight the next entity
|
||||
m_hHighlightEntity = pEnt;
|
||||
m_HighLightGlowObject.SetEntity( pEnt );
|
||||
|
||||
if ( m_hHighlightEntity.Get() )
|
||||
{
|
||||
if ( bGlow )
|
||||
{
|
||||
m_HighLightGlowObject.SetColor( Vector( 0.6f, 0.6f, 0.8f ) );
|
||||
m_HighLightGlowObject.SetAlpha( 0.7f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_HighLightGlowObject.SetColor( Vector( 0.3f, 0.3f, 0.3f ) );
|
||||
m_HighLightGlowObject.SetAlpha( 0.5f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
C_BaseEntity* CASWInput::GetHighlightEntity() const
|
||||
{
|
||||
return m_hHighlightEntity.Get();
|
||||
}
|
||||
|
||||
void CASWInput::UpdateHighlightEntity()
|
||||
{
|
||||
// if we're currently brightening any entity, stop
|
||||
SetHighlightEntity( NULL, false );
|
||||
// clear any additional cursor icons
|
||||
CASWHudCrosshair *pCrosshair = GET_HUDELEMENT( CASWHudCrosshair );
|
||||
if ( pCrosshair )
|
||||
{
|
||||
pCrosshair->SetShowGiveAmmo(false, -1);
|
||||
pCrosshair->SetShowGiveHealth( false );
|
||||
}
|
||||
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
C_ASW_Marine* pMarine = pPlayer->GetMarine();
|
||||
if ( !pMarine )
|
||||
return;
|
||||
|
||||
// see if the marine and his weapons want to highlight the current entity, or something near the cursor
|
||||
pMarine->MouseOverEntity( GetMouseOverEntity(), GetCrosshairAimingPos() );
|
||||
}
|
||||
|
||||
void CASWInput::SetUseGlowEntity( C_BaseEntity* pEnt )
|
||||
{
|
||||
// if we're currently highlighting something, stop
|
||||
if ( m_hUseGlowEntity.Get() )
|
||||
{
|
||||
C_BaseAnimating *pAnimating = dynamic_cast<C_BaseAnimating*>( m_hUseGlowEntity.Get() );
|
||||
if ( pAnimating )
|
||||
{
|
||||
// ASWTODO - put this back in when we have a material proxy that supports lighting a specific marine
|
||||
//pAnimating->SetHighlight(false);
|
||||
}
|
||||
}
|
||||
// highlight the next entity
|
||||
m_hUseGlowEntity = pEnt;
|
||||
bool bIsAllowed = true;
|
||||
if ( m_hUseGlowEntity.Get() )
|
||||
{
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
C_ASW_Marine* pMarine = pPlayer->GetMarine();
|
||||
if ( !pMarine )
|
||||
return;
|
||||
|
||||
C_ASW_Pickup *pPickup = dynamic_cast< C_ASW_Pickup * >( pEnt );
|
||||
if ( pPickup )
|
||||
{
|
||||
bIsAllowed = pPickup->AllowedToPickup( pMarine );
|
||||
}
|
||||
else
|
||||
{
|
||||
C_ASW_Weapon *pWeapon = dynamic_cast< C_ASW_Weapon * >( pEnt );
|
||||
if ( pWeapon )
|
||||
{
|
||||
bIsAllowed = pWeapon->AllowedToPickup( pMarine );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bIsAllowed )
|
||||
m_UseGlowObject.SetEntity( pEnt );
|
||||
else
|
||||
m_UseGlowObject.SetEntity( NULL );
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,176 @@
|
||||
#ifndef _INCLUDED_ASW_INPUT_H
|
||||
#define _INCLUDED_ASW_INPUT_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "input.h"
|
||||
#include "glow_outline_effect.h"
|
||||
|
||||
extern bool MarineBusy();
|
||||
|
||||
class CASW_Player;
|
||||
class C_ASW_Player;
|
||||
class IASW_Client_Aim_Target;
|
||||
|
||||
// storing autoaim data for debug visualisation
|
||||
void ASW_StoreLineCircle(int index, float alien_x, float alien_y, float alien_radius, float marine_x, float marine_y, Vector2D LineDir, int iCol);
|
||||
void ASW_GetLineCircle(int index, float &alien_x, float &alien_y, float &alien_radius, float &marine_x, float &marine_y, Vector2D &LineDir, int &iCol);
|
||||
void ASW_StoreClearAll();
|
||||
|
||||
bool MarineControllingTurret();
|
||||
|
||||
bool HUDTraceToWorld(float screenx, float screeny, Vector &HitLocation, bool bUseMarineHull=false);
|
||||
C_BaseEntity* HUDToWorld(float screenx, float screeny,
|
||||
Vector &HitLocation, IASW_Client_Aim_Target* &pAutoAimEnt, bool bPreferFlatAiming=false, bool bIgnoreCursorPosition = false, float flForwardMove = 0.0f, float flSideMove = 0.0f);
|
||||
void RoundToPixel(Vector &vecPos);
|
||||
void SmoothTurningYaw(CASW_Player *pPlayer, float &yaw);
|
||||
void SmoothControllerYaw(CASW_Player *pPlayer, float &yaw);
|
||||
|
||||
bool PlayerDriving();
|
||||
void ASW_UpdateControllerCodes();
|
||||
|
||||
// finding key names (uses controller binds in controller mode, translates names)
|
||||
const char* ASW_FindKeyBoundTo(const char *binding);
|
||||
const char* MakeHumanReadable(const char *key);
|
||||
|
||||
bool ASW_TryGroundShooting();
|
||||
void ASW_AdjustViewAngleForGroundShooting(QAngle &viewangles);
|
||||
|
||||
#define ASW_MAX_AIM_TRACE 3000.0f
|
||||
#define ASW_MAX_AUTO_AIM_RANGE 2560000.0f // 1600 squared
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: ASW Input interface
|
||||
//-----------------------------------------------------------------------------
|
||||
class CASWInput : public CInput, public IClientEntityListener
|
||||
{
|
||||
public:
|
||||
CASWInput();
|
||||
|
||||
virtual void ASW_GetWindowCenter( int&x, int& y ) { GetWindowCenter(x, y); }
|
||||
virtual void GetFullscreenMousePos( int *mx, int *my, int *unclampedx = NULL, int *unclampedy = NULL );
|
||||
virtual void GetSimulatedFullscreenMousePos( int *mx, int *my, int *unclampedx = 0, int *unclampedy = 0 );
|
||||
virtual void GetSimulatedFullscreenMousePosFromController( int *mx, int *my, float fControllerPitch, float fControllerYaw, float flForwardFraction = 0.4f );
|
||||
void TurnTowardMouse(QAngle& viewangles, CUserCmd *cmd); // asw
|
||||
|
||||
void ComputeNewMarineFacing( C_ASW_Player *pPlayer, const Vector &HitLocation, C_BaseEntity *pHitEnt, IASW_Client_Aim_Target *pAutoAimEnt, bool bPreferFlatAiming, float *pPitch, Vector *pNewMarineFacing );
|
||||
void TurnTowardController(QAngle& viewangles); // asw
|
||||
bool IsAttacking();
|
||||
virtual void ControllerMove( int nSlot, float frametime, CUserCmd *cmd );
|
||||
virtual bool ControllerModeActive() { return m_bControllerMode; }
|
||||
virtual bool JoyStickActive();
|
||||
virtual void JoyStickTurn( CUserCmd *cmd, float &yaw, float &pitch, float frametime, bool bAbsoluteYaw, bool bAbsolutePitch );
|
||||
virtual void JoyStickForwardSideControl( float forward, float side, float &joyForwardMove, float &joySideMove );
|
||||
virtual void JoyStickApplyMovement( CUserCmd *cmd, float joyForwardMove, float joySideMove );
|
||||
|
||||
int m_LastMouseX, m_LastMouseY;
|
||||
EHANDLE m_hLastMarine;
|
||||
bool m_bDontTurnMarine; // set when changing marines, so we don't turn them until the cursor moves
|
||||
float m_fJoypadPitch; // up/down on analogue stick
|
||||
float m_fJoypadYaw; // left/right on analogue stick
|
||||
float m_fJoypadFacingYaw; // desired yaw for our marine
|
||||
bool m_bAutoAttacking;
|
||||
|
||||
bool m_bCursorPlacement; // set to true when the aiming joystick should be used like a mouse for skill placement, rather than robotron-style shooting
|
||||
int m_nRelativeCursorX, m_nRelativeCursorY;
|
||||
float m_flDesiredCursorRadius;
|
||||
float m_flTimeSinceLastTurn;
|
||||
|
||||
virtual float ASW_GetCameraPitch( const float *pfDeathCamInterp = NULL );
|
||||
virtual float ASW_GetCameraYaw( const float *pfDeathCamInterp = NULL );
|
||||
virtual float ASW_GetCameraDist( const float *pfDeathCamInterp = NULL );
|
||||
void ASW_GetCameraLocation( C_ASW_Player *pPlayer, Vector &vecCameraLocation, QAngle &angCamera, int &nMouseX, int &nMouseY, bool bApplySmoothing );
|
||||
virtual int ASW_GetOrderingMarine() { return m_iOrderingMarine; } // ent index of the current marine we're ordering around
|
||||
virtual void ASW_SetOrderingMarine(int iMarineEntIndex) { m_iOrderingMarine = iMarineEntIndex; }
|
||||
|
||||
|
||||
// asw_in_camera.cpp:
|
||||
virtual void CAM_Think( void );
|
||||
virtual void CAM_ToThirdPerson( void );
|
||||
virtual int CAM_IsThirdPerson( int nSlot = -1 );
|
||||
virtual void CAM_ToFirstPerson( void );
|
||||
virtual void CAM_StartMouseMove( void );
|
||||
virtual void CAM_StartDistance( void );
|
||||
virtual void Init_Camera( void );
|
||||
|
||||
// asw_in_mouse.cpp:
|
||||
virtual void ActivateMouse( void );
|
||||
virtual void ResetMouse( void );
|
||||
virtual void AccumulateMouse( int nSlot );
|
||||
virtual void ApplyMouse( int nSlot, QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y );
|
||||
|
||||
// asw_in_main.cpp:
|
||||
virtual int KeyEvent( int down, ButtonCode_t code, const char *pszCurrentBinding );
|
||||
virtual void ExtraMouseSample( float frametime, bool active );
|
||||
virtual void CreateMove ( int sequence_number, float input_sample_frametime, bool active );
|
||||
virtual void Init_All( void );
|
||||
virtual int GetButtonBits( bool bResetState );
|
||||
|
||||
// This is the world position of our crosshair. It is usually raised from the floor to match the marine's gun height.
|
||||
// If the marine is auto-aiming up/down, this position will be raised/lowered.
|
||||
const Vector& GetCrosshairAimingPos() { return m_vecCrosshairAimingPos; }
|
||||
|
||||
// This is the world position of the floor/wall directly beneath the cursor (i.e. a ray traced from the camera through the crosshair into the world)
|
||||
const Vector& GetCrosshairTracePos() { return m_vecCrosshairTracePos; }
|
||||
|
||||
// the entity we're targeting
|
||||
void UpdateHighlightEntity();
|
||||
void SetHighlightEntity( C_BaseEntity* pEnt, bool bGlow );
|
||||
C_BaseEntity* GetHighlightEntity() const;
|
||||
|
||||
// the entity that can be used by the local player
|
||||
void SetUseGlowEntity( C_BaseEntity* pEnt );
|
||||
C_BaseEntity* GetUseGlowEntity() { return m_hUseGlowEntity.Get(); }
|
||||
|
||||
// the entity we're mousing over
|
||||
void SetMouseOverEntity( C_BaseEntity* pEnt );
|
||||
// the entity under our crosshair
|
||||
C_BaseEntity* GetMouseOverEntity() { return m_hMouseOverEntity.Get(); }
|
||||
|
||||
// the entity our weapon is autoaiming at
|
||||
void SetAutoaimEntity( C_BaseEntity* pEnt ) { m_hAutoaimEnt = pEnt; }
|
||||
// the entity under our crosshair
|
||||
C_BaseEntity* GetAutoaimEntity() { return m_hAutoaimEnt.Get(); }
|
||||
|
||||
// controller mode
|
||||
void SetControllerMode( bool bControllerMode );
|
||||
|
||||
virtual void OnEntityDeleted( C_BaseEntity *pEntity );
|
||||
|
||||
// Camera shift
|
||||
void SetCameraFixed( bool bFixed ) { m_bCameraFixed = bFixed; }
|
||||
|
||||
private:
|
||||
float m_fCurrentCameraPitch;
|
||||
float m_flCurrentCameraDist;
|
||||
Vector m_vecCameraVelocity;
|
||||
float m_fShiftFraction;
|
||||
bool m_bCameraFixed;
|
||||
|
||||
void CalculateCameraShift( C_ASW_Player *pPlayer, float flDeltaX, float flDeltaY, float &flShiftX, float &flShiftY );
|
||||
void SmoothCamera( C_ASW_Player *pPlayer, Vector &vecCameraLocation );
|
||||
|
||||
virtual bool ASWWriteVehicleMessage( bf_write *buf );
|
||||
void EngageControllerMode();
|
||||
|
||||
int m_iOrderingMarine; // entindex of marine we're ordering around
|
||||
|
||||
Vector m_vecCrosshairAimingPos;
|
||||
Vector m_vecCrosshairTracePos;
|
||||
EHANDLE m_hMouseOverEntity;
|
||||
bool m_bIsMouseOverEntFriendly;
|
||||
EHANDLE m_hHighlightEntity;
|
||||
EHANDLE m_hUseGlowEntity;
|
||||
EHANDLE m_hAutoaimEnt;
|
||||
|
||||
//CGlowObject m_MouseOverGlowObject;
|
||||
CGlowObject m_HighLightGlowObject;
|
||||
CGlowObject m_UseGlowObject;
|
||||
|
||||
bool m_bControllerMode;
|
||||
};
|
||||
|
||||
extern CASWInput *ASWInput();
|
||||
|
||||
#endif // _INCLUDED_ASW_INPUT_H
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "cbase.h"
|
||||
#include "asw_marineandobjectenumerator.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_player.h"
|
||||
|
||||
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Enumator class for finding other marines and objects close to the
|
||||
// local player's marine
|
||||
CASW_MarineAndObjectEnumerator::CASW_MarineAndObjectEnumerator( float radius )
|
||||
{
|
||||
m_flRadiusSquared = radius * radius;
|
||||
m_Objects.RemoveAll();
|
||||
m_pLocal = C_ASW_Player::GetLocalASWPlayer();
|
||||
}
|
||||
|
||||
int CASW_MarineAndObjectEnumerator::GetObjectCount()
|
||||
{
|
||||
return m_Objects.Count();
|
||||
}
|
||||
|
||||
C_BaseEntity *CASW_MarineAndObjectEnumerator::GetObject( int index )
|
||||
{
|
||||
if ( index < 0 || index >= GetObjectCount() )
|
||||
return NULL;
|
||||
|
||||
return m_Objects[ index ];
|
||||
}
|
||||
|
||||
// Actual work code
|
||||
IterationRetval_t CASW_MarineAndObjectEnumerator::EnumElement( IHandleEntity *pHandleEntity )
|
||||
{
|
||||
if ( !m_pLocal )
|
||||
return ITERATION_STOP;
|
||||
|
||||
C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() );
|
||||
if ( pEnt == NULL )
|
||||
return ITERATION_CONTINUE;
|
||||
|
||||
if ( pEnt == m_pLocal )
|
||||
return ITERATION_CONTINUE;
|
||||
|
||||
if ( !pEnt->IsPlayer() &&
|
||||
!pEnt->IsNPC() )
|
||||
{
|
||||
return ITERATION_CONTINUE;
|
||||
}
|
||||
|
||||
if ( pEnt->IsNPC() )
|
||||
{
|
||||
C_AI_BaseNPC *pNPC = (C_AI_BaseNPC *)pEnt;
|
||||
|
||||
if ( !pNPC->ShouldAvoidObstacle() )
|
||||
return ITERATION_CONTINUE;
|
||||
}
|
||||
|
||||
// Ignore vehicles, since they have vcollide collisions that's push me away
|
||||
if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_VEHICLE )
|
||||
return ITERATION_CONTINUE;
|
||||
|
||||
#ifdef TF2_CLIENT_DLL
|
||||
// If it's solid to player movement, don't steer around it since we'll just bump into it
|
||||
if ( pEnt->GetCollisionGroup() == TFCOLLISION_GROUP_OBJECT_SOLIDTOPLAYERMOVEMENT )
|
||||
return ITERATION_CONTINUE;
|
||||
#endif
|
||||
|
||||
C_ASW_Marine *pMarine = m_pLocal->GetMarine();
|
||||
if (!pMarine)
|
||||
return ITERATION_CONTINUE;
|
||||
|
||||
Vector deltaPos = pEnt->GetAbsOrigin() - pMarine->GetAbsOrigin();
|
||||
//if ( deltaPos.LengthSqr() > m_flRadiusSquared )
|
||||
//return ITERATION_CONTINUE;
|
||||
|
||||
CHandle< C_BaseEntity > h;
|
||||
h = pEnt;
|
||||
m_Objects.AddToTail( h );
|
||||
|
||||
return ITERATION_CONTINUE;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef _DEFINED_ASW_MARINEANDOBJECTENUMERATOR_H
|
||||
#define _DEFINED_ASW_MARINEANDOBJECTENUMERATOR_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "UtlVector.h"
|
||||
#include "ehandle.h"
|
||||
#include "ISpatialPartition.h"
|
||||
|
||||
class C_BaseEntity;
|
||||
class C_ASW_Player;
|
||||
|
||||
// Enumator class for finding other marines and objects close to the
|
||||
// local player's marine
|
||||
class CASW_MarineAndObjectEnumerator : public IPartitionEnumerator
|
||||
{
|
||||
DECLARE_CLASS_NOBASE( CASW_MarineAndObjectEnumerator );
|
||||
public:
|
||||
//Forced constructor
|
||||
CASW_MarineAndObjectEnumerator( float radius );
|
||||
|
||||
//Actual work code
|
||||
virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity );
|
||||
|
||||
int GetObjectCount();
|
||||
C_BaseEntity *GetObject( int index );
|
||||
|
||||
public:
|
||||
//Data members
|
||||
float m_flRadiusSquared;
|
||||
|
||||
CUtlVector< CHandle< C_BaseEntity > > m_Objects;
|
||||
C_ASW_Player *m_pLocal;
|
||||
};
|
||||
|
||||
#endif // _DEFINED_ASW_MARINEANDOBJECTENUMERATOR_H
|
||||
@@ -0,0 +1,749 @@
|
||||
#include "cbase.h"
|
||||
#include <KeyValues.h>
|
||||
#include <filesystem.h>
|
||||
#include "asw_medal_store.h"
|
||||
#include "asw_medals_shared.h"
|
||||
#include "asw_equipment_list.h"
|
||||
#include "c_asw_campaign_save.h"
|
||||
#include "steam/isteamremotestorage.h"
|
||||
#include "steam/steam_api.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern IFileSystem *filesystem;
|
||||
|
||||
C_ASW_Medal_Store g_ClientMedalStore;
|
||||
|
||||
C_ASW_Medal_Store* GetMedalStore() { return &g_ClientMedalStore; }
|
||||
|
||||
unsigned char g_ucMedalStoreEncryptionKey[8] = { 17, 67, 230, 65, 174, 52, 14, 14 };
|
||||
|
||||
C_ASW_Medal_Store::C_ASW_Medal_Store()
|
||||
{
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
m_MarineMedals[i].Purge();
|
||||
m_OfflineMarineMedals[i].Purge();
|
||||
}
|
||||
m_PlayerMedals.Purge();
|
||||
m_OfflinePlayerMedals.Purge();
|
||||
m_bLoaded = false;
|
||||
|
||||
m_iMissionsCompleted = 0;
|
||||
m_iCampaignsCompleted = 0;
|
||||
m_iAliensKilled = 0;
|
||||
|
||||
m_iOfflineMissionsCompleted = 0;
|
||||
m_iOfflineCampaignsCompleted = 0;
|
||||
m_iOfflineAliensKilled = 0;
|
||||
m_iXP = 0;
|
||||
m_iPromotion = 0;
|
||||
m_bFoundNewClientDat = false;
|
||||
}
|
||||
|
||||
ConVar asw_steam_cloud( "asw_steam_cloud", "1", FCVAR_NONE, "Whether Swarm data should be stored in the Steam Cloud" );
|
||||
|
||||
void C_ASW_Medal_Store::LoadMedalStore()
|
||||
{
|
||||
#if defined(NO_STEAM)
|
||||
AssertMsg( false, "SteamCloud not available." );
|
||||
#else
|
||||
ISteamRemoteStorage *pRemoteStorage = SteamClient() ? ( ISteamRemoteStorage * )SteamClient()->GetISteamGenericInterface(
|
||||
SteamAPI_GetHSteamUser(), SteamAPI_GetHSteamPipe(), STEAMREMOTESTORAGE_INTERFACE_VERSION ) : NULL;
|
||||
ISteamUser *pSteamUser = steamapicontext ? steamapicontext->SteamUser() : NULL;
|
||||
if ( !pSteamUser )
|
||||
return;
|
||||
|
||||
char szMedalFile[ 256 ];
|
||||
Q_snprintf( szMedalFile, sizeof( szMedalFile ), "cfg/clientc_%I64u.dat", pSteamUser->GetSteamID().ConvertToUint64() );
|
||||
int len = Q_strlen( szMedalFile );
|
||||
for ( int i = 0; i < len; i++ )
|
||||
{
|
||||
if ( szMedalFile[ i ] == ':' )
|
||||
szMedalFile[i] = '_';
|
||||
}
|
||||
|
||||
if ( asw_steam_cloud.GetBool() && pRemoteStorage )
|
||||
{
|
||||
if ( !GetFileFromRemoteStorage( pRemoteStorage, "PersistentMarines.dat", szMedalFile ) )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
Warning( "Failed to get client.dat from Steam Cloud.\n" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// clear out the currently loaded medals, if any
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
m_MarineMedals[i].Purge();
|
||||
m_OfflineMarineMedals[i].Purge();
|
||||
}
|
||||
m_PlayerMedals.Purge();
|
||||
m_OfflinePlayerMedals.Purge();
|
||||
|
||||
m_bLoaded = true;
|
||||
|
||||
FileHandle_t f = filesystem->Open( szMedalFile, "rb", "MOD" );
|
||||
if ( !f )
|
||||
return; // if we get here, it means the player has no clientc.dat file and therefore no medals
|
||||
|
||||
int fileSize = filesystem->Size(f);
|
||||
char *file_buffer = (char*)MemAllocScratch(fileSize + 1);
|
||||
Assert(file_buffer);
|
||||
filesystem->Read(file_buffer, fileSize, f); // read into local buffer
|
||||
file_buffer[fileSize] = 0; // null terminate file as EOF
|
||||
filesystem->Close( f ); // close file after reading
|
||||
|
||||
UTIL_DecodeICE( (unsigned char*)file_buffer, fileSize, g_ucMedalStoreEncryptionKey );
|
||||
|
||||
KeyValues *kv = new KeyValues( "CLIENTDAT" );
|
||||
if ( !kv->LoadFromBuffer( "CLIENTDAT", file_buffer, filesystem ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MemFreeScratch();
|
||||
|
||||
m_bFoundNewClientDat = true;
|
||||
|
||||
// pull out missions/campaigns/kills
|
||||
m_iMissionsCompleted = kv->GetInt("MC");
|
||||
m_iCampaignsCompleted = kv->GetInt("CC");
|
||||
m_iAliensKilled = kv->GetInt("AK");
|
||||
|
||||
m_iOfflineMissionsCompleted = kv->GetInt("OMC");
|
||||
m_iOfflineCampaignsCompleted = kv->GetInt("OCC");
|
||||
m_iOfflineAliensKilled = kv->GetInt("OAK");
|
||||
|
||||
m_iXP = kv->GetInt( "LPL" );
|
||||
m_iPromotion = kv->GetInt( "LPP" );
|
||||
|
||||
// new equip
|
||||
m_NewEquipment.Purge();
|
||||
KeyValues *pkvEquip = kv->FindKey("NEWEQUIP");
|
||||
char buffer[64];
|
||||
if ( pkvEquip )
|
||||
{
|
||||
for ( KeyValues *pKey = pkvEquip->GetFirstSubKey(); pKey; pKey = pKey->GetNextKey() )
|
||||
{
|
||||
m_NewEquipment.AddToTail( pKey->GetInt() );
|
||||
}
|
||||
}
|
||||
|
||||
// first subsection is player medals
|
||||
//KeyValues *pkvPlayerMedals = kv->GetFirstSubKey();
|
||||
KeyValues *pkvPlayerMedals = kv->FindKey("LP");
|
||||
int iMedalNum = 0;
|
||||
if (pkvPlayerMedals)
|
||||
{
|
||||
int iMedal = 0;
|
||||
while (iMedal != -1)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "M%d", iMedalNum);
|
||||
iMedal = pkvPlayerMedals->GetInt(buffer, -1);
|
||||
if (iMedal != -1 && IsPlayerMedal(iMedal))
|
||||
{
|
||||
m_PlayerMedals.AddToTail(iMedal);
|
||||
}
|
||||
iMedalNum++;
|
||||
}
|
||||
}
|
||||
|
||||
// now go through each marine
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "LA%d", i);
|
||||
KeyValues *pkvMarineMedals = kv->FindKey(buffer);
|
||||
if (pkvMarineMedals)
|
||||
{
|
||||
iMedalNum = 0;
|
||||
int iMedal = 0;
|
||||
while (iMedal != -1)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "M%d", iMedalNum);
|
||||
iMedal = pkvMarineMedals->GetInt(buffer, -1);
|
||||
if (iMedal != -1 && !IsPlayerMedal(iMedal))
|
||||
{
|
||||
m_MarineMedals[i].AddToTail(iMedal);
|
||||
}
|
||||
iMedalNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// offline medal store
|
||||
pkvPlayerMedals = kv->FindKey("FP");
|
||||
iMedalNum = 0;
|
||||
if (pkvPlayerMedals)
|
||||
{
|
||||
int iMedal = 0;
|
||||
while (iMedal != -1)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "M%d", iMedalNum);
|
||||
iMedal = pkvPlayerMedals->GetInt(buffer, -1);
|
||||
if (iMedal != -1 && IsPlayerMedal(iMedal))
|
||||
{
|
||||
m_OfflinePlayerMedals.AddToTail(iMedal);
|
||||
}
|
||||
iMedalNum++;
|
||||
}
|
||||
}
|
||||
|
||||
// now go through each marine
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "FA%d", i);
|
||||
KeyValues *pkvMarineMedals = kv->FindKey(buffer);
|
||||
if (pkvMarineMedals)
|
||||
{
|
||||
iMedalNum = 0;
|
||||
int iMedal = 0;
|
||||
while (iMedal != -1)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "M%d", iMedalNum);
|
||||
iMedal = pkvMarineMedals->GetInt(buffer, -1);
|
||||
if (iMedal != -1 && !IsPlayerMedal(iMedal))
|
||||
{
|
||||
m_OfflineMarineMedals[i].AddToTail(iMedal);
|
||||
}
|
||||
iMedalNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: encrypts an 8-byte sequence
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool C_ASW_Medal_Store::SaveMedalStore()
|
||||
{
|
||||
if ( !m_bLoaded )
|
||||
return false;
|
||||
|
||||
KeyValues *kv = new KeyValues( "CLIENTDAT" );
|
||||
|
||||
// output missions/campaigns/kills
|
||||
kv->SetInt("MC", m_iMissionsCompleted);
|
||||
kv->SetInt("CC", m_iCampaignsCompleted);
|
||||
kv->SetInt("AK", m_iAliensKilled);
|
||||
|
||||
kv->SetInt("OMC", m_iOfflineMissionsCompleted);
|
||||
kv->SetInt("OCC", m_iOfflineCampaignsCompleted);
|
||||
kv->SetInt("OAK", m_iOfflineAliensKilled);
|
||||
|
||||
kv->SetInt( "LPL", m_iXP );
|
||||
kv->SetInt( "LPP", m_iPromotion );
|
||||
|
||||
KeyValues *pSubSection = new KeyValues("NEWEQUIP");
|
||||
char buffer[64];
|
||||
if (pSubSection)
|
||||
{
|
||||
for (int i=0;i<m_NewEquipment.Count();i++)
|
||||
{
|
||||
pSubSection->SetInt( "EQUIP", m_NewEquipment[i]);
|
||||
}
|
||||
kv->AddSubKey(pSubSection);
|
||||
}
|
||||
|
||||
// output player medals
|
||||
pSubSection = new KeyValues("LP");
|
||||
if (pSubSection)
|
||||
{
|
||||
for (int i=0;i<m_PlayerMedals.Count();i++)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "M%d", i);
|
||||
pSubSection->SetInt(buffer, m_PlayerMedals[i]);
|
||||
}
|
||||
kv->AddSubKey(pSubSection);
|
||||
}
|
||||
|
||||
for (int k=0;k<ASW_NUM_MARINE_PROFILES;k++)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "LA%d", k);
|
||||
pSubSection = new KeyValues(buffer);
|
||||
if (pSubSection)
|
||||
{
|
||||
for (int i=0;i<m_MarineMedals[k].Count();i++)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "M%d", i);
|
||||
pSubSection->SetInt(buffer, m_MarineMedals[k][i]);
|
||||
}
|
||||
kv->AddSubKey(pSubSection);
|
||||
}
|
||||
}
|
||||
|
||||
// offline medal store
|
||||
pSubSection = new KeyValues("FP");
|
||||
if (pSubSection)
|
||||
{
|
||||
for (int i=0;i<m_OfflinePlayerMedals.Count();i++)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "M%d", i);
|
||||
pSubSection->SetInt(buffer, m_OfflinePlayerMedals[i]);
|
||||
}
|
||||
kv->AddSubKey(pSubSection);
|
||||
}
|
||||
|
||||
for (int k=0;k<ASW_NUM_MARINE_PROFILES;k++)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "FA%d", k);
|
||||
pSubSection = new KeyValues(buffer);
|
||||
if (pSubSection)
|
||||
{
|
||||
for (int i=0;i<m_OfflineMarineMedals[k].Count();i++)
|
||||
{
|
||||
Q_snprintf(buffer, sizeof(buffer), "M%d", i);
|
||||
pSubSection->SetInt(buffer, m_OfflineMarineMedals[k][i]);
|
||||
}
|
||||
kv->AddSubKey(pSubSection);
|
||||
}
|
||||
}
|
||||
|
||||
CUtlBuffer buf; //( 0, 0, CUtlBuffer::TEXT_BUFFER );
|
||||
kv->RecursiveSaveToFile( buf, 0 );
|
||||
|
||||
// pad buffer with zeroes to make a multiple of 8
|
||||
int nExtra = buf.TellPut() % 8;
|
||||
while ( nExtra != 0 && nExtra < 8 )
|
||||
{
|
||||
buf.PutChar( 0 );
|
||||
nExtra++;
|
||||
}
|
||||
UTIL_EncodeICE( (unsigned char*) buf.Base(), buf.TellPut(), g_ucMedalStoreEncryptionKey );
|
||||
|
||||
ISteamUser *pSteamUser = steamapicontext ? steamapicontext->SteamUser() : NULL;
|
||||
if ( !pSteamUser )
|
||||
return false;
|
||||
|
||||
char szMedalFile[ 256 ];
|
||||
Q_snprintf( szMedalFile, sizeof( szMedalFile ), "cfg/clientc_%I64u.dat", pSteamUser->GetSteamID().ConvertToUint64() );
|
||||
int len = Q_strlen( szMedalFile );
|
||||
for ( int i = 0; i < len; i++ )
|
||||
{
|
||||
if ( szMedalFile[ i ] == ':' )
|
||||
szMedalFile[i] = '_';
|
||||
}
|
||||
|
||||
bool bResult = filesystem->WriteFile( szMedalFile, "MOD", buf );
|
||||
if ( bResult )
|
||||
{
|
||||
#if defined(NO_STEAM)
|
||||
AssertMsg( false, "SteamCloud not available." );
|
||||
#else
|
||||
ISteamRemoteStorage *pRemoteStorage = SteamClient() ? ( ISteamRemoteStorage * )SteamClient()->GetISteamGenericInterface(
|
||||
SteamAPI_GetHSteamUser(), SteamAPI_GetHSteamPipe(), STEAMREMOTESTORAGE_INTERFACE_VERSION ) : NULL;
|
||||
|
||||
if ( asw_steam_cloud.GetBool() && pRemoteStorage )
|
||||
{
|
||||
WriteFileToRemoteStorage( pRemoteStorage, "PersistentMarines.dat", szMedalFile );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool C_ASW_Medal_Store::IsPlayerMedal(int i)
|
||||
{
|
||||
return (i == MEDAL_IAF_TRAINING || i == MEDAL_IAF_COMBAT_HONORS || i == MEDAL_IAF_BATTLE_HONORS
|
||||
|| i == MEDAL_IAF_CAMPAIGN_HONORS || i == MEDAL_IAF_WARTIME_SERVICE || i == MEDAL_PROFESSIONAL ||
|
||||
i == MEDAL_NEMESIS || i == MEDAL_RETRIBUTION || i == MEDAL_IAF_HERO);
|
||||
}
|
||||
|
||||
// output all the medals in the store
|
||||
void C_ASW_Medal_Store::DebugInfo()
|
||||
{
|
||||
Msg("Outputting online client medal store:\n");
|
||||
Msg("Missions: %d Campaigns: %d Kills: %d\n", m_iMissionsCompleted, m_iCampaignsCompleted, m_iAliensKilled);
|
||||
Msg("Player Medals: (%d)\n", m_PlayerMedals.Count());
|
||||
for (int i=0;i<m_PlayerMedals.Count();i++)
|
||||
{
|
||||
Msg("%d ", m_PlayerMedals[i]);
|
||||
}
|
||||
Msg("\n");
|
||||
|
||||
for (int k=0;k<ASW_NUM_MARINE_PROFILES;k++)
|
||||
{
|
||||
Msg("Marine %d Medals: (%d)\n", k, m_MarineMedals[k].Count());
|
||||
for (int i=0;i<m_MarineMedals[k].Count();i++)
|
||||
{
|
||||
Msg("%d ", m_MarineMedals[k][i]);
|
||||
}
|
||||
Msg("\n");
|
||||
}
|
||||
|
||||
Msg("Outputting offline client medal store:\n");
|
||||
Msg("Missions: %d Campaigns: %d Kills: %d\n", m_iOfflineMissionsCompleted, m_iOfflineCampaignsCompleted, m_iOfflineAliensKilled);
|
||||
Msg("Player Medals: (%d)\n", m_OfflinePlayerMedals.Count());
|
||||
for (int i=0;i<m_OfflinePlayerMedals.Count();i++)
|
||||
{
|
||||
Msg("%d ", m_OfflinePlayerMedals[i]);
|
||||
}
|
||||
Msg("\n");
|
||||
|
||||
for (int k=0;k<ASW_NUM_MARINE_PROFILES;k++)
|
||||
{
|
||||
Msg("Marine %d Medals: (%d)\n", k, m_OfflineMarineMedals[k].Count());
|
||||
for (int i=0;i<m_OfflineMarineMedals[k].Count();i++)
|
||||
{
|
||||
Msg("%d ", m_OfflineMarineMedals[k][i]);
|
||||
}
|
||||
Msg("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// a marine has just been awarded some medals - add to the client store
|
||||
// HUMMM - what if the level is cancelled and retried?
|
||||
// in single mission, this doesn't count, so medals should be awarded there fine.
|
||||
// in campaign - only matters for outstanding execution and speed run really - but let's only award those if all marines make it there alive
|
||||
bool C_ASW_Medal_Store::OnAwardedMedals(const char *pszMedalsAwarded, int iProfileIndex, bool bMultiplayer)
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
|
||||
// break up the medal string into medal numbers
|
||||
const char *p = pszMedalsAwarded;
|
||||
char token[128];
|
||||
bool bAddedMedal = false;
|
||||
|
||||
p = nexttoken( token, p, ' ' );
|
||||
while ( Q_strlen( token ) > 0 )
|
||||
{
|
||||
int iMedalIndex = atoi(token);
|
||||
bAddedMedal |= AddMarineMedal(iProfileIndex, iMedalIndex, bMultiplayer);
|
||||
if (p)
|
||||
p = nexttoken( token, p, ' ' );
|
||||
else
|
||||
token[0] = '\0';
|
||||
}
|
||||
|
||||
if (bAddedMedal)
|
||||
SaveMedalStore();
|
||||
|
||||
return bAddedMedal;
|
||||
}
|
||||
|
||||
// the player has been awarded medal(s), save it into our store
|
||||
bool C_ASW_Medal_Store::OnAwardedPlayerMedals(int iPlayerIndex, const char *pszPlayerMedals, bool bMultiplayer)
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
|
||||
if (iPlayerIndex < 0 || iPlayerIndex >= ASW_MAX_READY_PLAYERS)
|
||||
return false;
|
||||
|
||||
// NOTE: should only save if the playerindex matches the local player, but we can't check that here?
|
||||
// we'll assume our caller has checked this
|
||||
|
||||
// break up the medal string into medal numbers
|
||||
const char *p = pszPlayerMedals;
|
||||
char token[128];
|
||||
bool bAddedMedal = false;
|
||||
|
||||
p = nexttoken( token, p, ' ' );
|
||||
while ( Q_strlen( token ) > 0 )
|
||||
{
|
||||
int iMedalIndex = atoi(token);
|
||||
bAddedMedal |= AddPlayerMedal(iMedalIndex, bMultiplayer);
|
||||
if (p)
|
||||
p = nexttoken( token, p, ' ' );
|
||||
else
|
||||
token[0] = '\0';
|
||||
}
|
||||
|
||||
if (bAddedMedal)
|
||||
SaveMedalStore();
|
||||
|
||||
return bAddedMedal;
|
||||
}
|
||||
|
||||
bool C_ASW_Medal_Store::AddMarineMedal(int iProfileIndex, int iMedal, bool bMultiplayer)
|
||||
{
|
||||
if (iProfileIndex < 0 || iProfileIndex >= ASW_NUM_MARINE_PROFILES)
|
||||
return false;
|
||||
|
||||
if (IsPlayerMedal(iMedal))
|
||||
return false;
|
||||
|
||||
if (!bMultiplayer)
|
||||
{
|
||||
// marine already has the medal?
|
||||
if (m_OfflineMarineMedals[iProfileIndex].Find(iMedal) != m_OfflineMarineMedals[iProfileIndex].InvalidIndex())
|
||||
return false;
|
||||
|
||||
m_OfflineMarineMedals[iProfileIndex].AddToTail(iMedal);
|
||||
}
|
||||
else
|
||||
{
|
||||
// marine already has the medal?
|
||||
if (m_MarineMedals[iProfileIndex].Find(iMedal) != m_MarineMedals[iProfileIndex].InvalidIndex())
|
||||
return false;
|
||||
|
||||
m_MarineMedals[iProfileIndex].AddToTail(iMedal);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C_ASW_Medal_Store::AddPlayerMedal(int iMedal, bool bMultiplayer)
|
||||
{
|
||||
if (!bMultiplayer)
|
||||
{
|
||||
// player already has the medal?
|
||||
if (m_OfflinePlayerMedals.Find(iMedal) != m_OfflinePlayerMedals.InvalidIndex())
|
||||
return false;
|
||||
|
||||
if (!IsPlayerMedal(iMedal))
|
||||
return false;
|
||||
|
||||
m_OfflinePlayerMedals.AddToTail(iMedal);
|
||||
|
||||
if (iMedal == MEDAL_IAF_TRAINING) // add to multiplayer listing too, just so the multi collection is completable
|
||||
{
|
||||
m_PlayerMedals.AddToTail(iMedal);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// player already has the medal?
|
||||
if (m_PlayerMedals.Find(iMedal) != m_PlayerMedals.InvalidIndex())
|
||||
return false;
|
||||
|
||||
if (!IsPlayerMedal(iMedal))
|
||||
return false;
|
||||
|
||||
m_PlayerMedals.AddToTail(iMedal);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// clears all the medals/xp this player has found!
|
||||
void C_ASW_Medal_Store::ClearMedalStore()
|
||||
{
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
m_MarineMedals[i].Purge();
|
||||
m_OfflineMarineMedals[i].Purge();
|
||||
}
|
||||
m_PlayerMedals.Purge();
|
||||
m_OfflinePlayerMedals.Purge();
|
||||
m_iXP = 0;
|
||||
m_iPromotion = 0;
|
||||
m_NewEquipment.Purge();
|
||||
SaveMedalStore();
|
||||
}
|
||||
|
||||
bool C_ASW_Medal_Store::HasMedal(int iMedalIndex, bool bOffline, int iMarine)
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
|
||||
if (!bOffline)
|
||||
{
|
||||
if (IsPlayerMedal(iMedalIndex))
|
||||
{
|
||||
if (iMarine != -1)
|
||||
return false;
|
||||
int i = m_PlayerMedals.Find(iMedalIndex);
|
||||
if (i == m_PlayerMedals.InvalidIndex())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
if (i == iMarine || iMarine == -1)
|
||||
{
|
||||
int h = m_MarineMedals[i].Find(iMedalIndex);
|
||||
if (h != m_MarineMedals[i].InvalidIndex())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsPlayerMedal(iMedalIndex))
|
||||
{
|
||||
if (iMarine != -1)
|
||||
return false;
|
||||
int i = m_OfflinePlayerMedals.Find(iMedalIndex);
|
||||
if (i == m_OfflinePlayerMedals.InvalidIndex())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
if (i == iMarine || iMarine == -1)
|
||||
{
|
||||
int h = m_OfflineMarineMedals[i].Find(iMedalIndex);
|
||||
if (h != m_OfflineMarineMedals[i].InvalidIndex())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reset_xp_f()
|
||||
{
|
||||
if ( GetMedalStore() )
|
||||
{
|
||||
GetMedalStore()->ClearMedalStore();
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand reset_xp( "reset_xp", reset_xp_f, "Clears your experience", FCVAR_DEVELOPMENTONLY );
|
||||
|
||||
|
||||
void C_ASW_Medal_Store::OnIncreaseCounts(int iAddMission, int iAddCampaign, int iAddKills, bool bOffline)
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
|
||||
if (bOffline)
|
||||
{
|
||||
m_iOfflineMissionsCompleted += iAddMission;
|
||||
m_iOfflineCampaignsCompleted += iAddCampaign;
|
||||
m_iOfflineAliensKilled += iAddKills;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iMissionsCompleted += iAddMission;
|
||||
m_iCampaignsCompleted += iAddCampaign;
|
||||
m_iAliensKilled += iAddKills;
|
||||
}
|
||||
SaveMedalStore();
|
||||
}
|
||||
|
||||
void C_ASW_Medal_Store::GetCounts(int &iMissions, int &iCampaigns, int &iKills, bool bOffline)
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
|
||||
if (bOffline)
|
||||
{
|
||||
iMissions = m_iOfflineMissionsCompleted;
|
||||
iCampaigns = m_iOfflineCampaignsCompleted;
|
||||
iKills = m_iOfflineAliensKilled;
|
||||
}
|
||||
else
|
||||
{
|
||||
iMissions = m_iMissionsCompleted;
|
||||
iCampaigns = m_iCampaignsCompleted;
|
||||
iKills = m_iAliensKilled;
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Medal_Store::OnUnlockedEquipment( const char *pszWeaponUnlockClass )
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
if ( !ASWEquipmentList() )
|
||||
return;
|
||||
|
||||
int nEquipmentListIndex = ASWEquipmentList()->GetRegularIndex( pszWeaponUnlockClass );
|
||||
bool bExtraItem = false;
|
||||
if ( nEquipmentListIndex == -1 )
|
||||
{
|
||||
bExtraItem = true;
|
||||
nEquipmentListIndex = ASWEquipmentList()->GetExtraIndex( pszWeaponUnlockClass );
|
||||
if ( nEquipmentListIndex == -1 )
|
||||
return;
|
||||
}
|
||||
|
||||
int nIndexHash = nEquipmentListIndex + ( bExtraItem ? 100 : 0 );
|
||||
if ( m_NewEquipment.Find( nIndexHash ) == m_NewEquipment.InvalidIndex() )
|
||||
{
|
||||
m_NewEquipment.AddToTail( nIndexHash );
|
||||
SaveMedalStore();
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Medal_Store::OnSelectedEquipment( bool bExtraItem, int nEquipmentListIndex )
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
int nIndexHash = nEquipmentListIndex + ( bExtraItem ? 100 : 0 );
|
||||
if ( m_NewEquipment.Find( nIndexHash ) != m_NewEquipment.InvalidIndex() )
|
||||
{
|
||||
m_NewEquipment.FindAndRemove( nIndexHash );
|
||||
SaveMedalStore();
|
||||
}
|
||||
}
|
||||
|
||||
bool C_ASW_Medal_Store::IsWeaponNew( bool bExtraItem, int nEquipmentListIndex )
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
int nIndexHash = nEquipmentListIndex + ( bExtraItem ? 100 : 0 );
|
||||
//Msg( "C_ASW_Medal_Store::IsWeaponNew bextra=%d index=%d hash=%d found=%d m_NewEquipmentcount=%d\n", bExtraItem, nEquipmentListIndex, nIndexHash, ( m_NewEquipment.Find( nIndexHash ) != m_NewEquipment.InvalidIndex() ), m_NewEquipment.Count() );
|
||||
return ( m_NewEquipment.Find( nIndexHash ) != m_NewEquipment.InvalidIndex() );
|
||||
}
|
||||
|
||||
void C_ASW_Medal_Store::ClearNewWeapons()
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
m_NewEquipment.RemoveAll();
|
||||
}
|
||||
|
||||
void C_ASW_Medal_Store::SetExperience( int nXP )
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
m_iXP = nXP;
|
||||
}
|
||||
|
||||
int C_ASW_Medal_Store::GetExperience()
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
return m_iXP;
|
||||
}
|
||||
|
||||
void C_ASW_Medal_Store::SetPromotion( int nPromotion )
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
m_iPromotion = nPromotion;
|
||||
}
|
||||
|
||||
int C_ASW_Medal_Store::GetPromotion()
|
||||
{
|
||||
if (!m_bLoaded)
|
||||
{
|
||||
LoadMedalStore();
|
||||
}
|
||||
return m_iPromotion;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#ifndef _INCLUDED_C_ASW_MEDAL_STORE_H
|
||||
#define _INCLUDED_C_ASW_MEDAL_STORE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "asw_shareddefs.h"
|
||||
#include "asw_medals_shared.h"
|
||||
|
||||
// class responsible for loading/saving the client's medal store
|
||||
|
||||
class C_ASW_Marine_Resource;
|
||||
|
||||
class C_ASW_Medal_Store
|
||||
{
|
||||
public:
|
||||
C_ASW_Medal_Store();
|
||||
|
||||
void LoadMedalStore();
|
||||
bool SaveMedalStore();
|
||||
void ClearMedalStore();
|
||||
|
||||
bool IsPlayerMedal(int i);
|
||||
void DebugInfo();
|
||||
|
||||
bool OnAwardedMedals(const char *pszMedalsAwarded, int iProfileIndex, bool bMultiplayer);
|
||||
bool AddMarineMedal(int iProfileIndex, int iMedal, bool bMultiplayer);
|
||||
|
||||
bool OnAwardedPlayerMedals(int iPlayerIndex, const char *pszPlayerMedals, bool bMultiplayer);
|
||||
bool AddPlayerMedal(int iMedal, bool bMultiplayer);
|
||||
|
||||
void OnIncreaseCounts(int iAddMission, int iAddCampaign, int iAddKills, bool bOffline);
|
||||
void GetCounts(int &iMissions, int &iCampaigns, int &iKills, bool bOffline);
|
||||
|
||||
bool HasMedal(int iMedalIndex, bool bOffline, int iMarine=-1);
|
||||
|
||||
void OnUnlockedEquipment( const char *pszWeaponUnlockClass );
|
||||
void OnSelectedEquipment( bool bExtraItem, int nEquipmentListIndex );
|
||||
bool IsWeaponNew( bool bExtraItem, int nEquipmentListIndex );
|
||||
void ClearNewWeapons();
|
||||
|
||||
void SetExperience( int nXP );
|
||||
int GetExperience();
|
||||
|
||||
void SetPromotion( int nPromotion );
|
||||
int GetPromotion();
|
||||
|
||||
bool m_bFoundNewClientDat;
|
||||
|
||||
private:
|
||||
typedef CUtlVector<int> MedalList_t;
|
||||
|
||||
int m_iMissionsCompleted;
|
||||
int m_iCampaignsCompleted;
|
||||
int m_iAliensKilled;
|
||||
|
||||
int m_iOfflineMissionsCompleted;
|
||||
int m_iOfflineCampaignsCompleted;
|
||||
int m_iOfflineAliensKilled;
|
||||
|
||||
MedalList_t m_MarineMedals[ASW_NUM_MARINE_PROFILES];
|
||||
MedalList_t m_PlayerMedals;
|
||||
|
||||
MedalList_t m_OfflineMarineMedals[ASW_NUM_MARINE_PROFILES];
|
||||
MedalList_t m_OfflinePlayerMedals;
|
||||
bool m_bLoaded;
|
||||
|
||||
CUtlVector<int> m_NewEquipment;
|
||||
|
||||
int m_iXP;
|
||||
int m_iPromotion;
|
||||
};
|
||||
|
||||
C_ASW_Medal_Store* GetMedalStore();
|
||||
|
||||
#endif // _INCLUDED_C_ASW_MEDAL_STORE_H
|
||||
@@ -0,0 +1,315 @@
|
||||
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
#include "cbase.h"
|
||||
#include "prediction.h"
|
||||
#include "c_baseplayer.h"
|
||||
#include "igamemovement.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "prediction_private.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include "con_nprint.h"
|
||||
#include "IClientVehicle.h"
|
||||
#include "asw_movedata.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
static CASW_MoveData g_MoveData;
|
||||
CMoveData *g_pMoveData = &g_MoveData;
|
||||
extern IGameMovement *g_pGameMovement;
|
||||
|
||||
extern ConVar asw_allow_detach;
|
||||
extern ConVar cl_showerror;
|
||||
typedescription_t *FindFieldByName( const char *fieldname, datamap_t *dmap );
|
||||
|
||||
class CASW_Prediction : public CPrediction
|
||||
{
|
||||
DECLARE_CLASS( CASW_Prediction, CPrediction );
|
||||
|
||||
public:
|
||||
CASW_Prediction();
|
||||
|
||||
virtual void SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move );
|
||||
virtual void RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *moveHelper );
|
||||
|
||||
virtual void CheckError( int nSlot, C_BasePlayer *player, int commands_acknowledged );
|
||||
virtual void CheckMarineError( int nSlot, int commands_acknowledged );
|
||||
|
||||
protected:
|
||||
|
||||
bool m_bMarineOriginTypedescriptionSearched;
|
||||
CUtlVector< const typedescription_t * > m_MarineOriginTypeDescription; // A vector in cases where the .x, .y, and .z are separately listed
|
||||
|
||||
};
|
||||
|
||||
CASW_Prediction::CASW_Prediction() :
|
||||
m_bMarineOriginTypedescriptionSearched( false )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASW_Prediction::CheckError( int nSlot, C_BasePlayer *player, int commands_acknowledged )
|
||||
{
|
||||
#if !defined( NO_ENTITY_PREDICTION )
|
||||
// Infesed - check marine prediction error as well as player's:
|
||||
CheckMarineError(nSlot, commands_acknowledged);
|
||||
#endif
|
||||
|
||||
BaseClass::CheckError( nSlot, player, commands_acknowledged );
|
||||
}
|
||||
|
||||
void CASW_Prediction::CheckMarineError( int nSlot, int commands_acknowledged )
|
||||
{
|
||||
C_ASW_Player *player;
|
||||
Vector origin;
|
||||
Vector delta;
|
||||
float len;
|
||||
static int pos = 0;
|
||||
|
||||
// Not in the game yet
|
||||
if ( !engine->IsInGame() )
|
||||
return;
|
||||
|
||||
// Not running prediction
|
||||
if ( !cl_predict->GetInt() )
|
||||
return;
|
||||
|
||||
player = C_ASW_Player::GetLocalASWPlayer( nSlot );
|
||||
if ( !player )
|
||||
return;
|
||||
|
||||
C_ASW_Marine* pMarine = player->GetMarine();
|
||||
if (!pMarine)
|
||||
return;
|
||||
|
||||
// Not predictable yet (flush entity packet?)
|
||||
if ( !pMarine->IsIntermediateDataAllocated() )
|
||||
return;
|
||||
|
||||
origin = pMarine->GetNetworkOrigin();
|
||||
|
||||
const void *slot = pMarine->GetPredictedFrame( commands_acknowledged - 1 );
|
||||
if ( !slot )
|
||||
return;
|
||||
|
||||
if ( !m_bMarineOriginTypedescriptionSearched )
|
||||
{
|
||||
m_bMarineOriginTypedescriptionSearched = true;
|
||||
const typedescription_t *td = CPredictionCopy::FindFlatFieldByName( "m_vecNetworkOrigin", pMarine->GetPredDescMap() );
|
||||
if ( td )
|
||||
{
|
||||
m_MarineOriginTypeDescription.AddToTail( td );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_MarineOriginTypeDescription.Count() )
|
||||
return;
|
||||
|
||||
Vector predicted_origin;
|
||||
|
||||
memcpy( (Vector *)&predicted_origin, (Vector *)( (byte *)slot + m_MarineOriginTypeDescription[ 0 ]->flatOffset[ TD_OFFSET_PACKED ] ), sizeof( Vector ) );
|
||||
|
||||
// Compare what the server returned with what we had predicted it to be
|
||||
VectorSubtract ( predicted_origin, origin, delta );
|
||||
|
||||
len = VectorLength( delta );
|
||||
if (len > MAX_PREDICTION_ERROR )
|
||||
{
|
||||
// A teleport or something, clear out error
|
||||
len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( len > MIN_PREDICTION_EPSILON )
|
||||
{
|
||||
pMarine->NotePredictionError( delta );
|
||||
|
||||
if ( cl_showerror.GetInt() >= 1 )
|
||||
{
|
||||
con_nprint_t np;
|
||||
np.fixed_width_font = true;
|
||||
np.color[0] = 1.0f;
|
||||
np.color[1] = 0.95f;
|
||||
np.color[2] = 0.7f;
|
||||
np.index = 20 + ( ++pos % 20 );
|
||||
np.time_to_live = 2.0f;
|
||||
|
||||
engine->Con_NXPrintf( &np, "marine pred error %6.3f units (%6.3f %6.3f %6.3f)", len, delta.x, delta.y, delta.z );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASW_Prediction::SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper,
|
||||
CMoveData *move )
|
||||
{
|
||||
// Call the default SetupMove code.
|
||||
BaseClass::SetupMove( player, ucmd, pHelper, move );
|
||||
|
||||
CASW_Player *pASWPlayer = static_cast<CASW_Player*>( player );
|
||||
if ( !asw_allow_detach.GetBool() )
|
||||
{
|
||||
if ( pASWPlayer && pASWPlayer->GetMarine() )
|
||||
{
|
||||
// this forces horizontal movement
|
||||
move->m_vecAngles.x = 0;
|
||||
move->m_vecViewAngles.x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntity *pMoveParent = player->GetMoveParent();
|
||||
if (!pMoveParent)
|
||||
{
|
||||
move->m_vecAbsViewAngles = move->m_vecViewAngles;
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix3x4_t viewToParent, viewToWorld;
|
||||
AngleMatrix( move->m_vecViewAngles, viewToParent );
|
||||
ConcatTransforms( pMoveParent->EntityToWorldTransform(), viewToParent, viewToWorld );
|
||||
MatrixAngles( viewToWorld, move->m_vecAbsViewAngles );
|
||||
}
|
||||
CASW_MoveData *pASWMove = static_cast<CASW_MoveData*>( move );
|
||||
pASWMove->m_iForcedAction = ucmd->forced_action;
|
||||
// setup trace optimization
|
||||
g_pGameMovement->SetupMovementBounds( move );
|
||||
}
|
||||
|
||||
extern void DiffPrint( bool bServer, int nCommandNumber, char const *fmt, ... );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Predicts a single movement command for player
|
||||
// Input : *moveHelper -
|
||||
// *player -
|
||||
// *u -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASW_Prediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *moveHelper )
|
||||
{
|
||||
#if !defined( NO_ENTITY_PREDICTION )
|
||||
VPROF( "CPrediction::RunCommand" );
|
||||
#if defined( _DEBUG )
|
||||
char sz[ 32 ];
|
||||
Q_snprintf( sz, sizeof( sz ), "runcommand%04d", ucmd->command_number );
|
||||
PREDICTION_TRACKVALUECHANGESCOPE( sz );
|
||||
#endif
|
||||
|
||||
C_ASW_Player *pASWPlayer = (C_ASW_Player*)player;
|
||||
Assert( pASWPlayer );
|
||||
|
||||
StartCommand( player, ucmd );
|
||||
|
||||
pASWPlayer->SetHighlightEntity( C_BaseEntity::Instance( ucmd->crosshair_entity ) );
|
||||
|
||||
// Set globals appropriately
|
||||
gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL;
|
||||
gpGlobals->frametime = TICK_INTERVAL;
|
||||
|
||||
g_pGameMovement->StartTrackPredictionErrors( player );
|
||||
|
||||
// TODO
|
||||
// TODO: Check for impulse predicted?
|
||||
|
||||
// Do weapon selection
|
||||
if ( ucmd->weaponselect != 0 )
|
||||
{
|
||||
C_BaseCombatWeapon *weapon = dynamic_cast< C_BaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
|
||||
if (weapon)
|
||||
{
|
||||
pASWPlayer->ASWSelectWeapon(weapon, 0); //ucmd->weaponsubtype); // asw - subtype var used for sending marine profile index instead
|
||||
}
|
||||
}
|
||||
|
||||
// Latch in impulse.
|
||||
IClientVehicle *pVehicle = player->GetVehicle();
|
||||
if ( ucmd->impulse )
|
||||
{
|
||||
// Discard impulse commands unless the vehicle allows them.
|
||||
// FIXME: UsingStandardWeapons seems like a bad filter for this.
|
||||
// The flashlight is an impulse command, for example.
|
||||
if ( !pVehicle || player->UsingStandardWeaponsInVehicle() )
|
||||
{
|
||||
player->m_nImpulse = ucmd->impulse;
|
||||
}
|
||||
}
|
||||
|
||||
// Get button states
|
||||
player->UpdateButtonState( ucmd->buttons );
|
||||
|
||||
// TODO
|
||||
// CheckMovingGround( player, ucmd->frametime );
|
||||
|
||||
// TODO
|
||||
// g_pMoveData->m_vecOldAngles = player->pl.v_angle;
|
||||
|
||||
// Copy from command to player unless game .dll has set angle using fixangle
|
||||
// if ( !player->pl.fixangle )
|
||||
{
|
||||
player->SetLocalViewAngles( ucmd->viewangles );
|
||||
}
|
||||
|
||||
// Call standard client pre-think
|
||||
RunPreThink( player );
|
||||
|
||||
// Call Think if one is set
|
||||
RunThink( player, TICK_INTERVAL );
|
||||
|
||||
// Setup input.
|
||||
{
|
||||
|
||||
SetupMove( player, ucmd, moveHelper, g_pMoveData );
|
||||
}
|
||||
|
||||
// Run regular player movement if we're not controlling a marine
|
||||
if ( asw_allow_detach.GetBool() )
|
||||
{
|
||||
if ( !pVehicle )
|
||||
{
|
||||
Assert( g_pGameMovement );
|
||||
g_pGameMovement->ProcessMovement( player, g_pMoveData );
|
||||
}
|
||||
else
|
||||
{
|
||||
pVehicle->ProcessMovement( player, g_pMoveData );
|
||||
}
|
||||
}
|
||||
|
||||
// if ( !asw_allow_detach.GetBool() && pASWPlayer->GetMarine() )
|
||||
// {
|
||||
// g_pMoveData->SetAbsOrigin( pASWPlayer->GetMarine()->GetAbsOrigin() );
|
||||
// }
|
||||
|
||||
pASWPlayer->SetCrosshairTracePos( ucmd->crosshairtrace );
|
||||
|
||||
FinishMove( player, ucmd, g_pMoveData );
|
||||
|
||||
RunPostThink( player );
|
||||
|
||||
// let the player drive marine movement here
|
||||
pASWPlayer->DriveMarineMovement( ucmd, moveHelper );
|
||||
|
||||
g_pGameMovement->FinishTrackPredictionErrors( player );
|
||||
|
||||
FinishCommand( player );
|
||||
|
||||
player->m_nTickBase++;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Expose interface to engine
|
||||
// Expose interface to engine
|
||||
static CASW_Prediction g_Prediction;
|
||||
|
||||
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CASW_Prediction, IPrediction, VCLIENT_PREDICTION_INTERFACE_VERSION, g_Prediction );
|
||||
|
||||
CPrediction *prediction = &g_Prediction;
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
#include "cbase.h"
|
||||
#include "view.h"
|
||||
#include "view_shared.h"
|
||||
#include "KeyValues.h"
|
||||
#include "bitmap/tgawriter.h"
|
||||
#include "iviewrender.h"
|
||||
#include "filesystem.h"
|
||||
#include "p4lib/ip4.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// This takes a top down orthographic thumbnail screenshot of all rooms specified in roomthumbnails.txt
|
||||
|
||||
ConVar asw_building_room_thumbnails( "asw_building_room_thumbnails", "0", FCVAR_CHEAT, "Set to 1 to cause room thumbnails to be saved on next map load" );
|
||||
ConVar asw_add_room_thumbnails_to_perforce( "asw_add_room_thumbnails_to_perforce", "0", FCVAR_CHEAT, "Set to 1 to cause room thumbnails to be added to Perforce on creation" );
|
||||
|
||||
struct CRoomThumbnail
|
||||
{
|
||||
char m_szThumbnailName[MAX_PATH];
|
||||
float m_fRoomX;
|
||||
float m_fRoomY;
|
||||
float m_fRoomWide;
|
||||
float m_fRoomTall;
|
||||
int m_iOutputWide;
|
||||
int m_iOutputTall;
|
||||
};
|
||||
|
||||
static void SetupThumbnailView( CViewSetup &setup, CRoomThumbnail *pRoom )
|
||||
{
|
||||
memset( &setup, 0, sizeof(setup) );
|
||||
static int oldCRC = 0;
|
||||
|
||||
setup.m_bOrtho = true;
|
||||
setup.m_flAspectRatio = 1.0f;
|
||||
setup.m_bRenderToSubrectOfLargerScreen = true;
|
||||
setup.zNear = 7.0f;
|
||||
setup.zFar = 28400.0f;
|
||||
setup.fov = 90.0f;
|
||||
|
||||
float size_y = pRoom->m_fRoomTall;
|
||||
float size_x = pRoom->m_fRoomWide;
|
||||
|
||||
setup.origin.x = pRoom->m_fRoomX;
|
||||
setup.origin.y = pRoom->m_fRoomY;
|
||||
setup.origin.z = 400.0f;
|
||||
|
||||
setup.x = 0;
|
||||
setup.y = 0;
|
||||
setup.width = pRoom->m_iOutputWide;
|
||||
setup.height = pRoom->m_iOutputTall;
|
||||
|
||||
setup.m_OrthoLeft = 0;
|
||||
setup.m_OrthoTop = -size_y;
|
||||
setup.m_OrthoRight = size_x;
|
||||
setup.m_OrthoBottom = 0;
|
||||
|
||||
setup.angles = QAngle( 90, 90, 0 );
|
||||
}
|
||||
|
||||
static void TakeRoomThumbnailSnapshot( CRoomThumbnail *pRoom )
|
||||
{
|
||||
if ( IsX360() )
|
||||
return;
|
||||
|
||||
CViewSetup setup;
|
||||
SetupThumbnailView( setup, pRoom );
|
||||
|
||||
view->RenderView( setup, setup, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH | VIEW_CLEAR_FULL_TARGET, 0 );
|
||||
|
||||
unsigned char *pImage = ( unsigned char * )malloc( setup.width * 3 * setup.height );
|
||||
|
||||
// Get Bits from the material system
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->ReadPixels( 0, 0, setup.width, setup.height, pImage, IMAGE_FORMAT_RGB888 );
|
||||
|
||||
// allocate a buffer to write the tga into
|
||||
int iMaxTGASize = 1024 + (setup.width * setup.height * 4);
|
||||
void *pTGA = malloc( iMaxTGASize );
|
||||
CUtlBuffer buffer( pTGA, iMaxTGASize );
|
||||
|
||||
if( !TGAWriter::WriteToBuffer( pImage, buffer, setup.width, setup.height, IMAGE_FORMAT_RGB888, IMAGE_FORMAT_RGB888 ) )
|
||||
{
|
||||
Error( "Couldn't write bitmap data snapshot.\n" );
|
||||
}
|
||||
|
||||
free( pImage );
|
||||
|
||||
// async write to disk (this will take ownership of the memory)
|
||||
char szPathedFileName[_MAX_PATH];
|
||||
Q_snprintf( szPathedFileName, sizeof(szPathedFileName), "//MOD/%s", pRoom->m_szThumbnailName );
|
||||
|
||||
filesystem->AsyncWrite( szPathedFileName, buffer.Base(), buffer.TellPut(), true );
|
||||
|
||||
//videomode->TakeSnapshotTGARect( pRoom->m_szThumbnailName, 0, 0, setup.width, setup.height, setup.width, setup.height );
|
||||
Msg( "Took snapshot %s x=%f y=%f w=%f h=%f ow=%d oh=%d\n", pRoom->m_szThumbnailName,
|
||||
pRoom->m_fRoomX, pRoom->m_fRoomY, pRoom->m_fRoomWide, pRoom->m_fRoomTall,
|
||||
pRoom->m_iOutputWide, pRoom->m_iOutputTall );
|
||||
if ( p4 && asw_add_room_thumbnails_to_perforce.GetBool() )
|
||||
{
|
||||
char fullPath[MAX_PATH];
|
||||
g_pFullFileSystem->RelativePathToFullPath( pRoom->m_szThumbnailName, "GAME", fullPath, MAX_PATH );
|
||||
p4->OpenFileForAdd( fullPath );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !defined( DEDICATED ) && !defined( _X360 )
|
||||
|
||||
#define THUMBNAILS_FILE "resource/roomthumbnails.txt"
|
||||
|
||||
CON_COMMAND( asw_buildroomthumbnails, "Outputs room thumbnail TGAs for all rooms specific in roomthumbnails.txt" )
|
||||
{
|
||||
// load roomthumbnails file
|
||||
KeyValues *pKV = new KeyValues( "RoomThumbnails" );
|
||||
if ( !pKV->LoadFromFile( filesystem, THUMBNAILS_FILE, "GAME" ) )
|
||||
{
|
||||
Msg( "Error: Couldn't open %s\n", THUMBNAILS_FILE );
|
||||
pKV->deleteThis();
|
||||
return;
|
||||
}
|
||||
|
||||
// build a list of room thumbnails
|
||||
CUtlVector<CRoomThumbnail*> thumbnails;
|
||||
KeyValues *pkvEntry = pKV->GetFirstSubKey();
|
||||
while ( pkvEntry )
|
||||
{
|
||||
if ( !Q_stricmp( pkvEntry->GetName(), "Thumbnail" ) )
|
||||
{
|
||||
CRoomThumbnail *pThumbnail = new CRoomThumbnail;
|
||||
Q_strcpy( pThumbnail->m_szThumbnailName, pkvEntry->GetString( "Filename", "screenshots/thumbnail.tga" ) );
|
||||
pThumbnail->m_fRoomX = pkvEntry->GetFloat( "RoomX", 0.0f );
|
||||
pThumbnail->m_fRoomY = pkvEntry->GetFloat( "RoomY", 0.0f );
|
||||
pThumbnail->m_fRoomWide = pkvEntry->GetFloat( "RoomWide", 256.0f );
|
||||
pThumbnail->m_fRoomTall = pkvEntry->GetFloat( "RoomTall", 256.0f );
|
||||
pThumbnail->m_iOutputWide = pkvEntry->GetInt( "OutputWide", 20 );
|
||||
pThumbnail->m_iOutputTall = pkvEntry->GetInt( "OutputTall", 20 );
|
||||
thumbnails.AddToTail( pThumbnail );
|
||||
}
|
||||
pkvEntry = pkvEntry->GetNextKey();
|
||||
}
|
||||
|
||||
// go through the list and take a screenshot of each area
|
||||
for ( int i=0; i<thumbnails.Count(); i++ )
|
||||
{
|
||||
TakeRoomThumbnailSnapshot( thumbnails[i] );
|
||||
}
|
||||
|
||||
thumbnails.PurgeAndDeleteElements();
|
||||
pKV->deleteThis();
|
||||
}
|
||||
#endif // DEDICATED
|
||||
@@ -0,0 +1,305 @@
|
||||
#include "cbase.h"
|
||||
#include "asw_video.h"
|
||||
#include "engine/ienginesound.h"
|
||||
#include "asw_marine_profile.h"
|
||||
#include "c_asw_marine.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
#define BIK_MEDIA_FOLDER "media/"
|
||||
#define BIK_EXTENTION ".bik"
|
||||
|
||||
|
||||
const char *( g_szBIKVideoFaceCharacters[ ASW_VOICE_TYPE_TOTAL ] ) =
|
||||
{
|
||||
"kava", // SARGE
|
||||
"kava", // JAEGER
|
||||
"kava", // WILDCAT
|
||||
"kava", // WOLFE
|
||||
"kava", // FAITH
|
||||
"kava", // BASTILLE
|
||||
"kava", // CRASH
|
||||
"kava", // FLYNN
|
||||
"kava", // VEGAS
|
||||
};
|
||||
|
||||
const char *( g_szBIKVideoFaces[ ASW_VIDEO_FACE_TYPE_TOTAL ] ) =
|
||||
{
|
||||
"static",
|
||||
"healthy",
|
||||
"healthy_alt00",
|
||||
"needHealth",
|
||||
"pain",
|
||||
};
|
||||
|
||||
|
||||
CASW_Video_Face_BIKHandles CASW_Video::s_VideoFaceBIKHandles[ MAX_SPLITSCREEN_PLAYERS ];
|
||||
|
||||
CASW_Video_Face_BIKHandles::CASW_Video_Face_BIKHandles( void )
|
||||
{
|
||||
m_bInitialized = false;
|
||||
m_nBufferCount = 0;
|
||||
|
||||
for ( int i = 0; i < ASW_VIDEO_FACE_TYPE_TOTAL; ++i )
|
||||
{
|
||||
m_BIKHandles[ i ] = BIKHANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
CASW_Video_Face_BIKHandles::~CASW_Video_Face_BIKHandles( void )
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void CASW_Video_Face_BIKHandles::Init( int nCharacterVoiceType )
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
#if !defined( _X360 ) || defined( BINK_ENABLED_FOR_X360 )
|
||||
char szMaterialName[ FILENAME_MAX ];
|
||||
char szFileName[ FILENAME_MAX ];
|
||||
|
||||
for ( int i = 0; i < ASW_VIDEO_FACE_TYPE_TOTAL; ++i )
|
||||
{
|
||||
Q_snprintf( szMaterialName, sizeof( szMaterialName ), "VideoBIKMaterial%i", g_pBIK->GetGlobalMaterialAllocationNumber() );
|
||||
Q_snprintf( szFileName, sizeof( szFileName ), BIK_MEDIA_FOLDER "%s_%s" BIK_EXTENTION, g_szBIKVideoFaceCharacters[ nCharacterVoiceType ], g_szBIKVideoFaces[ i ] );
|
||||
|
||||
m_BIKHandles[ i ] = bik->CreateMaterial( szMaterialName, szFileName, "GAME", BIK_NO_AUDIO );
|
||||
Assert( m_BIKHandles[ i ] != BIKHANDLE_INVALID );
|
||||
|
||||
bik->Update( m_BIKHandles[ i ] );
|
||||
}
|
||||
#endif
|
||||
|
||||
m_bInitialized = true;
|
||||
}
|
||||
|
||||
void CASW_Video_Face_BIKHandles::Shutdown( void )
|
||||
{
|
||||
if ( !m_bInitialized )
|
||||
return;
|
||||
|
||||
#if !defined( _X360 ) || defined( BINK_ENABLED_FOR_X360 )
|
||||
for ( int i = 0; i < ASW_VIDEO_FACE_TYPE_TOTAL; ++i )
|
||||
{
|
||||
// Shut down this video
|
||||
if ( m_BIKHandles[ i ] != BIKHANDLE_INVALID )
|
||||
{
|
||||
bik->DestroyMaterial( m_BIKHandles[ i ] );
|
||||
m_BIKHandles[ i ] = BIKHANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_bInitialized = false;
|
||||
m_nBufferCount = 0;
|
||||
}
|
||||
|
||||
|
||||
void CASW_Video_Face_BIKHandles::Buffer( void )
|
||||
{
|
||||
if ( m_nBufferCount > 3 || !m_bInitialized )
|
||||
return;
|
||||
|
||||
#if !defined( _X360 ) || defined( BINK_ENABLED_FOR_X360 )
|
||||
for ( int i = 0; i < ASW_VIDEO_FACE_TYPE_TOTAL; ++i )
|
||||
{
|
||||
if ( m_BIKHandles[ i ] != BIKHANDLE_INVALID )
|
||||
{
|
||||
bik->Update( m_BIKHandles[ i ] );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_nBufferCount++;
|
||||
}
|
||||
|
||||
BIKMaterial_t CASW_Video_Face_BIKHandles::GetBIKHandle( int nFaceType ) const
|
||||
{
|
||||
if ( !m_bInitialized )
|
||||
{
|
||||
return BIKHANDLE_INVALID;
|
||||
}
|
||||
|
||||
return m_BIKHandles[ nFaceType ];
|
||||
}
|
||||
|
||||
|
||||
CASW_Video::CASW_Video() :
|
||||
m_nPlaybackWidth( 0 ),
|
||||
m_nPlaybackHeight( 0 ),
|
||||
m_bAllowInterruption( true ),
|
||||
m_bStarted( false )
|
||||
{
|
||||
|
||||
m_bAllowInterruption = false;
|
||||
|
||||
m_nLoopVideo = ASW_VIDEO_FACE_STATIC;
|
||||
m_nLastTempVideo = ASW_VIDEO_FACE_STATIC;
|
||||
m_nTransitionVideo = ASW_VIDEO_FACE_STATIC;
|
||||
|
||||
m_nNumLoopAlternatives = 0;
|
||||
m_fAlternateChance = 1.0f;
|
||||
m_bIsLoopVideo = true;
|
||||
m_bIsTransition = false;
|
||||
}
|
||||
|
||||
CASW_Video::~CASW_Video()
|
||||
{
|
||||
for ( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; ++i )
|
||||
{
|
||||
s_VideoFaceBIKHandles[ i ].Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Video::OnVideoOver()
|
||||
{
|
||||
if ( m_bIsTransition )
|
||||
{
|
||||
m_bIsTransition = false;
|
||||
BeginPlayback( m_nLastTempVideo );
|
||||
}
|
||||
else if ( !m_bIsLoopVideo )
|
||||
{
|
||||
m_bIsLoopVideo = true;
|
||||
BeginPlayback( m_nLoopVideo );
|
||||
}
|
||||
else if ( m_nNumLoopAlternatives > 0 && RandomFloat() < m_fAlternateChance )
|
||||
{
|
||||
PlayTempVideo( m_nLoopVideo + RandomInt( 1, m_nNumLoopAlternatives ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
bik->SetFrame( GetVideoFaceBIKHandles()->GetBIKHandle( m_nLoopVideo ), 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Begins playback of a movie
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CASW_Video::BeginPlayback( int nFaceType )
|
||||
{
|
||||
#if !defined( _X360 ) || defined( BINK_ENABLED_FOR_X360 )
|
||||
// Load and create our BINK video
|
||||
CASW_Video_Face_BIKHandles *pHandles = GetVideoFaceBIKHandles();
|
||||
if ( !pHandles->IsInitialized() )
|
||||
{
|
||||
C_ASW_Marine *pMarine = C_ASW_Marine::GetLocalMarine();
|
||||
if ( !pMarine )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CASW_Marine_Profile *pProfile = pMarine->GetMarineProfile();
|
||||
if ( !pProfile )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pHandles->Init( pProfile->m_VoiceType );
|
||||
}
|
||||
|
||||
m_bStarted = true;
|
||||
|
||||
bik->GetTexCoordRange( pHandles->GetBIKHandle( nFaceType ), &m_flU, &m_flV );
|
||||
|
||||
bik->SetFrame( pHandles->GetBIKHandle( nFaceType ), 0.0f );
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CASW_Video::Update()
|
||||
{
|
||||
#if !defined( _X360 ) || defined( BINK_ENABLED_FOR_X360 )
|
||||
if ( !m_bStarted )
|
||||
{
|
||||
BeginPlayback( m_nLoopVideo );
|
||||
}
|
||||
|
||||
// Update our frame
|
||||
GetVideoFaceBIKHandles()->Buffer();
|
||||
|
||||
if ( bik->Update( GetVideoFaceBIKHandles()->GetBIKHandle( GetCurrentVideo() ) ) == false )
|
||||
{
|
||||
// Issue a close command
|
||||
OnVideoOver();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CASW_Video::ReturnToLoopVideo( void )
|
||||
{
|
||||
if ( !m_bIsLoopVideo )
|
||||
{
|
||||
m_bIsLoopVideo = true;
|
||||
BeginPlayback( m_nLoopVideo );
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Video::PlayTempVideo( int nFaceType, int nTransitionFaceType /*= -1*/ )
|
||||
{
|
||||
if ( GetCurrentVideo() == nFaceType )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_nLastTempVideo = nFaceType;
|
||||
m_nTransitionVideo = nTransitionFaceType;
|
||||
|
||||
m_bIsLoopVideo = false;
|
||||
|
||||
m_bIsTransition = ( m_nTransitionVideo != -1 );
|
||||
|
||||
BeginPlayback( m_bIsTransition ? m_nTransitionVideo : m_nLastTempVideo );
|
||||
}
|
||||
|
||||
void CASW_Video::SetLoopVideo( int nFaceType, int nNumLoopAlternatives /*= 0*/, float fAlternateChance /*= 1.0f*/ )
|
||||
{
|
||||
m_nNumLoopAlternatives = nNumLoopAlternatives;
|
||||
m_fAlternateChance = fAlternateChance;
|
||||
|
||||
if ( m_nLoopVideo == nFaceType )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_nLoopVideo = nFaceType;
|
||||
|
||||
if ( m_bIsLoopVideo && m_bStarted )
|
||||
{
|
||||
BeginPlayback( m_nLoopVideo );
|
||||
}
|
||||
}
|
||||
|
||||
int CASW_Video::GetCurrentVideo( void ) const
|
||||
{
|
||||
if ( m_bIsTransition )
|
||||
{
|
||||
return GetTransitionVideo();
|
||||
}
|
||||
|
||||
return ( m_bIsLoopVideo ? GetLoopVideo() : GetLastTempVideo() );
|
||||
}
|
||||
|
||||
IMaterial* CASW_Video::GetMaterial()
|
||||
{
|
||||
#if !defined( _X360 ) || defined( BINK_ENABLED_FOR_X360 )
|
||||
return bik->GetMaterial( GetVideoFaceBIKHandles()->GetBIKHandle( GetCurrentVideo() ) );
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
CASW_Video_Face_BIKHandles* CASW_Video::GetVideoFaceBIKHandles( void )
|
||||
{
|
||||
ASSERT_LOCAL_PLAYER_RESOLVABLE();
|
||||
return &( s_VideoFaceBIKHandles[ GET_ACTIVE_SPLITSCREEN_SLOT() ] );
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#ifndef _INCLUDED_ASW_VIDEO_H
|
||||
#define _INCLUDED_ASW_VIDEO_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "avi/ibik.h"
|
||||
|
||||
|
||||
// Handles the face video material resources
|
||||
|
||||
enum ASW_Video_Face_Type
|
||||
{
|
||||
ASW_VIDEO_FACE_STATIC = 0,
|
||||
ASW_VIDEO_FACE_HEALTHY,
|
||||
ASW_VIDEO_FACE_HEALTHY_ALT00,
|
||||
ASW_VIDEO_FACE_NEEDHEALTH,
|
||||
ASW_VIDEO_FACE_PAIN,
|
||||
|
||||
ASW_VIDEO_FACE_TYPE_TOTAL
|
||||
};
|
||||
|
||||
class CASW_Video_Face_BIKHandles
|
||||
{
|
||||
public:
|
||||
CASW_Video_Face_BIKHandles( void );
|
||||
~CASW_Video_Face_BIKHandles( void );
|
||||
|
||||
void Init( int nCharacterVoiceType );
|
||||
void Shutdown( void );
|
||||
|
||||
bool IsInitialized( void ) { return m_bInitialized; }
|
||||
|
||||
void Buffer( void );
|
||||
|
||||
BIKMaterial_t GetBIKHandle( int nFaceType ) const;
|
||||
|
||||
private:
|
||||
|
||||
BIKMaterial_t m_BIKHandles[ ASW_VIDEO_FACE_TYPE_TOTAL ];
|
||||
bool m_bInitialized;
|
||||
int m_nBufferCount;
|
||||
};
|
||||
|
||||
|
||||
// this holds state for a bink video
|
||||
|
||||
class CASW_Video
|
||||
{
|
||||
public:
|
||||
CASW_Video();
|
||||
~CASW_Video();
|
||||
|
||||
virtual void OnVideoOver();
|
||||
|
||||
void Update();
|
||||
bool BeginPlayback( int nFaceType );
|
||||
|
||||
void SetBlackBackground( bool bBlack ){ m_bBlackBackground = bBlack; }
|
||||
void SetAllowInterrupt( bool bAllowInterrupt ) { m_bAllowInterruption = bAllowInterrupt; }
|
||||
|
||||
void ReturnToLoopVideo( void );
|
||||
void PlayTempVideo( int nFaceType, int nTransitionFaceType = -1 );
|
||||
void SetLoopVideo( int nFaceType, int nNumLoopAlternatives = 0, float fAlternateChance = 1.0f );
|
||||
|
||||
int GetCurrentVideo( void ) const;
|
||||
int GetLoopVideo( void ) const { return m_nLoopVideo; }
|
||||
int GetLastTempVideo( void ) const { return m_nLastTempVideo; }
|
||||
int GetTransitionVideo( void ) const { return m_nTransitionVideo; }
|
||||
|
||||
int GetWide() { return m_nWide; }
|
||||
int GetTall() { return m_nTall; }
|
||||
|
||||
IMaterial* GetMaterial();
|
||||
|
||||
float m_flU; // U,V ranges for video on its sheet
|
||||
float m_flV;
|
||||
|
||||
private:
|
||||
CASW_Video_Face_BIKHandles* GetVideoFaceBIKHandles( void );
|
||||
|
||||
protected:
|
||||
int m_nPlaybackHeight; // Calculated to address ratio changes
|
||||
int m_nPlaybackWidth;
|
||||
char m_szExitCommand[MAX_PATH]; // This call is fired at the engine when the video finishes or is interrupted
|
||||
|
||||
bool m_bAllowInterruption;
|
||||
bool m_bBlackBackground;
|
||||
|
||||
bool m_bStarted;
|
||||
|
||||
int m_nWide;
|
||||
int m_nTall;
|
||||
|
||||
private:
|
||||
int m_nLoopVideo;
|
||||
int m_nLastTempVideo;
|
||||
int m_nTransitionVideo;
|
||||
int m_nNumLoopAlternatives;
|
||||
float m_fAlternateChance;
|
||||
bool m_bIsLoopVideo;
|
||||
bool m_bIsTransition;
|
||||
|
||||
static CASW_Video_Face_BIKHandles s_VideoFaceBIKHandles[ MAX_SPLITSCREEN_PLAYERS ];
|
||||
};
|
||||
|
||||
#endif // _INCLUDED_ASW_VIDEO_H
|
||||
@@ -0,0 +1,386 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Responsible for drawing the scene
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "asw_view_scene.h"
|
||||
#include "view_scene.h"
|
||||
#include "precache_register.h"
|
||||
#include "materialsystem/imaterialsystemhardwareconfig.h"
|
||||
#include "c_asw_render_targets.h"
|
||||
#include "materialsystem/IMaterialVar.h"
|
||||
#include "renderparm.h"
|
||||
#include "asw_weapon_night_vision.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "functionproxy.h"
|
||||
#include "imaterialproxydict.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
float g_fMarinePoisonDuration = 0;
|
||||
bool g_bBlurredLastTime = false;
|
||||
ConVar asw_motionblur("asw_motionblur", "0", 0, "Motion Blur"); // motion blur on/off
|
||||
ConVar asw_motionblur_addalpha("asw_motionblur_addalpha", "0.1", 0, "Motion Blur Alpha"); // The amount of alpha to use when adding the FB to our custom buffer
|
||||
ConVar asw_motionblur_drawalpha("asw_motionblur_drawalpha", "1", 0, "Motion Blur Draw Alpha"); // The amount of alpha to use when adding our custom buffer to the FB
|
||||
ConVar asw_motionblur_time("asw_motionblur_time", "0.05", 0, "The amount of time to wait until updating the FB"); // Delay to add between capturing the FB
|
||||
ConVar asw_night_vision_self_illum_multiplier( "asw_night_vision_self_illum_multiplier", "25", 0, "For materials that use the NightVision proxy, multiply the result (normally in the [0,1] range) by this value." );
|
||||
ConVar asw_sniper_scope_self_illum_multiplier( "asw_sniper_scope_self_illum_multiplier", "0.5", 0, "For materials that use the NightVision proxy, multiply the result (normally in the [0,1] range) by this value." );
|
||||
|
||||
// @TODO: move this parameter to an entity property rather than convar
|
||||
ConVar mat_dest_alpha_range( "mat_dest_alpha_range", "1000", 0, "Amount to scale depth values before writing into destination alpha ([0,1] range)." );
|
||||
|
||||
PRECACHE_REGISTER_BEGIN( GLOBAL, ASWPrecacheViewRender )
|
||||
PRECACHE( MATERIAL, "swarm/effects/frontbuffer" )
|
||||
PRECACHE( MATERIAL, "effects/nightvision" )
|
||||
PRECACHE( MATERIAL, "effects/nightvision_flash" )
|
||||
PRECACHE( MATERIAL, "effects/nightvision_noise" )
|
||||
PRECACHE( MATERIAL, "effects/object_motion_blur" )
|
||||
PRECACHE_REGISTER_END()
|
||||
|
||||
static CASWViewRender g_ViewRender;
|
||||
|
||||
IViewRender *GetViewRenderInstance()
|
||||
{
|
||||
return &g_ViewRender;
|
||||
}
|
||||
|
||||
CASWViewRender::CASWViewRender()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CASWViewRender::OnRenderStart()
|
||||
{
|
||||
CViewRender::OnRenderStart();
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
|
||||
pRenderContext->SetFloatRenderingParameter( FLOAT_RENDERPARM_DEST_ALPHA_DEPTH_SCALE, mat_dest_alpha_range.GetFloat() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASWViewRender::Render2DEffectsPreHUD( const CViewSetup &view )
|
||||
{
|
||||
PerformNightVisionEffect( view ); // this needs to come before the HUD is drawn, or it will wash the HUD out
|
||||
#ifndef _X360
|
||||
// @TODO: Motion blur not supported on X360 yet due to EDRAM issues
|
||||
DoMotionBlur( view );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CASWViewRender::DoMotionBlur( const CViewSetup &view )
|
||||
{
|
||||
if ( asw_motionblur.GetInt() == 0 && g_fMarinePoisonDuration <= 0)
|
||||
{
|
||||
g_bBlurredLastTime = false;
|
||||
return;
|
||||
}
|
||||
|
||||
static float fNextDrawTime = 0.0f;
|
||||
|
||||
bool found;
|
||||
IMaterialVar* mv = NULL;
|
||||
IMaterial *pMatScreen = NULL;
|
||||
ITexture *pMotionBlur = NULL;
|
||||
ITexture *pOriginalTexture = NULL;
|
||||
|
||||
// Get the front buffer material
|
||||
pMatScreen = materials->FindMaterial( "swarm/effects/frontbuffer", TEXTURE_GROUP_OTHER, true );
|
||||
// Get our custom render target
|
||||
pMotionBlur = g_pASWRenderTargets->GetASWMotionBlurTexture();
|
||||
// Store the current render target
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
ITexture *pOriginalRenderTarget = pRenderContext->GetRenderTarget();
|
||||
|
||||
// Set the camera up so we can draw the overlay
|
||||
int oldX, oldY, oldW, oldH;
|
||||
pRenderContext->GetViewport( oldX, oldY, oldW, oldH );
|
||||
|
||||
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||||
pRenderContext->PushMatrix();
|
||||
pRenderContext->LoadIdentity();
|
||||
|
||||
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||||
pRenderContext->PushMatrix();
|
||||
pRenderContext->LoadIdentity();
|
||||
|
||||
// set our blur parameters, based on convars or the poison duration
|
||||
float add_alpha = asw_motionblur_addalpha.GetFloat();
|
||||
float blur_time = asw_motionblur_time.GetFloat();
|
||||
float draw_alpha = asw_motionblur_drawalpha.GetFloat();
|
||||
if (g_fMarinePoisonDuration > 0)
|
||||
{
|
||||
if (g_fMarinePoisonDuration < 1.0f)
|
||||
{
|
||||
draw_alpha = g_fMarinePoisonDuration;
|
||||
add_alpha = 0.3f;
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_alpha = 1.0f;
|
||||
float over_time = g_fMarinePoisonDuration - 1.0f;
|
||||
over_time = -MIN(4.0f, over_time);
|
||||
// map 0 to -4, to 0.3 to 0.05
|
||||
add_alpha = (over_time + 4) * 0.0625 + 0.05f;
|
||||
}
|
||||
blur_time = 0.05f;
|
||||
}
|
||||
if (!g_bBlurredLastTime)
|
||||
add_alpha = 1.0f; // add the whole buffer if this is the first time we're blurring after a while, so we don't end up with images from ages ago
|
||||
|
||||
if ( fNextDrawTime - gpGlobals->curtime > 1.0f)
|
||||
{
|
||||
fNextDrawTime = 0.0f;
|
||||
}
|
||||
|
||||
if( gpGlobals->curtime >= fNextDrawTime )
|
||||
{
|
||||
UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height );
|
||||
|
||||
// Set the alpha to whatever our console variable is
|
||||
mv = pMatScreen->FindVar( "$alpha", &found, false );
|
||||
if (found)
|
||||
{
|
||||
if ( fNextDrawTime == 0 )
|
||||
{
|
||||
mv->SetFloatValue( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
mv->SetFloatValue( add_alpha );
|
||||
}
|
||||
}
|
||||
|
||||
pRenderContext->SetRenderTarget( pMotionBlur );
|
||||
pRenderContext->DrawScreenSpaceQuad( pMatScreen );
|
||||
|
||||
// Set the next draw time according to the convar
|
||||
fNextDrawTime = gpGlobals->curtime + blur_time;
|
||||
}
|
||||
|
||||
// Set the alpha
|
||||
mv = pMatScreen->FindVar( "$alpha", &found, false );
|
||||
if (found)
|
||||
{
|
||||
mv->SetFloatValue( draw_alpha );
|
||||
}
|
||||
|
||||
// Set the texture to our buffer
|
||||
mv = pMatScreen->FindVar( "$basetexture", &found, false );
|
||||
if (found)
|
||||
{
|
||||
pOriginalTexture = mv->GetTextureValue();
|
||||
mv->SetTextureValue( pMotionBlur );
|
||||
}
|
||||
|
||||
// Pretend we were never here, set everything back
|
||||
pRenderContext->SetRenderTarget( pOriginalRenderTarget );
|
||||
pRenderContext->DrawScreenSpaceQuad( pMatScreen );
|
||||
|
||||
// Set our texture back to _rt_FullFrameFB
|
||||
if (found)
|
||||
{
|
||||
mv->SetTextureValue( pOriginalTexture );
|
||||
}
|
||||
|
||||
pRenderContext->DepthRange( 0.0f, 1.0f );
|
||||
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||||
pRenderContext->PopMatrix();
|
||||
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||||
pRenderContext->PopMatrix();
|
||||
|
||||
g_bBlurredLastTime = true;
|
||||
}
|
||||
|
||||
|
||||
inline bool ASW_SetMaterialVarFloat( IMaterial* pMat, const char* pVarName, float flValue )
|
||||
{
|
||||
Assert( pMat != NULL );
|
||||
Assert( pVarName != NULL );
|
||||
if ( pMat == NULL || pVarName == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bFound = false;
|
||||
IMaterialVar* pVar = pMat->FindVar( pVarName, &bFound );
|
||||
if ( bFound )
|
||||
{
|
||||
pVar->SetFloatValue( flValue );
|
||||
}
|
||||
|
||||
return bFound;
|
||||
}
|
||||
|
||||
inline bool ASW_SetMaterialVarInt( IMaterial* pMat, const char* pVarName, int iValue )
|
||||
{
|
||||
Assert( pMat != NULL );
|
||||
Assert( pVarName != NULL );
|
||||
if ( pMat == NULL || pVarName == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bFound = false;
|
||||
IMaterialVar* pVar = pMat->FindVar( pVarName, &bFound );
|
||||
if ( bFound )
|
||||
{
|
||||
pVar->SetIntValue( iValue );
|
||||
}
|
||||
|
||||
return bFound;
|
||||
}
|
||||
|
||||
inline bool ASW_SetMaterialVarVector4D( IMaterial* pMat, const char* pVarName, const Vector4D &vValue )
|
||||
{
|
||||
Assert( pMat != NULL );
|
||||
Assert( pVarName != NULL );
|
||||
if ( pMat == NULL || pVarName == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bFound = false;
|
||||
IMaterialVar* pVar = pMat->FindVar( pVarName, &bFound );
|
||||
if ( bFound )
|
||||
{
|
||||
pVar->SetVecValue( vValue.Base(), 4 );
|
||||
}
|
||||
|
||||
return bFound;
|
||||
}
|
||||
|
||||
// Set to true by the client mode when rendering glows, false when done
|
||||
bool g_bRenderingGlows;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Material proxy for getting the strength of the self-illum effect to
|
||||
// apply to objects when night vision is enabled (value is always 0 when
|
||||
// the effect is disabled)
|
||||
//-----------------------------------------------------------------------------
|
||||
class CASWNightVisionSelfIllumProxy : public CResultProxy
|
||||
{
|
||||
public:
|
||||
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
|
||||
virtual void OnBind( void *pC_BaseEntity );
|
||||
};
|
||||
|
||||
|
||||
bool CASWNightVisionSelfIllumProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
|
||||
{
|
||||
if ( !CResultProxy::Init( pMaterial, pKeyValues ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CASWNightVisionSelfIllumProxy::OnBind( void *pC_BaseEntity )
|
||||
{
|
||||
Assert( m_pResult );
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer || !pC_BaseEntity )
|
||||
{
|
||||
SetFloatResult( 0.0f );
|
||||
return;
|
||||
}
|
||||
|
||||
C_ASW_Marine *pMarine = pPlayer->GetMarine();
|
||||
if ( !pMarine )
|
||||
{
|
||||
SetFloatResult( 0.0f );
|
||||
return;
|
||||
}
|
||||
|
||||
C_BaseCombatWeapon* pExtraItem = pMarine->GetWeapon( 2 );
|
||||
if ( pExtraItem && pExtraItem->Classify() == CLASS_ASW_NIGHT_VISION )
|
||||
{
|
||||
C_ASW_Weapon_Night_Vision *pVision = assert_cast<CASW_Weapon_Night_Vision*>( pExtraItem );
|
||||
float flVisionAlpha = pVision->m_flVisionAlpha;
|
||||
if ( flVisionAlpha != 0.0f )
|
||||
{
|
||||
SetFloatResult( flVisionAlpha / 255.0f * asw_night_vision_self_illum_multiplier.GetFloat() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pPlayer->IsSniperScopeActive() && g_bRenderingGlows )
|
||||
{
|
||||
SetFloatResult( asw_sniper_scope_self_illum_multiplier.GetFloat() );
|
||||
return;
|
||||
}
|
||||
|
||||
SetFloatResult( 0.0f );
|
||||
}
|
||||
|
||||
EXPOSE_MATERIAL_PROXY( CASWNightVisionSelfIllumProxy, NightVisionSelfIllum );
|
||||
|
||||
|
||||
void CASWViewRender::PerformNightVisionEffect( const CViewSetup &view )
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
C_ASW_Marine *pMarine = pPlayer->GetMarine();
|
||||
if ( !pMarine )
|
||||
return;
|
||||
|
||||
float flVisionAlpha = 0.0f;
|
||||
float flFlashAlpha = 0.0f;
|
||||
C_BaseCombatWeapon* pExtraItem = pMarine->GetWeapon( 2 );
|
||||
if ( pExtraItem && pExtraItem->Classify() == CLASS_ASW_NIGHT_VISION )
|
||||
{
|
||||
C_ASW_Weapon_Night_Vision *pVision = assert_cast<CASW_Weapon_Night_Vision*>( pExtraItem );
|
||||
flVisionAlpha = pVision->UpdateVisionAlpha();
|
||||
flFlashAlpha = pVision->UpdateFlashAlpha();
|
||||
}
|
||||
|
||||
if ( flVisionAlpha > 0 )
|
||||
{
|
||||
IMaterial *pMaterial = materials->FindMaterial( "effects/nightvision", TEXTURE_GROUP_CLIENT_EFFECTS, true );
|
||||
|
||||
if ( pMaterial )
|
||||
{
|
||||
byte overlaycolor[4] = { 0, 255, 0, 255 };
|
||||
|
||||
UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height );
|
||||
|
||||
overlaycolor[3] = flVisionAlpha;
|
||||
|
||||
render->ViewDrawFade( overlaycolor, pMaterial );
|
||||
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
pRenderContext->DrawScreenSpaceQuad( pMaterial );
|
||||
render->ViewDrawFade( overlaycolor, pMaterial );
|
||||
pRenderContext->DrawScreenSpaceQuad( pMaterial );
|
||||
}
|
||||
IMaterial *pNoiseMaterial = materials->FindMaterial( "effects/nightvision_noise", TEXTURE_GROUP_CLIENT_EFFECTS, true );
|
||||
|
||||
if ( pNoiseMaterial )
|
||||
{
|
||||
byte overlaycolor[4] = { 255, 255, 255, 255 };
|
||||
overlaycolor[3] = MAX( flFlashAlpha, 16.0f );
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
render->ViewDrawFade( overlaycolor, pNoiseMaterial );
|
||||
}
|
||||
}
|
||||
if ( flFlashAlpha > 0 )
|
||||
{
|
||||
IMaterial *pMaterial = materials->FindMaterial( "effects/nightvision_flash", TEXTURE_GROUP_CLIENT_EFFECTS, true );
|
||||
|
||||
if ( pMaterial )
|
||||
{
|
||||
byte overlaycolor[4] = { 255, 255, 255, 255 };
|
||||
overlaycolor[3] = flFlashAlpha;
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
render->ViewDrawFade( overlaycolor, pMaterial );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef ASW_VIEW_SCENE_H
|
||||
#define ASW_VIEW_SCENE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "viewrender.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Implements the interview to view rendering for the client .dll
|
||||
//-----------------------------------------------------------------------------
|
||||
class CASWViewRender : public CViewRender
|
||||
{
|
||||
public:
|
||||
CASWViewRender();
|
||||
|
||||
virtual void OnRenderStart();
|
||||
virtual void Render2DEffectsPreHUD( const CViewSetup &view );
|
||||
|
||||
virtual bool AllowScreenspaceFade( void ) { return false; }
|
||||
|
||||
private:
|
||||
void DoMotionBlur( const CViewSetup &view );
|
||||
void PerformNightVisionEffect( const CViewSetup &view );
|
||||
};
|
||||
|
||||
#endif //ASW_VIEW_SCENE_H
|
||||
@@ -0,0 +1,694 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_alien.h"
|
||||
#include "eventlist.h"
|
||||
#include "decals.h"
|
||||
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
||||
#include "c_asw_generic_emitter_entity.h"
|
||||
#include "c_asw_marine_resource.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_game_resource.h"
|
||||
#include "asw_shareddefs.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include "c_asw_fx.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
#include "baseparticleentity.h"
|
||||
#include "c_asw_clientragdoll.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "functionproxy.h"
|
||||
#include "imaterialproxydict.h"
|
||||
#include "proxyentity.h"
|
||||
#include "materialsystem/IMaterialVar.h"
|
||||
#include "materialsystem/itexture.h"
|
||||
//#include "c_asw_physics_prop_statue.h"
|
||||
#include "c_asw_mesh_emitter_entity.h"
|
||||
#include "c_asw_egg.h"
|
||||
#include "props_shared.h"
|
||||
#include "c_asw_player.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define ASW_GIB_ASAP 0.175f
|
||||
|
||||
ConVar asw_alien_object_motion_blur_scale( "asw_alien_object_motion_blur_scale", "0.2" );
|
||||
ConVar asw_drone_gib_time_min("asw_drone_gib_time_min", "0.2", 0, "Minimum time a Swarm Drone ragdoll will stay around before gibbing");
|
||||
ConVar asw_drone_gib_time_max("asw_drone_gib_time_max", "0.2", 0, "Maximum time a Swarm Drone ragdoll will stay around before gibbing");
|
||||
ConVar asw_drone_fade_time_min("asw_drone_fade_time_min", "2.0", 0, "Minimum time a Swarm Drone ragdoll will stay around before fading");
|
||||
ConVar asw_drone_fade_time_max("asw_drone_fade_time_max", "4.0", 0, "Maximum time a Swarm Drone ragdoll will stay around before fading");
|
||||
ConVar asw_directional_shadows("asw_directional_shadows", "1", 0, "Whether aliens should have flashlight directional shadows");
|
||||
ConVar asw_alien_shadows("asw_alien_shadows", "0", 0, "If set to one, aliens will always have shadows (WARNING: Big fps cost when lots of aliens are active)");
|
||||
ConVar asw_alien_footstep_interval( "asw_alien_footstep_interval", "0.25", 0, "Minimum interval between alien footstep sounds. Used to keep them from piling up and preventing others from playing." );
|
||||
ConVar asw_breakable_aliens( "asw_breakable_aliens", "1", 0, "If set, aliens can break into ragdoll gibs" );
|
||||
extern ConVar asw_override_footstep_volume;
|
||||
extern ConVar asw_alien_debug_death_style;
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( ASW_Alien, DT_ASW_Alien )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CASW_Alien, DT_ASW_Alien )
|
||||
RecvPropVectorXY( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ), 0, C_BaseEntity::RecvProxy_CellOriginXY ),
|
||||
RecvPropFloat( RECVINFO_NAME( m_vecNetworkOrigin[2], m_vecOrigin[2] ), 0, C_BaseEntity::RecvProxy_CellOriginZ ),
|
||||
|
||||
RecvPropFloat( RECVINFO_NAME( m_angNetworkAngles[0], m_angRotation[0] ) ),
|
||||
RecvPropFloat( RECVINFO_NAME( m_angNetworkAngles[1], m_angRotation[1] ) ),
|
||||
RecvPropFloat( RECVINFO_NAME( m_angNetworkAngles[2], m_angRotation[2] ) ),
|
||||
|
||||
RecvPropBool( RECVINFO( m_bElectroStunned ) ),// not using ElectroStunned
|
||||
//RecvPropBool( RECVINFO( m_bElectroShockSmall ) ),
|
||||
//RecvPropBool( RECVINFO( m_bElectroShockBig ) ),
|
||||
RecvPropBool( RECVINFO( m_bOnFire ) ),
|
||||
RecvPropInt( RECVINFO( m_nDeathStyle ), SPROP_UNSIGNED ),
|
||||
RecvPropInt ( RECVINFO( m_iHealth) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
PRECACHE_REGISTER_BEGIN( GLOBAL, ASW_Alien )
|
||||
PRECACHE( MATERIAL, "effects/TiledFire/fire_tiled_precache" )
|
||||
PRECACHE( MATERIAL, "effects/model_layer_shock_1_precache" )
|
||||
PRECACHE( MATERIAL, "effects/model_layer_ice_1_precache" )
|
||||
PRECACHE( PARTICLE_SYSTEM, "damage_numbers" )
|
||||
PRECACHE_REGISTER_END()
|
||||
|
||||
IMPLEMENT_AUTO_LIST( IClientAimTargetsAutoList );
|
||||
|
||||
float C_ASW_Alien::sm_flLastFootstepTime = 0.0f;
|
||||
|
||||
C_ASW_Alien::C_ASW_Alien() :
|
||||
m_GlowObject( this ),
|
||||
m_MotionBlurObject( this, 0.0f )
|
||||
{
|
||||
m_bStepSideLeft = false;
|
||||
m_nLastSetModel = 0;
|
||||
m_fNextElectroStunEffect = 0;
|
||||
m_fLastCustomContribution = 0;
|
||||
m_vecLastCustomDir = vec3_origin;
|
||||
m_iLastCustomFrame = -1;
|
||||
m_bClientOnFire = false;
|
||||
m_vecLastRenderedPos = vec3_origin;
|
||||
m_pBurningEffect = NULL;
|
||||
|
||||
m_GlowObject.SetColor( Vector( 0.3f, 0.6f, 0.1f ) );
|
||||
m_GlowObject.SetAlpha( 0.55f );
|
||||
m_GlowObject.SetRenderFlags( false, false );
|
||||
m_GlowObject.SetFullBloomRender( true );
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Alien::~C_ASW_Alien()
|
||||
{
|
||||
m_bOnFire = false;
|
||||
UpdateFireEmitters();
|
||||
}
|
||||
|
||||
|
||||
void C_ASW_Alien::FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
|
||||
{
|
||||
if ( event == AE_ASW_FOOTSTEP || event == AE_MARINE_FOOTSTEP )
|
||||
{
|
||||
Vector vel;
|
||||
EstimateAbsVelocity( vel );
|
||||
surfacedata_t *pSurface = GetGroundSurface();
|
||||
if (pSurface)
|
||||
MarineStepSound( pSurface, GetAbsOrigin(), vel );
|
||||
}
|
||||
else if (event == AE_REMOVE_CLIENT_AIM)
|
||||
{
|
||||
IASW_Client_Aim_Target::Remove( this );
|
||||
}
|
||||
else if ( event == AE_RAGDOLL )
|
||||
{
|
||||
|
||||
}
|
||||
BaseClass::FireEvent(origin, angles, event, options);
|
||||
}
|
||||
|
||||
void C_ASW_Alien::MarineStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity )
|
||||
{
|
||||
int fWalking;
|
||||
float fvol;
|
||||
Vector knee;
|
||||
Vector feet;
|
||||
float height;
|
||||
float speed;
|
||||
float velrun;
|
||||
float velwalk;
|
||||
float flduck;
|
||||
int fLadder;
|
||||
|
||||
if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS))
|
||||
return;
|
||||
|
||||
if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER )
|
||||
return;
|
||||
|
||||
if ( gpGlobals->curtime - sm_flLastFootstepTime < asw_alien_footstep_interval.GetFloat() )
|
||||
return;
|
||||
|
||||
speed = VectorLength( vecVelocity );
|
||||
float groundspeed = Vector2DLength( vecVelocity.AsVector2D() );
|
||||
|
||||
// determine if we are on a ladder
|
||||
fLadder = ( GetMoveType() == MOVETYPE_LADDER );
|
||||
|
||||
// UNDONE: need defined numbers for run, walk, crouch, crouch run velocities!!!!
|
||||
if ( ( GetFlags() & FL_DUCKING) || fLadder )
|
||||
{
|
||||
velwalk = 60; // These constants should be based on cl_movespeedkey * cl_forwardspeed somehow
|
||||
velrun = 80;
|
||||
flduck = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
velwalk = 90;
|
||||
velrun = 220;
|
||||
flduck = 0;
|
||||
}
|
||||
|
||||
bool onground = true; //( GetFlags() & FL_ONGROUND );
|
||||
bool movingalongground = ( groundspeed > 0.0f );
|
||||
bool moving_fast_enough = ( speed >= velwalk );
|
||||
|
||||
// To hear step sounds you must be either on a ladder or moving along the ground AND
|
||||
// You must be moving fast enough
|
||||
//Msg("og=%d ma=%d mf=%d\n", onground, movingalongground, moving_fast_enough);
|
||||
if ( !moving_fast_enough || !(fLadder || ( onground && movingalongground )) )
|
||||
return;
|
||||
|
||||
// MoveHelper()->PlayerSetAnimation( PLAYER_WALK );
|
||||
|
||||
fWalking = speed < velrun;
|
||||
|
||||
VectorCopy( vecOrigin, knee );
|
||||
VectorCopy( vecOrigin, feet );
|
||||
|
||||
height = 72.0f; // bad
|
||||
|
||||
knee[2] = vecOrigin[2] + 0.2 * height;
|
||||
|
||||
// find out what we're stepping in or on...
|
||||
if ( fLadder )
|
||||
{
|
||||
psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "ladder" ) );
|
||||
fvol = 0.5;
|
||||
}
|
||||
else if ( enginetrace->GetPointContents( knee ) & MASK_WATER )
|
||||
{
|
||||
static int iSkipStep = 0;
|
||||
|
||||
if ( iSkipStep == 0 )
|
||||
{
|
||||
iSkipStep++;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( iSkipStep++ == 3 )
|
||||
{
|
||||
iSkipStep = 0;
|
||||
}
|
||||
psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) );
|
||||
fvol = 0.65;
|
||||
}
|
||||
else if ( enginetrace->GetPointContents( feet ) & MASK_WATER )
|
||||
{
|
||||
psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) );
|
||||
fvol = fWalking ? 0.2 : 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !psurface )
|
||||
return;
|
||||
|
||||
switch ( psurface->game.material )
|
||||
{
|
||||
default:
|
||||
case CHAR_TEX_CONCRETE:
|
||||
fvol = fWalking ? 0.2 : 0.5;
|
||||
break;
|
||||
|
||||
case CHAR_TEX_METAL:
|
||||
fvol = fWalking ? 0.2 : 0.5;
|
||||
break;
|
||||
|
||||
case CHAR_TEX_DIRT:
|
||||
fvol = fWalking ? 0.25 : 0.55;
|
||||
break;
|
||||
|
||||
case CHAR_TEX_VENT:
|
||||
fvol = fWalking ? 0.4 : 0.7;
|
||||
break;
|
||||
|
||||
case CHAR_TEX_GRATE:
|
||||
fvol = fWalking ? 0.2 : 0.5;
|
||||
break;
|
||||
|
||||
case CHAR_TEX_TILE:
|
||||
fvol = fWalking ? 0.2 : 0.5;
|
||||
break;
|
||||
|
||||
case CHAR_TEX_SLOSH:
|
||||
fvol = fWalking ? 0.2 : 0.5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// play the sound
|
||||
// 65% volume if ducking
|
||||
if ( GetFlags() & FL_DUCKING )
|
||||
{
|
||||
fvol *= 0.65;
|
||||
}
|
||||
|
||||
if ( asw_override_footstep_volume.GetFloat() > 0 )
|
||||
{
|
||||
fvol = asw_override_footstep_volume.GetFloat();
|
||||
}
|
||||
|
||||
PlayStepSound( feet, psurface, fvol, false );
|
||||
}
|
||||
|
||||
|
||||
surfacedata_t* C_ASW_Alien::GetGroundSurface()
|
||||
{
|
||||
//
|
||||
// Find the name of the material that lies beneath the player.
|
||||
//
|
||||
Vector start, end;
|
||||
VectorCopy( GetAbsOrigin(), start );
|
||||
VectorCopy( start, end );
|
||||
|
||||
// Straight down
|
||||
end.z -= 38; // was 64
|
||||
|
||||
// Fill in default values, just in case.
|
||||
|
||||
Ray_t ray;
|
||||
ray.Init( start, end, GetCollideable()->OBBMins(), GetCollideable()->OBBMaxs() );
|
||||
|
||||
trace_t trace;
|
||||
UTIL_TraceRay( ray, MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NPC, &trace );
|
||||
|
||||
if ( trace.fraction == 1.0f )
|
||||
return NULL; // no ground
|
||||
|
||||
return physprops->GetSurfaceData( trace.surface.surfaceProps );
|
||||
}
|
||||
|
||||
void C_ASW_Alien::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force )
|
||||
{
|
||||
if ( !psurface )
|
||||
return;
|
||||
|
||||
unsigned short stepSoundName = m_bStepSideLeft ? psurface->sounds.runStepLeft : psurface->sounds.runStepRight;
|
||||
m_bStepSideLeft = !m_bStepSideLeft;
|
||||
|
||||
if ( !stepSoundName )
|
||||
return;
|
||||
|
||||
const char *pSoundName = physprops->GetString( stepSoundName );
|
||||
CSoundParameters params;
|
||||
if ( !CBaseEntity::GetParametersForSound( pSoundName, params, NULL ) )
|
||||
return;
|
||||
|
||||
// do the surface dependent sound
|
||||
CLocalPlayerFilter filter;
|
||||
|
||||
EmitSound_t ep;
|
||||
ep.m_nChannel = CHAN_BODY;
|
||||
ep.m_pSoundName = params.soundname;
|
||||
ep.m_flVolume = ( asw_override_footstep_volume.GetBool() ) ? fvol : params.volume;
|
||||
ep.m_SoundLevel = params.soundlevel;
|
||||
ep.m_nFlags = 0;
|
||||
ep.m_nPitch = params.pitch;
|
||||
ep.m_pOrigin = &vecOrigin;
|
||||
|
||||
EmitSound( filter, entindex(), ep );
|
||||
|
||||
DoAlienFootstep(vecOrigin, fvol);
|
||||
}
|
||||
|
||||
// plays alien type specific footstep sound
|
||||
void C_ASW_Alien::DoAlienFootstep(Vector &vecOrigin, float fvol)
|
||||
{
|
||||
CSoundParameters params;
|
||||
if ( !CBaseEntity::GetParametersForSound( "ASW_Drone.FootstepSoft", params, NULL ) )
|
||||
return;
|
||||
|
||||
CLocalPlayerFilter filter;
|
||||
|
||||
// do the alienfleshy foot sound
|
||||
EmitSound_t ep2;
|
||||
ep2.m_nChannel = CHAN_AUTO;
|
||||
ep2.m_pSoundName = params.soundname;
|
||||
ep2.m_flVolume = fvol;
|
||||
ep2.m_SoundLevel = params.soundlevel;
|
||||
ep2.m_nFlags = 0;
|
||||
ep2.m_nPitch = params.pitch;
|
||||
ep2.m_pOrigin = &vecOrigin;
|
||||
|
||||
EmitSound( filter, entindex(), ep2 );
|
||||
|
||||
sm_flLastFootstepTime = gpGlobals->curtime;
|
||||
}
|
||||
|
||||
C_BaseAnimating * C_ASW_Alien::BecomeRagdollOnClient( void )
|
||||
{
|
||||
// if we have a custom death force get it here, before the ragdoll is created
|
||||
// the shield bug uses this
|
||||
if ( HasCustomDeathForce() )
|
||||
{
|
||||
m_vecForce = GetCustomDeathForce();
|
||||
}
|
||||
//Msg("[C] C_ASW_Alien::BecomeRagdollOnClient on fire? %d / %d", ( GetFlags() & FL_ONFIRE ), m_bOnFire.Get());
|
||||
C_BaseAnimating* pEnt = BaseClass::BecomeRagdollOnClient();
|
||||
C_ASW_ClientRagdoll* pRagdoll = dynamic_cast<C_ASW_ClientRagdoll*>(pEnt);
|
||||
if (pRagdoll)
|
||||
{
|
||||
if ( asw_alien_debug_death_style.GetBool() )
|
||||
{
|
||||
Msg( "'%s' C_ASW_Alien::BecomeRagdollOnClient: m_nDeathStyle = %d\n", GetClassname(), m_nDeathStyle );
|
||||
}
|
||||
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
|
||||
pRagdoll->m_nDeathStyle = m_nDeathStyle;
|
||||
pRagdoll->AddEffects(EF_NOSHADOW);
|
||||
// if we broke don't draw the ragdoll
|
||||
if ( m_nDeathStyle == kDIE_BREAKABLE )
|
||||
{
|
||||
if ( asw_breakable_aliens.GetBool() )
|
||||
{
|
||||
pRagdoll->AddEffects(EF_NODRAW);
|
||||
}
|
||||
pRagdoll->m_fASWGibTime = gpGlobals->curtime + ASW_GIB_ASAP; //gpGlobals->curtime + random->RandomFloat( 0.2f, 0.4f );
|
||||
}
|
||||
// make this ragdoll gib RIGHT MEOW
|
||||
else if ( m_nDeathStyle == kDIE_INSTAGIB )
|
||||
{
|
||||
// force instant gib
|
||||
// this happens when an alien takes a large amount of damage
|
||||
pRagdoll->m_fASWGibTime = gpGlobals->curtime + ASW_GIB_ASAP;
|
||||
}
|
||||
else if ( m_bOnFire.Get() )
|
||||
{
|
||||
pRagdoll->m_fASWGibTime = gpGlobals->curtime + random->RandomFloat( 0.3f, 0.7f );
|
||||
}
|
||||
else if ( IsHurler() )
|
||||
{
|
||||
pRagdoll->m_fASWGibTime = gpGlobals->curtime + random->RandomFloat( 4, 9 );
|
||||
pRagdoll->pszGibParticleEffect = GetRagdollGibParticleEffectName();
|
||||
}
|
||||
else if ( IsMeleeThrown() )
|
||||
{
|
||||
pRagdoll->m_fASWGibTime = gpGlobals->curtime + random->RandomFloat( 4, 9 );
|
||||
pRagdoll->pszGibParticleEffect = GetRagdollGibParticleEffectName();
|
||||
}
|
||||
else if ( m_nDeathStyle == kDIE_RAGDOLLFADE )
|
||||
{
|
||||
pRagdoll->m_fASWGibTime = gpGlobals->curtime + random->RandomFloat(asw_drone_fade_time_min.GetFloat(), asw_drone_fade_time_max.GetFloat());
|
||||
pRagdoll->pszGibParticleEffect = GetRagdollGibParticleEffectName();
|
||||
}
|
||||
else
|
||||
{
|
||||
pRagdoll->m_fASWGibTime = gpGlobals->curtime + random->RandomFloat(asw_drone_gib_time_min.GetFloat(), asw_drone_gib_time_max.GetFloat());
|
||||
pRagdoll->pszGibParticleEffect = GetRagdollGibParticleEffectName();
|
||||
}
|
||||
|
||||
if ( m_bOnFire.Get() )
|
||||
{
|
||||
pRagdoll->AddFlag( FL_ONFIRE );
|
||||
|
||||
CNewParticleEffect *pBurningEffect = pRagdoll->ParticleProp()->Create( "ent_on_fire", PATTACH_ABSORIGIN_FOLLOW );
|
||||
if (pBurningEffect)
|
||||
{
|
||||
Vector vecOffest1 = (pRagdoll->WorldSpaceCenter() - pRagdoll->GetAbsOrigin()) + Vector( 0, 0, 16 );
|
||||
pPlayer->ParticleProp()->AddControlPoint( pBurningEffect, 1, pRagdoll, PATTACH_ABSORIGIN_FOLLOW, NULL, vecOffest1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_bElectroStunned )
|
||||
{
|
||||
pRagdoll->m_bElectroShock = true;
|
||||
}
|
||||
|
||||
if ( pPlayer )
|
||||
{
|
||||
// if we're going to ragdoll, create a big blood spurt now so players get feedback about killing this alien
|
||||
QAngle vecAngles;
|
||||
if ( m_vecForce == vec3_origin )
|
||||
{
|
||||
m_vecForce = Vector( RandomFloat( 1, 100 ), RandomFloat( 1, 100 ), 100.0f );
|
||||
}
|
||||
VectorAngles( m_vecForce, vecAngles );
|
||||
Vector vecForward, vecRight, vecUp;
|
||||
AngleVectors( vecAngles, &vecForward, &vecRight, &vecUp );
|
||||
|
||||
const char *pchEffectName = NULL;
|
||||
|
||||
switch ( m_nDeathStyle )
|
||||
{
|
||||
case kDIE_TUMBLEGIB:
|
||||
case kDIE_RAGDOLLFADE:
|
||||
pchEffectName = GetSmallDeathParticleEffectName();
|
||||
break;
|
||||
|
||||
case kDIE_INSTAGIB:
|
||||
case kDIE_BREAKABLE:
|
||||
pchEffectName = GetBigDeathParticleEffectName();
|
||||
break;
|
||||
|
||||
default:
|
||||
pchEffectName = GetDeathParticleEffectName();
|
||||
break;
|
||||
}
|
||||
|
||||
CUtlReference< CNewParticleEffect > pEffect;
|
||||
pEffect = pPlayer->ParticleProp()->Create( pchEffectName, PATTACH_ABSORIGIN_FOLLOW );
|
||||
|
||||
if ( pEffect )
|
||||
{
|
||||
pPlayer->ParticleProp()->AddControlPoint( pEffect, 1, pRagdoll, PATTACH_CUSTOMORIGIN );
|
||||
pEffect->SetControlPoint( 1, WorldSpaceCenter() );//origin - pMarine->GetAbsOrigin()
|
||||
pEffect->SetControlPointOrientation( 1, vecForward, vecRight, vecUp );
|
||||
pEffect->SetControlPointEntity( 0, pRagdoll );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "Could not create effect for alien death: %s", pchEffectName );
|
||||
}
|
||||
}
|
||||
|
||||
if ( IsHurler() )
|
||||
{
|
||||
ASWHurlRagdollAtCamera( pRagdoll );
|
||||
}
|
||||
else if ( IsMeleeThrown() )
|
||||
{
|
||||
ASWMeleeThrowRagdoll( pRagdoll );
|
||||
}
|
||||
}
|
||||
}
|
||||
return pRagdoll;
|
||||
}
|
||||
|
||||
C_ClientRagdoll *C_ASW_Alien::CreateClientRagdoll( bool bRestoring )
|
||||
{
|
||||
return new C_ASW_ClientRagdoll( bRestoring );
|
||||
}
|
||||
|
||||
// shadow direction test
|
||||
bool C_ASW_Alien::GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const
|
||||
{
|
||||
VPROF_BUDGET( "C_ASW_Alien::GetShadowCastDistance", VPROF_BUDGETGROUP_ASW_CLIENT );
|
||||
|
||||
if (!asw_directional_shadows.GetBool())
|
||||
return false;
|
||||
|
||||
if (m_fLastCustomContribution > 0)
|
||||
{
|
||||
Vector vecDir = m_vecLastCustomDir;
|
||||
vecDir += (*pDirection) * (1.0f - m_fLastCustomContribution);
|
||||
vecDir.NormalizeInPlace();
|
||||
pDirection->x = vecDir.x;
|
||||
pDirection->y = vecDir.y;
|
||||
pDirection->z = vecDir.z;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ShadowType_t C_ASW_Alien::ShadowCastType()
|
||||
{
|
||||
if (asw_alien_shadows.GetBool())
|
||||
return BaseClass::ShadowCastType();
|
||||
float fContribution = 0;
|
||||
Vector vecDir = vec3_origin;
|
||||
GetShadowFromFlashlight(vecDir, fContribution);
|
||||
m_fLastCustomContribution = fContribution;
|
||||
m_vecLastCustomDir = vecDir;
|
||||
m_iLastCustomFrame = gpGlobals->framecount;
|
||||
if (m_fLastCustomContribution <= 0)
|
||||
{
|
||||
return SHADOWS_NONE;
|
||||
}
|
||||
return BaseClass::ShadowCastType();
|
||||
}
|
||||
|
||||
void C_ASW_Alien::GetShadowFromFlashlight(Vector &vecDir, float &fContribution) const
|
||||
{
|
||||
if (gpGlobals->framecount == m_iLastCustomFrame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ASWGameResource() )
|
||||
{
|
||||
// go through all marines
|
||||
int iMaxMarines = ASWGameResource()->GetMaxMarineResources();
|
||||
for (int i=0;i<iMaxMarines;i++)
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = ASWGameResource()->GetMarineResource(i);
|
||||
C_ASW_Marine *pMarine = pMR ? pMR->GetMarineEntity() : NULL;
|
||||
if (pMarine && pMarine->m_pFlashlight) // if this is a marine with a flashlight
|
||||
{
|
||||
Vector diff = WorldSpaceCenter() - pMarine->EyePosition();
|
||||
if (diff.Length() < 700.0f)
|
||||
{
|
||||
diff.NormalizeInPlace();
|
||||
Vector vecMarineFacing(0,0,0);
|
||||
AngleVectors(pMarine->GetAbsAngles(), &vecMarineFacing);
|
||||
float dot = vecMarineFacing.Dot(diff);
|
||||
if (dot > 0.2) // if the flashlight is facing us
|
||||
{
|
||||
vecDir += dot * diff;
|
||||
fContribution += (dot - 0.2f) * 1.25f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Alien::PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::PostDataUpdate(updateType);
|
||||
// If this entity was new, then latch in various values no matter what.
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// We want to think every frame.
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
Vector C_ASW_Alien::GetLocalAutoTargetRadiusPos()
|
||||
{
|
||||
// drone overrides this
|
||||
return m_vecLastRenderedPos;
|
||||
}
|
||||
|
||||
void C_ASW_Alien::ClientThink()
|
||||
{
|
||||
BaseClass::ClientThink();
|
||||
|
||||
// asw temp fix demo playback
|
||||
//ASWUpdateClientSideAnimation();
|
||||
|
||||
m_vecLastRenderedPos = WorldSpaceCenter();
|
||||
m_vecAutoTargetRadiusPos = GetLocalAutoTargetRadiusPos();
|
||||
|
||||
if ( GetHealth() > 0 && m_bElectroStunned && m_fNextElectroStunEffect <= gpGlobals->curtime)
|
||||
{
|
||||
// apply electro stun effect
|
||||
HACK_GETLOCALPLAYER_GUARD( "C_ASW_Alien::ClientThink FX_ElectroStun" );
|
||||
FX_ElectroStun(this);
|
||||
m_fNextElectroStunEffect = gpGlobals->curtime + RandomFloat( 0.3, 1.0 );
|
||||
//Msg( "%f - ElectroStunEffect\n", gpGlobals->curtime );
|
||||
}
|
||||
|
||||
UpdateFireEmitters();
|
||||
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pPlayer && pPlayer->IsSniperScopeActive() )
|
||||
{
|
||||
m_GlowObject.SetRenderFlags( true, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_GlowObject.SetRenderFlags( false, false );
|
||||
}
|
||||
}
|
||||
|
||||
// asw - test always advancing the frames
|
||||
void C_ASW_Alien::ASWUpdateClientSideAnimation()
|
||||
{
|
||||
if ( GetSequence() != -1 )
|
||||
{
|
||||
// latch old values
|
||||
//OnLatchInterpolatedVariables( LATCH_ANIMATION_VAR );
|
||||
// move frame forward
|
||||
//FrameAdvance( 0.0f ); // 0 means to use the time we last advanced instead of a constant
|
||||
|
||||
CStudioHdr *hdr = GetModelPtr();
|
||||
float cyclerate = hdr ? GetSequenceCycleRate( hdr, GetSequence() ) : 1.0f;
|
||||
float addcycle = gpGlobals->frametime * cyclerate * m_flPlaybackRate;
|
||||
float flNewCycle = GetCycle() + addcycle;
|
||||
m_flAnimTime = gpGlobals->curtime;
|
||||
|
||||
if ( (flNewCycle < 0.0f) || (flNewCycle >= 1.0f) )
|
||||
{
|
||||
if (flNewCycle >= 1.0f) // asw
|
||||
ReachedEndOfSequence(); // asw
|
||||
if ( IsSequenceLooping( hdr, GetSequence() ) )
|
||||
{
|
||||
flNewCycle -= (int)(flNewCycle);
|
||||
}
|
||||
else
|
||||
{
|
||||
flNewCycle = (flNewCycle < 0.0f) ? 0.0f : 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
SetCycle( flNewCycle );
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Alien::UpdateFireEmitters()
|
||||
{
|
||||
bool bOnFire = (m_bOnFire.Get() && !IsEffectActive(EF_NODRAW));
|
||||
if (bOnFire != m_bClientOnFire)
|
||||
{
|
||||
m_bClientOnFire = bOnFire;
|
||||
if (m_bClientOnFire)
|
||||
{
|
||||
if ( !m_pBurningEffect )
|
||||
{
|
||||
m_pBurningEffect = UTIL_ASW_CreateFireEffect( this );
|
||||
}
|
||||
EmitSound( "ASWFire.BurningFlesh" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_pBurningEffect )
|
||||
{
|
||||
ParticleProp()->StopEmission( m_pBurningEffect );
|
||||
m_pBurningEffect = NULL;
|
||||
}
|
||||
StopSound("ASWFire.BurningFlesh");
|
||||
if ( C_BaseEntity::IsAbsQueriesValid() )
|
||||
EmitSound("ASWFire.StopBurning");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Alien::UpdateOnRemove( void )
|
||||
{
|
||||
BaseClass::UpdateOnRemove();
|
||||
m_bOnFire = false;
|
||||
UpdateFireEmitters();
|
||||
}
|
||||
|
||||
// aliens require extra interpolation time due to think rate
|
||||
ConVar cl_alien_extra_interp( "cl_alien_extra_interp", "0.1", FCVAR_NONE, "Extra interpolation for aliens." );
|
||||
|
||||
float C_ASW_Alien::GetInterpolationAmount( int flags )
|
||||
{
|
||||
return BaseClass::GetInterpolationAmount( flags ) + cl_alien_extra_interp.GetFloat();
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#ifndef _INCLUDED_C_ASW_ALIEN_H
|
||||
#define _INCLUDED_C_ASW_ALIEN_H
|
||||
|
||||
#include "asw_alien_shared.h"
|
||||
#include "c_ai_basenpc.h"
|
||||
#include "iasw_client_aim_target.h"
|
||||
#include "asw_shareddefs.h"
|
||||
#include "glow_outline_effect.h"
|
||||
#include "object_motion_blur_effect.h"
|
||||
|
||||
class CNewParticleEffect;
|
||||
|
||||
class C_ASW_Alien : public C_AI_BaseNPC, public IASW_Client_Aim_Target
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Alien, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
#include "asw_alien_shared_classmembers.h"
|
||||
|
||||
C_ASW_Alien();
|
||||
virtual ~C_ASW_Alien();
|
||||
|
||||
virtual void PostDataUpdate( DataUpdateType_t updateType );
|
||||
|
||||
// death;
|
||||
virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr );
|
||||
virtual void Bleed( const CTakeDamageInfo &info, const Vector &vecPos, const Vector &vecDir, trace_t *ptr );
|
||||
virtual void DoBloodDecal( float flDamage, const Vector &vecPos, const Vector &vecDir, trace_t *ptr, int bitsDamageType );
|
||||
virtual const char *GetDeathParticleEffectName( void ) { return "drone_death"; }
|
||||
virtual const char *GetBigDeathParticleEffectName( void ) { return "drone_death_big"; }
|
||||
virtual const char *GetSmallDeathParticleEffectName( void ) { return "drone_death_sml"; }
|
||||
virtual const char *GetRagdollGibParticleEffectName( void ) { return "drone_ragdoll_gib"; }
|
||||
virtual C_ClientRagdoll* CreateClientRagdoll( bool bRestoring = false );
|
||||
virtual C_BaseAnimating* BecomeRagdollOnClient( void );
|
||||
DeathStyle_t m_nDeathStyle;
|
||||
inline bool IsHurler(); ///< is this drone set to go flinging at the camera
|
||||
inline bool IsMeleeThrown();
|
||||
virtual bool HasCustomDeathForce(){ return false; };
|
||||
virtual Vector GetCustomDeathForce(){ return vec3_origin; };
|
||||
|
||||
// footsteps
|
||||
void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
|
||||
void MarineStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity );
|
||||
surfacedata_t* GetGroundSurface();
|
||||
void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force );
|
||||
virtual void DoAlienFootstep( Vector &vecOrigin, float fvol );
|
||||
bool m_bStepSideLeft;
|
||||
|
||||
// stun
|
||||
CNetworkVar(bool, m_bElectroStunned);
|
||||
float m_fNextElectroStunEffect;
|
||||
|
||||
// electro shocked
|
||||
//CNetworkVar(bool, m_bElectroShockSmall);
|
||||
//CNetworkVar(bool, m_bElectroShockBig);
|
||||
// fire
|
||||
CNetworkVar(bool, m_bOnFire);
|
||||
bool m_bClientOnFire;
|
||||
CUtlReference<CNewParticleEffect> m_pBurningEffect;
|
||||
virtual void UpdateFireEmitters();
|
||||
virtual void UpdateOnRemove();
|
||||
|
||||
// aim target interface
|
||||
IMPLEMENT_AUTO_LIST_GET();
|
||||
|
||||
virtual float GetRadius() { return 23; }
|
||||
virtual bool IsAimTarget() { return GetHealth() > 0; }
|
||||
virtual const Vector& GetAimTargetPos(const Vector &vecFiringSrc, bool bWeaponPrefersFlatAiming) { return m_vecLastRenderedPos; }
|
||||
virtual const Vector& GetAimTargetRadiusPos(const Vector &vecFiringSrc) { return m_vecAutoTargetRadiusPos; }
|
||||
virtual Vector GetLocalAutoTargetRadiusPos();
|
||||
|
||||
// custom shadow
|
||||
virtual bool GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const;
|
||||
ShadowType_t ShadowCastType();
|
||||
void GetShadowFromFlashlight(Vector &vecDir, float &fContribution) const;
|
||||
float m_fLastCustomContribution;
|
||||
Vector m_vecLastCustomDir;
|
||||
int m_iLastCustomFrame;
|
||||
|
||||
int m_nLastSetModel;
|
||||
virtual void ASWUpdateClientSideAnimation();
|
||||
virtual void ClientThink();
|
||||
|
||||
// storing our location for autoaim
|
||||
Vector m_vecLastRenderedPos;
|
||||
Vector m_vecAutoTargetRadiusPos;
|
||||
|
||||
// health
|
||||
virtual int GetHealth() const { return m_iHealth; }
|
||||
int GetMaxHealth( void ) const { return m_iMaxHealth; }
|
||||
int m_iMaxHealth;
|
||||
|
||||
virtual float GetInterpolationAmount( int flags );
|
||||
|
||||
// Glows are enabled when the sniper scope is used
|
||||
CGlowObject m_GlowObject;
|
||||
CMotionBlurObject m_MotionBlurObject;
|
||||
private:
|
||||
C_ASW_Alien( const C_ASW_Alien & ); // not defined, not accessible
|
||||
static float sm_flLastFootstepTime;
|
||||
};
|
||||
|
||||
extern ConVar asw_drone_ridiculous;
|
||||
inline bool C_ASW_Alien::IsHurler()
|
||||
{
|
||||
return m_nDeathStyle == kDIE_HURL || asw_drone_ridiculous.GetBool();
|
||||
}
|
||||
|
||||
inline bool C_ASW_Alien::IsMeleeThrown()
|
||||
{
|
||||
return m_nDeathStyle == kDIE_MELEE_THROW;
|
||||
}
|
||||
|
||||
#endif /* _INCLUDED_C_ASW_ALIEN_H */
|
||||
@@ -0,0 +1,159 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_ammo.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "asw_gamerules.h"
|
||||
#include "ammodef.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
//------------
|
||||
// Rifle Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Rifle, DT_ASW_Ammo_Rifle, CASW_Ammo_Rifle )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Rifle::C_ASW_Ammo_Rifle()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_rifle");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_rifle");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_rifle_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_R");
|
||||
}
|
||||
|
||||
//------------
|
||||
// Autogun Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Autogun, DT_ASW_Ammo_Autogun, CASW_Ammo_Autogun )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Autogun::C_ASW_Ammo_Autogun()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_autogun");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_autogun");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_autogun_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_AG");
|
||||
}
|
||||
|
||||
//------------
|
||||
// Shotgun Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Shotgun, DT_ASW_Ammo_Shotgun, CASW_Ammo_Shotgun )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Shotgun::C_ASW_Ammo_Shotgun()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_shotgun");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_shotgun");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_shotgun_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_SG");
|
||||
}
|
||||
|
||||
//------------
|
||||
// Vindicator (Assault Shotgun) Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Assault_Shotgun, DT_ASW_Ammo_Assault_Shotgun, CASW_Ammo_Assault_Shotgun )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Assault_Shotgun::C_ASW_Ammo_Assault_Shotgun()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_vindicator");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_vindicator");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_vindicator_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_ASG");
|
||||
}
|
||||
|
||||
//------------
|
||||
// Flamer Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Flamer, DT_ASW_Ammo_Flamer, CASW_Ammo_Flamer )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Flamer::C_ASW_Ammo_Flamer()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_flamer");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_flamer");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_flamer_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_F");
|
||||
}
|
||||
|
||||
//------------
|
||||
// Pistol Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Pistol, DT_ASW_Ammo_Pistol, CASW_Ammo_Pistol )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Pistol::C_ASW_Ammo_Pistol()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_pistol");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_pistol");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_pistol_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_P");
|
||||
}
|
||||
|
||||
//------------
|
||||
// Mining Laser Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Mining_Laser, DT_ASW_Ammo_Mining_Laser, CASW_Ammo_Mining_Laser )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Mining_Laser::C_ASW_Ammo_Mining_Laser()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_mining_laser");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_mining_laser");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_mining_laser_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_ML");
|
||||
}
|
||||
|
||||
//------------
|
||||
// Railgun Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Railgun, DT_ASW_Ammo_Railgun, CASW_Ammo_Railgun )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Railgun::C_ASW_Ammo_Railgun()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_railgun");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_railgun");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_railgun_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_RG");
|
||||
}
|
||||
|
||||
//------------
|
||||
// Chainsaw Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_Chainsaw, DT_ASW_Ammo_Chainsaw, CASW_Ammo_Chainsaw )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_Chainsaw::C_ASW_Ammo_Chainsaw()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_chainsaw");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_chainsaw");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_chainsaw_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_CS");
|
||||
}
|
||||
|
||||
//------------
|
||||
// PDW Ammo
|
||||
//------------
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Ammo_PDW, DT_ASW_Ammo_PDW, CASW_Ammo_PDW )
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Ammo_PDW::C_ASW_Ammo_PDW()
|
||||
{
|
||||
Q_snprintf(m_szUseIconText, sizeof(m_szUseIconText), "#asw_take_ammo_pdw");
|
||||
Q_snprintf(m_szNoGunText, sizeof(m_szNoGunText), "#asw_ammo_pdw");
|
||||
Q_snprintf(m_szAmmoFullText, sizeof(m_szAmmoFullText), "#asw_ammo_pdw_full");
|
||||
m_iAmmoIndex = GetAmmoDef()->Index("ASW_PDW");
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#ifndef _DEFINED_C_ASW_AMMO_H
|
||||
#define _DEFINED_C_ASW_AMMO_H
|
||||
|
||||
#include "c_asw_pickup.h"
|
||||
|
||||
class C_ASW_Ammo : public C_ASW_Pickup
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo, C_ASW_Pickup );
|
||||
|
||||
virtual bool AllowedToPickup(C_ASW_Marine *pMarine);
|
||||
|
||||
char m_szAmmoFullText[32];
|
||||
char m_szNoGunText[32];
|
||||
int m_iAmmoIndex;
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Rifle : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Rifle, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakeRifleAmmo; }
|
||||
C_ASW_Ammo_Rifle();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_RIFLE; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Autogun : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Autogun, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakeAutogunAmmo; }
|
||||
C_ASW_Ammo_Autogun();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_AUTOGUN; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Shotgun : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Shotgun, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakeShotgunAmmo; }
|
||||
C_ASW_Ammo_Shotgun();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_SHOTGUN; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Assault_Shotgun : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Assault_Shotgun, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakeVindicatorAmmo; }
|
||||
C_ASW_Ammo_Assault_Shotgun();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_ASSAULT_SHOTGUN; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Flamer : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Flamer, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakeFlamerAmmo; }
|
||||
C_ASW_Ammo_Flamer();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_FLAMER; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Pistol : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Pistol, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakePistolAmmo; }
|
||||
C_ASW_Ammo_Pistol();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_PISTOL; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Mining_Laser : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Mining_Laser, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakeMiningLaserAmmo; }
|
||||
C_ASW_Ammo_Mining_Laser();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_MINING_LASER; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Railgun : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Railgun, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakeRailgunAmmo; }
|
||||
C_ASW_Ammo_Railgun();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_RAILGUN; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_Chainsaw : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Chainsaw, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTake; }
|
||||
C_ASW_Ammo_Chainsaw();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_CHAINSAW; }
|
||||
};
|
||||
|
||||
class C_ASW_Ammo_PDW : public C_ASW_Ammo
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_PDW, C_ASW_Ammo );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual int GetUseIconTextureID() { BaseClass::GetUseIconTextureID(); return s_nUseIconTakePDWAmmo; }
|
||||
C_ASW_Ammo_PDW();
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_AMMO_PDW; }
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_AMMO_H */
|
||||
@@ -0,0 +1,233 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_ammo_drop.h"
|
||||
#include "asw_ammo_drop_shared.h"
|
||||
#include "c_asw_weapon.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include <vgui/ILocalize.h>
|
||||
#include "vguimatsurface/imatsystemsurface.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "ammodef.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "asw_input.h"
|
||||
#include "asw_hud_use_icon.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Ammo_Drop, DT_ASW_Ammo_Drop, CASW_Ammo_Drop)
|
||||
RecvPropInt( RECVINFO( m_iAmmoUnitsRemaining ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_ASW_Ammo_Drop )
|
||||
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
bool C_ASW_Ammo_Drop::s_bLoadedUseActionIcons = false;
|
||||
int C_ASW_Ammo_Drop::s_nUseActionIconTextureID = -1;
|
||||
|
||||
CUtlVector<C_ASW_Ammo_Drop*> g_AmmoDrops;
|
||||
|
||||
vgui::HFont C_ASW_Ammo_Drop::s_hAmmoFont = vgui::INVALID_FONT;
|
||||
|
||||
C_ASW_Ammo_Drop::C_ASW_Ammo_Drop() :
|
||||
m_GlowObject( this, Vector( 0.0f, 0.4f, 0.75f ), 1.0f, false, true )
|
||||
{
|
||||
m_iAmmoUnitsRemaining = DEFAULT_AMMO_DROP_UNITS;
|
||||
|
||||
g_AmmoDrops.AddToTail( this );
|
||||
|
||||
m_bEnoughAmmo = false;
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Ammo_Drop::~C_ASW_Ammo_Drop()
|
||||
{
|
||||
g_AmmoDrops.FindAndRemove( this );
|
||||
}
|
||||
|
||||
bool C_ASW_Ammo_Drop::ShouldDraw()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int C_ASW_Ammo_Drop::DrawModel( int flags, const RenderableInstance_t &instance )
|
||||
{
|
||||
int d = BaseClass::DrawModel(flags, instance);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
int C_ASW_Ammo_Drop::GetAmmoDropIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedUseActionIcons)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nUseActionIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nUseActionIconTextureID, "vgui/swarm/UseIcons/UseIconTakeAmmoDrop", true, false);
|
||||
s_bLoadedUseActionIcons = true;
|
||||
}
|
||||
|
||||
return s_nUseActionIconTextureID;
|
||||
}
|
||||
|
||||
bool C_ASW_Ammo_Drop::IsUsable(C_BaseEntity *pUser)
|
||||
{
|
||||
return (pUser && pUser->GetAbsOrigin().DistTo(GetAbsOrigin()) < ASW_MARINE_USE_RADIUS); // near enough?
|
||||
}
|
||||
|
||||
bool C_ASW_Ammo_Drop::GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser)
|
||||
{
|
||||
action.iUseIconTexture = GetAmmoDropIconTextureID();
|
||||
action.UseTarget = this;
|
||||
|
||||
if ( !AllowedToPickup( pUser ) )
|
||||
{
|
||||
if ( !m_bEnoughAmmo )
|
||||
{
|
||||
TryLocalize( "#asw_not_enough_ammo_drop", action.wszText, sizeof( action.wszText ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
TryLocalize( "#asw_full_ammo_drop", action.wszText, sizeof( action.wszText ) );
|
||||
}
|
||||
|
||||
action.fProgress = -1;
|
||||
|
||||
action.UseIconRed = 255;
|
||||
action.UseIconGreen = 0;
|
||||
action.UseIconBlue = 0;
|
||||
action.TextRed = 164;
|
||||
action.TextGreen = 164;
|
||||
action.TextBlue = 164;
|
||||
action.bTextGlow = false;
|
||||
action.bShowUseKey = false;
|
||||
action.iInventorySlot = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TryLocalize( "#asw_use_ammo_drop", action.wszText, sizeof( action.wszText ) );
|
||||
|
||||
action.fProgress = -1;
|
||||
|
||||
action.UseIconRed = 255;
|
||||
action.UseIconGreen = 255;
|
||||
action.UseIconBlue = 255;
|
||||
action.bShowUseKey = true;
|
||||
action.iInventorySlot = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void C_ASW_Ammo_Drop::CustomPaint(int ix, int iy, int alpha, vgui::Panel *pUseIcon)
|
||||
{
|
||||
if (s_hAmmoFont == vgui::INVALID_FONT)
|
||||
{
|
||||
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew");
|
||||
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme(scheme);
|
||||
if (pScheme)
|
||||
s_hAmmoFont = vgui::scheme()->GetIScheme(scheme)->GetFont("DefaultSmall", true);
|
||||
}
|
||||
|
||||
if (s_hAmmoFont == vgui::INVALID_FONT || alpha <= 0)
|
||||
return;
|
||||
|
||||
Color textColor( 255, 255, 255, 255 );
|
||||
|
||||
if ( pUseIcon )
|
||||
{
|
||||
CASW_HUD_Use_Icon *pUseIconPanel = static_cast<CASW_HUD_Use_Icon*>(pUseIcon);
|
||||
float flProgress = (float) GetAmmoUnitsRemaining() / 100.0f;
|
||||
char szCountText[64];
|
||||
Q_snprintf( szCountText, sizeof( szCountText ), "%d%%", MAX( GetAmmoUnitsRemaining(), 0 ) );
|
||||
pUseIconPanel->CustomPaintProgressBar( ix, iy, alpha / 255.0f, flProgress, szCountText, s_hAmmoFont, textColor, "#asw_ammo_label" );
|
||||
}
|
||||
}
|
||||
|
||||
int C_ASW_Ammo_Drop::GetAmmoUnitCost( int iAmmoType )
|
||||
{
|
||||
return CASW_Ammo_Drop_Shared::GetAmmoUnitCost( iAmmoType );
|
||||
}
|
||||
|
||||
C_ASW_Weapon* C_ASW_Ammo_Drop::GetAmmoUseUnits( C_ASW_Marine *pMarine )
|
||||
{
|
||||
if ( pMarine )
|
||||
{
|
||||
CASW_Weapon *pWeapon = pMarine->GetActiveASWWeapon();
|
||||
if ( !pWeapon || pWeapon->Classify() == CLASS_ASW_AMMO_SATCHEL )
|
||||
{
|
||||
//pWeapon
|
||||
C_ASW_Weapon *pOtherWeapon = pMarine->GetASWWeapon( 0 );
|
||||
if ( pOtherWeapon && pOtherWeapon != pWeapon )
|
||||
{
|
||||
pWeapon = pOtherWeapon;
|
||||
}
|
||||
else
|
||||
{
|
||||
pOtherWeapon = pMarine->GetASWWeapon( 1 );
|
||||
if ( pOtherWeapon && pOtherWeapon != pWeapon )
|
||||
{
|
||||
pWeapon = pOtherWeapon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( pWeapon && pWeapon->IsOffensiveWeapon() )
|
||||
{
|
||||
int iAmmoType = pWeapon->GetPrimaryAmmoType();
|
||||
int iGuns = pMarine->GetNumberOfWeaponsUsingAmmo( iAmmoType );
|
||||
int iMaxAmmoCount = GetAmmoDef()->MaxCarry( iAmmoType, pMarine ) * iGuns;
|
||||
int iBullets = pMarine->GetAmmoCount( iAmmoType );
|
||||
int iAmmoCost = CASW_Ammo_Drop_Shared::GetAmmoUnitCost( iAmmoType );
|
||||
|
||||
m_bEnoughAmmo = m_iAmmoUnitsRemaining >= iAmmoCost;
|
||||
|
||||
if ( ( iBullets < iMaxAmmoCount ) && m_bEnoughAmmo )
|
||||
{
|
||||
return pWeapon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool C_ASW_Ammo_Drop::AllowedToPickup( C_ASW_Marine *pMarine )
|
||||
{
|
||||
// if the marine can't use it, the use portion is zero
|
||||
return ( GetAmmoUseUnits( pMarine ) != NULL );
|
||||
}
|
||||
|
||||
void C_ASW_Ammo_Drop::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Ammo_Drop::ClientThink()
|
||||
{
|
||||
bool bShouldGlow = false;
|
||||
float flDistanceToMarineSqr = 0.0f;
|
||||
float flWithinDistSqr = (ASW_MARINE_USE_RADIUS*4)*(ASW_MARINE_USE_RADIUS*4);
|
||||
|
||||
C_ASW_Player *pLocalPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pLocalPlayer && pLocalPlayer->GetMarine() && ASWInput()->GetUseGlowEntity() != this && AllowedToPickup( pLocalPlayer->GetMarine() ) )
|
||||
{
|
||||
flDistanceToMarineSqr = (pLocalPlayer->GetMarine()->GetAbsOrigin() - WorldSpaceCenter()).LengthSqr();
|
||||
if ( flDistanceToMarineSqr < flWithinDistSqr )
|
||||
bShouldGlow = true;
|
||||
}
|
||||
|
||||
m_GlowObject.SetRenderFlags( false, bShouldGlow );
|
||||
|
||||
if ( m_GlowObject.IsRendering() )
|
||||
{
|
||||
m_GlowObject.SetAlpha( MIN( 0.7f, (1.0f - (flDistanceToMarineSqr / flWithinDistSqr)) * 1.0f) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef C_ASW_AMMO_DROP_H
|
||||
#define C_ASW_AMMO_DROP_H
|
||||
|
||||
#include "iasw_client_usable_entity.h"
|
||||
#include "glow_outline_effect.h"
|
||||
|
||||
#include <vgui/vgui.h>
|
||||
|
||||
class C_ASW_Marine;
|
||||
class C_ASW_Weapon;
|
||||
|
||||
class C_ASW_Ammo_Drop : public C_BaseAnimating, public IASW_Client_Usable_Entity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Ammo_Drop, C_BaseAnimating );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
C_ASW_Ammo_Drop();
|
||||
virtual ~C_ASW_Ammo_Drop();
|
||||
|
||||
bool ShouldDraw();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
void ClientThink();
|
||||
|
||||
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
|
||||
|
||||
int GetAmmoDropIconTextureID();
|
||||
static bool s_bLoadedUseActionIcons;
|
||||
static int s_nUseActionIconTextureID;
|
||||
|
||||
CNetworkVar(int, m_iAmmoUnitsRemaining);
|
||||
|
||||
int GetAmmoUnitCost( int iAmmoType );
|
||||
int GetAmmoUnitsRemaining() { return m_iAmmoUnitsRemaining; }
|
||||
C_ASW_Weapon* GetAmmoUseUnits( C_ASW_Marine *pMarine );
|
||||
bool AllowedToPickup( C_ASW_Marine *pMarine );
|
||||
|
||||
// IASW_Client_Usable_Entity
|
||||
virtual C_BaseEntity* GetEntity() { return this; }
|
||||
virtual bool IsUsable( C_BaseEntity *pUser );
|
||||
virtual bool GetUseAction( ASWUseAction &action, C_ASW_Marine *pUser );
|
||||
virtual void CustomPaint( int ix, int iy, int alpha, vgui::Panel *pUseIcon );
|
||||
virtual bool ShouldPaintBoxAround() { return true; }
|
||||
virtual bool NeedsLOSCheck() { return true; }
|
||||
|
||||
static vgui::HFont s_hAmmoFont;
|
||||
|
||||
CGlowObject m_GlowObject;
|
||||
|
||||
private:
|
||||
C_ASW_Ammo_Drop( const C_ASW_Ammo_Drop & ); // not defined, not accessible
|
||||
bool m_bEnoughAmmo;
|
||||
};
|
||||
|
||||
extern CUtlVector<C_ASW_Ammo_Drop*> g_AmmoDrops;
|
||||
|
||||
#endif /* C_ASW_AMMO_DROP_H */
|
||||
@@ -0,0 +1,546 @@
|
||||
#include "cbase.h"
|
||||
#include "precache_register.h"
|
||||
#include "particles_simple.h"
|
||||
#include "iefx.h"
|
||||
#include "dlight.h"
|
||||
#include "view.h"
|
||||
#include "fx.h"
|
||||
#include "clientsideeffects.h"
|
||||
#include "c_pixel_visibility.h"
|
||||
#include "c_asw_aoegrenade_projectile.h"
|
||||
#include "soundenvelope.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_weapon.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//Precahce the effects
|
||||
PRECACHE_REGISTER_BEGIN( GLOBAL, ASWPrecacheEffectAOEGrenades )
|
||||
PRECACHE( MATERIAL, "swarm/effects/blueflare" )
|
||||
PRECACHE( MATERIAL, "effects/yellowflare" )
|
||||
PRECACHE( MATERIAL, "effects/yellowflare_noz" )
|
||||
PRECACHE_REGISTER_END()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: RecvProxy that converts a marine's player UtlVector to entindexes
|
||||
//-----------------------------------------------------------------------------
|
||||
void RecvProxy_AOEGrenList( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||
{
|
||||
C_ASW_AOEGrenade_Projectile *pAOEGren = (C_ASW_AOEGrenade_Projectile*)pStruct;
|
||||
|
||||
CBaseHandle *pHandle = (CBaseHandle*)(&(pAOEGren->m_hAOETargets[pData->m_iElement]));
|
||||
RecvProxy_IntToEHandle( pData, pStruct, pHandle );
|
||||
|
||||
// update the heal beams
|
||||
pAOEGren->m_bUpdateAOETargets = true;
|
||||
}
|
||||
|
||||
void RecvProxyArrayLength_AOEGrenArray( void *pStruct, int objectID, int currentArrayLength )
|
||||
{
|
||||
C_ASW_AOEGrenade_Projectile *pAOEGren = (C_ASW_AOEGrenade_Projectile*)pStruct;
|
||||
|
||||
if ( pAOEGren->m_hAOETargets.Count() != currentArrayLength )
|
||||
pAOEGren->m_hAOETargets.SetSize( currentArrayLength );
|
||||
|
||||
// update the heal beams
|
||||
pAOEGren->m_bUpdateAOETargets = true;
|
||||
}
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_AOEGrenade_Projectile, DT_ASW_AOEGrenade_Projectile, CASW_AOEGrenade_Projectile )
|
||||
RecvPropArray2(
|
||||
RecvProxyArrayLength_AOEGrenArray,
|
||||
RecvPropInt( "aoegren_array_element", 0, SIZEOF_IGNORE, 0, RecvProxy_AOEGrenList ),
|
||||
MAX_PLAYERS,
|
||||
0,
|
||||
"aoetarget_array"
|
||||
),
|
||||
RecvPropFloat( RECVINFO( m_flTimeBurnOut ) ),
|
||||
//RecvPropFloat( RECVINFO( m_flTimePulse ) ),
|
||||
RecvPropFloat( RECVINFO( m_flScale ) ),
|
||||
RecvPropBool( RECVINFO( m_bSettled ) ),
|
||||
RecvPropFloat( RECVINFO( m_flRadius ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
// aoegrenades maintain a linked list of themselves, for quick checking for autoaim
|
||||
C_ASW_AOEGrenade_Projectile* g_pHeadAOEGrenade = NULL;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_ASW_AOEGrenade_Projectile::C_ASW_AOEGrenade_Projectile()
|
||||
{
|
||||
m_flTimeBurnOut = 0.0f;
|
||||
//m_flTimePulse = 0.0f;
|
||||
m_pDLight = NULL;
|
||||
|
||||
m_bSettled = false;
|
||||
m_bPlayingSound = false;
|
||||
|
||||
//SetDynamicallyAllocated( false );
|
||||
m_queryHandle = 0;
|
||||
m_fStartLightTime = 0;
|
||||
m_fLightRadius = 0;
|
||||
|
||||
m_bUpdateAOETargets = false;
|
||||
|
||||
m_pPulseEffect = NULL;
|
||||
|
||||
m_hSphereModel = NULL;
|
||||
m_flTimeCreated = -1;
|
||||
|
||||
m_fUpdateAttachFXTime = 0;
|
||||
}
|
||||
|
||||
C_ASW_AOEGrenade_Projectile::~C_ASW_AOEGrenade_Projectile( void )
|
||||
{
|
||||
if (m_pDLight)
|
||||
{
|
||||
m_pDLight->die = gpGlobals->curtime;
|
||||
m_pDLight = NULL;
|
||||
}
|
||||
|
||||
if (m_hSphereModel.Get())
|
||||
{
|
||||
UTIL_Remove( m_hSphereModel.Get() );
|
||||
m_hSphereModel = NULL;
|
||||
}
|
||||
|
||||
StopSound( GetIdleLoopSoundName() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : state -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_AOEGrenade_Projectile::NotifyShouldTransmit( ShouldTransmitState_t state )
|
||||
{
|
||||
if ( state == SHOULDTRANSMIT_END )
|
||||
{
|
||||
AddEffects( EF_NODRAW );
|
||||
}
|
||||
else if ( state == SHOULDTRANSMIT_START )
|
||||
{
|
||||
RemoveEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
BaseClass::NotifyShouldTransmit( state );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : updateType -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_AOEGrenade_Projectile::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
//SetSortOrigin( GetAbsOrigin() );
|
||||
SoundInit();
|
||||
SetNextClientThink(CLIENT_THINK_ALWAYS);
|
||||
}
|
||||
|
||||
if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
|
||||
{
|
||||
}
|
||||
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( m_bUpdateAOETargets )
|
||||
{
|
||||
UpdateTargetAOEEffects();
|
||||
m_bUpdateAOETargets = false;
|
||||
}
|
||||
|
||||
UpdatePingEffects();
|
||||
}
|
||||
|
||||
void C_ASW_AOEGrenade_Projectile::UpdateTargetAOEEffects( void )
|
||||
{
|
||||
// Find all the targets we've stopped giving a buff to
|
||||
AOEGrenTargetFXList_t::IndexLocalType_t i = m_hAOETargetEffects.Head();
|
||||
while ( m_hAOETargetEffects.IsValidIndex(i) )
|
||||
{
|
||||
AOETargetEffects_t &aoeTargetEffect = m_hAOETargetEffects[i];
|
||||
Assert( m_hAOETargetEffects[i].me == &m_hAOETargetEffects[i] );
|
||||
bool bStillAOEGren = false;
|
||||
|
||||
// Are we still buffing this target?
|
||||
for ( int target = 0; target < m_hAOETargets.Count(); target++ )
|
||||
{
|
||||
if ( m_hAOETargets[target] && m_hAOETargets[target] == aoeTargetEffect.hTarget.Get() )
|
||||
{
|
||||
bStillAOEGren = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// advance before deleting the pointer out from under us
|
||||
const AOEGrenTargetFXList_t::IndexLocalType_t oldi = i;
|
||||
i = m_hAOETargetEffects.Next( i );
|
||||
|
||||
if ( !bStillAOEGren )
|
||||
{
|
||||
ParticleProp()->StopEmission( aoeTargetEffect.pEffect );
|
||||
|
||||
// stop the sound on this marine
|
||||
C_ASW_Marine *pMarine = dynamic_cast<C_ASW_Marine*>( m_hAOETargetEffects[oldi].hTarget.Get() );
|
||||
if ( pMarine && pMarine->GetCommander() )
|
||||
{
|
||||
C_ASW_Player *pLocalPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pMarine->GetCommander() == pLocalPlayer && pMarine->IsInhabited() && m_hAOETargetEffects[oldi].pBuffLoopSound )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_hAOETargetEffects[oldi].pBuffLoopSound );
|
||||
m_hAOETargetEffects[oldi].pBuffLoopSound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
m_hAOETargetEffects.Remove(oldi);
|
||||
}
|
||||
}
|
||||
|
||||
// Now add any new targets
|
||||
for ( int i = 0; i < m_hAOETargets.Count(); i++ )
|
||||
{
|
||||
C_BaseEntity *pTarget = m_hAOETargets[i].Get();
|
||||
|
||||
// Loops through the aoe targets, and make sure we have an effect for each of them
|
||||
if ( pTarget )
|
||||
{
|
||||
bool bHaveEffect = false;
|
||||
|
||||
for ( AOEGrenTargetFXList_t::IndexLocalType_t i = m_hAOETargetEffects.Head() ;
|
||||
m_hAOETargetEffects.IsValidIndex(i) ;
|
||||
i = m_hAOETargetEffects.Next(i) )
|
||||
{
|
||||
if ( m_hAOETargetEffects[i].hTarget.Get() == pTarget )
|
||||
{
|
||||
bHaveEffect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bHaveEffect )
|
||||
{
|
||||
CNewParticleEffect *pEffect = ParticleProp()->Create( GetArcEffectName(), PATTACH_ABSORIGIN_FOLLOW );
|
||||
|
||||
AOEGrenTargetFXList_t::IndexLocalType_t iIndex = m_hAOETargetEffects.AddToTail();
|
||||
m_hAOETargetEffects[iIndex].hTarget = pTarget;
|
||||
m_hAOETargetEffects[iIndex].pEffect = pEffect;
|
||||
Assert( m_hAOETargetEffects[iIndex].me == &m_hAOETargetEffects[iIndex] );
|
||||
|
||||
UpdateParticleAttachments( m_hAOETargetEffects[iIndex].pEffect, pTarget );
|
||||
|
||||
// Start the sound over again every time we start a new beam
|
||||
//StopSound( GetLoopSoundName() );
|
||||
|
||||
C_ASW_Marine *pMarine = C_ASW_Marine::AsMarine( pTarget );
|
||||
if ( pMarine && pMarine->GetCommander() )
|
||||
{
|
||||
C_ASW_Player *pLocalPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pMarine->GetCommander() == pLocalPlayer && pMarine->IsInhabited() )
|
||||
{
|
||||
if ( m_hAOETargetEffects[iIndex].pBuffLoopSound )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_hAOETargetEffects[iIndex].pBuffLoopSound );
|
||||
m_hAOETargetEffects[iIndex].pBuffLoopSound = NULL;
|
||||
}
|
||||
|
||||
CSingleUserRecipientFilter filter( pLocalPlayer );
|
||||
EmitSound( filter, pMarine->entindex(), GetStartSoundName() );
|
||||
m_hAOETargetEffects[iIndex].pBuffLoopSound = CSoundEnvelopeController::GetController().SoundCreate( filter, pMarine->entindex(), GetLoopSoundName() );
|
||||
CSoundEnvelopeController::GetController().Play( m_hAOETargetEffects[iIndex].pBuffLoopSound, 1.0, 100 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_AOEGrenade_Projectile::UpdateParticleAttachments( CNewParticleEffect *pEffect, C_BaseEntity *pTarget )
|
||||
{
|
||||
if ( GetArcAttachmentName() )
|
||||
{
|
||||
bool bAttachWeapon = false;
|
||||
if ( ShouldAttachEffectToWeapon() )
|
||||
{
|
||||
C_ASW_Marine *pMarine = C_ASW_Marine::AsMarine( pTarget );
|
||||
if ( pMarine && pMarine->GetActiveASWWeapon() )
|
||||
{
|
||||
C_ASW_Weapon *pWeapon = pMarine->GetActiveASWWeapon();
|
||||
int iAttachment = pWeapon->LookupAttachment( "muzzle" );
|
||||
if ( pWeapon->IsOffensiveWeapon() && iAttachment > 0 )
|
||||
{
|
||||
bAttachWeapon = true;
|
||||
ParticleProp()->AddControlPoint( pEffect, 1, pWeapon, PATTACH_POINT_FOLLOW, "muzzle" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bAttachWeapon )
|
||||
ParticleProp()->AddControlPoint( pEffect, 1, pTarget, PATTACH_POINT_FOLLOW, GetArcAttachmentName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
ParticleProp()->AddControlPoint( pEffect, 1, pTarget, PATTACH_ABSORIGIN_FOLLOW );
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_AOEGrenade_Projectile::UpdatePingEffects( void )
|
||||
{
|
||||
if ( m_bSettled && m_pPulseEffect.GetObject() == NULL )
|
||||
{
|
||||
m_pPulseEffect = ParticleProp()->Create( GetPingEffectName(), PATTACH_ABSORIGIN_FOLLOW, -1, Vector( 0, 0, 8 ) );
|
||||
if ( m_pPulseEffect )
|
||||
{
|
||||
m_pPulseEffect->SetControlPoint( 1, Vector( m_flRadius, 0, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ShouldSpawnSphere() && m_bSettled && m_hSphereModel.Get() == NULL )
|
||||
{
|
||||
C_BaseAnimating *pEnt = new C_BaseAnimating;
|
||||
if (!pEnt)
|
||||
{
|
||||
Msg("Error, couldn't create new C_BaseAnimating\n");
|
||||
return;
|
||||
}
|
||||
if (!pEnt->InitializeAsClientEntity( "models/items/shield_bubble/shield_bubble.mdl", false ))
|
||||
//if (!pEnt->InitializeAsClientEntity( "models/props_combine/coreball.mdl", false ))
|
||||
{
|
||||
Msg("Error, couldn't InitializeAsClientEntity\n");
|
||||
pEnt->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
pEnt->SetParent( this );
|
||||
pEnt->SetLocalOrigin( Vector( 0, 0, 0 ) );
|
||||
pEnt->SetLocalAngles( QAngle( 0, 0, 0 ) );
|
||||
pEnt->SetSolid( SOLID_NONE );
|
||||
pEnt->SetSkin( GetSphereSkin() );
|
||||
pEnt->RemoveEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
|
||||
|
||||
m_hSphereModel = pEnt;
|
||||
m_flTimeCreated = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
const Vector& C_ASW_AOEGrenade_Projectile::GetEffectOrigin()
|
||||
{
|
||||
static Vector s_vecEffectPos;
|
||||
Vector forward, right, up;
|
||||
AngleVectors(GetAbsAngles(), &forward, &right, &up);
|
||||
s_vecEffectPos = GetAbsOrigin() + up * 5;
|
||||
return s_vecEffectPos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : timeDelta -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_AOEGrenade_Projectile::ClientThink( void )
|
||||
{
|
||||
float baseScale = m_flScale;
|
||||
float flTimeLeft = m_flTimeBurnOut - gpGlobals->curtime;
|
||||
//Account for fading out
|
||||
if ( ( m_flTimeBurnOut != -1.0f ) && ( flTimeLeft <= 5.0f ) )
|
||||
{
|
||||
baseScale *= ( flTimeLeft / 5.0f );
|
||||
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pLoopedSound, clamp<float>(0.6f * baseScale, 0.0f, 0.6f), 0 );
|
||||
|
||||
AOEGrenTargetFXList_t::IndexLocalType_t i = m_hAOETargetEffects.Head();
|
||||
while ( m_hAOETargetEffects.IsValidIndex(i) )
|
||||
{
|
||||
// Are we still buffing this target?
|
||||
for ( int target = 0; target < m_hAOETargets.Count(); target++ )
|
||||
{
|
||||
if ( m_hAOETargetEffects[i].pBuffLoopSound )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_hAOETargetEffects[i].pBuffLoopSound, clamp<float>(0.6f * baseScale, 0.0f, 0.6f), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
i = m_hAOETargetEffects.Next( i );
|
||||
}
|
||||
}
|
||||
|
||||
if ( baseScale < 0.01f )
|
||||
return;
|
||||
//
|
||||
// Dynamic light
|
||||
//
|
||||
|
||||
if ( m_fStartLightTime == 0.0f )
|
||||
{
|
||||
m_fStartLightTime = gpGlobals->curtime;
|
||||
}
|
||||
if ( !m_pDLight )
|
||||
{
|
||||
m_pDLight = effects->CL_AllocDlight( index );
|
||||
|
||||
Color rgbaGrenadeColor = GetGrenadeColor();
|
||||
|
||||
m_pDLight->color.r = rgbaGrenadeColor.r();
|
||||
m_pDLight->color.g = rgbaGrenadeColor.g();
|
||||
m_pDLight->color.b = rgbaGrenadeColor.b();
|
||||
m_pDLight->color.exponent = 1;
|
||||
}
|
||||
|
||||
|
||||
m_pDLight->origin = GetAbsOrigin() + Vector(0, 0, 5); // make the dlight slightly higher than the aoegrenade, so it doesn't bury the light being so close to the ground
|
||||
|
||||
if ( m_fLightRadius < 32.0f )
|
||||
{
|
||||
m_fLightRadius += flTimeLeft * (1.0f + random->RandomFloat() * 36.0f);
|
||||
if (m_fLightRadius > 32.0f)
|
||||
m_fLightRadius = 100.0f;
|
||||
}
|
||||
|
||||
m_pDLight->radius = baseScale * 120 * (m_fLightRadius/32.0f);
|
||||
|
||||
if ( flTimeLeft > 4.0f )
|
||||
{
|
||||
m_pDLight->die = gpGlobals->curtime + 30.0f;
|
||||
}
|
||||
|
||||
|
||||
// spehere bubble models
|
||||
if ( !ShouldSpawnSphere() || !m_hSphereModel.Get() )
|
||||
return;
|
||||
|
||||
C_BaseAnimating *pSphere = static_cast<C_BaseAnimating*>( m_hSphereModel.Get() );
|
||||
if ( pSphere )
|
||||
{
|
||||
float flTimeLeft = m_flTimeBurnOut - gpGlobals->curtime;
|
||||
|
||||
float flScale = GetSphereScale();
|
||||
|
||||
if ( m_flTimeCreated > 0 && ( gpGlobals->curtime - m_flTimeCreated ) < 0.25f )
|
||||
{
|
||||
pSphere->SetModelScale( MIN( ((gpGlobals->curtime - m_flTimeCreated)/0.25f)*flScale, 1.0f ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
pSphere->SetModelScale( flScale );
|
||||
}
|
||||
|
||||
if ( flTimeLeft < 0.25f )
|
||||
{
|
||||
pSphere->SetModelScale( MAX( (flTimeLeft/0.25f)*flScale, 0.01f ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_fUpdateAttachFXTime < gpGlobals->curtime )
|
||||
{
|
||||
AOEGrenTargetFXList_t::IndexLocalType_t i = m_hAOETargetEffects.Head();
|
||||
while ( m_hAOETargetEffects.IsValidIndex(i) )
|
||||
{
|
||||
// Are we still buffing this target?
|
||||
for ( int target = 0; target < m_hAOETargets.Count(); target++ )
|
||||
{
|
||||
C_BaseEntity *pTarget = m_hAOETargets[target].Get();
|
||||
if ( m_hAOETargetEffects[i].hTarget.Get() == pTarget && m_hAOETargetEffects[i].pEffect )
|
||||
UpdateParticleAttachments( m_hAOETargetEffects[i].pEffect, pTarget );
|
||||
}
|
||||
|
||||
i = m_hAOETargetEffects.Next( i );
|
||||
}
|
||||
|
||||
/*
|
||||
for ( int i = 0; i < m_hAOETargets.Count(); i++ )
|
||||
{
|
||||
C_BaseEntity *pTarget = m_hAOETargets[i].Get();
|
||||
|
||||
// Loops through the aoe targets, and make sure we have an effect for each of them
|
||||
if ( pTarget )
|
||||
{
|
||||
bool bHaveEffect = false;
|
||||
|
||||
for ( AOEGrenTargetFXList_t::IndexLocalType_t j = m_hAOETargetEffects.Head() ;
|
||||
m_hAOETargetEffects.IsValidIndex(j) ;
|
||||
i = m_hAOETargetEffects.Next(j) )
|
||||
{
|
||||
if ( m_hAOETargetEffects[j].hTarget.Get() == pTarget && m_hAOETargetEffects[j].pEffect )
|
||||
{
|
||||
UpdateParticleAttachments( m_hAOETargetEffects[j].pEffect, pTarget );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
m_fUpdateAttachFXTime = gpGlobals->curtime + 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_AOEGrenade_Projectile::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
SoundInit();
|
||||
}
|
||||
|
||||
void C_ASW_AOEGrenade_Projectile::UpdateOnRemove()
|
||||
{
|
||||
BaseClass::UpdateOnRemove();
|
||||
SoundShutdown();
|
||||
}
|
||||
|
||||
void C_ASW_AOEGrenade_Projectile::SoundInit()
|
||||
{
|
||||
// play aoegrenade start sound!!
|
||||
CPASAttenuationFilter filter( this );
|
||||
|
||||
EmitSound( GetActivateSoundName() );
|
||||
|
||||
// Bring up the aoegrenade burning loop sound
|
||||
if( !m_pLoopedSound )
|
||||
{
|
||||
m_pLoopedSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), GetIdleLoopSoundName() );
|
||||
CSoundEnvelopeController::GetController().Play( m_pLoopedSound, 0.0, 100 );
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pLoopedSound, 0.6, 2.0 );
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_AOEGrenade_Projectile::SoundShutdown()
|
||||
{
|
||||
AOEGrenTargetFXList_t::IndexLocalType_t i = m_hAOETargetEffects.Head();
|
||||
while ( m_hAOETargetEffects.IsValidIndex(i) )
|
||||
{
|
||||
// Are we still buffing this target?
|
||||
for ( int target = 0; target < m_hAOETargets.Count(); target++ )
|
||||
{
|
||||
if ( m_hAOETargetEffects[i].pBuffLoopSound )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_hAOETargetEffects[i].pBuffLoopSound );
|
||||
m_hAOETargetEffects[i].pBuffLoopSound = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
C_ASW_Marine *pMarine = dynamic_cast<C_ASW_Marine*>( m_hAOETargets[target].Get() );
|
||||
if ( pMarine && pMarine->GetCommander() )
|
||||
{
|
||||
C_ASW_Player *pLocalPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pMarine->GetCommander() == pLocalPlayer && pMarine->IsInhabited() && m_hAOETargetEffects[i].pBuffLoopSound )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_hAOETargetEffects[i].pBuffLoopSound );
|
||||
m_hAOETargetEffects[i].pBuffLoopSound = NULL;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
m_hAOETargetEffects.Remove(i);
|
||||
}
|
||||
|
||||
if ( m_pLoopedSound )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_pLoopedSound );
|
||||
m_pLoopedSound = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef _C_ASW_AOEGREN_PROJECTILE_H
|
||||
#define _C_ASW_AOEGREN_PROJECTILE_H
|
||||
#pragma once
|
||||
|
||||
struct dlight_t;
|
||||
|
||||
#include "c_pixel_visibility.h"
|
||||
|
||||
class C_ASW_AOEGrenade_Projectile : public C_BaseCombatCharacter
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_AOEGrenade_Projectile, C_BaseCombatCharacter );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_AOEGrenade_Projectile();
|
||||
virtual ~C_ASW_AOEGrenade_Projectile();
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void ClientThink( void );
|
||||
void NotifyDestroyParticle( Particle* pParticle );
|
||||
void NotifyShouldTransmit( ShouldTransmitState_t state );
|
||||
void RestoreResources( void );
|
||||
void UpdateTargetAOEEffects( void );
|
||||
void UpdateParticleAttachments( CNewParticleEffect *pEffect, C_BaseEntity *pTarget );
|
||||
virtual void UpdatePingEffects( void );
|
||||
const Vector& GetEffectOrigin();
|
||||
virtual float GetEffectRadius( void ) { return m_flRadius.Get(); }
|
||||
|
||||
virtual Color GetGrenadeColor( void ) { return Color( 16, 16, 80, 255 ); }
|
||||
virtual const char* GetIdleLoopSoundName( void ) { return "ASW_BuffGrenade.ActiveLoop"; }
|
||||
virtual const char* GetLoopSoundName( void ) { return "ASW_BuffGrenade.BuffLoop"; }
|
||||
virtual const char* GetStartSoundName( void ) { return "ASW_BuffGrenade.StartBuff"; }
|
||||
virtual const char* GetActivateSoundName( void ) { return "ASW_BuffGrenade.GrenadeActivate"; }
|
||||
virtual const char* GetPingEffectName( void ) { return "buffgrenade_pulse"; }
|
||||
virtual const char* GetArcEffectName( void ) { return "buffgrenade_attach_arc"; }
|
||||
virtual const char* GetArcAttachmentName( void ) { return "weapon_aim_attachment"; }
|
||||
virtual bool ShouldAttachEffectToWeapon( void ) { return false; }
|
||||
virtual bool ShouldSpawnSphere( void ) { return false; }
|
||||
virtual float GetSphereScale( void ) { return 1.0f; }
|
||||
virtual int GetSphereSkin( void ) { return 0; }
|
||||
|
||||
float m_flTimeBurnOut;
|
||||
float m_flScale;
|
||||
bool m_bSettled;
|
||||
dlight_t *m_pDLight;
|
||||
float m_fStartLightTime;
|
||||
float m_fLightRadius;
|
||||
float m_fUpdateAttachFXTime;
|
||||
|
||||
pixelvis_handle_t m_queryHandle;
|
||||
|
||||
// sound
|
||||
void SoundShutdown();
|
||||
void SoundInit();
|
||||
virtual void UpdateOnRemove();
|
||||
virtual void OnRestore();
|
||||
CSoundPatch *m_pLoopedSound;
|
||||
|
||||
bool m_bUpdateAOETargets;
|
||||
CUtlVector< CHandle<C_BaseEntity> > m_hAOETargets;
|
||||
|
||||
EHANDLE m_hSphereModel;
|
||||
float m_flTimeCreated;
|
||||
|
||||
private:
|
||||
bool m_bPlayingSound;
|
||||
CNetworkVar( float, m_flRadius );
|
||||
|
||||
C_ASW_AOEGrenade_Projectile( const C_ASW_AOEGrenade_Projectile & );
|
||||
|
||||
struct AOETargetEffects_t
|
||||
{
|
||||
CHandle<C_BaseEntity> hTarget;
|
||||
CUtlReference<CNewParticleEffect> pEffect;
|
||||
CSoundPatch *pBuffLoopSound;
|
||||
#ifdef DEBUG
|
||||
AOETargetEffects_t * me;
|
||||
#endif
|
||||
AOETargetEffects_t()
|
||||
{
|
||||
hTarget = NULL;
|
||||
pEffect = NULL;
|
||||
pBuffLoopSound = NULL;
|
||||
#ifdef DEBUG
|
||||
me = this;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef CUtlFixedLinkedList<AOETargetEffects_t> AOEGrenTargetFXList_t;
|
||||
AOEGrenTargetFXList_t m_hAOETargetEffects;
|
||||
|
||||
CUtlReference<CNewParticleEffect> m_pPulseEffect;
|
||||
};
|
||||
|
||||
|
||||
#endif // _C_ASW_AOEGREN_PROJECTILE_H
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_boomer.h"
|
||||
#include "c_asw_clientragdoll.h"
|
||||
#include "asw_fx_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Boomer, DT_ASW_Boomer, CASW_Boomer)
|
||||
RecvPropBool( RECVINFO( m_bInflated ) ),
|
||||
RecvPropBool( RECVINFO( m_bInflating ) )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
C_ASW_Boomer::C_ASW_Boomer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Boomer::~C_ASW_Boomer()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
void C_ASW_Boomer::SpawnClientSideEffects()
|
||||
{
|
||||
//was i inflated?
|
||||
if ( m_bInflated )
|
||||
{
|
||||
ParticleProp()->Create( "boomer_explode", PATTACH_POINT, "attach_explosion" );
|
||||
ParticleProp()->Create( "joint_goo", PATTACH_POINT, "leg_1_explode" );
|
||||
ParticleProp()->Create( "joint_goo", PATTACH_POINT, "leg_2_explode" );
|
||||
ParticleProp()->Create( "joint_goo", PATTACH_POINT, "leg_3_explode" );
|
||||
ParticleProp()->Create( "joint_goo", PATTACH_POINT, "up_leg_1_explode" );
|
||||
ParticleProp()->Create( "joint_goo", PATTACH_POINT, "up_leg_2_explode" );
|
||||
ParticleProp()->Create( "joint_goo", PATTACH_POINT, "up_leg_3_explode" );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
C_BaseAnimating * C_ASW_Boomer::BecomeRagdollOnClient( void )
|
||||
{
|
||||
// effects get spawned in C_ASW_Alien::BecomeRagdollOnClient
|
||||
//SpawnClientSideEffects();
|
||||
|
||||
return BaseClass::BecomeRagdollOnClient();
|
||||
}
|
||||
|
||||
C_ClientRagdoll *C_ASW_Boomer::CreateClientRagdoll( bool bRestoring )
|
||||
{
|
||||
return new C_ASW_ClientRagdoll( bRestoring );
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef __INCLUDE_C_ASW_BOOMER_H
|
||||
#define __INCLUDE_C_ASW_BOOMER_H
|
||||
|
||||
#include "c_asw_alien.h"
|
||||
|
||||
class C_ASW_Boomer : public C_ASW_Alien
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Boomer, C_ASW_Alien )
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Boomer();
|
||||
virtual ~C_ASW_Boomer();
|
||||
|
||||
virtual Class_T Classify() { return (Class_T) CLASS_ASW_BOOMER; }
|
||||
|
||||
// death;
|
||||
virtual C_ClientRagdoll* CreateClientRagdoll( bool bRestoring = false );
|
||||
virtual C_BaseAnimating* BecomeRagdollOnClient( void );
|
||||
virtual const char *GetDeathParticleEffectName( void ) { return "boomer_death"; }
|
||||
virtual const char *GetBigDeathParticleEffectName( void ) { return "boomer_explode"; }
|
||||
|
||||
virtual const Vector& GetAimTargetPos(const Vector &vecFiringSrc, bool bWeaponPrefersFlatAiming) { return WorldSpaceCenter(); }
|
||||
virtual const Vector& GetAimTargetRadiusPos(const Vector &vecFiringSrc) { return WorldSpaceCenter(); }
|
||||
|
||||
// did i explode?
|
||||
CNetworkVar(bool, m_bBoomerExplode);
|
||||
//void SpawnClientSideEffects();
|
||||
CNetworkVar( bool, m_bInflated );
|
||||
CNetworkVar( bool, m_bInflating );
|
||||
|
||||
private:
|
||||
C_ASW_Boomer ( const C_ASW_Boomer & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif // __INCLUDE_C_ASW_BOOMER_H
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "cbase.h"
|
||||
|
||||
#include "c_asw_buffgrenade_projectile.h"
|
||||
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
//Precahce the effects
|
||||
PRECACHE_REGISTER_BEGIN( GLOBAL, ASWPrecacheEffectBuffGrenades )
|
||||
PRECACHE( MATERIAL, "swarm/effects/blueflare" )
|
||||
PRECACHE( MATERIAL, "effects/yellowflare" )
|
||||
PRECACHE( MATERIAL, "effects/yellowflare_noz" )
|
||||
PRECACHE_REGISTER_END()
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_BuffGrenade_Projectile, DT_ASW_BuffGrenade_Projectile, CASW_BuffGrenade_Projectile )
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
ConVar asw_buffgrenade( "asw_buffgrenade", "98 34 16", 0, "Color of grenades" );
|
||||
|
||||
|
||||
Color C_ASW_BuffGrenade_Projectile::GetGrenadeColor( void )
|
||||
{
|
||||
return asw_buffgrenade.GetColor();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef _INCLUDED_C_ASW_BUFFGREN_PROJECTILE_H
|
||||
#define _INCLUDED_C_ASW_BUFFGREN_PROJECTILE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "c_asw_aoegrenade_projectile.h"
|
||||
|
||||
|
||||
class C_ASW_BuffGrenade_Projectile : public C_ASW_AOEGrenade_Projectile
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_BuffGrenade_Projectile, C_ASW_AOEGrenade_Projectile );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
virtual Color GetGrenadeColor( void );
|
||||
virtual const char* GetLoopSoundName( void ) { return "ASW_BuffGrenade.BuffLoop"; }
|
||||
virtual const char* GetStartSoundName( void ) { return "ASW_BuffGrenade.StartBuff"; }
|
||||
virtual const char* GetActivateSoundName( void ) { return "ASW_BuffGrenade.GrenadeActivate"; }
|
||||
virtual const char* GetPingEffectName( void ) { return "buffgrenade_pulse"; }
|
||||
virtual const char* GetArcEffectName( void ) { return "buffgrenade_attach_arc"; }
|
||||
virtual const char* GetArcAttachmentName( void ) { return "beam_attach"; }
|
||||
virtual bool ShouldAttachEffectToWeapon( void ) { return true; }
|
||||
virtual bool ShouldSpawnSphere( void ) { return true; }
|
||||
virtual float GetSphereScale( void ) { return 0.98f; }
|
||||
virtual int GetSphereSkin( void ) { return 1; }
|
||||
|
||||
EHANDLE m_hSphereModel;
|
||||
//float m_flPrevRotAngle;
|
||||
float m_flTimeCreated;
|
||||
};
|
||||
|
||||
|
||||
#endif // _INCLUDED_C_ASW_BUFFGREN_PROJECTILE_H
|
||||
@@ -0,0 +1,191 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_button_area.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_player.h"
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include "c_asw_door.h"
|
||||
#include "asw_marine_profile.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "igameevents.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Button_Area, DT_ASW_Button_Area, CASW_Button_Area )
|
||||
RecvPropInt (RECVINFO(m_iHackLevel)),
|
||||
RecvPropBool (RECVINFO(m_bIsLocked)),
|
||||
RecvPropBool (RECVINFO(m_bIsDoorButton)),
|
||||
RecvPropBool(RECVINFO(m_bIsInUse)),
|
||||
RecvPropFloat(RECVINFO(m_fHackProgress)),
|
||||
RecvPropBool(RECVINFO(m_bNoPower)),
|
||||
RecvPropBool(RECVINFO(m_bWaitingForInput)),
|
||||
RecvPropString( RECVINFO( m_NoPowerMessage ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
bool C_ASW_Button_Area::s_bLoadedLockedIconTexture = false;
|
||||
int C_ASW_Button_Area::s_nLockedIconTextureID = -1;
|
||||
bool C_ASW_Button_Area::s_bLoadedOpenIconTexture = false;
|
||||
int C_ASW_Button_Area::s_nOpenIconTextureID = -1;
|
||||
bool C_ASW_Button_Area::s_bLoadedCloseIconTexture = false;
|
||||
int C_ASW_Button_Area::s_nCloseIconTextureID = -1;
|
||||
bool C_ASW_Button_Area::s_bLoadedUseIconTexture = false;
|
||||
int C_ASW_Button_Area::s_nUseIconTextureID = -1;
|
||||
bool C_ASW_Button_Area::s_bLoadedHackIconTexture = false;
|
||||
int C_ASW_Button_Area::s_nHackIconTextureID = -1;
|
||||
bool C_ASW_Button_Area::s_bLoadedNoPowerIconTexture = false;
|
||||
int C_ASW_Button_Area::s_nNoPowerIconTextureID = -1;
|
||||
|
||||
C_ASW_Button_Area::C_ASW_Button_Area()
|
||||
{
|
||||
m_bOldWaitingForInput = false;
|
||||
}
|
||||
|
||||
C_ASW_Door* C_ASW_Button_Area::GetDoor()
|
||||
{
|
||||
return dynamic_cast<C_ASW_Door*>(GetUseTargetHandle().Get());
|
||||
}
|
||||
|
||||
// use icon textures
|
||||
|
||||
int C_ASW_Button_Area::GetLockedIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedLockedIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nLockedIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nLockedIconTextureID, "vgui/swarm/UseIcons/PanelLocked", true, false);
|
||||
s_bLoadedLockedIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nLockedIconTextureID;
|
||||
}
|
||||
int C_ASW_Button_Area::GetOpenIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedOpenIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nOpenIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nOpenIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedOpenIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nOpenIconTextureID;
|
||||
}
|
||||
int C_ASW_Button_Area::GetCloseIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedCloseIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nCloseIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nCloseIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedCloseIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nCloseIconTextureID;
|
||||
}
|
||||
int C_ASW_Button_Area::GetUseIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedUseIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nUseIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nUseIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedUseIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nUseIconTextureID;
|
||||
}
|
||||
int C_ASW_Button_Area::GetHackIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedHackIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nHackIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nHackIconTextureID, "vgui/swarm/UseIcons/PanelLocked", true, false);
|
||||
s_bLoadedHackIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nHackIconTextureID;
|
||||
}
|
||||
|
||||
int C_ASW_Button_Area::GetNoPowerIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedNoPowerIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nNoPowerIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nNoPowerIconTextureID, "vgui/swarm/UseIcons/PanelNoPower", true, false);
|
||||
s_bLoadedNoPowerIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nNoPowerIconTextureID;
|
||||
}
|
||||
|
||||
bool C_ASW_Button_Area::GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser)
|
||||
{
|
||||
action.UseIconRed = 255;
|
||||
action.UseIconGreen = 255;
|
||||
action.UseIconBlue = 255;
|
||||
action.bShowUseKey = true;
|
||||
action.iInventorySlot = -1;
|
||||
if (!HasPower())
|
||||
{
|
||||
action.iUseIconTexture = GetNoPowerIconTextureID();
|
||||
TryLocalize( GetNoPowerText(), action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
action.fProgress = GetHackProgress();
|
||||
action.bShowUseKey = false;
|
||||
return true;
|
||||
}
|
||||
if (IsLocked())
|
||||
{
|
||||
CASW_Marine_Profile *pProfile = pUser->GetMarineProfile();
|
||||
|
||||
if ( pProfile->CanHack() )
|
||||
{
|
||||
action.iUseIconTexture = GetHackIconTextureID();
|
||||
TryLocalize( GetHackIconText(pUser), action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
action.fProgress = GetHackProgress();
|
||||
}
|
||||
else
|
||||
{
|
||||
action.iUseIconTexture = GetLockedIconTextureID();
|
||||
TryLocalize( GetLockedIconText(), action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
action.fProgress = GetHackProgress();
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
action.iUseIconTexture = GetUseIconTextureID();
|
||||
TryLocalize( GetUseIconText(), action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
action.fProgress = -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* C_ASW_Button_Area::GetNoPowerText()
|
||||
{
|
||||
const char *szCustom = GetNoPowerMessage();
|
||||
if (!szCustom || Q_strlen(szCustom) <= 0)
|
||||
return "#asw_no_power";
|
||||
|
||||
return szCustom;
|
||||
}
|
||||
|
||||
const char* C_ASW_Button_Area::GetHackIconText(C_ASW_Marine *pUser)
|
||||
{
|
||||
if (m_bIsInUse)
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer && pPlayer->GetMarine() && pPlayer->GetMarine()->m_hUsingEntity.Get() == this)
|
||||
{
|
||||
return "#asw_exit_panel";
|
||||
}
|
||||
}
|
||||
return "#asw_hack_panel";
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#ifndef _DEFINED_C_ASW_BUTTON_AREA_H
|
||||
#define _DEFINED_C_ASW_BUTTON_AREA_H
|
||||
|
||||
#include "c_asw_use_area.h"
|
||||
|
||||
class C_ASW_Door;
|
||||
|
||||
class C_ASW_Button_Area : public C_ASW_Use_Area
|
||||
{
|
||||
DECLARE_CLASS( C_ASW_Button_Area, C_ASW_Use_Area );
|
||||
DECLARE_CLIENTCLASS();
|
||||
public:
|
||||
C_ASW_Button_Area();
|
||||
|
||||
bool IsLocked() { return m_bIsLocked; }
|
||||
int GetHackLevel() { return m_iHackLevel; }
|
||||
bool IsDoorButton() { return m_bIsDoorButton; }
|
||||
C_ASW_Door* GetDoor();
|
||||
|
||||
Class_T Classify( void ) { return (Class_T) CLASS_ASW_BUTTON_PANEL; }
|
||||
|
||||
// accessors for icons
|
||||
int GetLockedIconTextureID();
|
||||
const char* GetLockedIconText() { return "#asw_requires_tech"; }
|
||||
int GetOpenIconTextureID();
|
||||
const char* GetOpenIconText() { return "#asw_open"; }
|
||||
int GetCloseIconTextureID();
|
||||
const char* GetCloseIconText() { return "#asw_close"; }
|
||||
int GetUseIconTextureID();
|
||||
const char* GetUseIconText() { return "#asw_use_panel"; }
|
||||
int GetHackIconTextureID();
|
||||
const char* GetHackIconText(C_ASW_Marine *pUser);
|
||||
int GetNoPowerIconTextureID();
|
||||
const char* GetNoPowerText();
|
||||
|
||||
virtual bool GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser);
|
||||
virtual void CustomPaint(int ix, int iy, int alpha, vgui::Panel *pUseIcon ) { }
|
||||
virtual C_BaseEntity* GetGlowEntity() { return m_hPanelProp.Get(); }
|
||||
|
||||
// traditional Swarm hacking
|
||||
float GetHackProgress() { return m_fHackProgress; }
|
||||
CNetworkVar(bool, m_bIsInUse);
|
||||
CNetworkVar(float, m_fHackProgress);
|
||||
|
||||
virtual const char* GetNoPowerMessage() { return m_NoPowerMessage; }
|
||||
char m_NoPowerMessage[255];
|
||||
|
||||
bool HasPower() { return !m_bNoPower; }
|
||||
bool IsWaitingForInput( void ) const { return m_bWaitingForInput; }
|
||||
|
||||
protected:
|
||||
bool m_bIsLocked;
|
||||
bool m_bNoPower;
|
||||
bool m_bWaitingForInput;
|
||||
bool m_bOldWaitingForInput;
|
||||
int m_iHackLevel;
|
||||
bool m_bIsDoorButton;
|
||||
C_ASW_Button_Area( const C_ASW_Button_Area & ); // not defined, not accessible
|
||||
|
||||
// icons used to interact with buttons
|
||||
static bool s_bLoadedLockedIconTexture;
|
||||
static int s_nLockedIconTextureID;
|
||||
|
||||
static bool s_bLoadedOpenIconTexture;
|
||||
static int s_nOpenIconTextureID;
|
||||
|
||||
static bool s_bLoadedCloseIconTexture;
|
||||
static int s_nCloseIconTextureID;
|
||||
|
||||
static bool s_bLoadedUseIconTexture;
|
||||
static int s_nUseIconTextureID;
|
||||
|
||||
static bool s_bLoadedHackIconTexture;
|
||||
static int s_nHackIconTextureID;
|
||||
|
||||
static bool s_bLoadedNoPowerIconTexture;
|
||||
static int s_nNoPowerIconTextureID;
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_BUTTON_AREA_H */
|
||||
@@ -0,0 +1,191 @@
|
||||
#include "cbase.h"
|
||||
#include "c_AI_BaseNPC.h"
|
||||
#include "soundenvelope.h"
|
||||
#include "iasw_client_aim_target.h"
|
||||
#include "c_asw_alien.h"
|
||||
#include "c_asw_buzzer.h"
|
||||
#include "c_asw_generic_emitter_entity.h"
|
||||
#include "c_asw_fx.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "baseparticleentity.h"
|
||||
#include "asw_util_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Buzzer is our flying poisoning alien (based on the hl2 manhack code)
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Buzzer, DT_ASW_Buzzer, CASW_Buzzer)
|
||||
RecvPropIntWithMinusOneFlag(RECVINFO(m_nEnginePitch1)),
|
||||
RecvPropFloat(RECVINFO(m_flEnginePitch1Time)),
|
||||
RecvPropBool(RECVINFO(m_bOnFire)),
|
||||
RecvPropBool(RECVINFO(m_bElectroStunned)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
C_ASW_Buzzer::C_ASW_Buzzer()
|
||||
: m_GlowObject( this )
|
||||
{
|
||||
//m_fAmbientLight = 0.02f;
|
||||
m_bClientOnFire = false;
|
||||
m_fNextElectroStunEffect = 0;
|
||||
m_pBurningEffect = NULL;
|
||||
|
||||
m_GlowObject.SetColor( Vector( 0.3f, 0.6f, 0.1f ) );
|
||||
m_GlowObject.SetAlpha( 0.55f );
|
||||
m_GlowObject.SetRenderFlags( false, false );
|
||||
m_GlowObject.SetFullBloomRender( true );
|
||||
}
|
||||
|
||||
C_ASW_Buzzer::~C_ASW_Buzzer()
|
||||
{
|
||||
m_bOnFire = false;
|
||||
UpdateFireEmitters();
|
||||
|
||||
if ( m_pTrailEffect )
|
||||
{
|
||||
ParticleProp()->StopEmissionAndDestroyImmediately( m_pTrailEffect );
|
||||
m_pTrailEffect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start the buzzer's engine sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Buzzer::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
BaseClass::OnDataChanged( type );
|
||||
|
||||
if (( m_nEnginePitch1 <= 0 ) )
|
||||
{
|
||||
SoundShutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
SoundInit();
|
||||
}
|
||||
UpdateFireEmitters();
|
||||
|
||||
if ( type == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// We want to think every frame.
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
|
||||
if ( !m_pTrailEffect )
|
||||
{
|
||||
m_pTrailEffect = this->ParticleProp()->Create( "buzzer_trail", PATTACH_ABSORIGIN_FOLLOW );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Buzzer::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
SoundInit();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start the buzzer's engine sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Buzzer::UpdateOnRemove( void )
|
||||
{
|
||||
BaseClass::UpdateOnRemove();
|
||||
SoundShutdown();
|
||||
m_bOnFire = false;
|
||||
UpdateFireEmitters();
|
||||
|
||||
if ( m_pTrailEffect )
|
||||
{
|
||||
ParticleProp()->StopEmission( m_pTrailEffect, false, true, false );
|
||||
m_pTrailEffect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start the buzzer's engine sound.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Buzzer::SoundInit( void )
|
||||
{
|
||||
if (( m_nEnginePitch1 <= 0 ) )
|
||||
return;
|
||||
|
||||
// play an engine start sound!!
|
||||
CPASAttenuationFilter filter( this );
|
||||
|
||||
// Bring up the engine looping sound.
|
||||
if( !m_pEngineSound1 )
|
||||
{
|
||||
m_pEngineSound1 = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "ASW_Buzzer.Idle" );
|
||||
CSoundEnvelopeController::GetController().Play( m_pEngineSound1, 0.0, m_nEnginePitch1 );
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pEngineSound1, 0.7, 2.0 );
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Buzzer::SoundShutdown(void)
|
||||
{
|
||||
if ( m_pEngineSound1 )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_pEngineSound1 );
|
||||
m_pEngineSound1 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C_ASW_Buzzer::UpdateFireEmitters()
|
||||
{
|
||||
bool bOnFire = (m_bOnFire && !IsEffectActive(EF_NODRAW));
|
||||
if (bOnFire != m_bClientOnFire)
|
||||
{
|
||||
m_bClientOnFire = bOnFire;
|
||||
if (m_bClientOnFire)
|
||||
{
|
||||
if ( !m_pBurningEffect )
|
||||
{
|
||||
m_pBurningEffect = UTIL_ASW_CreateFireEffect( this );
|
||||
}
|
||||
EmitSound( "ASWFire.BurningFlesh" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_pBurningEffect )
|
||||
{
|
||||
ParticleProp()->StopEmission( m_pBurningEffect );
|
||||
m_pBurningEffect = NULL;
|
||||
}
|
||||
StopSound("ASWFire.BurningFlesh");
|
||||
if ( C_BaseEntity::IsAbsQueriesValid() )
|
||||
EmitSound("ASWFire.StopBurning");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Buzzer::ClientThink()
|
||||
{
|
||||
BaseClass::ClientThink();
|
||||
|
||||
if (m_bElectroStunned && m_fNextElectroStunEffect <= gpGlobals->curtime)
|
||||
{
|
||||
// apply electro stun effect
|
||||
FX_ElectroStun(this);
|
||||
m_fNextElectroStunEffect = gpGlobals->curtime + RandomFloat( 0.2, 0.7 );
|
||||
}
|
||||
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pPlayer && pPlayer->IsSniperScopeActive() )
|
||||
{
|
||||
m_GlowObject.SetRenderFlags( true, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_GlowObject.SetRenderFlags( false, false );
|
||||
}
|
||||
}
|
||||
|
||||
int C_ASW_Buzzer::DrawModel( int flags, const RenderableInstance_t &instance )
|
||||
{
|
||||
m_vecLastRenderedPos = WorldSpaceCenter();
|
||||
|
||||
return BaseClass::DrawModel( flags, instance );
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef _INLCUDE_C_ASW_BUZZER_H
|
||||
#define _INLCUDE_C_ASW_BUZZER_H
|
||||
|
||||
#include "c_asw_alien.h"
|
||||
#include "asw_shareddefs.h"
|
||||
#include "glow_outline_effect.h"
|
||||
|
||||
class CNewParticleEffect;
|
||||
|
||||
// Buzzer is our flying poisoning alien (based on the hl2 manhack code)
|
||||
|
||||
class C_ASW_Buzzer : public C_AI_BaseNPC, public IASW_Client_Aim_Target
|
||||
{
|
||||
public:
|
||||
C_ASW_Buzzer();
|
||||
virtual ~C_ASW_Buzzer();
|
||||
|
||||
DECLARE_CLASS( C_ASW_Buzzer, C_AI_BaseNPC );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
// Purpose: Start the buzzer's engine sound.
|
||||
virtual void OnDataChanged( DataUpdateType_t type );
|
||||
virtual void UpdateOnRemove( void );
|
||||
virtual void OnRestore();
|
||||
|
||||
Class_T Classify( void ) { return (Class_T) CLASS_ASW_BUZZER; }
|
||||
|
||||
IMPLEMENT_AUTO_LIST_GET();
|
||||
virtual float GetRadius() { return 18; }
|
||||
virtual bool IsAimTarget() { return true; }
|
||||
virtual const Vector& GetAimTargetPos(const Vector &vecFiringSrc, bool bWeaponPrefersFlatAiming) { return m_vecLastRenderedPos; }
|
||||
virtual const Vector& GetAimTargetRadiusPos(const Vector &vecFiringSrc) { return m_vecLastRenderedPos; }
|
||||
|
||||
CNetworkVar(bool, m_bOnFire);
|
||||
bool m_bClientOnFire;
|
||||
CNewParticleEffect *m_pBurningEffect;
|
||||
virtual void UpdateFireEmitters();
|
||||
|
||||
CNetworkVar(bool, m_bElectroStunned);
|
||||
float m_fNextElectroStunEffect;
|
||||
virtual void ClientThink();
|
||||
|
||||
// storing our location for autoaim
|
||||
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
|
||||
Vector m_vecLastRenderedPos;
|
||||
|
||||
private:
|
||||
C_ASW_Buzzer( const C_ASW_Buzzer & );
|
||||
|
||||
// Purpose: Start + stop the buzzer's engine sound.
|
||||
void SoundInit( void );
|
||||
void SoundShutdown( void );
|
||||
|
||||
CGlowObject m_GlowObject;
|
||||
|
||||
CSoundPatch *m_pEngineSound1;
|
||||
|
||||
int m_nEnginePitch1;
|
||||
float m_flEnginePitch1Time;
|
||||
|
||||
CUtlReference<CNewParticleEffect> m_pTrailEffect;
|
||||
};
|
||||
|
||||
#endif /* _INLCUDE_C_ASW_BUZZER_H */
|
||||
@@ -0,0 +1,198 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_camera_volume.h"
|
||||
#include "mapentities_shared.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
#include "gamestringpool.h"
|
||||
|
||||
CUtlVector<C_ASW_Camera_Volume*> g_ASWCameraVolumes;
|
||||
|
||||
C_ASW_Camera_Volume::C_ASW_Camera_Volume()
|
||||
{
|
||||
g_ASWCameraVolumes.AddToTail(this);
|
||||
m_fCameraPitch = 90;
|
||||
}
|
||||
|
||||
C_ASW_Camera_Volume::~C_ASW_Camera_Volume()
|
||||
{
|
||||
g_ASWCameraVolumes.FindAndRemove(this);
|
||||
}
|
||||
|
||||
C_ASW_Camera_Volume *C_ASW_Camera_Volume::CreateNew( bool bForce )
|
||||
{
|
||||
return new C_ASW_Camera_Volume();
|
||||
}
|
||||
|
||||
void C_ASW_Camera_Volume::Spawn()
|
||||
{
|
||||
SetSolid( SOLID_BBOX );
|
||||
SetModel( STRING( GetModelName() ) ); // set size and link into world
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
m_takedamage = DAMAGE_NO;
|
||||
}
|
||||
|
||||
bool C_ASW_Camera_Volume::Initialize()
|
||||
{
|
||||
if ( InitializeAsClientEntity( NULL, false ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Spawn();
|
||||
|
||||
const model_t *mod = GetModel();
|
||||
if ( mod )
|
||||
{
|
||||
Vector mins, maxs;
|
||||
modelinfo->GetModelBounds( mod, mins, maxs );
|
||||
SetCollisionBounds( mins, maxs );
|
||||
}
|
||||
|
||||
SetBlocksLOS( false ); // this should be a small object
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float C_ASW_Camera_Volume::IsPointInCameraVolume(const Vector &src)
|
||||
{
|
||||
int c=g_ASWCameraVolumes.Count();
|
||||
for (int i=0;i<c;i++)
|
||||
{
|
||||
if (g_ASWCameraVolumes[i]->CollisionProp()->IsPointInBounds(src))
|
||||
return g_ASWCameraVolumes[i]->m_fCameraPitch;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void C_ASW_Camera_Volume::RecreateAll()
|
||||
{
|
||||
DestroyAll();
|
||||
ParseAllEntities( engine->GetMapEntitiesString() );
|
||||
}
|
||||
|
||||
void C_ASW_Camera_Volume::DestroyAll()
|
||||
{
|
||||
while (g_ASWCameraVolumes.Count() > 0 )
|
||||
{
|
||||
C_ASW_Camera_Volume *p = g_ASWCameraVolumes[0];
|
||||
p->Release();
|
||||
}
|
||||
}
|
||||
|
||||
const char *C_ASW_Camera_Volume::ParseEntity( const char *pEntData )
|
||||
{
|
||||
CEntityMapData entData( (char*)pEntData );
|
||||
char className[MAPKEY_MAXLENGTH];
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
if (!entData.ExtractValue("classname", className))
|
||||
{
|
||||
Error( "classname missing from entity!\n" );
|
||||
}
|
||||
|
||||
if ( !Q_strcmp( className, "asw_camera_control" ) )
|
||||
{
|
||||
// always force clientside entities placed in maps
|
||||
C_ASW_Camera_Volume *pEntity = C_ASW_Camera_Volume::CreateNew( true );
|
||||
|
||||
if ( pEntity )
|
||||
{ // Set up keyvalues.
|
||||
pEntity->ParseMapData(&entData);
|
||||
|
||||
if ( !pEntity->Initialize() )
|
||||
pEntity->Release();
|
||||
|
||||
return entData.CurrentBufferPosition();
|
||||
}
|
||||
}
|
||||
|
||||
// Just skip past all the keys.
|
||||
char keyName[MAPKEY_MAXLENGTH];
|
||||
char value[MAPKEY_MAXLENGTH];
|
||||
if ( entData.GetFirstKey(keyName, value) )
|
||||
{
|
||||
do
|
||||
{
|
||||
}
|
||||
while ( entData.GetNextKey(keyName, value) );
|
||||
}
|
||||
|
||||
//
|
||||
// Return the current parser position in the data block
|
||||
//
|
||||
return entData.CurrentBufferPosition();
|
||||
}
|
||||
|
||||
bool C_ASW_Camera_Volume::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "model" ) )
|
||||
{
|
||||
SetModelName( AllocPooledString( szValue ) );
|
||||
return true;
|
||||
}
|
||||
if ( FStrEq( szKeyName, "angtype" ) )
|
||||
{
|
||||
int iAngleType = atoi(szValue);
|
||||
if (iAngleType == 0) // 0 is top down
|
||||
{
|
||||
m_fCameraPitch = 90.0f;
|
||||
}
|
||||
else // 1 is 40 degree
|
||||
{
|
||||
m_fCameraPitch = 40.0f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return BaseClass::KeyValue(szKeyName, szValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Only called on BSP load. Parses and spawns all the entities in the BSP.
|
||||
// Input : pMapData - Pointer to the entity data block to parse.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Camera_Volume::ParseAllEntities(const char *pMapData)
|
||||
{
|
||||
int nEntities = 0;
|
||||
|
||||
char szTokenBuffer[MAPKEY_MAXLENGTH];
|
||||
|
||||
//
|
||||
// Loop through all entities in the map data, creating each.
|
||||
//
|
||||
for ( ; true; pMapData = MapEntity_SkipToNextEntity(pMapData, szTokenBuffer) )
|
||||
{
|
||||
//
|
||||
// Parse the opening brace.
|
||||
//
|
||||
char token[MAPKEY_MAXLENGTH];
|
||||
pMapData = MapEntity_ParseToken( pMapData, token );
|
||||
|
||||
//
|
||||
// Check to see if we've finished or not.
|
||||
//
|
||||
if (!pMapData)
|
||||
break;
|
||||
|
||||
if (token[0] != '{')
|
||||
{
|
||||
Error( "C_ASW_Camera_Volume::ParseAllEntities: found %s when expecting {", token);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the entity and add it to the spawn list.
|
||||
//
|
||||
|
||||
pMapData = ParseEntity( pMapData );
|
||||
|
||||
nEntities++;
|
||||
}
|
||||
}
|
||||
|
||||
bool C_ASW_Camera_Volume::ShouldDraw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef _INCLUDED_C_ASW_CAMERA_VOLUME_H
|
||||
#define _INCLUDED_C_ASW_CAMERA_VOLUME_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// A clientside only entity used to control the camera
|
||||
// in_camera.cpp will check if the marine is within any of these camera volumes and if so,
|
||||
// tilt the camera to the pitch specified in the volume
|
||||
|
||||
class C_ASW_Camera_Volume : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Camera_Volume, C_BaseEntity );
|
||||
|
||||
C_ASW_Camera_Volume();
|
||||
virtual ~C_ASW_Camera_Volume();
|
||||
|
||||
bool Initialize();
|
||||
void Spawn();
|
||||
bool ShouldDraw();
|
||||
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
static void RecreateAll(); // recreate all clientside camera volumes in map
|
||||
static void DestroyAll(); // clear all clientside created camera volumes
|
||||
static C_ASW_Camera_Volume *CreateNew(bool bForce = false);
|
||||
static float IsPointInCameraVolume(const Vector &src); // is this point located within any of the camera volumes
|
||||
|
||||
int m_fCameraPitch;
|
||||
|
||||
protected:
|
||||
static const char * ParseEntity( const char *pEntData );
|
||||
static void ParseAllEntities(const char *pMapData);
|
||||
};
|
||||
|
||||
extern CUtlVector<C_ASW_Camera_Volume*> g_ASWCameraVolumes;
|
||||
|
||||
#endif // _INCLUDED_C_ASW_CAMERA_VOLUME_H
|
||||
@@ -0,0 +1,145 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_campaign_save.h"
|
||||
#include "steam/isteamremotestorage.h"
|
||||
#include "filesystem.h"
|
||||
#include "igameevents.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Campaign_Save, DT_ASW_Campaign_Save, CASW_Campaign_Save )
|
||||
RecvPropString(RECVINFO(m_CampaignName)),
|
||||
RecvPropInt(RECVINFO(m_iCurrentPosition)),
|
||||
RecvPropInt(RECVINFO(m_iNumMissionsComplete)),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_MissionComplete), RecvPropInt( RECVINFO(m_MissionComplete[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_NumRetries), RecvPropInt( RECVINFO(m_NumRetries[0]))),
|
||||
|
||||
RecvPropArray3( RECVINFO_ARRAY( m_bMarineWounded ), RecvPropBool( RECVINFO( m_bMarineWounded[0] ) ) ),
|
||||
RecvPropArray3( RECVINFO_ARRAY( m_bMarineDead ), RecvPropBool( RECVINFO( m_bMarineDead[0] ) ) ),
|
||||
|
||||
RecvPropArray( RecvPropString( RECVINFO( m_MissionsCompleteNames[0]) ), m_MissionsCompleteNames ),
|
||||
RecvPropArray( RecvPropString( RECVINFO( m_Medals[0]) ), m_Medals ),
|
||||
RecvPropBool(RECVINFO(m_bMultiplayerGame)),
|
||||
RecvPropString(RECVINFO(m_DateTime)),
|
||||
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_NumVotes), RecvPropInt( RECVINFO(m_NumVotes[0]))),
|
||||
RecvPropFloat( RECVINFO(m_fVoteEndTime) ),
|
||||
RecvPropBool( RECVINFO(m_bFixedSkillPoints) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Campaign_Save::C_ASW_Campaign_Save()
|
||||
{
|
||||
m_iVersion = 0;
|
||||
m_CampaignName[0] = '\0';
|
||||
m_szPreviousCampaignName[0] = '\0';
|
||||
m_iCurrentPosition = 0;
|
||||
m_bMultiplayerGame = false;
|
||||
}
|
||||
|
||||
C_ASW_Campaign_Save::~C_ASW_Campaign_Save()
|
||||
{
|
||||
}
|
||||
|
||||
const char* C_ASW_Campaign_Save::GetCampaignName()
|
||||
{
|
||||
return m_CampaignName;
|
||||
}
|
||||
|
||||
int C_ASW_Campaign_Save::GetRetries()
|
||||
{
|
||||
if (m_iCurrentPosition <0 || m_iCurrentPosition >= ASW_MAX_MISSIONS_PER_CAMPAIGN)
|
||||
return -1;
|
||||
|
||||
return m_NumRetries[m_iCurrentPosition];
|
||||
}
|
||||
|
||||
void C_ASW_Campaign_Save::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( Q_strcmp( m_szPreviousCampaignName, m_CampaignName ) )
|
||||
{
|
||||
Q_strncpy( m_szPreviousCampaignName, m_CampaignName, sizeof( m_szPreviousCampaignName ) );
|
||||
|
||||
IGameEvent * event = gameeventmanager->CreateEvent( "campaign_changed" );
|
||||
if ( event )
|
||||
{
|
||||
event->SetString( "campaign", m_CampaignName );
|
||||
gameeventmanager->FireEventClientSide( event );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConVar asw_steam_cloud_debug( "asw_steam_cloud_debug", "1", FCVAR_NONE, "Print Steam Cloud messages" );
|
||||
|
||||
bool GetFileFromRemoteStorage( ISteamRemoteStorage *pRemoteStorage, const char *pszRemoteFileName, const char *pszLocalFileName )
|
||||
{
|
||||
bool bSuccess = false;
|
||||
|
||||
// check if file exists in Steam Cloud first
|
||||
int32 nFileSize = pRemoteStorage->GetFileSize( pszRemoteFileName );
|
||||
|
||||
if ( nFileSize > 0 )
|
||||
{
|
||||
CUtlMemory<char> buf( 0, nFileSize );
|
||||
if ( pRemoteStorage->FileRead( pszRemoteFileName, buf.Base(), nFileSize ) == nFileSize )
|
||||
{
|
||||
FileHandle_t hFile = g_pFullFileSystem->Open( pszLocalFileName, "wb", "MOD" );
|
||||
if( hFile )
|
||||
{
|
||||
bSuccess = g_pFullFileSystem->Write( buf.Base(), nFileSize, hFile ) == nFileSize;
|
||||
g_pFullFileSystem->Close( hFile );
|
||||
|
||||
if ( asw_steam_cloud_debug.GetBool() )
|
||||
{
|
||||
if ( bSuccess )
|
||||
{
|
||||
DevMsg( "[Cloud]: SUCCEESS retrieved %s from remote storage into %s\n", pszRemoteFileName, pszLocalFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
DevMsg( "[Cloud]: FAILED retrieved %s from remote storage into %s\n", pszRemoteFileName, pszLocalFileName );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
bool WriteFileToRemoteStorage( ISteamRemoteStorage *pRemoteStorage, const char *pszRemoteFileName, const char *pszLocalFileName )
|
||||
{
|
||||
bool bSuccess = false;
|
||||
|
||||
if ( g_pFullFileSystem->FileExists( pszLocalFileName, "MOD" ) )
|
||||
{
|
||||
FileHandle_t hFile = g_pFullFileSystem->Open( pszLocalFileName, "rb", "MOD" );
|
||||
if ( FILESYSTEM_INVALID_HANDLE != hFile )
|
||||
{
|
||||
unsigned int unSize = g_pFullFileSystem->Size( hFile );
|
||||
|
||||
byte *pBuffer = (byte*) malloc( unSize );
|
||||
if ( g_pFullFileSystem->Read( pBuffer, unSize, hFile ) == (int) unSize )
|
||||
{
|
||||
bSuccess = pRemoteStorage->FileWrite( pszRemoteFileName, pBuffer, unSize );
|
||||
}
|
||||
free( pBuffer );
|
||||
g_pFullFileSystem->Close( hFile );
|
||||
}
|
||||
}
|
||||
|
||||
if ( asw_steam_cloud_debug.GetBool() )
|
||||
{
|
||||
if ( bSuccess )
|
||||
{
|
||||
DevMsg( "[Cloud]: SUCCEESS wrote %s from local storage into remote file %s\n", pszLocalFileName, pszRemoteFileName );
|
||||
}
|
||||
else
|
||||
{
|
||||
DevMsg( "[Cloud]: FAILED writing %s from local storage into remote file %s\n", pszLocalFileName, pszRemoteFileName );
|
||||
}
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef _INCLUDED_C_ASW_CAMPAIGN_SAVE_H
|
||||
#define _INCLUDED_C_ASW_CAMPAIGN_SAVE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "asw_shareddefs.h"
|
||||
|
||||
class C_ASW_Player;
|
||||
class CASW_Campaign_Info;
|
||||
|
||||
// This class describes the state of the current campaign game. This is what gets saved when the players save their game.
|
||||
// When a savegame is loaded in, it is networked to all the clients (so they can bring up the campaign map, etc)
|
||||
|
||||
class C_ASW_Campaign_Save : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Campaign_Save, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Campaign_Save();
|
||||
virtual ~C_ASW_Campaign_Save();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
|
||||
// savegame version (current is 0)
|
||||
CNetworkVar(int, m_iVersion);
|
||||
|
||||
// the campaign this save game is meant for
|
||||
char m_CampaignName[255];
|
||||
char m_szPreviousCampaignName[255];
|
||||
|
||||
// the mission ID of the location the squad is current in
|
||||
CNetworkVar(int, m_iCurrentPosition);
|
||||
|
||||
// a list of IDs describing the missions the squad has completed so far
|
||||
CNetworkVar(int, m_iNumMissionsComplete);
|
||||
|
||||
CNetworkArray(int, m_NumRetries, ASW_MAX_MISSIONS_PER_CAMPAIGN);
|
||||
CNetworkArray(int, m_MissionComplete, ASW_MAX_MISSIONS_PER_CAMPAIGN);
|
||||
|
||||
CNetworkVar(float, m_fVoteEndTime);
|
||||
CNetworkArray(int, m_NumVotes, ASW_MAX_MISSIONS_PER_CAMPAIGN); // number of votes each mission has
|
||||
|
||||
bool UsingFixedSkillPoints() { return m_bFixedSkillPoints.Get(); }
|
||||
CNetworkVar(bool, m_bFixedSkillPoints);
|
||||
|
||||
CNetworkArray(bool, m_bMarineWounded, ASW_NUM_MARINE_PROFILES);
|
||||
CNetworkArray(bool, m_bMarineDead, ASW_NUM_MARINE_PROFILES);
|
||||
bool IsMarineWounded(int iProfileIndex);
|
||||
bool IsMarineAlive(int iProfileIndex);
|
||||
|
||||
// data specific to each marine that needs to be saved
|
||||
char m_MissionsCompleteNames[ ASW_NUM_MARINE_PROFILES ][255];
|
||||
char m_Medals[ ASW_NUM_MARINE_PROFILES ][255];
|
||||
|
||||
// single or multiplayer game
|
||||
CNetworkVar(bool, m_bMultiplayerGame);
|
||||
|
||||
// date/time
|
||||
char m_DateTime[255];
|
||||
|
||||
// helper functions for examining the campaign save state
|
||||
bool IsMissionLinkedToACompleteMission(int i, CASW_Campaign_Info* pCampaignInfo);
|
||||
|
||||
// todo: any extra data, such as optional objectives complete, fancy stuff unlocked?
|
||||
|
||||
const char* GetCampaignName();
|
||||
|
||||
int GetRetries();
|
||||
};
|
||||
|
||||
class ISteamRemoteStorage;
|
||||
|
||||
bool GetFileFromRemoteStorage( ISteamRemoteStorage *pRemoteStorage, const char *pszRemoteFileName, const char *pszLocalFileName );
|
||||
bool WriteFileToRemoteStorage( ISteamRemoteStorage *pRemoteStorage, const char *pszRemoteFileName, const char *pszLocalFileName );
|
||||
|
||||
#endif // _INCLUDED_C_ASW_CAMPAIGN_SAVE_H
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_client_corpse.h"
|
||||
#include "c_asw_clientragdoll.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Client_Corpse, DT_ASW_Client_Corpse, CASW_Client_Corpse)
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Client_Corpse::C_ASW_Client_Corpse()
|
||||
{
|
||||
}
|
||||
|
||||
typedef CHandle<C_ASW_ClientRagdoll> ClientRagdollHandle_t;
|
||||
CUtlVector<ClientRagdollHandle_t> g_ClientRagdolls;
|
||||
|
||||
bool AlreadyCreatedRagdollFor(int iEntityIndex)
|
||||
{
|
||||
// ASWTODO - put this back if m_iSourceEntityIndex is added to ragdolls again
|
||||
int c = g_ClientRagdolls.Count();
|
||||
for (int i=c-1;i>=0;i--)
|
||||
{
|
||||
C_ASW_ClientRagdoll *pRagdoll = g_ClientRagdolls[i].Get();
|
||||
if (!pRagdoll)
|
||||
{
|
||||
g_ClientRagdolls.Remove(i);
|
||||
continue;
|
||||
}
|
||||
if (pRagdoll->m_iSourceEntityIndex == iEntityIndex)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
C_ClientRagdoll *C_ASW_Client_Corpse::CreateClientRagdoll( bool bRestoring )
|
||||
{
|
||||
return new C_ASW_ClientRagdoll( bRestoring );
|
||||
}
|
||||
|
||||
C_BaseAnimating* C_ASW_Client_Corpse::BecomeRagdollOnClient( void )
|
||||
{
|
||||
if ( AlreadyCreatedRagdollFor( entindex() ) )
|
||||
{
|
||||
//m_builtRagdoll = true;
|
||||
return NULL;
|
||||
}
|
||||
C_BaseAnimating *pAnim = BaseClass::BecomeRagdollOnClient();
|
||||
|
||||
C_ASW_ClientRagdoll *pClientRagdoll = dynamic_cast<C_ASW_ClientRagdoll*>(pAnim);
|
||||
if (pClientRagdoll)
|
||||
{
|
||||
pClientRagdoll->m_iSourceEntityIndex = entindex();
|
||||
g_ClientRagdolls.AddToTail(pClientRagdoll);
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("Error: failed to cast client corpse into a client ragdoll!\n");
|
||||
}
|
||||
|
||||
// turn off collision callbacks on this ragdoll, so it doesn't make noises falling to the ground on creation
|
||||
// todo: turn the callbacks back on again after we've settled?
|
||||
if (pAnim && pAnim->m_pRagdoll)
|
||||
{
|
||||
ragdoll_t *pRagdollT = pAnim->m_pRagdoll->GetRagdoll();
|
||||
if (pRagdollT)
|
||||
{
|
||||
for ( int i = 0; i < pRagdollT->listCount; i++ )
|
||||
{
|
||||
const ragdollelement_t &element = pRagdollT->list[i];
|
||||
if ( element.pObject )
|
||||
{
|
||||
element.pObject->SetCallbackFlags(element.pObject->GetCallbackFlags() & ~CALLBACK_GLOBAL_COLLISION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pAnim;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef _INCLUDED_C_ASW_CLIENT_CORPSE_H
|
||||
#define _INCLUDED_C_ASW_CLIENT_CORPSE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "c_baseanimating.h"
|
||||
|
||||
// a clientside ragdoll (to save on server cpu + bandwidth)
|
||||
|
||||
class C_ASW_Client_Corpse : public C_BaseAnimating
|
||||
{
|
||||
DECLARE_CLASS( C_ASW_Client_Corpse, C_BaseAnimating );
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Client_Corpse();
|
||||
|
||||
virtual bool AddRagdollToFadeQueue( void ) { return false; }
|
||||
virtual C_BaseAnimating* BecomeRagdollOnClient( void );
|
||||
virtual C_ClientRagdoll* CreateClientRagdoll( bool bRestoring = false );
|
||||
};
|
||||
|
||||
#endif /* _INCLUDED_C_ASW_CLIENT_CORPSE_H */
|
||||
@@ -0,0 +1,316 @@
|
||||
#include "cbase.h"
|
||||
#include "asw_alien_shared_classmembers.h"
|
||||
#include "c_asw_clientragdoll.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "c_asw_fx.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "asw_input.h"
|
||||
#include "props_shared.h"
|
||||
#include "c_asw_alien.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
BEGIN_DATADESC( C_ASW_ClientRagdoll )
|
||||
DEFINE_FIELD( m_fASWGibTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_iSourceEntityIndex, FIELD_INTEGER ),
|
||||
END_DATADESC()
|
||||
|
||||
ConVar asw_drone_ridiculous( "asw_drone_ridiculous", "0", FCVAR_CHEAT, "If true, hurl drone ragdolls at camera in a ridiculous fashion." );
|
||||
ConVar asw_drone_gib_velocity( "asw_drone_gib_velocity", "1.75", FCVAR_CHEAT, "Drone gibs will inherit the velocity of the parent ragdoll scaled by this" );
|
||||
extern ConVar asw_breakable_aliens;
|
||||
extern ConVar asw_alien_debug_death_style;
|
||||
|
||||
C_ASW_ClientRagdoll::C_ASW_ClientRagdoll( bool bRestoring ) : BaseClass( bRestoring )
|
||||
{
|
||||
m_nDeathStyle = 0;
|
||||
m_bElectroShock = false;
|
||||
m_bHurled = false;
|
||||
|
||||
pszGibParticleEffect = NULL;
|
||||
}
|
||||
|
||||
/// @brief given an origin point, a destination, and a gravity, return a
|
||||
/// velocity that will apex exactly at the destination.
|
||||
/// @param flGravity should be positive, assumed to be aimed down -z
|
||||
Vector ComputeParabolicTrajectoryToApex( const Vector &vOrigin, const Vector &vDestination, const float flGravity )
|
||||
{
|
||||
// transform everything so the object's origin is at 0,0,0
|
||||
const Vector vApex = vDestination - vOrigin;
|
||||
/*
|
||||
V = <x,z> // z is up, x out in this formulation
|
||||
x(t) = tVx
|
||||
y(t) = tVy
|
||||
z(t) = tVz - 0.5gt^2
|
||||
|V| = sqrt(Vx^2 + Vz^2)
|
||||
at apex,
|
||||
0 = Vz - gt -> t = Vz/g
|
||||
X1 = tVx for t = Vz/g
|
||||
Y1 = tVy for t = Vz/g
|
||||
Z1 = tVz - 0.5gt^2 for t=Vz/g
|
||||
solving the linear system gets you
|
||||
Vz^2 = 2*Z1*g
|
||||
Vx = g * X1 / Vz
|
||||
Vy = g * Y1 / Vz
|
||||
*/
|
||||
|
||||
// return value
|
||||
float flX, flY, flZ;
|
||||
|
||||
float flZSquared = 2.0f * vApex.z * flGravity;
|
||||
float flRecipZ = FastRSqrt( flZSquared ); // 1/vZ
|
||||
flZ = flRecipZ * flZSquared; // Vz^2 / Vz = Vz
|
||||
flX = flRecipZ * flGravity * vApex.x;
|
||||
flY = flRecipZ * flGravity * vApex.y;
|
||||
|
||||
return Vector( flX, flY, flZ );
|
||||
}
|
||||
|
||||
extern ConVar cl_ragdoll_gravity;
|
||||
void ASWHurlRagdollAtCamera( C_ASW_ClientRagdoll * RESTRICT pEntity, const Vector &vCameraPosition, const QAngle &vCameraAngles )
|
||||
{
|
||||
Assert( pEntity );
|
||||
// AssertMsg1( pEntity->VPhysicsGetObject(), "Tried to throw %s at camera but it has no VPhysics\n", pEntity->GetDebugName() );
|
||||
pEntity->SetAbsVelocity( Vector(0,0,0) );
|
||||
|
||||
Vector vViewForward; // =CurrentViewForward();
|
||||
AngleVectors( vCameraAngles, &vViewForward );
|
||||
|
||||
float radius = MAX(pEntity->BoundingRadius(), 20.0f );
|
||||
Vector vApex = vCameraPosition + ( vViewForward * ( radius * 2 ) );
|
||||
// NDebugOverlay::Sphere( vApex, vCamAngles , pEntity->BoundingRadius() * 0.5f, 255, 0, 0, 255, false, 1.0f );
|
||||
// NDebugOverlay::Box( vApex, Vector(-6,-6,-6), Vector(6,6,6), 255, 0, 0, 55, 1.0f );
|
||||
|
||||
// pEntity->ApplyAbsVelocityImpulse( ComputeParabolicTrajectoryToApex( pEntity->GetAbsOrigin(), vApex, cl_ragdoll_gravity.GetFloat() ) );
|
||||
Vector vel = ComputeParabolicTrajectoryToApex( pEntity->GetAbsOrigin(), vApex, cl_ragdoll_gravity.GetFloat() );
|
||||
if ( !vel.IsValid() )
|
||||
return;
|
||||
|
||||
IPhysicsObject *ppPhysObjs[ VPHYSICS_MAX_OBJECT_LIST_COUNT ];
|
||||
int nNumPhysObjs = pEntity->VPhysicsGetObjectList( ppPhysObjs, VPHYSICS_MAX_OBJECT_LIST_COUNT );
|
||||
if ( nNumPhysObjs > 0 )
|
||||
{
|
||||
{
|
||||
AngularImpulse spin = RandomAngularImpulse(-720, 720);
|
||||
ppPhysObjs[ 0 ]->SetVelocity( &vel, &spin );
|
||||
}
|
||||
|
||||
for ( int i = 1; i < nNumPhysObjs; i++ )
|
||||
{
|
||||
ppPhysObjs[ i ]->SetVelocity( &vel, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ASWHurlRagdollAtCamera( C_ASW_ClientRagdoll * RESTRICT pEntity )
|
||||
{
|
||||
// Verify that we have input.
|
||||
Assert( ASWInput() != NULL );
|
||||
if ( !ASWInput() )
|
||||
return;
|
||||
|
||||
HACK_GETLOCALPLAYER_GUARD( "HurlObjectAtCamera needs to care about which camera" );
|
||||
Vector vCamPos; QAngle vCamAngles;
|
||||
int omx, omy;
|
||||
// const Vector vCamPos = CurrentViewOrigin();
|
||||
ASWInput()->ASW_GetCameraLocation( C_ASW_Player::GetLocalASWPlayer(), vCamPos, vCamAngles, omx, omy, false );
|
||||
return ASWHurlRagdollAtCamera( pEntity, vCamPos, vCamAngles );
|
||||
}
|
||||
|
||||
|
||||
void ASWMeleeThrowRagdoll( C_ASW_ClientRagdoll * RESTRICT pEntity )
|
||||
{
|
||||
Assert( pEntity );
|
||||
pEntity->SetAbsVelocity( Vector(0,0,0) );
|
||||
|
||||
Vector vecThrowDir = pEntity->GetDeathForce();
|
||||
vecThrowDir.z = 0;
|
||||
vecThrowDir.NormalizeInPlace();
|
||||
|
||||
Vector vApex = pEntity->GetAbsOrigin() + vecThrowDir * 170.0f + Vector( 0, 0, 50 );
|
||||
|
||||
Vector vel = ComputeParabolicTrajectoryToApex( pEntity->GetAbsOrigin(), vApex, cl_ragdoll_gravity.GetFloat() );
|
||||
if ( !vel.IsValid() )
|
||||
return;
|
||||
|
||||
IPhysicsObject *ppPhysObjs[ VPHYSICS_MAX_OBJECT_LIST_COUNT ];
|
||||
int nNumPhysObjs = pEntity->VPhysicsGetObjectList( ppPhysObjs, VPHYSICS_MAX_OBJECT_LIST_COUNT );
|
||||
if ( nNumPhysObjs > 0 )
|
||||
{
|
||||
{
|
||||
AngularImpulse spin = RandomAngularImpulse(-720, 720);
|
||||
ppPhysObjs[ 0 ]->SetVelocity( &vel, &spin );
|
||||
}
|
||||
|
||||
for ( int i = 1; i < nNumPhysObjs; i++ )
|
||||
{
|
||||
ppPhysObjs[ i ]->SetVelocity( &vel, NULL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_ClientRagdoll::BreakRagdoll()
|
||||
{
|
||||
|
||||
IPhysicsObject *pPhysics = VPhysicsGetObject();
|
||||
|
||||
Vector velocity;
|
||||
velocity = m_vecForce / 140.0f;
|
||||
if ( velocity == vec3_origin )
|
||||
velocity = Vector( RandomFloat( 1, 15 ), RandomFloat( 1, 15 ), 75.0f );
|
||||
velocity.z += 100.0;
|
||||
AngularImpulse angVelocity = RandomAngularImpulse( -500.0f, 500.0f );
|
||||
breakablepropparams_t params( GetAbsOrigin(), GetAbsAngles(), velocity, angVelocity );
|
||||
params.impactEnergyScale = 1.25f;
|
||||
params.defBurstScale = 125.0f;
|
||||
params.defCollisionGroup = COLLISION_GROUP_DEBRIS;
|
||||
params.useThisRawVelocity = true;
|
||||
PropBreakableCreateAll( GetModelIndex(), pPhysics, params, this, -1, true, true );
|
||||
|
||||
SUB_Remove(); // destroy ragdoll
|
||||
}
|
||||
|
||||
//ConVar test_hurl( "test_hurl", "0.25" );
|
||||
void C_ASW_ClientRagdoll::ClientThink( void )
|
||||
{
|
||||
// if parent is going to delete us, make sure we do nothing else
|
||||
if ( m_bReleaseRagdoll )
|
||||
{
|
||||
BaseClass::ClientThink();
|
||||
return;
|
||||
}
|
||||
|
||||
BaseClass::ClientThink();
|
||||
|
||||
// OLD STUFF
|
||||
/*
|
||||
if ( m_fASWGibTime > 0 && gpGlobals->curtime > m_fASWGibTime )
|
||||
{
|
||||
// should gib this
|
||||
CLocalPlayerFilter filter;
|
||||
C_BaseEntity::EmitSound( filter, entindex(), "ASW_Drone.GibSplatLight" );
|
||||
UTIL_ASW_ClientsideGib(this);
|
||||
Release();
|
||||
}
|
||||
*/
|
||||
|
||||
if ( !m_pRagdoll || IsFadingOut() )
|
||||
return;
|
||||
|
||||
// force-reset the velocity one frame after spawning in case the grenade explosion
|
||||
// has somehow accumulated again on top of it even though we told it not to.
|
||||
if ( m_nDeathStyle == kDIE_HURL && !m_bHurled && ( ( SpawnTime() + 0.05f ) < gpGlobals->curtime ) )
|
||||
{
|
||||
// SetMoveType( MOVETYPE_VPHYSICS );
|
||||
ASWHurlRagdollAtCamera( this );
|
||||
m_bHurled = true;
|
||||
}
|
||||
else if ( m_nDeathStyle == kDIE_MELEE_THROW && !m_bHurled && ( ( SpawnTime() + 0.05f ) < gpGlobals->curtime ) )
|
||||
{
|
||||
ASWMeleeThrowRagdoll( this );
|
||||
m_bHurled = true;
|
||||
}
|
||||
|
||||
if ( m_fASWGibTime > 0 && gpGlobals->curtime > m_fASWGibTime )
|
||||
{
|
||||
if ( asw_alien_debug_death_style.GetBool() )
|
||||
Msg( "C_ASW_ClientRagdoll::ClientThink: m_nDeathStyle = %d\n", m_nDeathStyle );
|
||||
|
||||
if ( m_nDeathStyle == kDIE_BREAKABLE && asw_breakable_aliens.GetBool() )
|
||||
{
|
||||
BreakRagdoll();
|
||||
return;
|
||||
}
|
||||
// if we die and are on fire, the ragdoll burns away
|
||||
if ( GetFlags() & FL_ONFIRE )
|
||||
{
|
||||
CUtlReference<CNewParticleEffect> pBurnEffect = ParticleProp()->Create( "burned_alien_death", PATTACH_ABSORIGIN_FOLLOW );
|
||||
|
||||
EmitSound( "ASW_Alien.Flame_Death_Flash" );
|
||||
|
||||
// this tells the ragdoll to fade out.
|
||||
SUB_Remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// if we're set to fade, MAKE IT SO
|
||||
if ( m_nDeathStyle == kDIE_RAGDOLLFADE )
|
||||
{
|
||||
// this tells the ragdoll to fade out.
|
||||
SUB_Remove();
|
||||
|
||||
//if ( pszGibParticleEffect )
|
||||
// ParticleProp()->Create( pszGibParticleEffect, PATTACH_ABSORIGIN_FOLLOW );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// we might use this code int he future, but for now, we're using models in the particle system to spawn the instagib effects
|
||||
/*
|
||||
KeyValues * modelKeyValues = new KeyValues("");
|
||||
if ( modelKeyValues->LoadFromBuffer( GetModelName(), modelinfo->GetModelKeyValueText( GetModel() ) ) )
|
||||
{
|
||||
KeyValues *pkvMeshParticleEffect = modelKeyValues->FindKey("MeshParticles");
|
||||
if ( pkvMeshParticleEffect )
|
||||
{
|
||||
|
||||
for ( KeyValues *pSingleEffect = pkvMeshParticleEffect->GetFirstSubKey(); pSingleEffect; pSingleEffect = pSingleEffect->GetNextKey() )
|
||||
{
|
||||
const char *pszParticleEffect = pSingleEffect->GetString( "effectName", "" );
|
||||
const char *pszModelName = pSingleEffect->GetString( "modelName", "" );
|
||||
const char *pszBoneName = pSingleEffect->GetString( "boneName", "" );
|
||||
//const char *pszBoneAxis = pSingleEffect->GetString( "boneAxis", "0 1 0" );
|
||||
|
||||
Vector vGibOrigin;
|
||||
QAngle aGibAngles;
|
||||
|
||||
int iBoneIdx = -1;
|
||||
if ( pszBoneName )
|
||||
{
|
||||
iBoneIdx = LookupBone( pszBoneName );
|
||||
}
|
||||
|
||||
// See if we can find the appropriate bone
|
||||
if ( iBoneIdx > -1 )
|
||||
{
|
||||
GetBonePosition( iBoneIdx, vGibOrigin, aGibAngles );
|
||||
}
|
||||
else
|
||||
{
|
||||
//if no bone was specified, pop a warning and then use the ragdoll's centre, or the worldspace origin...
|
||||
Warning("Failed to find the bone specified for particle effect in model '%s' keyvalues section. Trying to spawn effect '%s' on attachment named '%s'. Spawning effect at origin of ragdoll.\n", GetModelName(), pszParticleEffect, pszBoneName );
|
||||
|
||||
Vector vMins, vMaxs;
|
||||
if ( m_pRagdoll )
|
||||
{
|
||||
m_pRagdoll->GetRagdollBounds( vMins, vMaxs );
|
||||
vGibOrigin = m_pRagdoll->GetRagdollOrigin() + ( ( vMins + vMaxs ) / 2.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
vGibOrigin = WorldSpaceCenter();
|
||||
}
|
||||
}
|
||||
|
||||
Vector vGibVelocity(0,0,0);
|
||||
if ( m_pRagdoll )
|
||||
{
|
||||
m_pRagdoll->GetElement(0)->GetVelocity(&vGibVelocity,NULL);
|
||||
}
|
||||
|
||||
FX_GibMeshEmitter( pszModelName, pszParticleEffect, vGibOrigin, vGibVelocity * asw_drone_gib_velocity.GetFloat(), GetSkin() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_ASW_ClientsideGib( this );
|
||||
}
|
||||
|
||||
modelKeyValues->deleteThis();
|
||||
}
|
||||
*/
|
||||
|
||||
Release();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef C_ASW_CLIENTRAGDOLL_H
|
||||
#define C_ASW_CLIENTRAGDOLL_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class C_ASW_ClientRagdoll : public C_ClientRagdoll
|
||||
{
|
||||
|
||||
public:
|
||||
C_ASW_ClientRagdoll( bool bRestoring = true );
|
||||
DECLARE_CLASS( C_ASW_ClientRagdoll, C_ClientRagdoll );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual void ClientThink( void );
|
||||
|
||||
void BreakRagdoll();
|
||||
|
||||
const Vector& GetDeathForce() { return m_vecForce; }
|
||||
|
||||
float m_fASWGibTime;
|
||||
int m_iSourceEntityIndex;
|
||||
|
||||
int m_nDeathStyle;
|
||||
|
||||
bool m_bElectroShock;
|
||||
const char *pszGibParticleEffect;
|
||||
bool m_bHurled;
|
||||
};
|
||||
|
||||
|
||||
void ASWHurlRagdollAtCamera( C_ASW_ClientRagdoll * RESTRICT pEntity );
|
||||
void ASWMeleeThrowRagdoll( C_ASW_ClientRagdoll * RESTRICT pEntity );
|
||||
|
||||
#endif // C_ASW_CLIENTRAGDOLL_H
|
||||
@@ -0,0 +1,275 @@
|
||||
#include "cbase.h"
|
||||
#include "C_ASW_Computer_Area.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include "c_asw_door.h"
|
||||
#include "asw_marine_profile.h"
|
||||
#include "c_asw_hack.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "igameevents.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Computer_Area, DT_ASW_Computer_Area, CASW_Computer_Area )
|
||||
RecvPropInt (RECVINFO(m_iHackLevel)),
|
||||
RecvPropFloat (RECVINFO(m_fDownloadTime)),
|
||||
RecvPropBool (RECVINFO(m_bIsLocked)),
|
||||
RecvPropBool(RECVINFO(m_bIsInUse)),
|
||||
RecvPropBool(RECVINFO(m_bWaitingForInput)),
|
||||
RecvPropFloat(RECVINFO(m_fHackProgress)),
|
||||
|
||||
RecvPropInt (RECVINFO(m_bIsLocked)),
|
||||
RecvPropFloat (RECVINFO(m_fHackProgress)),
|
||||
|
||||
RecvPropEHandle( RECVINFO( m_hSecurityCam1 ) ),
|
||||
RecvPropEHandle( RECVINFO( m_hTurret1 ) ),
|
||||
|
||||
RecvPropString( RECVINFO( m_MailFile ) ),
|
||||
RecvPropString( RECVINFO( m_NewsFile ) ),
|
||||
RecvPropString( RECVINFO( m_StocksSeed ) ),
|
||||
RecvPropString( RECVINFO( m_WeatherSeed ) ),
|
||||
RecvPropString( RECVINFO( m_PlantFile ) ),
|
||||
RecvPropString( RECVINFO( m_PDAName ) ),
|
||||
|
||||
RecvPropString( RECVINFO( m_SecurityCamLabel1 ) ),
|
||||
RecvPropString( RECVINFO( m_SecurityCamLabel2 ) ),
|
||||
RecvPropString( RECVINFO( m_SecurityCamLabel3 ) ),
|
||||
RecvPropString( RECVINFO( m_TurretLabel1 ) ),
|
||||
RecvPropString( RECVINFO( m_TurretLabel2 ) ),
|
||||
RecvPropString( RECVINFO( m_TurretLabel3 ) ),
|
||||
|
||||
RecvPropString( RECVINFO( m_DownloadObjectiveName ) ),
|
||||
RecvPropBool( RECVINFO(m_bDownloadedDocs) ),
|
||||
|
||||
RecvPropBool (RECVINFO(m_bSecurityCam1Locked)),
|
||||
RecvPropBool (RECVINFO(m_bTurret1Locked)),
|
||||
RecvPropBool (RECVINFO(m_bMailFileLocked)),
|
||||
RecvPropBool (RECVINFO(m_bNewsFileLocked)),
|
||||
RecvPropBool (RECVINFO(m_bStocksFileLocked)),
|
||||
RecvPropBool (RECVINFO(m_bWeatherFileLocked)),
|
||||
RecvPropBool (RECVINFO(m_bPlantFileLocked)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
bool C_ASW_Computer_Area::s_bLoadedLockedIconTexture = false;
|
||||
int C_ASW_Computer_Area::s_nLockedIconTextureID = -1;
|
||||
bool C_ASW_Computer_Area::s_bLoadedOpenIconTexture = false;
|
||||
int C_ASW_Computer_Area::s_nOpenIconTextureID = -1;
|
||||
bool C_ASW_Computer_Area::s_bLoadedCloseIconTexture = false;
|
||||
int C_ASW_Computer_Area::s_nCloseIconTextureID = -1;
|
||||
bool C_ASW_Computer_Area::s_bLoadedUseIconTexture = false;
|
||||
int C_ASW_Computer_Area::s_nUseIconTextureID = -1;
|
||||
bool C_ASW_Computer_Area::s_bLoadedHackIconTexture = false;
|
||||
int C_ASW_Computer_Area::s_nHackIconTextureID = -1;
|
||||
bool C_ASW_Computer_Area::s_bLoadedUseIconPDA = false;
|
||||
int C_ASW_Computer_Area::s_nUseIconPDA = -1;
|
||||
|
||||
C_ASW_Computer_Area::C_ASW_Computer_Area()
|
||||
{
|
||||
m_bOldWaitingForInput = false;
|
||||
|
||||
m_iActiveCam = 1; // should be set serverside and networked down depending on which cam we're using?
|
||||
m_fLastPositiveSoundTime = 0;
|
||||
}
|
||||
|
||||
C_ASW_Door* C_ASW_Computer_Area::GetDoor()
|
||||
{
|
||||
return dynamic_cast<C_ASW_Door*>(GetUseTargetHandle().Get());
|
||||
}
|
||||
|
||||
// use icon textures
|
||||
|
||||
int C_ASW_Computer_Area::GetLockedIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedLockedIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nLockedIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nLockedIconTextureID, "vgui/swarm/UseIcons/PanelLocked", true, false);
|
||||
s_bLoadedLockedIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nLockedIconTextureID;
|
||||
}
|
||||
int C_ASW_Computer_Area::GetOpenIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedOpenIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nOpenIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nOpenIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedOpenIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nOpenIconTextureID;
|
||||
}
|
||||
int C_ASW_Computer_Area::GetCloseIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedCloseIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nCloseIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nCloseIconTextureID, "vgui/swarm/UseIcons/PanelNoPower", true, false);
|
||||
s_bLoadedCloseIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nCloseIconTextureID;
|
||||
}
|
||||
int C_ASW_Computer_Area::GetUseIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedUseIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nUseIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nUseIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedUseIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nUseIconTextureID;
|
||||
}
|
||||
int C_ASW_Computer_Area::GetHackIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedHackIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nHackIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nHackIconTextureID, "vgui/swarm/UseIcons/PanelLocked", true, false);
|
||||
s_bLoadedHackIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nHackIconTextureID;
|
||||
}
|
||||
|
||||
int C_ASW_Computer_Area::GetUseIconPDATextureID()
|
||||
{
|
||||
if (!s_bLoadedUseIconPDA)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nUseIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nUseIconTextureID, "vgui/swarm/UseIcons/UseIconPDA", true, false);
|
||||
s_bLoadedUseIconPDA = true;
|
||||
}
|
||||
|
||||
return s_nUseIconTextureID;
|
||||
}
|
||||
|
||||
int C_ASW_Computer_Area::GetNumMenuOptions()
|
||||
{
|
||||
int n=0;
|
||||
|
||||
if (m_DownloadObjectiveName.Get()[0] != 0 && GetHackProgress() < 1.0f) n++;
|
||||
if (m_MailFile.Get()[0] != 0) n++;
|
||||
if (m_NewsFile.Get()[0] != 0) n++;
|
||||
if (m_StocksSeed.Get()[0] != 0) n++;
|
||||
if (m_WeatherSeed.Get()[0] != 0) n++;
|
||||
if (m_PlantFile.Get()[0] != 0) n++;
|
||||
|
||||
if (m_hSecurityCam1.Get() != NULL) n++;
|
||||
if (m_hTurret1.Get() != NULL) n++;
|
||||
|
||||
if (n > 6) // clamp it to 6 options, since that's all our UI supports
|
||||
n = 6;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
bool C_ASW_Computer_Area::GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser)
|
||||
{
|
||||
CASW_Marine_Profile *pProfile = pUser->GetMarineProfile();
|
||||
bool bTech = pProfile->CanHack();
|
||||
|
||||
action.UseIconRed = 255;
|
||||
action.UseIconGreen = 255;
|
||||
action.UseIconBlue = 255;
|
||||
action.bShowUseKey = true;
|
||||
action.iInventorySlot = -1;
|
||||
if (pUser->m_hCurrentHack.Get())
|
||||
{
|
||||
// if we're a tech and we're on the 'access denied' screen, then change use icon to be an 'override'
|
||||
if (bTech && pUser->m_hCurrentHack->CanOverrideHack())
|
||||
{
|
||||
action.iUseIconTexture = GetHackIconTextureID();
|
||||
TryLocalize( "#asw_override_security", action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
if (IsLocked())
|
||||
action.fProgress = GetTumblerProgress(pUser);
|
||||
else
|
||||
action.fProgress = GetHackProgress();
|
||||
}
|
||||
else
|
||||
{
|
||||
action.iUseIconTexture = GetHackIconTextureID();
|
||||
TryLocalize( "#asw_log_off", action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
if (IsLocked())
|
||||
action.fProgress = GetTumblerProgress(pUser);
|
||||
else
|
||||
action.fProgress = GetHackProgress();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsLocked())
|
||||
{
|
||||
if (bTech)
|
||||
{
|
||||
action.iUseIconTexture = GetHackIconTextureID();
|
||||
TryLocalize( "#asw_hack_comp", action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
action.fProgress = GetHackProgress();
|
||||
}
|
||||
else
|
||||
{
|
||||
action.iUseIconTexture = GetLockedIconTextureID();
|
||||
TryLocalize( "#asw_requires_tech", action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
action.fProgress = GetHackProgress();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action.iUseIconTexture = GetUseIconTextureID();
|
||||
if ( IsPDA() )
|
||||
{
|
||||
action.iUseIconTexture = GetUseIconPDATextureID();
|
||||
TryLocalize( GetUseIconPDAText(), action.wszText, sizeof( action.wszText ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
TryLocalize( GetUseIconText(), action.wszText, sizeof( action.wszText ) );
|
||||
}
|
||||
action.UseTarget = this;
|
||||
action.fProgress = -1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C_ASW_Computer_Area::IsPDA()
|
||||
{
|
||||
return m_PDAName.Get()[0] != 0;
|
||||
}
|
||||
|
||||
float C_ASW_Computer_Area::GetTumblerProgress(C_ASW_Marine *pUser)
|
||||
{
|
||||
if (!pUser || !pUser->m_hCurrentHack.Get())
|
||||
return 0;
|
||||
|
||||
return pUser->m_hCurrentHack->GetTumblerProgress();
|
||||
}
|
||||
|
||||
void C_ASW_Computer_Area::PlayPositiveSound(C_ASW_Player *pHackingPlayer)
|
||||
{
|
||||
if (gpGlobals->curtime > m_fLastPositiveSoundTime + 0.6f)
|
||||
{
|
||||
m_fLastPositiveSoundTime = gpGlobals->curtime;
|
||||
CLocalPlayerFilter filter;
|
||||
C_BaseEntity::EmitSound( filter, entindex(), "ASWComputer.NumberAligned" );
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Computer_Area::PlayNegativeSound(C_ASW_Player *pHackingPlayer)
|
||||
{
|
||||
// none atm
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#ifndef _DEFINED_C_ASW_COMPUTER_AREA_H
|
||||
#define _DEFINED_C_ASW_COMPUTER_AREA_H
|
||||
|
||||
#include "c_asw_use_area.h"
|
||||
|
||||
class C_ASW_Door;
|
||||
class C_ASW_Player;
|
||||
|
||||
class C_ASW_Computer_Area : public C_ASW_Use_Area
|
||||
{
|
||||
DECLARE_CLASS( C_ASW_Computer_Area, C_ASW_Use_Area );
|
||||
DECLARE_CLIENTCLASS();
|
||||
public:
|
||||
C_ASW_Computer_Area();
|
||||
|
||||
bool IsLocked() { return m_bIsLocked; }
|
||||
int GetHackLevel() { return m_iHackLevel; }
|
||||
C_ASW_Door* GetDoor();
|
||||
|
||||
Class_T Classify( void ) { return (Class_T) CLASS_ASW_COMPUTER_AREA; }
|
||||
|
||||
// accessors for icons
|
||||
int GetLockedIconTextureID();
|
||||
const char* GetLockedIconText() { return "#asw_attempt_access"; }
|
||||
int GetOpenIconTextureID();
|
||||
const char* GetOpenIconText() { return "#asw_open"; }
|
||||
int GetCloseIconTextureID();
|
||||
const char* GetCloseIconText() { return "#asw_close"; }
|
||||
int GetUseIconTextureID();
|
||||
const char* GetUseIconText() { return "#asw_access_terminal"; }
|
||||
int GetHackIconTextureID();
|
||||
const char* GetHackIconText() { return "#asw_access_terminal"; }
|
||||
int GetUseIconPDATextureID();
|
||||
const char* GetUseIconPDAText() { return "#asw_access_pda"; }
|
||||
|
||||
virtual float GetTumblerProgress(C_ASW_Marine *pUser);
|
||||
virtual bool GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser);
|
||||
virtual void CustomPaint( int ix, int iy, int alpha, vgui::Panel *pUseIcon ) { }
|
||||
virtual C_BaseEntity* GetGlowEntity() { return m_hPanelProp.Get(); }
|
||||
|
||||
int GetNumMenuOptions();
|
||||
|
||||
CNetworkString( m_MailFile, 255 );
|
||||
CNetworkString( m_NewsFile, 255 );
|
||||
CNetworkString( m_StocksSeed, 255 );
|
||||
CNetworkString( m_WeatherSeed, 255 );
|
||||
CNetworkString( m_PlantFile, 255 );
|
||||
CNetworkString( m_PDAName, 255 );
|
||||
|
||||
CNetworkString( m_SecurityCamLabel1, 255 );
|
||||
CNetworkString( m_SecurityCamLabel2, 255 );
|
||||
CNetworkString( m_SecurityCamLabel3, 255 );
|
||||
CNetworkString( m_TurretLabel1, 255 );
|
||||
CNetworkString( m_TurretLabel2, 255 );
|
||||
CNetworkString( m_TurretLabel3, 255 );
|
||||
|
||||
CNetworkString( m_DownloadObjectiveName, 255 );
|
||||
CNetworkVar( bool, m_bDownloadedDocs );
|
||||
|
||||
CNetworkVar( bool, m_bSecurityCam1Locked );
|
||||
CNetworkVar( bool, m_bTurret1Locked );
|
||||
CNetworkVar( bool, m_bMailFileLocked );
|
||||
CNetworkVar( bool, m_bNewsFileLocked );
|
||||
CNetworkVar( bool, m_bStocksFileLocked );
|
||||
CNetworkVar( bool, m_bWeatherFileLocked );
|
||||
CNetworkVar( bool, m_bPlantFileLocked );
|
||||
|
||||
CNetworkHandle( CBaseEntity, m_hSecurityCam1 );
|
||||
CNetworkHandle( CBaseEntity, m_hTurret1 );
|
||||
|
||||
// traditional Swarm hacking
|
||||
float GetHackProgress() { return m_fHackProgress; }
|
||||
CNetworkVar(bool, m_bIsInUse);
|
||||
CNetworkVar(float, m_fHackProgress);
|
||||
|
||||
bool IsWaitingForInput( void ) const { return m_bWaitingForInput; }
|
||||
int m_iActiveCam;
|
||||
|
||||
// does this computer area represent a PDA instead of a typical computer?
|
||||
bool IsPDA();
|
||||
|
||||
void PlayPositiveSound(C_ASW_Player *pPlayer);
|
||||
void PlayNegativeSound(C_ASW_Player *pPlayer);
|
||||
float m_fLastPositiveSoundTime;
|
||||
|
||||
protected:
|
||||
bool m_bIsLocked;
|
||||
bool m_bWaitingForInput;
|
||||
bool m_bOldWaitingForInput;
|
||||
int m_iHackLevel;
|
||||
float m_fDownloadTime;
|
||||
C_ASW_Computer_Area( const C_ASW_Computer_Area & ); // not defined, not accessible
|
||||
|
||||
// icons used to interact with computers
|
||||
static bool s_bLoadedLockedIconTexture;
|
||||
static int s_nLockedIconTextureID;
|
||||
|
||||
static bool s_bLoadedOpenIconTexture;
|
||||
static int s_nOpenIconTextureID;
|
||||
|
||||
static bool s_bLoadedCloseIconTexture;
|
||||
static int s_nCloseIconTextureID;
|
||||
|
||||
static bool s_bLoadedUseIconTexture;
|
||||
static int s_nUseIconTextureID;
|
||||
|
||||
static bool s_bLoadedHackIconTexture;
|
||||
static int s_nHackIconTextureID;
|
||||
|
||||
static bool s_bLoadedUseIconPDA;
|
||||
static int s_nUseIconPDA;
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_COMPUTER_AREA_H */
|
||||
@@ -0,0 +1,800 @@
|
||||
#include "cbase.h"
|
||||
#include "input.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine_resource.h"
|
||||
#include "c_asw_game_resource.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_weapon.h"
|
||||
#include "c_asw_objective.h"
|
||||
#include "asw_marine_profile.h"
|
||||
#include "c_asw_generic_emitter.h"
|
||||
#include "c_asw_generic_emitter_entity.h"
|
||||
#include "clientmode_asw.h"
|
||||
#include "asw_vgui_edit_emitter.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "c_asw_jeep_clientside.h"
|
||||
#include "vgui\asw_hud_minimap.h"
|
||||
#include "asw_vgui_manipulator.h"
|
||||
#include "c_asw_camera_volume.h"
|
||||
#include "c_asw_mesh_emitter_entity.h"
|
||||
#include "MedalCollectionPanel.h"
|
||||
#include "PlayerListPanel.h"
|
||||
#include "PlayerListContainer.h"
|
||||
#include "vgui\nb_mission_panel.h"
|
||||
#ifndef _X360
|
||||
#include "steam/isteamuserstats.h"
|
||||
#include "steam/isteamfriends.h"
|
||||
#include "steam/isteamutils.h"
|
||||
#include "steam/steam_api.h"
|
||||
#include "matchmaking/imatchframework.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern ConVar cam_idealdist;
|
||||
extern ConVar cam_idealpitch;
|
||||
extern ConVar cam_idealyaw;
|
||||
|
||||
extern vgui::DHANDLE<vgui::Frame> g_hBriefingFrame;
|
||||
|
||||
// displays the mission objectives in the game resource
|
||||
void ListObjectives(void)
|
||||
{
|
||||
C_ASW_Game_Resource *pGameResource = ASWGameResource();
|
||||
if ( !pGameResource )
|
||||
return;
|
||||
|
||||
for (int i=0;i<12;i++)
|
||||
{
|
||||
if ( pGameResource->GetObjective(i) == NULL )
|
||||
Msg("Objective %d = empty\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand listobjectives("listobjectives", ListObjectives, "Shows names of objectives in the objectives array", FCVAR_CHEAT);
|
||||
|
||||
void ListMarineResources(void)
|
||||
{
|
||||
C_ASW_Game_Resource *pGameResource = ASWGameResource();
|
||||
if ( !pGameResource )
|
||||
return;
|
||||
|
||||
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
|
||||
{
|
||||
if (pGameResource->GetMarineResource(i) == NULL)
|
||||
Msg("MarineResource %d = empty\n", i);
|
||||
else
|
||||
{
|
||||
Msg("MarineResource %d = present, profileindex %d, commander %d commander index %d\n",
|
||||
i, pGameResource->GetMarineResource(i)->m_MarineProfileIndex,
|
||||
pGameResource->GetMarineResource(i)->GetCommander(),
|
||||
pGameResource->GetMarineResource(i)->GetCommanderIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand listmarineresources("listmarineresources", ListMarineResources, "Shows contents of the marine resource array", FCVAR_CHEAT);
|
||||
|
||||
void listroster_f(void)
|
||||
{
|
||||
C_ASW_Game_Resource *pGameResource = ASWGameResource();
|
||||
if (!pGameResource)
|
||||
return;
|
||||
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
Msg("[C] Roster %d selected=%d\n", i, pGameResource->IsRosterSelected(i));
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand listroster("listroster", listroster_f, "Shows which marines in the roster are selected", FCVAR_CHEAT);
|
||||
|
||||
void asw_credits_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->LaunchCredits();
|
||||
}
|
||||
}
|
||||
static ConCommand asw_credits("asw_credits", asw_credits_f, "Test shows credits", FCVAR_CHEAT);
|
||||
|
||||
|
||||
void asw_cain_mail_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
pPlayer->LaunchCainMail();
|
||||
}
|
||||
}
|
||||
static ConCommand asw_cain_mail("asw_cain_mail", asw_cain_mail_f, "Test shows cain mail", FCVAR_CHEAT);
|
||||
|
||||
// lists a few basic details about a marine's profile
|
||||
void ASW_InspectProfile( const CCommand &args )
|
||||
{
|
||||
int i = atoi( args[1] );
|
||||
Msg("Marine profile %d\n", i);
|
||||
|
||||
CASW_Marine_Profile *profile = MarineProfileList()->m_Profiles[i];
|
||||
if (profile != NULL)
|
||||
{
|
||||
Msg("Name: %s\n", profile->m_ShortName);
|
||||
Msg("Age: %d\n",
|
||||
profile->m_Age);
|
||||
if (profile->GetMarineClass() == MARINE_CLASS_TECH)
|
||||
Msg("Tech\n");
|
||||
if (profile->GetMarineClass() == MARINE_CLASS_MEDIC)
|
||||
Msg("First Aid\n");
|
||||
if (profile->GetMarineClass() == MARINE_CLASS_SPECIAL_WEAPONS)
|
||||
Msg("Special Weapons\n");
|
||||
if (profile->GetMarineClass() == MARINE_CLASS_NCO)
|
||||
Msg("Sapper\n");
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand asw_inspect_profile("asw_inspect_profile", ASW_InspectProfile, "Display a marine's profile", FCVAR_CHEAT);
|
||||
|
||||
|
||||
void CC_ASWEditEmitterFrame(void)
|
||||
{
|
||||
using namespace vgui;
|
||||
|
||||
// find the asw player
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (!pPlayer)
|
||||
return;
|
||||
|
||||
// fine the nearest emitter
|
||||
float distance = 0;
|
||||
float best_distance = 0;
|
||||
C_ASW_Emitter* pEmitter = NULL;
|
||||
C_ASW_Emitter* pTemp = NULL;
|
||||
|
||||
unsigned int c = ClientEntityList().GetHighestEntityIndex();
|
||||
for ( unsigned int i = 0; i <= c; i++ )
|
||||
{
|
||||
C_BaseEntity *e = ClientEntityList().GetBaseEntity( i );
|
||||
if ( !e )
|
||||
continue;
|
||||
|
||||
pTemp = dynamic_cast<C_ASW_Emitter*>(e);
|
||||
if (pTemp)
|
||||
{
|
||||
distance = pTemp->GetAbsOrigin().DistTo(pPlayer->GetAbsOrigin());
|
||||
if (best_distance == 0 || distance < best_distance)
|
||||
{
|
||||
best_distance = distance;
|
||||
pEmitter = pTemp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pEmitter == NULL)
|
||||
{
|
||||
Msg("Couldn't find any asw_emitter to edit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// create the basic frame which holds our briefing panels
|
||||
CASW_VGUI_Edit_Emitter* pEditEmitterFrame = new CASW_VGUI_Edit_Emitter( GetClientMode()->GetViewport(), "EditEmitterFrame" );
|
||||
HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew");
|
||||
pEditEmitterFrame->SetScheme(scheme);
|
||||
pEditEmitterFrame->Activate();// set visible, move to front, request focus
|
||||
pEditEmitterFrame->SetEmitter((C_ASW_Emitter*) pEmitter);
|
||||
pEditEmitterFrame->InitFrom((C_ASW_Emitter*) pEmitter);
|
||||
}
|
||||
|
||||
static ConCommand ASW_EditEmitterFrame("ASW_EditEmitterFrame", CC_ASWEditEmitterFrame, "The vgui panel used to edit emitters", FCVAR_CHEAT);
|
||||
|
||||
|
||||
void ASW_MessageLog_f(void)
|
||||
{
|
||||
// find the asw player
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
pPlayer->ShowMessageLog();
|
||||
}
|
||||
static ConCommand ASW_MessageLog("ASW_MessageLog", ASW_MessageLog_f, "Shows a log of info messages you've read so far in this mission", 0);
|
||||
|
||||
|
||||
void asw_weapon_switch_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
C_ASW_Marine *pMarine = pPlayer->GetMarine();
|
||||
if ( !pMarine )
|
||||
return;
|
||||
|
||||
C_BaseCombatWeapon *pCurrent = pMarine->GetActiveWeapon();
|
||||
C_BaseCombatWeapon *pPrimary = pMarine->GetWeapon( ASW_INVENTORY_SLOT_PRIMARY );
|
||||
if ( pCurrent != pPrimary && pPrimary )
|
||||
{
|
||||
::input->MakeWeaponSelection( pPrimary );
|
||||
}
|
||||
C_BaseCombatWeapon *pSecondary = pMarine->GetWeapon( ASW_INVENTORY_SLOT_SECONDARY );
|
||||
if ( pCurrent != pSecondary && pSecondary )
|
||||
{
|
||||
::input->MakeWeaponSelection( pSecondary );
|
||||
}
|
||||
}
|
||||
ConCommand ASW_InvLast( "ASW_InvLast", asw_weapon_switch_f, "Switches between primary and secondary weapons", 0 );
|
||||
ConCommand ASW_InvNext( "ASW_InvNext", asw_weapon_switch_f, "Makes your marine select the next weapon", 0 );
|
||||
ConCommand ASW_InvPrev( "ASW_InvPrev", asw_weapon_switch_f, "Makes your marine select the previous weapon", 0 );
|
||||
|
||||
// Binds for activating primary/secondary/extra items
|
||||
|
||||
void ASW_ActivatePrimary_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
|
||||
if (pPlayer && pPlayer->GetMarine())
|
||||
{
|
||||
pPlayer->ActivateInventoryItem(0);
|
||||
}
|
||||
}
|
||||
void ASW_ActivateSecondary_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
|
||||
if (pPlayer && pPlayer->GetMarine())
|
||||
{
|
||||
pPlayer->ActivateInventoryItem(1);
|
||||
}
|
||||
}
|
||||
void ASW_ActivateExtra_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
|
||||
if (pPlayer && pPlayer->GetMarine())
|
||||
{
|
||||
pPlayer->ActivateInventoryItem(2);
|
||||
}
|
||||
}
|
||||
ConCommand ASW_ActivatePrimary( "ASW_ActivatePrimary", ASW_ActivatePrimary_f, "Activates the item in your primary inventory slot", 0 );
|
||||
ConCommand ASW_ActivateSecondary( "ASW_ActivateSecondary", ASW_ActivateSecondary_f, "Activates the item in your secondary inventory slot", 0 );
|
||||
ConCommand ASW_ActivateExtra( "ASW_ActivateExtra", ASW_ActivateExtra_f, "Activates the item in your extra inventory slot", 0 );
|
||||
|
||||
C_ASW_PropJeep_Clientside* g_pJeep = NULL;
|
||||
void asw_make_jeep_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
C_ASW_PropJeep_Clientside* pJeep = C_ASW_PropJeep_Clientside::CreateNew(false);
|
||||
pJeep->SetAbsOrigin(pPlayer->GetAbsOrigin());
|
||||
pJeep->Initialize();
|
||||
g_pJeep = pJeep;
|
||||
// need to set player?
|
||||
}
|
||||
}
|
||||
ConCommand asw_make_jeep( "asw_make_jeep", asw_make_jeep_f, "Creates a clientside jeep", FCVAR_CHEAT );
|
||||
|
||||
|
||||
void asw_make_jeep_phys_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer && g_pJeep)
|
||||
{
|
||||
g_pJeep->InitPhysics();
|
||||
}
|
||||
}
|
||||
ConCommand asw_make_jeep_phys( "asw_make_jeep_phys", asw_make_jeep_phys_f, "Creates physics for test clientside jeep", FCVAR_CHEAT );
|
||||
|
||||
/*
|
||||
void asw_snow_test_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer && pPlayer->GetMarine())
|
||||
{
|
||||
int i = atoi( args[1] );
|
||||
if (i == 0)
|
||||
{
|
||||
pPlayer->GetMarine()->m_hSnowEmitter->m_bLocalCoordSpace = false;
|
||||
pPlayer->GetMarine()->m_hSnowEmitter->m_bWrapParticlesToSpawnBounds = false;
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
pPlayer->GetMarine()->m_hSnowEmitter->m_bLocalCoordSpace = true;
|
||||
pPlayer->GetMarine()->m_hSnowEmitter->m_bWrapParticlesToSpawnBounds = false;
|
||||
}
|
||||
else if (i == 2)
|
||||
{
|
||||
pPlayer->GetMarine()->m_hSnowEmitter->m_bLocalCoordSpace = true;
|
||||
pPlayer->GetMarine()->m_hSnowEmitter->m_bWrapParticlesToSpawnBounds = true;
|
||||
}
|
||||
else if (i == 3)
|
||||
{
|
||||
pPlayer->GetMarine()->m_hSnowEmitter->m_bLocalCoordSpace = false;
|
||||
pPlayer->GetMarine()->m_hSnowEmitter->m_bWrapParticlesToSpawnBounds = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ConCommand asw_snow_test( "asw_snow_test", asw_snow_test_f, "Changes snow emitter state", FCVAR_CHEAT );
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
void asw_minimap_scale_f( const CCommand &args )
|
||||
{
|
||||
CASWHudMinimap *pMiniMap = GET_HUDELEMENT(CASWHudMinimap);
|
||||
if (!pMiniMap)
|
||||
return;
|
||||
|
||||
if (args.ArgC() == 2)
|
||||
{
|
||||
pMiniMap->m_fMapScale = atof( args[1] );
|
||||
Msg("Set minimap scale to %f\n", pMiniMap->m_fMapScale);
|
||||
}
|
||||
}
|
||||
ConCommand asw_minimap_scale( "asw_minimap_scale", asw_minimap_scale_f, "Overrides scale of the minimap", FCVAR_CHEAT );
|
||||
|
||||
void asw_entindex_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
Msg("Hidehud is %d\n", pPlayer->m_Local.m_iHideHUD);
|
||||
Msg("Local player entity index is %d\n", pPlayer->entindex());
|
||||
if (pPlayer->GetMarine())
|
||||
{
|
||||
Msg(" and your current marine's entity index is %d\n", pPlayer->GetMarine()->entindex());
|
||||
if (pPlayer->GetMarine()->GetMarineResource())
|
||||
{
|
||||
Msg(" and your current marine's marine info's entity index is %d\n", pPlayer->GetMarine()->GetMarineResource()->entindex());
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg(" and your current marine has no marine info\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg(" and you have no current marine\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("No local player!\n");
|
||||
}
|
||||
}
|
||||
ConCommand asw_entindex( "asw_entindex", asw_entindex_f, "Returns the entity index of the player", FCVAR_CHEAT );
|
||||
|
||||
/*
|
||||
void asw_campaign_test_f()
|
||||
{
|
||||
if (!ASWGameRules())
|
||||
return;
|
||||
|
||||
C_ASW_Game_Resource* pGameResource = ASWGameRules()->ASWGameResource();
|
||||
if (!pGameResource)
|
||||
return;
|
||||
|
||||
Msg("Making test campaign...\n");
|
||||
ASWGameRules()->m_pCampaignInfo = new CASW_Campaign_Info;
|
||||
if (ASWGameRules()->m_pCampaignInfo)
|
||||
{
|
||||
Msg("Loading jacob campaign into it\n");
|
||||
ASWGameRules()->m_pCampaignInfo->LoadCampaign("jacob");
|
||||
int num_missions = ASWGameRules()->m_pCampaignInfo->GetNumMissions();
|
||||
Msg(" Num Missions = %d\n", num_missions);
|
||||
for (int i=0;i<num_missions;i++)
|
||||
{
|
||||
Msg("Mission %d name is %s\n", i, ASWGameRules()->m_pCampaignInfo->GetMission(i)->m_MissionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
ConCommand asw_campaign_test( "asw_campaign_test", asw_campaign_test_f, "Campaign code test function", FCVAR_CHEAT );
|
||||
|
||||
void asw_campaign_panel_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
pPlayer->LaunchCampaignFrame();
|
||||
}
|
||||
ConCommand asw_campaign_panel( "asw_campaign_panel", asw_campaign_panel_f, "Campaign panel test function", FCVAR_CHEAT );
|
||||
*/
|
||||
|
||||
void asw_edit_panel_f( const CCommand &args )
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (!pPlayer)
|
||||
return;
|
||||
if (!GetClientMode()->GetViewport())
|
||||
{
|
||||
Msg("No viewport!\n");
|
||||
return;
|
||||
}
|
||||
GetClientMode()->GetViewport();
|
||||
vgui::Panel *pPanel = GetClientMode()->GetViewport()->FindChildByName(args[1], true);
|
||||
if (pPanel)
|
||||
{
|
||||
vgui::Panel *pParent = GetClientModeASW()->m_hCampaignFrame.Get();
|
||||
if (!pParent)
|
||||
pParent = GetClientModeASW()->GetViewport();
|
||||
CASW_VGUI_Manipulator::EditPanel( pParent, pPanel );
|
||||
}
|
||||
else
|
||||
{
|
||||
CASW_VGUI_Manipulator::EditPanel(NULL, NULL);
|
||||
Msg("No panel found with that name in viewport! Clearing manipulator.\n");
|
||||
}
|
||||
}
|
||||
ConCommand asw_edit_panel( "asw_edit_panel", asw_edit_panel_f, "ASW Edit a VGUI panel by name", FCVAR_CHEAT );
|
||||
void asw_marine_update_visibility_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer && pPlayer->GetMarine())
|
||||
{
|
||||
pPlayer->GetMarine()->UpdateVisibility();
|
||||
}
|
||||
}
|
||||
ConCommand asw_marine_update_visibility( "asw_marine_update_visibility", asw_marine_update_visibility_f, "Updates marine visibility", FCVAR_CHEAT );
|
||||
|
||||
void asw_camera_volume_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer && pPlayer->GetMarine())
|
||||
{
|
||||
Msg("Marine inside camera volume = %d\n", C_ASW_Camera_Volume::IsPointInCameraVolume(pPlayer->GetMarine()->GetAbsOrigin()));
|
||||
}
|
||||
}
|
||||
ConCommand asw_camera_volume( "asw_camera_volume", asw_camera_volume_f, "check if the marine is inside an asw_camera_control volume", FCVAR_CHEAT );
|
||||
|
||||
void asw_camera_report_defaults_f()
|
||||
{
|
||||
QAngle default_ang(cam_idealpitch.GetFloat(),cam_idealyaw.GetFloat(),0);
|
||||
Vector default_dir;
|
||||
AngleVectors(default_ang, &default_dir);
|
||||
Msg("Default dir: %f, %f, %f\n", default_dir.x, default_dir.y, default_dir.z);
|
||||
default_dir *= -cam_idealdist.GetFloat();
|
||||
Msg("Default offset: %f, %f, %f\n", default_dir.x, default_dir.y, default_dir.z);
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
Msg("RTS cam is at: %f, %f, %f\n", VectorExpand( pPlayer->GetAbsOrigin() ) );
|
||||
}
|
||||
}
|
||||
ConCommand asw_camera_report_defaults( "asw_camera_report_defaults", asw_camera_report_defaults_f, "Report default vectors on the camera based on current settings", FCVAR_CHEAT );
|
||||
|
||||
|
||||
|
||||
void asw_mesh_emitter_test_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer && pPlayer->GetMarine())
|
||||
{
|
||||
C_ASW_Marine *pMarine = pPlayer->GetMarine();
|
||||
C_ASW_Mesh_Emitter *pEmitter = new C_ASW_Mesh_Emitter;
|
||||
if (pEmitter)
|
||||
{
|
||||
if (pEmitter->InitializeAsClientEntity( "models/swarm/DroneGibs/dronepart01.mdl", false ))
|
||||
{
|
||||
Vector vecForward;
|
||||
AngleVectors(pMarine->GetAbsAngles(), &vecForward);
|
||||
Vector vecEmitterPos = pMarine->GetAbsOrigin() + vecForward * 200.0f;
|
||||
Q_snprintf(pEmitter->m_szTemplateName, sizeof(pEmitter->m_szTemplateName), "dronegiblots");
|
||||
pEmitter->m_fScale = 1.0f;
|
||||
pEmitter->m_bEmit = true;
|
||||
pEmitter->SetAbsOrigin(vecEmitterPos);
|
||||
pEmitter->CreateEmitter(vec3_origin);
|
||||
pEmitter->SetAbsOrigin(vecEmitterPos);
|
||||
pEmitter->SetDieTime(gpGlobals->curtime + 15.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
pEmitter->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ConCommand asw_mesh_emitter_test( "asw_mesh_emitter_test", asw_mesh_emitter_test_f, "Test spawning a clientside mesh emitter", FCVAR_CHEAT );
|
||||
|
||||
|
||||
void ShowPlayerList()
|
||||
{
|
||||
if ( gpGlobals->maxClients <= 1 )
|
||||
return;
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (!pPlayer)
|
||||
return;
|
||||
|
||||
if (engine->IsLevelMainMenuBackground()) // don't show player list on main menu
|
||||
{
|
||||
return;
|
||||
}
|
||||
vgui::Panel *pContainer = GetClientMode()->GetViewport()->FindChildByName("g_PlayerListFrame", true);
|
||||
if (pContainer)
|
||||
{
|
||||
pContainer->SetVisible(false);
|
||||
pContainer->MarkForDeletion();
|
||||
pContainer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
vgui::Frame* pFrame = NULL;
|
||||
|
||||
if (g_hBriefingFrame.Get())
|
||||
pContainer = new PlayerListContainer( g_hBriefingFrame.Get(), "g_PlayerListFrame" );
|
||||
else
|
||||
{
|
||||
if (GetClientModeASW()->m_hCampaignFrame.Get())
|
||||
{
|
||||
pContainer = new PlayerListContainer( GetClientModeASW()->m_hCampaignFrame.Get(), "g_PlayerListFrame" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetClientModeASW()->m_hMissionCompleteFrame.Get())
|
||||
{
|
||||
pContainer = new PlayerListContainer( GetClientModeASW()->m_hMissionCompleteFrame.Get(), "g_PlayerListFrame" );
|
||||
}
|
||||
else
|
||||
{
|
||||
pFrame = new PlayerListContainerFrame( GetClientMode()->GetViewport(), "g_PlayerListFrame" );
|
||||
pContainer = pFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew");
|
||||
pContainer->SetScheme(scheme);
|
||||
|
||||
// the panel to show the info
|
||||
PlayerListPanel *playerlistpanel = new PlayerListPanel( pContainer, "PlayerListPanel" );
|
||||
playerlistpanel->SetVisible( true );
|
||||
|
||||
if (!pContainer)
|
||||
{
|
||||
Msg("Error: Player list pContainer frame was closed immediately on opening\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
pContainer->RequestFocus();
|
||||
pContainer->SetVisible(true);
|
||||
pContainer->SetEnabled(true);
|
||||
pContainer->SetKeyBoardInputEnabled(false);
|
||||
pContainer->SetZPos(200);
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand playerlist("playerlist", ShowPlayerList, "Shows the player list and allows voting", 0);
|
||||
|
||||
void ShowInGameBriefing()
|
||||
{
|
||||
using namespace vgui;
|
||||
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (!pPlayer)
|
||||
return;
|
||||
|
||||
if (engine->IsLevelMainMenuBackground()) // don't show player list on main menu
|
||||
{
|
||||
return;
|
||||
}
|
||||
vgui::Panel *pContainer = GetClientMode()->GetViewport()->FindChildByName("InGameBriefingContainer", true);
|
||||
if (pContainer)
|
||||
{
|
||||
pContainer->SetVisible(false);
|
||||
pContainer->MarkForDeletion();
|
||||
pContainer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_hBriefingFrame.Get() || GetClientModeASW()->m_hCampaignFrame.Get() || GetClientModeASW()->m_hMissionCompleteFrame.Get())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vgui::Frame* pFrame = new InGameMissionPanelFrame( GetClientMode()->GetViewport(), "InGameBriefingContainer" );
|
||||
HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew");
|
||||
pFrame->SetScheme(scheme);
|
||||
|
||||
// the panel to show the info
|
||||
CNB_Mission_Panel *missionpanel = new CNB_Mission_Panel( pFrame, "MissionPanel" );
|
||||
missionpanel->SetVisible( true );
|
||||
|
||||
if (!pFrame)
|
||||
{
|
||||
Msg("Error: ingame briefing frame was closed immediately on opening\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
pFrame->RequestFocus();
|
||||
pFrame->SetVisible(true);
|
||||
pFrame->SetEnabled(true);
|
||||
pFrame->SetKeyBoardInputEnabled(false);
|
||||
pFrame->SetZPos(200);
|
||||
GetClientModeASW()->m_hInGameBriefingFrame = pFrame;
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand ingamebriefing("ingamebriefing", ShowInGameBriefing, "Shows the mission briefing panel", 0);
|
||||
|
||||
|
||||
void ShowMedalCollection()
|
||||
{
|
||||
using namespace vgui;
|
||||
|
||||
vgui::Panel *pMedalPanel = GetClientMode()->GetViewport()->FindChildByName("MedalCollectionPanel", true);
|
||||
if (pMedalPanel)
|
||||
{
|
||||
pMedalPanel->SetVisible(false);
|
||||
pMedalPanel->MarkForDeletion();
|
||||
pMedalPanel = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
vgui::Frame* pFrame = NULL;
|
||||
// create the basic frame which holds our briefing panels
|
||||
//Msg("Assigning player list frame\n");
|
||||
if (g_hBriefingFrame.Get()) // todo: handle if they bring it up during debrief or campaign map too
|
||||
pMedalPanel = new vgui::Panel( g_hBriefingFrame.Get(), "MedalCollectionPanel" );
|
||||
else
|
||||
{
|
||||
pFrame = new vgui::Frame( GetClientMode()->GetViewport(), "MedalCollectionPanel" );
|
||||
pMedalPanel = pFrame;
|
||||
}
|
||||
HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew");
|
||||
pMedalPanel->SetScheme(scheme);
|
||||
pMedalPanel->SetBounds(0, 0, GetClientMode()->GetViewport()->GetWide(), GetClientMode()->GetViewport()->GetTall());
|
||||
//pMedalPanel->SetPos(GetClientMode()->GetViewport()->GetWide() * 0.15f, GetClientMode()->GetViewport()->GetTall() * 0.15f);
|
||||
//pMedalPanel->SetSize( GetClientMode()->GetViewport()->GetWide() * 0.7f, GetClientMode()->GetViewport()->GetTall() * 0.7f );
|
||||
|
||||
if (pFrame)
|
||||
{
|
||||
pFrame->SetMoveable(false);
|
||||
pFrame->SetSizeable(false);
|
||||
pFrame->SetMenuButtonVisible(false);
|
||||
pFrame->SetMaximizeButtonVisible(false);
|
||||
pFrame->SetMinimizeToSysTrayButtonVisible(false);
|
||||
pFrame->SetCloseButtonVisible(true);
|
||||
pFrame->SetTitleBarVisible(false);
|
||||
}
|
||||
pMedalPanel->SetPaintBackgroundEnabled(false);
|
||||
pMedalPanel->SetBgColor(Color(0,0,0, 192));
|
||||
|
||||
// the panel to show the info
|
||||
MedalCollectionPanel *collection = new MedalCollectionPanel( pMedalPanel, "Collection" );
|
||||
collection->SetVisible( true );
|
||||
collection->SetBounds(0, 0, pMedalPanel->GetWide(),pMedalPanel->GetTall());
|
||||
|
||||
if (!pMedalPanel)
|
||||
{
|
||||
Msg("Error: pMedalPanel frame was closed immediately on opening\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
pMedalPanel->RequestFocus();
|
||||
pMedalPanel->SetVisible(true);
|
||||
pMedalPanel->SetEnabled(true);
|
||||
pMedalPanel->SetKeyBoardInputEnabled(false);
|
||||
pMedalPanel->SetZPos(200);
|
||||
}
|
||||
}
|
||||
|
||||
//static ConCommand asw_medals("asw_medals", ShowMedalCollection, "Shows the players medal collection", FCVAR_CHEAT);
|
||||
|
||||
|
||||
|
||||
void asw_list_sounds_f()
|
||||
{
|
||||
Msg("listing all sounds\n");
|
||||
|
||||
CUtlVector< SndInfo_t > sndlist;
|
||||
enginesound->GetActiveSounds(sndlist);
|
||||
for (int i=0;i<sndlist.Count();i++)
|
||||
{
|
||||
//SndInfo_t& sound = sndlist[i];
|
||||
//Msg("sound %d: %s\n", i, sound.m);
|
||||
Msg("sound %d\n", i);
|
||||
}
|
||||
}
|
||||
ConCommand asw_sounds("asw_sounds", asw_list_sounds_f, "lists sounds playing", 0);
|
||||
|
||||
void asw_test_music_f()
|
||||
{
|
||||
Msg("listing all active sounds:\n");
|
||||
|
||||
CUtlVector< SndInfo_t > sndlist;
|
||||
enginesound->GetActiveSounds(sndlist);
|
||||
for (int i=0;i<sndlist.Count();i++)
|
||||
{
|
||||
//SndInfo_t& sound = sndlist[i];
|
||||
//Msg("sound %d: %s\n", i, sound.m_pszName);
|
||||
Msg("sound %d\n", i);
|
||||
}
|
||||
if (GetClientModeASW())
|
||||
{
|
||||
Msg("Briefing music pointer is: %d\n", GetClientModeASW()->m_pBriefingMusic);
|
||||
if (GetClientModeASW()->m_pBriefingMusic)
|
||||
{
|
||||
Msg("asw_test_music_f calling StopBriefingMusic\n");
|
||||
GetClientModeASW()->StopBriefingMusic();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg("No local player\n");
|
||||
}
|
||||
}
|
||||
ConCommand asw_test_music("asw_test_music", asw_test_music_f, "lists music pointer", 0);
|
||||
|
||||
void asw_debug_spectator_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
Msg("Clientside spectator flag is %d\n", GetClientModeASW() ? GetClientModeASW()->m_bSpectator : 0);
|
||||
engine->ClientCmd("asw_debug_spectator_server");
|
||||
}
|
||||
}
|
||||
ConCommand asw_debug_spectator( "asw_debug_spectator", asw_debug_spectator_f, "Prints info on spectator", FCVAR_CHEAT );
|
||||
|
||||
// TODO: Remove this before ship?
|
||||
void reset_steam_stats_f()
|
||||
{
|
||||
Assert( steamapicontext->SteamUserStats() );
|
||||
if ( !steamapicontext->SteamUserStats() )
|
||||
return;
|
||||
|
||||
steamapicontext->SteamUserStats()->ResetAllStats( false );
|
||||
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pPlayer )
|
||||
{
|
||||
pPlayer->RequestExperience();
|
||||
}
|
||||
}
|
||||
ConCommand reset_steam_stats( "reset_steam_stats", reset_steam_stats_f, "Resets steam stats (experience, etc.)", FCVAR_DEVELOPMENTONLY );
|
||||
|
||||
|
||||
|
||||
void asw_show_xp_f()
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pPlayer )
|
||||
{
|
||||
Msg( "pPlayer->GetLevel() = %d\n", pPlayer->GetLevel() );
|
||||
Msg( "pPlayer->GetExperience() = %d\n", pPlayer->GetExperience() );
|
||||
Msg( "pPlayer->GetExperienceBeforeDebrief() = %d\n", pPlayer->GetExperienceBeforeDebrief() );
|
||||
}
|
||||
}
|
||||
ConCommand asw_show_xp( "asw_show_xp", asw_show_xp_f, "Print local player's XP and level", FCVAR_NONE );
|
||||
|
||||
CON_COMMAND( make_game_public, "Changes access for the current game to public." )
|
||||
{
|
||||
if ( !g_pMatchFramework || !g_pMatchFramework->GetMatchSession() )
|
||||
return;
|
||||
|
||||
if ( !ASWGameResource() || ASWGameResource()->GetLeader() != C_ASW_Player::GetLocalASWPlayer() )
|
||||
return;
|
||||
|
||||
KeyValues *pSettings = new KeyValues( "update" );
|
||||
KeyValues::AutoDelete autodelete( pSettings );
|
||||
|
||||
pSettings->SetString( "update/system/access", "public" );
|
||||
|
||||
g_pMatchFramework->GetMatchSession()->UpdateSessionSettings( pSettings );
|
||||
}
|
||||
|
||||
CON_COMMAND( make_game_friends_only, "Changes access for the current game to friends only." )
|
||||
{
|
||||
if ( !g_pMatchFramework || !g_pMatchFramework->GetMatchSession() )
|
||||
return;
|
||||
|
||||
if ( !ASWGameResource() || ASWGameResource()->GetLeader() != C_ASW_Player::GetLocalASWPlayer() )
|
||||
return;
|
||||
|
||||
KeyValues *pSettings = new KeyValues( "update" );
|
||||
KeyValues::AutoDelete autodelete( pSettings );
|
||||
|
||||
pSettings->SetString( "update/system/access", "friends" );
|
||||
|
||||
g_pMatchFramework->GetMatchSession()->UpdateSessionSettings( pSettings );
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_debrief_stats.h"
|
||||
#include "MissionStatsPanel.h"
|
||||
#include "iclientmode.h"
|
||||
#include "c_asw_player.h"
|
||||
#include <vgui_controls/Frame.h>
|
||||
#include "asw_medal_store.h"
|
||||
#include "asw_gamerules.h"
|
||||
#include "c_asw_game_resource.h"
|
||||
#include "c_asw_marine_resource.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Debrief_Stats, DT_ASW_Debrief_Stats, CASW_Debrief_Stats)
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iKills), RecvPropInt( RECVINFO(m_iKills[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_fAccuracy), RecvPropFloat( RECVINFO(m_fAccuracy[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iFF), RecvPropInt( RECVINFO(m_iFF[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamage), RecvPropInt( RECVINFO(m_iDamage[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFired), RecvPropInt( RECVINFO(m_iShotsFired[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsHit), RecvPropInt( RECVINFO(m_iShotsFired[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWounded), RecvPropInt( RECVINFO(m_iWounded[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iAliensBurned), RecvPropInt( RECVINFO(m_iAliensBurned[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iHealthHealed), RecvPropInt( RECVINFO(m_iHealthHealed[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iFastHacks), RecvPropInt( RECVINFO(m_iFastHacks[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iSkillPointsAwarded), RecvPropInt( RECVINFO(m_iSkillPointsAwarded[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iStartingEquip0), RecvPropInt( RECVINFO(m_iStartingEquip0[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iStartingEquip1), RecvPropInt( RECVINFO(m_iStartingEquip1[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iStartingEquip2), RecvPropInt( RECVINFO(m_iStartingEquip2[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iAmmoDeployed), RecvPropInt( RECVINFO(m_iAmmoDeployed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iSentryGunsDeployed), RecvPropInt( RECVINFO(m_iSentryGunsDeployed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iSentryFlamerDeployed), RecvPropInt( RECVINFO(m_iSentryFlamerDeployed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iSentryFreezeDeployed), RecvPropInt( RECVINFO(m_iSentryFreezeDeployed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iSentryCannonDeployed), RecvPropInt( RECVINFO(m_iSentryCannonDeployed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iMedkitsUsed), RecvPropInt( RECVINFO(m_iMedkitsUsed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iFlaresUsed), RecvPropInt( RECVINFO(m_iFlaresUsed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iAdrenalineUsed), RecvPropInt( RECVINFO(m_iAdrenalineUsed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iTeslaTrapsDeployed), RecvPropInt( RECVINFO(m_iTeslaTrapsDeployed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iFreezeGrenadesThrown), RecvPropInt( RECVINFO(m_iFreezeGrenadesThrown[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iElectricArmorUsed), RecvPropInt( RECVINFO(m_iElectricArmorUsed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iHealGunHeals), RecvPropInt( RECVINFO(m_iHealGunHeals[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iHealBeaconHeals), RecvPropInt( RECVINFO(m_iHealBeaconHeals[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iHealGunHeals_Self), RecvPropInt( RECVINFO(m_iHealGunHeals_Self[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iHealBeaconHeals_Self), RecvPropInt( RECVINFO(m_iHealBeaconHeals_Self[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAmpsUsed), RecvPropInt( RECVINFO(m_iDamageAmpsUsed[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iHealBeaconsDeployed), RecvPropInt( RECVINFO(m_iHealBeaconsDeployed[0]))),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWeaponClassAndKills0), RecvPropInt( RECVINFO(m_iWeaponClassAndKills0[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAndFF0), RecvPropInt( RECVINFO(m_iDamageAndFF0[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFiredAndHit0), RecvPropInt( RECVINFO(m_iShotsFiredAndHit0[0]))),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWeaponClassAndKills1), RecvPropInt( RECVINFO(m_iWeaponClassAndKills1[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAndFF1), RecvPropInt( RECVINFO(m_iDamageAndFF1[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFiredAndHit1), RecvPropInt( RECVINFO(m_iShotsFiredAndHit1[0]))),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWeaponClassAndKills2), RecvPropInt( RECVINFO(m_iWeaponClassAndKills2[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAndFF2), RecvPropInt( RECVINFO(m_iDamageAndFF2[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFiredAndHit2), RecvPropInt( RECVINFO(m_iShotsFiredAndHit2[0]))),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWeaponClassAndKills3), RecvPropInt( RECVINFO(m_iWeaponClassAndKills3[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAndFF3), RecvPropInt( RECVINFO(m_iDamageAndFF3[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFiredAndHit3), RecvPropInt( RECVINFO(m_iShotsFiredAndHit3[0]))),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWeaponClassAndKills4), RecvPropInt( RECVINFO(m_iWeaponClassAndKills4[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAndFF4), RecvPropInt( RECVINFO(m_iDamageAndFF4[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFiredAndHit4), RecvPropInt( RECVINFO(m_iShotsFiredAndHit4[0]))),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWeaponClassAndKills5), RecvPropInt( RECVINFO(m_iWeaponClassAndKills5[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAndFF5), RecvPropInt( RECVINFO(m_iDamageAndFF5[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFiredAndHit5), RecvPropInt( RECVINFO(m_iShotsFiredAndHit5[0]))),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWeaponClassAndKills6), RecvPropInt( RECVINFO(m_iWeaponClassAndKills6[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAndFF6), RecvPropInt( RECVINFO(m_iDamageAndFF6[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFiredAndHit6), RecvPropInt( RECVINFO(m_iShotsFiredAndHit6[0]))),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWeaponClassAndKills7), RecvPropInt( RECVINFO(m_iWeaponClassAndKills7[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iDamageAndFF7), RecvPropInt( RECVINFO(m_iDamageAndFF7[0]))),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iShotsFiredAndHit7), RecvPropInt( RECVINFO(m_iShotsFiredAndHit7[0]))),
|
||||
|
||||
RecvPropFloat(RECVINFO(m_fTimeTaken)),
|
||||
RecvPropInt(RECVINFO(m_iTotalKills)),
|
||||
RecvPropInt(RECVINFO(m_iEggKills)),
|
||||
RecvPropInt(RECVINFO(m_iParasiteKills)),
|
||||
RecvPropInt(RECVINFO(m_iDroneKills)),
|
||||
RecvPropInt(RECVINFO(m_iShieldbugKills)),
|
||||
|
||||
RecvPropString( RECVINFO( m_DebriefText1 ) ),
|
||||
RecvPropString( RECVINFO( m_DebriefText2 ) ),
|
||||
RecvPropString( RECVINFO( m_DebriefText3 ) ),
|
||||
|
||||
RecvPropBool( RECVINFO( m_bJustUnlockedCarnage ) ),
|
||||
RecvPropBool( RECVINFO( m_bJustUnlockedUber ) ),
|
||||
RecvPropBool( RECVINFO( m_bJustUnlockedHardcore ) ),
|
||||
RecvPropBool( RECVINFO( m_bBeatSpeedrunTime ) ),
|
||||
|
||||
RecvPropFloat(RECVINFO(m_fBestTimeTaken)),
|
||||
RecvPropInt(RECVINFO(m_iBestKills)),
|
||||
RecvPropInt(RECVINFO(m_iSpeedrunTime)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Debrief_Stats *g_pDebriefStats = NULL;
|
||||
C_ASW_Debrief_Stats* GetDebriefStats() { return g_pDebriefStats; }
|
||||
|
||||
C_ASW_Debrief_Stats::C_ASW_Debrief_Stats()
|
||||
{
|
||||
m_bCreated = false;
|
||||
g_pDebriefStats = this;
|
||||
}
|
||||
|
||||
C_ASW_Debrief_Stats::~C_ASW_Debrief_Stats()
|
||||
{
|
||||
if ( g_pDebriefStats == this )
|
||||
{
|
||||
g_pDebriefStats = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C_ASW_Debrief_Stats::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
BaseClass::OnDataChanged( type );
|
||||
if ( type == DATA_UPDATE_CREATED )
|
||||
{
|
||||
m_bCreated = true;
|
||||
|
||||
// notify the debrief stats page that all data is here and it should start counting numbers/bars up
|
||||
HACK_GETLOCALPLAYER_GUARD( "MissionCompleteFrame needs to be a child of the main client .dll viewport (now a parent to both client mode viewports)" );
|
||||
MissionStatsPanel *pStatsPanel = dynamic_cast<MissionStatsPanel*>(GetClientMode()->GetViewport()->FindChildByName("MissionStatsPanel", true));
|
||||
|
||||
if (pStatsPanel)
|
||||
{
|
||||
pStatsPanel->InitFrom(this);
|
||||
}
|
||||
|
||||
// update our kill counts
|
||||
#ifdef USE_MEDAL_STORE
|
||||
if (GetMedalStore() && ASWGameRules() && ASWGameResource() && !ASWGameRules()->m_bCheated
|
||||
&& !engine->IsPlayingDemo())
|
||||
{
|
||||
C_ASW_Game_Resource *pGameResource = ASWGameResource();
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
int iMissions = ASWGameRules()->GetMissionSuccess() ? 1 : 0; // award 1 extra mission if it was a success
|
||||
int iKills = 0;
|
||||
// go through each marine belonging to the local player and increment kills
|
||||
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
|
||||
if (pMR && pMR->GetCommanderIndex() == pPlayer->entindex())
|
||||
iKills += m_iKills[i];
|
||||
}
|
||||
if (iKills > 0) // only increment their counts if they actually killed something
|
||||
GetMedalStore()->OnIncreaseCounts(iMissions, 0, iKills, (gpGlobals->maxClients <= 1));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// Msg( "Debrief stats data changed\n" );
|
||||
//
|
||||
// for ( int i = 0; i < ASW_MAX_MARINE_RESOURCES; i++ )
|
||||
// {
|
||||
// Msg( "health healed[%d] = %d", i, GetHealthHealed( i ) );
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
int C_ASW_Debrief_Stats::GetHighestKills()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetKills(i);
|
||||
if (k > best)
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
float C_ASW_Debrief_Stats::GetHighestAccuracy()
|
||||
{
|
||||
float best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
float k = GetAccuracy(i);
|
||||
if (k > best)
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetHighestFriendlyFire()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetFriendlyFire(i);
|
||||
if (k != 0 && (k > best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetHighestDamageTaken()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetDamageTaken(i);
|
||||
if (k != 0 && (k > best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetHighestShotsFired()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetShotsFired(i);
|
||||
if (k != 0 && (k > best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetHighestAliensBurned()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetAliensBurned(i);
|
||||
if (k != 0 && (k > best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetHighestHealthHealed()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetHealthHealed(i);
|
||||
if (k != 0 && (k > best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetHighestFastHacks()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetFastHacks(i);
|
||||
if (k != 0 && (k > best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetHighestSkillPointsAwarded()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetSkillPointsAwarded(i);
|
||||
if (k != 0 && (k > best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetLowestFriendlyFire()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetFriendlyFire(i);
|
||||
if (k != 0 && (k < best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
int C_ASW_Debrief_Stats::GetLowestDamageTaken()
|
||||
{
|
||||
int best = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
int k = GetDamageTaken(i);
|
||||
if (k != 0 && (k < best || best == 0))
|
||||
{
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
bool C_ASW_Debrief_Stats::GetWeaponStats( int iMarineIndex, int iEquipIndex, int &iDamage, int &iFFDamage, int &iShotsFired, int &iShotsHit, int &iKills )
|
||||
{
|
||||
if( (unsigned)iEquipIndex == ( ( m_iWeaponClassAndKills0.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF ) )
|
||||
{
|
||||
iDamage = ( m_iDamageAndFF0.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iFFDamage = m_iDamageAndFF0.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iShotsFired = ( m_iShotsFiredAndHit0.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iShotsHit = m_iShotsFiredAndHit0.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iKills = m_iWeaponClassAndKills0.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
else if( (unsigned)iEquipIndex == ( ( m_iWeaponClassAndKills1.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF ) )
|
||||
{
|
||||
iDamage = ( m_iDamageAndFF1.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iFFDamage = m_iDamageAndFF1.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iShotsFired = ( m_iShotsFiredAndHit1.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iShotsHit = m_iShotsFiredAndHit1.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iKills = m_iWeaponClassAndKills1.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
else if( (unsigned)iEquipIndex == ( ( m_iWeaponClassAndKills2.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF ) )
|
||||
{
|
||||
iDamage = ( m_iDamageAndFF2.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iFFDamage = m_iDamageAndFF2.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iShotsFired = ( m_iShotsFiredAndHit2.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iShotsHit = m_iShotsFiredAndHit2.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iKills = m_iWeaponClassAndKills2.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
else if( (unsigned)iEquipIndex == ( ( m_iWeaponClassAndKills3.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF ) )
|
||||
{
|
||||
iDamage = ( m_iDamageAndFF3.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iFFDamage = m_iDamageAndFF3.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iShotsFired = ( m_iShotsFiredAndHit3.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iShotsHit = m_iShotsFiredAndHit3.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iKills = m_iWeaponClassAndKills3.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
else if( (unsigned)iEquipIndex == ( ( m_iWeaponClassAndKills4.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF ) )
|
||||
{
|
||||
iDamage = ( m_iDamageAndFF4.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iFFDamage = m_iDamageAndFF4.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iShotsFired = ( m_iShotsFiredAndHit4.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iShotsHit = m_iShotsFiredAndHit4.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iKills = m_iWeaponClassAndKills4.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
else if( (unsigned)iEquipIndex == ( ( m_iWeaponClassAndKills5.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF ) )
|
||||
{
|
||||
iDamage = ( m_iDamageAndFF5.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iFFDamage = m_iDamageAndFF5.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iShotsFired = ( m_iShotsFiredAndHit5.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iShotsHit = m_iShotsFiredAndHit5.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iKills = m_iWeaponClassAndKills5.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
else if( (unsigned)iEquipIndex == ( ( m_iWeaponClassAndKills6.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF ) )
|
||||
{
|
||||
iDamage = ( m_iDamageAndFF6.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iFFDamage = m_iDamageAndFF6.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iShotsFired = ( m_iShotsFiredAndHit6.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iShotsHit = m_iShotsFiredAndHit6.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iKills = m_iWeaponClassAndKills6.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
else if( (unsigned)iEquipIndex == ( ( m_iWeaponClassAndKills7.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF ) )
|
||||
{
|
||||
iDamage = ( m_iDamageAndFF7.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iFFDamage = m_iDamageAndFF7.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iShotsFired = ( m_iShotsFiredAndHit7.Get( iMarineIndex ) >> 16 ) & 0x0000FFFF;
|
||||
iShotsHit = m_iShotsFiredAndHit7.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
iKills = m_iWeaponClassAndKills7.Get( iMarineIndex ) & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
#ifndef _INCLUDED_C_ASW_DEBRIEF_STATS_H
|
||||
#define _INCLUDED_C_ASW_DEBRIEF_STATS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "asw_shareddefs.h"
|
||||
|
||||
class C_ASW_Debrief_Stats : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Debrief_Stats, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Debrief_Stats();
|
||||
virtual ~C_ASW_Debrief_Stats();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t type );
|
||||
|
||||
int GetKills(int iMarineIndex) { return m_iKills[iMarineIndex]; }
|
||||
float GetAccuracy(int iMarineIndex) { return m_fAccuracy[iMarineIndex]; }
|
||||
int GetFriendlyFire(int iMarineIndex) { return m_iFF[iMarineIndex]; }
|
||||
int GetDamageTaken(int iMarineIndex) { return m_iDamage[iMarineIndex]; }
|
||||
int GetShotsFired(int iMarineIndex) { return m_iShotsFired[iMarineIndex]; }
|
||||
int GetShotsHit(int iMarineIndex) { return m_iShotsHit[iMarineIndex]; }
|
||||
int GetAliensBurned(int iMarineIndex) { return m_iAliensBurned[iMarineIndex]; }
|
||||
int GetHealthHealed(int iMarineIndex) { return m_iHealthHealed[iMarineIndex]; }
|
||||
int GetFastHacks(int iMarineIndex) { return m_iFastHacks[iMarineIndex]; }
|
||||
int GetSkillPointsAwarded(int iMarineIndex) { return m_iSkillPointsAwarded[iMarineIndex]; }
|
||||
bool IsWounded(int iMarineIndex) { return (m_iWounded[iMarineIndex] > 0); }
|
||||
int GetStartingPrimaryEquip( int iMarineIndex ) { return m_iStartingEquip0[iMarineIndex]; }
|
||||
int GetStartingSecondaryEquip( int iMarineIndex ) { return m_iStartingEquip1[iMarineIndex]; }
|
||||
int GetStartingExtraEquip( int iMarineIndex ) { return m_iStartingEquip2[iMarineIndex]; }
|
||||
|
||||
int GetAmmoDeployed( int iMarineIndex ) { return m_iAmmoDeployed[iMarineIndex]; }
|
||||
int GetSentrygunsDeployed( int iMarineIndex ) { return m_iSentryGunsDeployed[iMarineIndex]; }
|
||||
int GetSentryFlamersDeployed( int iMarineIndex ) { return m_iSentryFlamerDeployed[iMarineIndex]; }
|
||||
int GetSentryFreezeDeployed( int iMarineIndex ) { return m_iSentryFreezeDeployed[iMarineIndex]; }
|
||||
int GetSentryCannonDeployed( int iMarineIndex ) { return m_iSentryCannonDeployed[iMarineIndex]; }
|
||||
int GetMedkitsUsed( int iMarineIndex ) { return m_iMedkitsUsed[iMarineIndex]; }
|
||||
int GetFlaresUsed( int iMarineIndex ) { return m_iFlaresUsed[iMarineIndex]; }
|
||||
int GetAdrenalineUsed( int iMarineIndex ) { return m_iAdrenalineUsed[iMarineIndex]; }
|
||||
int GetTeslaTrapsDeployed( int iMarineIndex ) { return m_iTeslaTrapsDeployed[iMarineIndex]; }
|
||||
int GetFreezeGrenadesThrown( int iMarineIndex ) { return m_iFreezeGrenadesThrown[iMarineIndex]; }
|
||||
int GetElectricArmorUsed( int iMarineIndex ) { return m_iElectricArmorUsed[iMarineIndex]; }
|
||||
int GetHealgunHeals( int iMarineIndex ) { return m_iHealGunHeals[iMarineIndex]; }
|
||||
int GetHealgunHeals_Self( int iMarineIndex ) { return m_iHealGunHeals_Self[iMarineIndex]; }
|
||||
int GetHealbeaconHeals( int iMarineIndex ) { return m_iHealBeaconHeals[iMarineIndex]; }
|
||||
int GetHealbeaconHeals_self( int iMarineIndex ) { return m_iHealBeaconHeals_Self[iMarineIndex]; }
|
||||
int GetDamageAmpsUsed( int iMarineIndex ) { return m_iDamageAmpsUsed[iMarineIndex]; }
|
||||
int GetHealbeaconsDeployed( int iMarineIndex ) { return m_iHealBeaconsDeployed[iMarineIndex]; }
|
||||
|
||||
int GetHighestKills();
|
||||
float GetHighestAccuracy();
|
||||
int GetHighestFriendlyFire();
|
||||
int GetHighestDamageTaken();
|
||||
int GetHighestShotsFired();
|
||||
int GetHighestAliensBurned();
|
||||
int GetHighestHealthHealed();
|
||||
int GetHighestFastHacks();
|
||||
int GetLowestFriendlyFire();
|
||||
int GetLowestDamageTaken();
|
||||
int GetHighestSkillPointsAwarded();
|
||||
|
||||
int GetTotalKills() { return m_iTotalKills; }
|
||||
float GetTimeTaken() { return m_fTimeTaken; }
|
||||
|
||||
int GetBestKills() { return m_iBestKills; }
|
||||
float GetBestTime() { return m_fBestTimeTaken; }
|
||||
int GetSpeedrunTime() { return m_iSpeedrunTime; }
|
||||
|
||||
bool GetWeaponStats( int iMarineIndex, int iEquipIndex, int &iDamage, int &iFFDamage, int &iShotsFired, int &iShotsHit, int &iKills );
|
||||
|
||||
// per marine
|
||||
CNetworkArray( int, m_iKills, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( float, m_fAccuracy, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iFF, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iDamage, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iShotsFired, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iShotsHit, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iWounded, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iAliensBurned, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iHealthHealed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iFastHacks, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iSkillPointsAwarded, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iStartingEquip0, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iStartingEquip1, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iStartingEquip2, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iAmmoDeployed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iSentryGunsDeployed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iSentryFlamerDeployed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iSentryFreezeDeployed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iSentryCannonDeployed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iMedkitsUsed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iFlaresUsed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iAdrenalineUsed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iTeslaTrapsDeployed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iFreezeGrenadesThrown, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iElectricArmorUsed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iHealGunHeals, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iHealBeaconHeals, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iHealGunHeals_Self, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iHealBeaconHeals_Self, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iDamageAmpsUsed, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( int, m_iHealBeaconsDeployed, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
// Weapon stats for the marine (8 weapons max)
|
||||
CNetworkArray( unsigned int, m_iWeaponClassAndKills0, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iDamageAndFF0, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iShotsFiredAndHit0, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
CNetworkArray( unsigned int, m_iWeaponClassAndKills1, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iDamageAndFF1, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iShotsFiredAndHit1, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
CNetworkArray( unsigned int, m_iWeaponClassAndKills2, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iDamageAndFF2, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iShotsFiredAndHit2, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
CNetworkArray( unsigned int, m_iWeaponClassAndKills3, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iDamageAndFF3, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iShotsFiredAndHit3, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
CNetworkArray( unsigned int, m_iWeaponClassAndKills4, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iDamageAndFF4, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iShotsFiredAndHit4, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
CNetworkArray( unsigned int, m_iWeaponClassAndKills5, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iDamageAndFF5, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iShotsFiredAndHit5, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
CNetworkArray( unsigned int, m_iWeaponClassAndKills6, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iDamageAndFF6, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iShotsFiredAndHit6, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
CNetworkArray( unsigned int, m_iWeaponClassAndKills7, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iDamageAndFF7, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( unsigned int, m_iShotsFiredAndHit7, ASW_MAX_MARINE_RESOURCES );
|
||||
|
||||
// for the team
|
||||
CNetworkVar( float, m_fTimeTaken );
|
||||
CNetworkVar( int, m_iTotalKills );
|
||||
CNetworkVar( int, m_iEggKills );
|
||||
CNetworkVar( int, m_iParasiteKills );
|
||||
CNetworkVar( int, m_iDroneKills );
|
||||
CNetworkVar( int, m_iShieldbugKills );
|
||||
|
||||
// debrief text
|
||||
CNetworkString( m_DebriefText1, 255 );
|
||||
CNetworkString( m_DebriefText2, 255 );
|
||||
CNetworkString( m_DebriefText3, 255 );
|
||||
|
||||
CNetworkVar( bool, m_bJustUnlockedCarnage );
|
||||
CNetworkVar( bool, m_bJustUnlockedUber );
|
||||
CNetworkVar( bool, m_bJustUnlockedHardcore );
|
||||
CNetworkVar( bool, m_bBeatSpeedrunTime );
|
||||
|
||||
CNetworkVar( float, m_fBestTimeTaken );
|
||||
CNetworkVar( int, m_iBestKills );
|
||||
CNetworkVar( int, m_iSpeedrunTime );
|
||||
|
||||
bool m_bCreated; // has this client entity had its data update created yet
|
||||
|
||||
private:
|
||||
C_ASW_Debrief_Stats( const C_ASW_Debrief_Stats & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
C_ASW_Debrief_Stats* GetDebriefStats();
|
||||
|
||||
#endif // _INCLUDED_C_ASW_DEBRIEF_STATS_H
|
||||
@@ -0,0 +1,308 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_door.h"
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include "vgui/IInput.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
#include "asw_shareddefs.h"
|
||||
#include "effect_dispatch_data.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Door, DT_ASW_Door, CASW_Door )
|
||||
RecvPropFloat (RECVINFO(m_flTotalSealTime)),
|
||||
RecvPropFloat (RECVINFO(m_flCurrentSealTime)),
|
||||
RecvPropInt (RECVINFO(m_iDoorStrength)),
|
||||
RecvPropInt (RECVINFO(m_iDoorType)),
|
||||
RecvPropInt (RECVINFO(m_lifeState)),
|
||||
RecvPropInt (RECVINFO(m_iHealth) ),
|
||||
RecvPropBool (RECVINFO(m_bAutoOpen)),
|
||||
RecvPropBool (RECVINFO(m_bBashable)),
|
||||
RecvPropBool (RECVINFO(m_bShootable)),
|
||||
RecvPropBool (RECVINFO(m_bCanCloseToWeld)),
|
||||
RecvPropBool (RECVINFO(m_bRecommendedSeal)),
|
||||
RecvPropBool (RECVINFO(m_bWasWeldedByMarine)),
|
||||
RecvPropFloat (RECVINFO(m_fLastMomentFlipDamage)),
|
||||
RecvPropVector (RECVINFO(m_vecClosedPosition)),
|
||||
RecvPropBool (RECVINFO(m_bSkillMarineHelping)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
bool C_ASW_Door::s_bLoadedSealedIconTexture = false;
|
||||
bool C_ASW_Door::s_bLoadedFullySealedIconTexture = false;
|
||||
int C_ASW_Door::s_nSealedIconTextureID = -1;
|
||||
int C_ASW_Door::s_nFullySealedIconTextureID = -1;
|
||||
|
||||
// for mousing over door health
|
||||
CUtlVector<C_ASW_Door*> g_ClientDoorList;
|
||||
|
||||
C_ASW_Door::C_ASW_Door()
|
||||
{
|
||||
m_fLastWeldedTime = 0.0f;
|
||||
|
||||
Q_snprintf(m_szSealedIconTexture, sizeof(m_szSealedIconTexture), "vgui/swarm/UseIcons/UseIconDoorPartlySealed");
|
||||
|
||||
g_ClientDoorList.AddToTail(this);
|
||||
}
|
||||
|
||||
C_ASW_Door::~C_ASW_Door()
|
||||
{
|
||||
g_ClientDoorList.FindAndRemove(this);
|
||||
}
|
||||
|
||||
// returns how sealed this door is, from 0 to 1.0
|
||||
float C_ASW_Door::GetSealAmount()
|
||||
{
|
||||
if (m_flTotalSealTime <= 0)
|
||||
return 0;
|
||||
|
||||
return (m_flCurrentSealTime/m_flTotalSealTime);
|
||||
}
|
||||
|
||||
int C_ASW_Door::GetSealedIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedSealedIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nSealedIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nSealedIconTextureID, m_szSealedIconTexture, true, false);
|
||||
s_bLoadedSealedIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nSealedIconTextureID;
|
||||
}
|
||||
|
||||
int C_ASW_Door::GetFullySealedIconTextureID()
|
||||
{
|
||||
if (!s_bLoadedFullySealedIconTexture)
|
||||
{
|
||||
s_nFullySealedIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nFullySealedIconTextureID, "vgui/swarm/UseIcons/UseIconDoorFullySealed", true, false);
|
||||
s_bLoadedFullySealedIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nFullySealedIconTextureID;
|
||||
}
|
||||
|
||||
const char* C_ASW_Door::GetSealedIconText()
|
||||
{
|
||||
if ( gpGlobals->curtime > m_fLastWeldedTime + 1.0f )
|
||||
{
|
||||
if ( m_bWasWeldedByMarine )
|
||||
{
|
||||
if ( GetSealAmount() >= 1.0f )
|
||||
{
|
||||
return "#asw_door_fully_reinforced";
|
||||
}
|
||||
else if ( GetSealAmount() >= 0.5f )
|
||||
{
|
||||
return "#asw_door_reinforced";
|
||||
}
|
||||
}
|
||||
|
||||
return "#asw_door_sealed";
|
||||
}
|
||||
|
||||
if ( m_bUnwelding )
|
||||
{
|
||||
return "#asw_door_unsealing";
|
||||
}
|
||||
|
||||
if ( GetSealAmount() >= 0.5f )
|
||||
{
|
||||
return "#asw_door_reinforcing";
|
||||
}
|
||||
|
||||
return "#asw_door_sealing";
|
||||
}
|
||||
|
||||
|
||||
bool C_ASW_Door::IsOpen()
|
||||
{
|
||||
Vector diff = GetAbsOrigin() - m_vecClosedPosition;
|
||||
float dist = diff.LengthSqr();
|
||||
return (dist > 2); // 2 to allow for network rounding...
|
||||
}
|
||||
|
||||
bool C_ASW_Door::IsMoving()
|
||||
{
|
||||
Vector vel;
|
||||
EstimateAbsVelocity(vel);
|
||||
return vel.LengthSqr() > 0;
|
||||
}
|
||||
|
||||
#define DOOR_CORNER_DISTANCE 62.0f
|
||||
#define DOOR_HEIGHT 135.0f
|
||||
|
||||
Vector C_ASW_Door::GetWeldFacingPoint(C_BaseEntity* pOther)
|
||||
{
|
||||
// work out which side of the door the marine is on
|
||||
Vector diff = pOther->GetAbsOrigin() - GetAbsOrigin();
|
||||
VectorNormalize(diff);
|
||||
QAngle angDoorFacing = GetAbsAngles();
|
||||
Vector vecDoorFacing = vec3_origin;
|
||||
AngleVectors(angDoorFacing, &vecDoorFacing);
|
||||
bool bFrontSide = (DotProduct(vecDoorFacing, diff) > 0);
|
||||
|
||||
// depending on the side, get one of the corners
|
||||
angDoorFacing.y -= bFrontSide ? 81 : 102;
|
||||
AngleVectors(angDoorFacing, &vecDoorFacing);
|
||||
Vector result = GetAbsOrigin() + vecDoorFacing * DOOR_CORNER_DISTANCE;
|
||||
|
||||
// correct by height
|
||||
result.z += DOOR_HEIGHT * (1.0f - GetSealAmount());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector C_ASW_Door::GetSparkNormal( C_BaseEntity* pOther )
|
||||
{
|
||||
// work out which side of the door the marine is on
|
||||
Vector diff = pOther->GetAbsOrigin() - GetAbsOrigin();
|
||||
VectorNormalize(diff);
|
||||
QAngle angDoorFacing = GetAbsAngles();
|
||||
Vector vecDoorFacing = vec3_origin;
|
||||
AngleVectors(angDoorFacing, &vecDoorFacing);
|
||||
bool bFrontSide = (DotProduct(vecDoorFacing, diff) > 0);
|
||||
|
||||
if (bFrontSide)
|
||||
return vecDoorFacing;
|
||||
|
||||
return -vecDoorFacing;
|
||||
}
|
||||
|
||||
// checks the client door list for a door near this position
|
||||
// NOTE: currently only returns damaged doors
|
||||
#define ASW_DOOR_NEAR_PADDING 20
|
||||
C_ASW_Door* C_ASW_Door::GetDoorNear(Vector vecSrc)
|
||||
{
|
||||
for (int i=0;i<g_ClientDoorList.Count();i++)
|
||||
{
|
||||
C_ASW_Door *pEnt = g_ClientDoorList[i];
|
||||
int iDoorType;
|
||||
if (!pEnt || pEnt->GetHealth() <= 0 || pEnt->GetHealthFraction(iDoorType) >= 1.0f)
|
||||
continue;
|
||||
|
||||
Vector mins, maxs;
|
||||
|
||||
// get the size of the door
|
||||
pEnt->GetRenderBoundsWorldspace(mins,maxs);
|
||||
|
||||
// pull out all 8 corners of this volume
|
||||
Vector worldPos[8];
|
||||
Vector screenPos[8];
|
||||
worldPos[0] = mins;
|
||||
worldPos[1] = mins; worldPos[1].x = maxs.x;
|
||||
worldPos[2] = mins; worldPos[2].y = maxs.y;
|
||||
worldPos[3] = mins; worldPos[3].z = maxs.z;
|
||||
worldPos[4] = mins;
|
||||
worldPos[5] = maxs; worldPos[5].x = mins.x;
|
||||
worldPos[6] = maxs; worldPos[6].y = mins.y;
|
||||
worldPos[7] = maxs; worldPos[7].z = mins.z;
|
||||
|
||||
// convert them to screen space
|
||||
for (int k=0;k<8;k++)
|
||||
{
|
||||
debugoverlay->ScreenPosition( worldPos[k], screenPos[k] );
|
||||
}
|
||||
|
||||
// find the rectangle bounding all screen space points
|
||||
Vector topLeft = screenPos[0];
|
||||
Vector bottomRight = screenPos[0];
|
||||
for (int k=0;k<8;k++)
|
||||
{
|
||||
topLeft.x = MIN(screenPos[k].x, topLeft.x);
|
||||
topLeft.y = MIN(screenPos[k].y, topLeft.y);
|
||||
bottomRight.x = MAX(screenPos[k].x, bottomRight.x);
|
||||
bottomRight.y = MAX(screenPos[k].y, bottomRight.y);
|
||||
}
|
||||
int BracketSize = 5; // todo: set by screen res?
|
||||
|
||||
// pad it a bit
|
||||
topLeft.x -= BracketSize * 2;
|
||||
topLeft.y -= BracketSize * 2;
|
||||
bottomRight.x += BracketSize * 2;
|
||||
bottomRight.y += BracketSize * 2;
|
||||
|
||||
// check if the cursor is inside this
|
||||
int x, y;
|
||||
vgui::input()->GetCursorPos( x, y );
|
||||
|
||||
if (x >= topLeft.x && x <= bottomRight.x &&
|
||||
y >= topLeft.y && y <= bottomRight.y)
|
||||
{
|
||||
return pEnt;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float C_ASW_Door::GetHealthFraction(int &iDoorType) const
|
||||
{
|
||||
if ( m_iDoorStrength == 0 ) // indestructable
|
||||
{
|
||||
iDoorType = 2;
|
||||
return 1.0f;
|
||||
}
|
||||
if ( m_iDoorStrength == ASW_DOOR_NORMAL_HEALTH ) // normal
|
||||
{
|
||||
iDoorType = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
iDoorType = 1; // reinforced
|
||||
}
|
||||
|
||||
return ( static_cast< float >( MAX( 0, m_iHealth ) ) - MIN( 0.0f, m_fLastMomentFlipDamage ) ) / static_cast< float >( m_iDoorStrength );
|
||||
}
|
||||
|
||||
void C_ASW_Door::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
BaseClass::OnDataChanged( type );
|
||||
|
||||
if ( !IsAlive() && VPhysicsGetObject())
|
||||
{
|
||||
VPhysicsDestroyObject();
|
||||
}
|
||||
|
||||
if ( m_flOldSealTime != m_flCurrentSealTime )
|
||||
{
|
||||
m_fLastWeldedTime = gpGlobals->curtime;
|
||||
m_bUnwelding = ( m_flOldSealTime > m_flCurrentSealTime );
|
||||
m_flOldSealTime = m_flCurrentSealTime;
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Door::ImpactTrace( trace_t *pTrace, int iDamageType, char *pCustomImpactName )
|
||||
{
|
||||
Assert( pTrace->m_pEnt );
|
||||
|
||||
CBaseEntity *pEntity = pTrace->m_pEnt;
|
||||
|
||||
// Build the impact data
|
||||
CEffectData data;
|
||||
data.m_vOrigin = pTrace->endpos;
|
||||
data.m_vStart = pTrace->startpos;
|
||||
data.m_nSurfaceProp = pTrace->surface.surfaceProps;
|
||||
if (!m_bShootable)
|
||||
data.m_nSurfaceProp = physprops->GetSurfaceIndex("metal");
|
||||
data.m_nDamageType = iDamageType;
|
||||
data.m_nHitBox = pTrace->hitbox;
|
||||
#ifdef CLIENT_DLL
|
||||
data.m_hEntity = ClientEntityList().EntIndexToHandle( pEntity->entindex() );
|
||||
#else
|
||||
data.m_nEntIndex = pEntity->entindex();
|
||||
#endif
|
||||
|
||||
// Send it on its way
|
||||
if ( !pCustomImpactName )
|
||||
{
|
||||
DispatchEffect( "Impact", data );
|
||||
}
|
||||
else
|
||||
{
|
||||
DispatchEffect( pCustomImpactName, data );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef _DEFINED_C_ASW_DOOR_H
|
||||
#define _DEFINED_C_ASW_DOOR_H
|
||||
|
||||
#include "c_props.h"
|
||||
#include "asw_shareddefs.h"
|
||||
|
||||
class C_ASW_Door : public C_BasePropDoor
|
||||
{
|
||||
DECLARE_CLASS( C_ASW_Door, C_BasePropDoor );
|
||||
DECLARE_CLIENTCLASS();
|
||||
public:
|
||||
C_ASW_Door();
|
||||
virtual ~C_ASW_Door();
|
||||
float GetSealAmount(); // returns how sealed this door is, from 0 to 1.0
|
||||
int GetSealedIconTextureID();
|
||||
int GetFullySealedIconTextureID();
|
||||
const char* GetSealedIconText();
|
||||
const char* GetUnsealedIconText() { return "#asw_door_unsealed"; }
|
||||
bool IsOpen();
|
||||
bool IsMoving();
|
||||
virtual int GetHealth() const { return m_iHealth; }
|
||||
virtual float GetHealthFraction(int &iDoorType) const;
|
||||
virtual void OnDataChanged( DataUpdateType_t type );
|
||||
Class_T Classify( void ) { return (Class_T) CLASS_ASW_DOOR; }
|
||||
|
||||
virtual void ImpactTrace( trace_t *pTrace, int iDamageType, char *pCustomImpactName );
|
||||
|
||||
Vector GetWeldFacingPoint( C_BaseEntity* pOther ); // the point a marine should look to weld this door
|
||||
Vector GetSparkNormal( C_BaseEntity* pOther ); // the angle sparks should shoot out when welding
|
||||
|
||||
bool IsRecommendedSeal( void ) { return m_bRecommendedSeal; }
|
||||
CNetworkVar(bool, m_bSkillMarineHelping); // is an engineer helping a weld on this door currently?
|
||||
|
||||
// sent from server
|
||||
float m_flTotalSealTime;
|
||||
float m_flCurrentSealTime;
|
||||
float m_flOldSealTime;
|
||||
bool m_bUnwelding;
|
||||
int m_iDoorStrength;
|
||||
int m_iDoorType;
|
||||
|
||||
bool m_bAutoOpen;
|
||||
bool m_bBashable;
|
||||
bool m_bShootable;
|
||||
bool m_bCanCloseToWeld;
|
||||
bool m_bRecommendedSeal;
|
||||
bool m_bWasWeldedByMarine;
|
||||
float m_fLastMomentFlipDamage;
|
||||
Vector m_vecClosedPosition;
|
||||
|
||||
float m_fLastWeldedTime;
|
||||
|
||||
// checks the client door list for a door near this position
|
||||
static C_ASW_Door* GetDoorNear(Vector vecSrc);
|
||||
|
||||
protected:
|
||||
C_ASW_Door( const C_ASW_Door & ); // not defined, not accessible
|
||||
|
||||
char m_szSealedIconTexture[96];
|
||||
|
||||
static bool s_bLoadedSealedIconTexture, s_bLoadedFullySealedIconTexture;
|
||||
static int s_nSealedIconTextureID;
|
||||
static int s_nFullySealedIconTextureID;
|
||||
};
|
||||
|
||||
extern CUtlVector<C_ASW_Door*> g_ClientDoorList;
|
||||
|
||||
#endif /* _DEFINED_C_ASW_DOOR_H */
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_door.h"
|
||||
#include "c_asw_door_area.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include "asw_weapon_welder_shared.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "asw_hud_master.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Door_Area, DT_ASW_Door_Area, CASW_Door_Area )
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Door_Area::C_ASW_Door_Area()
|
||||
{
|
||||
}
|
||||
|
||||
C_ASW_Door* C_ASW_Door_Area::GetASWDoor()
|
||||
{
|
||||
return dynamic_cast<C_ASW_Door*>(GetUseTargetHandle().Get());
|
||||
}
|
||||
|
||||
bool C_ASW_Door_Area::GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser)
|
||||
{
|
||||
C_ASW_Door* pDoor = GetASWDoor();
|
||||
if ( !pDoor || !pUser )
|
||||
return false;
|
||||
|
||||
bool bHasWelder = pUser->Weapon_OwnsThisType( "asw_weapon_welder" ) != NULL;
|
||||
|
||||
if ( !bHasWelder )
|
||||
{
|
||||
CASW_Hud_Master *pHUDMaster = GET_HUDELEMENT( CASW_Hud_Master );
|
||||
if ( pHUDMaster )
|
||||
{
|
||||
int nWelderPosition = pHUDMaster->GetHotBarSlot( "asw_weapon_welder" );
|
||||
|
||||
if ( nWelderPosition != -1 && pHUDMaster->OwnsHotBarSlot( pUser->GetCommander(), nWelderPosition ) )
|
||||
{
|
||||
bHasWelder = true;
|
||||
if ( nWelderPosition >= 100 )
|
||||
{
|
||||
V_strncpy( action.szCommand, "+walk", sizeof( action.szCommand ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
V_snprintf( action.szCommand, sizeof( action.szCommand ), "asw_squad_hotbar %i", nWelderPosition + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
V_strncpy( action.szCommand, "+grenade1", sizeof( action.szCommand ) );
|
||||
}
|
||||
|
||||
// if door is sealed
|
||||
// add sealed icon with bar showing seal percent
|
||||
if ( pDoor->GetHealth() > 0 )
|
||||
{
|
||||
if ( pDoor->GetSealAmount() > 0 )
|
||||
{
|
||||
if (pDoor->GetSealAmount() >= 1.0f)
|
||||
action.iUseIconTexture = pDoor->GetFullySealedIconTextureID();
|
||||
else
|
||||
action.iUseIconTexture = pDoor->GetSealedIconTextureID();
|
||||
TryLocalize( pDoor->GetSealedIconText(), action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
action.fProgress = pDoor->GetSealAmount();
|
||||
action.UseIconRed = 255;
|
||||
action.UseIconGreen = 255;
|
||||
action.UseIconBlue = 255;
|
||||
action.bShowUseKey = bHasWelder;
|
||||
action.iInventorySlot = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( pUser->GetActiveWeapon() )
|
||||
{
|
||||
if ( bHasWelder )
|
||||
{
|
||||
if ( pDoor->GetSealAmount() >= 1.0f )
|
||||
{
|
||||
action.iUseIconTexture = pDoor->GetFullySealedIconTextureID();
|
||||
}
|
||||
else
|
||||
{
|
||||
action.iUseIconTexture = pDoor->GetSealedIconTextureID();
|
||||
}
|
||||
|
||||
TryLocalize( pDoor->GetUnsealedIconText(), action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = this;
|
||||
action.fProgress = pDoor->GetSealAmount();
|
||||
action.UseIconRed = 255;
|
||||
action.UseIconGreen = 255;
|
||||
action.UseIconBlue = 255;
|
||||
action.bShowUseKey = true;
|
||||
action.iInventorySlot = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef _DEFINED_C_ASW_DOOR_AREA_H
|
||||
#define _DEFINED_C_ASW_DOOR_AREA_H
|
||||
|
||||
#include "c_asw_use_area.h"
|
||||
|
||||
class C_ASW_Door;
|
||||
|
||||
class C_ASW_Door_Area : public C_ASW_Use_Area
|
||||
{
|
||||
DECLARE_CLASS( C_ASW_Door_Area, C_ASW_Use_Area );
|
||||
DECLARE_CLIENTCLASS();
|
||||
public:
|
||||
C_ASW_Door_Area();
|
||||
|
||||
C_ASW_Door* GetASWDoor();
|
||||
|
||||
virtual bool GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser);
|
||||
virtual void CustomPaint(int ix, int iy, int alpha, vgui::Panel *pUseIcon) { }
|
||||
virtual bool ShouldPaintBoxAround() { return false; }
|
||||
|
||||
virtual Class_T Classify( void ) { return (Class_T) CLASS_ASW_DOOR_AREA; }
|
||||
|
||||
protected:
|
||||
C_ASW_Door_Area( const C_ASW_Door_Area & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_DOOR_AREA_H */
|
||||
@@ -0,0 +1,346 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_drone_advanced.h"
|
||||
#include "engine/IVDebugOverlay.h"
|
||||
#include "asw_shareddefs.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include "con_nprint.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Drone_Advanced, DT_ASW_Drone_Advanced, CASW_Drone_Advanced)
|
||||
RecvPropEHandle( RECVINFO( m_hAimTarget ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_ASW_Drone_Advanced )
|
||||
DEFINE_PRED_FIELD( m_flPoseParameter, FIELD_FLOAT, FTYPEDESC_OVERRIDE | FTYPEDESC_PRIVATE | FTYPEDESC_NOERRORCHECK ),
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
ConVar cl_asw_drone_travel_yaw("cl_asw_drone_travel_yaw", "0", FCVAR_CHEAT, "Show the clientside estimated travel yaw for swarm drones");
|
||||
ConVar cl_asw_drone_travel_yaw_rate("cl_asw_drone_travel_yaw_rate", "4.0f", FCVAR_CHEAT, "How fast the drones alter their move_yaw param");
|
||||
ConVar asw_debug_drone_pose( "asw_debug_drone_pose", "0", FCVAR_NONE, "Set to drone entity index to output drone pose params" );
|
||||
ConVar asw_drone_jump_pitch_min( "asw_drone_jump_pitch_min", "-45", FCVAR_NONE, "Min pitch for drone's jumping pose parameter" );
|
||||
ConVar asw_drone_jump_pitch_max( "asw_drone_jump_pitch_max", "45", FCVAR_NONE, "Min pitch for drone's jumping pose parameter" );
|
||||
ConVar asw_drone_jump_pitch_speed( "asw_drone_jump_pitch_speed", "3.0", FCVAR_NONE, "Speed for drone's pitch jumping pose parameter transition" );
|
||||
|
||||
namespace
|
||||
{
|
||||
float AI_ClampYaw( float yawSpeedPerSec, float current, float target, float time )
|
||||
{
|
||||
if (current != target)
|
||||
{
|
||||
float speed = yawSpeedPerSec * time;
|
||||
float move = target - current;
|
||||
|
||||
if (target > current)
|
||||
{
|
||||
if (move >= 180)
|
||||
move = move - 360;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (move <= -180)
|
||||
move = move + 360;
|
||||
}
|
||||
|
||||
if (move > 0)
|
||||
{// turning to the npc's left
|
||||
if (move > speed)
|
||||
move = speed;
|
||||
}
|
||||
else
|
||||
{// turning to the npc's right
|
||||
if (move < -speed)
|
||||
move = -speed;
|
||||
}
|
||||
|
||||
return anglemod(current + move);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
C_ASW_Drone_Advanced::C_ASW_Drone_Advanced()
|
||||
{
|
||||
m_flCurrentTravelYaw = -1;
|
||||
m_flCurrentTravelSpeed = 0;
|
||||
m_bWasJumping = 0.0f;
|
||||
|
||||
for (int i=0;i<MAXSTUDIOPOSEPARAM;i++)
|
||||
{
|
||||
m_flClientPoseParameter[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Drone_Advanced::~C_ASW_Drone_Advanced()
|
||||
{
|
||||
}
|
||||
|
||||
// get the full velocity we can run at for the current direction (i.e. relative to our facing)
|
||||
float C_ASW_Drone_Advanced::GetRunSpeed()
|
||||
{
|
||||
return GetSequenceGroundSpeed(LookupSequence("run_idle"));
|
||||
}
|
||||
|
||||
void C_ASW_Drone_Advanced::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// We want to think every frame.
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
extern ConVar asw_alien_object_motion_blur_scale;
|
||||
|
||||
void C_ASW_Drone_Advanced::ClientThink()
|
||||
{
|
||||
BaseClass::ClientThink();
|
||||
|
||||
UpdatePoseParams();
|
||||
|
||||
// TODO: Fix this to not be doing all these lookups/strcmps (could make drone attack activities server/client shared and use GetSequenceActivity( GetSequence() )
|
||||
/*
|
||||
if ( GetSequence() == LookupSequence( "Lunge_Attack01" )
|
||||
|| GetSequence() == LookupSequence( "Lunge_Attack02" )
|
||||
|| GetSequence() == LookupSequence( "Lunge_Attack03" )
|
||||
|| GetSequence() == LookupSequence( "Jump_Glide" )
|
||||
)
|
||||
{
|
||||
m_MotionBlurObject.SetVelocityScale( asw_alien_object_motion_blur_scale.GetFloat() );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_MotionBlurObject.SetVelocityScale( 0.0f );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void C_ASW_Drone_Advanced::UpdatePoseParams()
|
||||
{
|
||||
VPROF_BUDGET( "C_ASW_Drone_Advanced::UpdatePoseParams", VPROF_BUDGETGROUP_ASW_CLIENT );
|
||||
// update pose params based on velocity and our angles
|
||||
|
||||
// calculate the angle difference between our facing and our velocity
|
||||
Vector v;
|
||||
EstimateAbsVelocity(v);
|
||||
float travel_yaw = anglemod(UTIL_VecToYaw(v));
|
||||
float current_yaw = anglemod( GetLocalAngles().y );
|
||||
float travel_pitch = UTIL_VecToPitch(v);
|
||||
|
||||
// Draw a green triangle on the ground for the travel yaw
|
||||
if (cl_asw_drone_travel_yaw.GetBool())
|
||||
{
|
||||
float flBaseSize = 10;
|
||||
float flHeight = 80;
|
||||
Vector vBasePos = GetAbsOrigin() + Vector( 0, 0, 5 );
|
||||
QAngle angles( 0, 0, 0 );
|
||||
Vector vForward, vRight, vUp;
|
||||
angles[YAW] = travel_yaw;
|
||||
AngleVectors( angles, &vForward, &vRight, &vUp );
|
||||
debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 0, 255, 0, 255, false, 0.01 );
|
||||
}
|
||||
|
||||
// calculate our fraction of full anim velocity
|
||||
float speed_fraction = 0;
|
||||
float ground_speed = GetRunSpeed();
|
||||
if (ground_speed > 0)
|
||||
speed_fraction = clamp<float>(
|
||||
(v.Length()) / ground_speed,
|
||||
0.0f, 1.0f);
|
||||
speed_fraction = 1.0f - speed_fraction;
|
||||
|
||||
// smooth out the travel yaw to prevent sudden changes in move_yaw pose parameter
|
||||
if (m_flCurrentTravelYaw == -1)
|
||||
m_flCurrentTravelYaw = travel_yaw;
|
||||
else
|
||||
{
|
||||
float travel_diff = AngleDiff(m_flCurrentTravelYaw, travel_yaw);
|
||||
if (travel_diff < 0)
|
||||
travel_diff = -travel_diff;
|
||||
travel_diff = clamp<float>(travel_diff, 32.0f, 256.0f); // alter the yaw by this amount - i.e. faster if the angle is bigger, but clamped
|
||||
if (speed_fraction > 0.75f) // change the angle even quicker if we're moving very slowly
|
||||
{
|
||||
travel_diff *= (2.0f + ((speed_fraction - 0.75f) * 8.0f));
|
||||
}
|
||||
if (speed_fraction < 1.0f) // don't bother adjusting the yaw if we're standing still
|
||||
m_flCurrentTravelYaw = AI_ClampYaw( travel_diff * cl_asw_drone_travel_yaw_rate.GetFloat(), m_flCurrentTravelYaw, travel_yaw, gpGlobals->frametime );
|
||||
else
|
||||
m_flCurrentTravelYaw = travel_yaw; // if we're standing still, immediately change
|
||||
|
||||
travel_yaw = m_flCurrentTravelYaw;
|
||||
}
|
||||
|
||||
// set the move_yaw pose parameter
|
||||
float diff = AngleDiff(travel_yaw, current_yaw);
|
||||
|
||||
// Draw a green triangle on the ground for the move yaw
|
||||
if (cl_asw_drone_travel_yaw.GetBool())
|
||||
{
|
||||
float flBaseSize = 10;
|
||||
float flHeight = 10 + (100 * speed_fraction);
|
||||
Vector vBasePos = GetAbsOrigin() + Vector( 0, 0, 5 );
|
||||
QAngle angles( 0, 0, 0 );
|
||||
Vector vForward, vRight, vUp;
|
||||
angles[YAW] = travel_yaw;
|
||||
AngleVectors( angles, &vForward, &vRight, &vUp );
|
||||
debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 0, 0, 255, 255, false, 0.01 );
|
||||
|
||||
angles[YAW] = diff;
|
||||
AngleVectors( angles, &vForward, &vRight, &vUp );
|
||||
debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 255, 0, 0, 255, false, 0.01 );
|
||||
}
|
||||
|
||||
|
||||
diff = clamp<float>(diff, -180.0f, 180.0f);
|
||||
int pose_index = LookupPoseParameter( "move_yaw" );
|
||||
if (pose_index >= 0)
|
||||
{
|
||||
m_flClientPoseParameter[pose_index] = ((diff + 180.0f) / 360.0f);
|
||||
}
|
||||
|
||||
// smooth out our speed fraction to prevent sudden changes to idle_move pose parameter
|
||||
if (m_flCurrentTravelSpeed == -1)
|
||||
{
|
||||
m_flCurrentTravelSpeed = speed_fraction;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_flCurrentTravelSpeed < speed_fraction)
|
||||
{
|
||||
m_flCurrentTravelSpeed = clamp<float>(
|
||||
m_flCurrentTravelSpeed + gpGlobals->frametime,
|
||||
0.0f, speed_fraction);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flCurrentTravelSpeed = clamp<float>(
|
||||
m_flCurrentTravelSpeed - gpGlobals->frametime * 3.0f,
|
||||
speed_fraction, 1.0f);
|
||||
}
|
||||
speed_fraction = m_flCurrentTravelSpeed;
|
||||
}
|
||||
|
||||
// set the idle_move pose parameter
|
||||
pose_index = LookupPoseParameter( "idle_move" );
|
||||
if (pose_index >= 0)
|
||||
{
|
||||
// blend to goal
|
||||
if (speed_fraction > m_flClientPoseParameter[pose_index])
|
||||
m_flClientPoseParameter[pose_index] = MIN(speed_fraction, m_flClientPoseParameter[pose_index] + gpGlobals->frametime * 12.0f);
|
||||
else
|
||||
m_flClientPoseParameter[pose_index] = MAX(speed_fraction, m_flClientPoseParameter[pose_index] - gpGlobals->frametime * 12.0f);
|
||||
}
|
||||
|
||||
pose_index = LookupPoseParameter( "aim_yaw" );
|
||||
if ( pose_index >= 0 )
|
||||
{
|
||||
float flTargetAimPose = 0.0f;
|
||||
if ( m_hAimTarget.Get() )
|
||||
{
|
||||
C_BaseEntity *pEnemy = m_hAimTarget.Get();
|
||||
Vector vecToEnemy = pEnemy->WorldSpaceCenter() - WorldSpaceCenter();
|
||||
float flYaw = UTIL_VecToYaw( vecToEnemy );
|
||||
flYaw = AngleDiff( flYaw, GetAbsAngles()[ YAW ] );
|
||||
//Msg( "Yaw to enemy = %f ", flYaw );
|
||||
flYaw /= -45.0f;
|
||||
flYaw = clamp<float>( flYaw, -1.0f, 1.0f );
|
||||
flYaw = 0.5f + 0.5f * flYaw;
|
||||
//Msg( " clamped+scaled = %f ", flYaw );
|
||||
flTargetAimPose = flYaw;
|
||||
//Msg( " current = %f\n", m_flClientPoseParameter[ pose_index ] );
|
||||
}
|
||||
|
||||
UTIL_ApproachTarget( flTargetAimPose, 3.0f, 3.0f, &m_flClientPoseParameter[ pose_index ] );
|
||||
}
|
||||
|
||||
static int s_nJumpSequence = LookupSequence( "Jump_Glide" );
|
||||
bool bJumping = ( GetSequence() == s_nJumpSequence );
|
||||
if ( bJumping )
|
||||
{
|
||||
pose_index = LookupPoseParameter( "jump_angle" );
|
||||
if ( pose_index >= 0 )
|
||||
{
|
||||
if ( !m_bWasJumping )
|
||||
{
|
||||
m_flClientPoseParameter[ pose_index ] = 0.0f;
|
||||
}
|
||||
|
||||
float flTargetPose = clamp<float>( travel_pitch, asw_drone_jump_pitch_min.GetFloat(), asw_drone_jump_pitch_max.GetFloat() );
|
||||
flTargetPose = ( flTargetPose - asw_drone_jump_pitch_min.GetFloat() ) / ( asw_drone_jump_pitch_max.GetFloat() - asw_drone_jump_pitch_min.GetFloat() );
|
||||
UTIL_ApproachTarget( flTargetPose, asw_drone_jump_pitch_speed.GetFloat(), asw_drone_jump_pitch_speed.GetFloat(), &m_flClientPoseParameter[ pose_index ] );
|
||||
}
|
||||
}
|
||||
m_bWasJumping = bJumping;
|
||||
|
||||
if ( asw_debug_drone_pose.GetInt() == entindex() )
|
||||
{
|
||||
con_nprint_t np;
|
||||
np.fixed_width_font = true;
|
||||
np.color[0] = 0.8f;
|
||||
np.color[1] = 1.0f;
|
||||
np.color[2] = 1.0f;
|
||||
np.time_to_live = 2.0f;
|
||||
np.index = 2;
|
||||
|
||||
pose_index = LookupPoseParameter( "idle_move" );
|
||||
if ( pose_index >= 0 )
|
||||
{
|
||||
engine->Con_NXPrintf( &np, "idle_move: %.2f", m_flClientPoseParameter[pose_index] );
|
||||
np.index++;
|
||||
}
|
||||
pose_index = LookupPoseParameter( "aim_yaw" );
|
||||
if ( pose_index >= 0 )
|
||||
{
|
||||
engine->Con_NXPrintf( &np, "aim_yaw: %.2f", m_flClientPoseParameter[pose_index] );
|
||||
np.index++;
|
||||
}
|
||||
pose_index = LookupPoseParameter( "move_yaw" );
|
||||
if ( pose_index >= 0 )
|
||||
{
|
||||
engine->Con_NXPrintf( &np, "move_yaw: %.2f", m_flClientPoseParameter[pose_index] );
|
||||
np.index++;
|
||||
}
|
||||
pose_index = LookupPoseParameter( "jump_angle" );
|
||||
if ( pose_index >= 0 )
|
||||
{
|
||||
engine->Con_NXPrintf( &np, "jump_angle: %.2f", m_flClientPoseParameter[pose_index] );
|
||||
np.index++;
|
||||
engine->Con_NXPrintf( &np, "travel_pitch: %.2f", travel_pitch );
|
||||
np.index++;
|
||||
|
||||
// if ( !engine->IsPaused() )
|
||||
// {
|
||||
// float flTargetPose = clamp<float>( travel_pitch, asw_drone_jump_pitch_min.GetFloat(), asw_drone_jump_pitch_max.GetFloat() );
|
||||
// flTargetPose = ( flTargetPose - asw_drone_jump_pitch_min.GetFloat() ) / ( asw_drone_jump_pitch_max.GetFloat() - asw_drone_jump_pitch_min.GetFloat() );
|
||||
// Msg( "Travel pitch = %.2f angle = %.2f flTargetPose = %.2f\n", travel_pitch, m_flClientPoseParameter[pose_index], flTargetPose );
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hardcoded to match with the gun offset in the marine's autoaim
|
||||
// this is to generally keep the marine's gun horizontal, so guns like the shotgun can more easily hit multiple enemies in one shot
|
||||
const Vector& C_ASW_Drone_Advanced::GetAimTargetPos(const Vector &vecFiringSrc, bool bWeaponPrefersFlatAiming)
|
||||
{
|
||||
static Vector aim_pos;
|
||||
aim_pos = m_vecLastRenderedPos - (WorldSpaceCenter() - GetAbsOrigin()); // last rendered stores our worldspacecenter, so convert to back origin
|
||||
aim_pos.z += ASW_MARINE_GUN_OFFSET_Z;
|
||||
return aim_pos;
|
||||
}
|
||||
|
||||
void C_ASW_Drone_Advanced::GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM])
|
||||
{
|
||||
if ( !pStudioHdr )
|
||||
return;
|
||||
|
||||
for( int i=0; i < pStudioHdr->GetNumPoseParameters(); i++)
|
||||
{
|
||||
poseParameter[i] = m_flClientPoseParameter[i];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef _INLCUDE_C_ASW_DRONE_ADVANCED_H
|
||||
#define _INLCUDE_C_ASW_DRONE_ADVANCED_H
|
||||
|
||||
#include "c_asw_alien.h"
|
||||
#include "interpolatedvar.h"
|
||||
|
||||
class C_ASW_Drone_Advanced : public C_ASW_Alien
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Drone_Advanced, C_ASW_Alien );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
C_ASW_Drone_Advanced();
|
||||
virtual ~C_ASW_Drone_Advanced();
|
||||
|
||||
Class_T Classify( void ) { return (Class_T) CLASS_ASW_DRONE; }
|
||||
|
||||
float GetRunSpeed();
|
||||
virtual void ClientThink();
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
void UpdatePoseParams();
|
||||
virtual const Vector& GetAimTargetPos(const Vector &vecFiringSrc, bool bWeaponPrefersFlatAiming);
|
||||
virtual void GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM]);
|
||||
|
||||
CNetworkVar( EHANDLE, m_hAimTarget );
|
||||
|
||||
|
||||
private:
|
||||
C_ASW_Drone_Advanced( const C_ASW_Drone_Advanced & ); // not defined, not accessible
|
||||
float m_flCurrentTravelYaw;
|
||||
float m_flCurrentTravelSpeed;
|
||||
float m_flClientPoseParameter[MAXSTUDIOPOSEPARAM];
|
||||
bool m_bWasJumping;
|
||||
};
|
||||
|
||||
#endif /* _INLCUDE_C_ASW_DRONE_ADVANCED_H */
|
||||
@@ -0,0 +1,143 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_dummy_vehicle.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include "asw_util_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Dummy_Vehicle, DT_ASW_Dummy_Vehicle, CASW_Dummy_Vehicle)
|
||||
RecvPropEHandle( RECVINFO( m_hDriver ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Dummy_Vehicle::C_ASW_Dummy_Vehicle()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Dummy_Vehicle::~C_ASW_Dummy_Vehicle()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// implement driver interface
|
||||
C_ASW_Marine* C_ASW_Dummy_Vehicle::ASWGetDriver()
|
||||
{
|
||||
return dynamic_cast<C_ASW_Marine*>(m_hDriver.Get());
|
||||
}
|
||||
|
||||
// implement client vehicle interface
|
||||
bool C_ASW_Dummy_Vehicle::s_bLoadedDriveIconTexture = false;
|
||||
int C_ASW_Dummy_Vehicle::s_nDriveIconTextureID = -1;
|
||||
bool C_ASW_Dummy_Vehicle::s_bLoadedRideIconTexture = false;
|
||||
int C_ASW_Dummy_Vehicle::s_nRideIconTextureID = -1;
|
||||
|
||||
int C_ASW_Dummy_Vehicle::GetDriveIconTexture()
|
||||
{
|
||||
if (!s_bLoadedDriveIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nDriveIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nDriveIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedDriveIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nDriveIconTextureID;
|
||||
}
|
||||
int C_ASW_Dummy_Vehicle::GetRideIconTexture()
|
||||
{
|
||||
if (!s_bLoadedRideIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nRideIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nRideIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedRideIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nRideIconTextureID;
|
||||
}
|
||||
|
||||
bool C_ASW_Dummy_Vehicle::MarineInVehicle()
|
||||
{
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
return (pPlayer && pPlayer->GetMarine() && pPlayer->GetMarine()->IsInVehicle());
|
||||
}
|
||||
|
||||
const char* C_ASW_Dummy_Vehicle::GetDriveIconText()
|
||||
{
|
||||
if (MarineInVehicle())
|
||||
return "Exit Vehicle";
|
||||
|
||||
return "Drive";
|
||||
}
|
||||
|
||||
const char* C_ASW_Dummy_Vehicle::GetRideIconText()
|
||||
{
|
||||
if (MarineInVehicle())
|
||||
return "Exit Vehicle";
|
||||
|
||||
return "Passenger";
|
||||
}
|
||||
|
||||
void C_ASW_Dummy_Vehicle::ClientThink()
|
||||
{
|
||||
if (!ASWGetDriver() || !ASWGetDriver()->GetClientsideVehicle())
|
||||
{
|
||||
UpdateVisibility();
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
}
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
bool C_ASW_Dummy_Vehicle::ShouldDraw()
|
||||
{
|
||||
// don't draw this if the client has a clientside vehicle to use instead
|
||||
if (gpGlobals->maxClients > 1)
|
||||
{
|
||||
if (ASWGetDriver() && ASWGetDriver()->GetClientsideVehicle())
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS ); // we need to check if we should show ourselves again
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::ShouldDraw();
|
||||
}
|
||||
|
||||
ShadowType_t C_ASW_Dummy_Vehicle::ShadowCastType()
|
||||
{
|
||||
// don't draw this if the client has a clientside vehicle to use instead
|
||||
if (gpGlobals->maxClients > 1)
|
||||
{
|
||||
if (ASWGetDriver() && ASWGetDriver()->GetClientsideVehicle())
|
||||
{
|
||||
return SHADOWS_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::ShadowCastType();
|
||||
}
|
||||
|
||||
bool C_ASW_Dummy_Vehicle::IsUsable(C_BaseEntity *pUser)
|
||||
{
|
||||
return (pUser && pUser->GetAbsOrigin().DistTo(GetAbsOrigin()) < ASW_MARINE_USE_RADIUS); // near enough?
|
||||
}
|
||||
|
||||
bool C_ASW_Dummy_Vehicle::GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser)
|
||||
{
|
||||
action.iUseIconTexture = GetDriveIconTexture();
|
||||
TryLocalize( GetDriveIconText(), action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = GetEntity();
|
||||
action.fProgress = -1;
|
||||
action.UseIconRed = 255;
|
||||
action.UseIconGreen = 255;
|
||||
action.UseIconBlue = 255;
|
||||
action.bShowUseKey = true;
|
||||
action.iInventorySlot = -1;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef _INCLUDED_C_ASW_DUMMY_VEHICLE_H
|
||||
#define _INCLUDED_C_ASW_DUMMY_VEHICLE_H
|
||||
|
||||
#include "iasw_client_vehicle.h"
|
||||
|
||||
class C_ASW_Dummy_Vehicle : public C_BaseAnimating, public IASW_Client_Vehicle
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Dummy_Vehicle, C_BaseAnimating );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Dummy_Vehicle();
|
||||
virtual ~C_ASW_Dummy_Vehicle();
|
||||
|
||||
bool MarineInVehicle();
|
||||
|
||||
// implement our asw vehicle interface
|
||||
virtual int ASWGetNumPassengers() { return 0; } // todo: implement
|
||||
virtual C_ASW_Marine* ASWGetDriver();
|
||||
virtual C_ASW_Marine* ASWGetPassenger(int i) { return NULL; } // todo: implement
|
||||
CNetworkHandle(C_ASW_Marine, m_hDriver);
|
||||
// implement client vehicle interface
|
||||
virtual bool ValidUseTarget() { return true; }
|
||||
virtual int GetDriveIconTexture();
|
||||
virtual int GetRideIconTexture();
|
||||
virtual const char* GetDriveIconText();
|
||||
virtual const char* GetRideIconText();
|
||||
virtual C_BaseEntity* GetEntity() { return this; }
|
||||
static bool s_bLoadedRideIconTexture;
|
||||
static int s_nRideIconTextureID;
|
||||
static bool s_bLoadedDriveIconTexture;
|
||||
static int s_nDriveIconTextureID;
|
||||
// no clientside prediction with this kind of vehicle
|
||||
virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) { }
|
||||
virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { }
|
||||
virtual void ASWStartEngine() { }
|
||||
virtual void ASWStopEngine() { }
|
||||
|
||||
virtual bool ShouldDraw();
|
||||
virtual ShadowType_t ShadowCastType();
|
||||
virtual void ClientThink();
|
||||
|
||||
virtual bool IsUsable(C_BaseEntity *pUser);
|
||||
virtual bool GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser);
|
||||
virtual void CustomPaint(int ix, int iy, int alpha, vgui::Panel *pUseIcon) { }
|
||||
virtual bool ShouldPaintBoxAround() { return (ASWGetDriver() == NULL); }
|
||||
|
||||
private:
|
||||
C_ASW_Dummy_Vehicle( const C_ASW_Dummy_Vehicle & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif /* _INCLUDED_C_ASW_DUMMY_VEHICLE_H */
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "cbase.h"
|
||||
#include "dlight.h"
|
||||
#include "iefx.h"
|
||||
#include "IViewRender.h"
|
||||
#include "c_asw_dynamic_light.h"
|
||||
#include "asw_shareddefs.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_DynamicLight, DT_ASW_Dynamic_Light, CASW_Dynamic_Light)
|
||||
RecvPropInt (RECVINFO(m_Flags)),
|
||||
RecvPropInt (RECVINFO(m_LightStyle)),
|
||||
RecvPropFloat (RECVINFO(m_Radius)),
|
||||
RecvPropInt (RECVINFO(m_Exponent)),
|
||||
RecvPropFloat (RECVINFO(m_InnerAngle)),
|
||||
RecvPropFloat (RECVINFO(m_OuterAngle)),
|
||||
RecvPropFloat (RECVINFO(m_SpotRadius)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_DynamicLight::C_ASW_DynamicLight(void) : m_pSpotlightEnd(0)
|
||||
{
|
||||
m_pDynamicLight = NULL;
|
||||
}
|
||||
|
||||
C_ASW_DynamicLight::~C_ASW_DynamicLight()
|
||||
{
|
||||
if (m_pDynamicLight)
|
||||
{
|
||||
m_pDynamicLight->die = gpGlobals->curtime;
|
||||
m_pDynamicLight = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_DynamicLight::OnDataChanged(DataUpdateType_t updateType)
|
||||
{
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink(gpGlobals->curtime + 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
bool C_ASW_DynamicLight::ShouldDraw()
|
||||
{
|
||||
//return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void C_ASW_DynamicLight::ClientThink(void)
|
||||
{
|
||||
Vector forward;
|
||||
AngleVectors( GetAbsAngles(), &forward );
|
||||
|
||||
if ( (m_Flags & DLIGHT_NO_MODEL_ILLUMINATION) == 0 )
|
||||
{
|
||||
if (!m_pDynamicLight || m_pDynamicLight->key != ASW_LIGHT_INDEX_FIRES + index)
|
||||
{
|
||||
m_pDynamicLight = effects->CL_AllocDlight( ASW_LIGHT_INDEX_FIRES + index );
|
||||
}
|
||||
m_pDynamicLight->color.b = GetRenderColorB();
|
||||
m_pDynamicLight->color.g = GetRenderColorG();
|
||||
m_pDynamicLight->color.r = GetRenderColorR();
|
||||
|
||||
m_pDynamicLight->origin = GetAbsOrigin();
|
||||
m_pDynamicLight->radius = m_Radius;
|
||||
m_pDynamicLight->color.exponent = m_Exponent;
|
||||
|
||||
m_pDynamicLight->die = gpGlobals->curtime + 30.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// In this case, the m_Flags could have changed; which is how we turn the light off
|
||||
if (m_pDynamicLight)
|
||||
{
|
||||
m_pDynamicLight->die = gpGlobals->curtime;
|
||||
m_pDynamicLight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SetNextClientThink(gpGlobals->curtime + 0.001);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef _INCLUDED_C_ASW_DYNAMIC_LIGHT_H
|
||||
#define _INCLUDED_C_ASW_DYNAMIC_LIGHT_H
|
||||
|
||||
class C_ASW_DynamicLight : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_DynamicLight, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_DynamicLight();
|
||||
virtual ~C_ASW_DynamicLight();
|
||||
|
||||
public:
|
||||
void OnDataChanged(DataUpdateType_t updateType);
|
||||
bool ShouldDraw();
|
||||
void ClientThink( void );
|
||||
|
||||
unsigned char m_Flags;
|
||||
unsigned char m_LightStyle;
|
||||
|
||||
float m_Radius;
|
||||
int m_Exponent;
|
||||
float m_InnerAngle;
|
||||
float m_OuterAngle;
|
||||
float m_SpotRadius;
|
||||
|
||||
private:
|
||||
dlight_t* m_pDynamicLight;
|
||||
dlight_t* m_pSpotlightEnd;
|
||||
};
|
||||
|
||||
#endif // _INCLUDED_C_ASW_DYNAMIC_LIGHT_H
|
||||
@@ -0,0 +1,190 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_egg.h"
|
||||
#include "baseparticleentity.h"
|
||||
#include "c_asw_generic_emitter_entity.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "functionproxy.h"
|
||||
#include "asw_fx_shared.h"
|
||||
#include "takedamageinfo.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Egg, DT_ASW_Egg, CASW_Egg)
|
||||
RecvPropBool( RECVINFO( m_bOnFire ) ),
|
||||
RecvPropFloat( RECVINFO( m_fEggAwake ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
|
||||
C_ASW_Egg::C_ASW_Egg()
|
||||
: m_GlowObject( this )
|
||||
{
|
||||
m_bClientOnFire = false;
|
||||
m_pBurningEffect = NULL;
|
||||
m_fEggAwake = 0;
|
||||
|
||||
m_GlowObject.SetColor( Vector( 0.3f, 0.6f, 0.1f ) );
|
||||
m_GlowObject.SetAlpha( 0.55f );
|
||||
m_GlowObject.SetRenderFlags( false, false );
|
||||
m_GlowObject.SetFullBloomRender( true );
|
||||
}
|
||||
|
||||
C_ASW_Egg::~C_ASW_Egg()
|
||||
{
|
||||
m_bClientOnFire = false;
|
||||
UpdateFireEmitters();
|
||||
}
|
||||
|
||||
void C_ASW_Egg::UpdateOnRemove()
|
||||
{
|
||||
BaseClass::UpdateOnRemove();
|
||||
m_bOnFire = false;
|
||||
UpdateFireEmitters();
|
||||
}
|
||||
|
||||
void C_ASW_Egg::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
BaseClass::OnDataChanged( type );
|
||||
UpdateFireEmitters();
|
||||
|
||||
if ( type == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// We want to think every frame.
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Egg::UpdateFireEmitters()
|
||||
{
|
||||
bool bOnFire = (m_bOnFire && !IsEffectActive(EF_NODRAW));
|
||||
if (bOnFire != m_bClientOnFire)
|
||||
{
|
||||
m_bClientOnFire = bOnFire;
|
||||
if (m_bClientOnFire)
|
||||
{
|
||||
if ( !m_pBurningEffect )
|
||||
{
|
||||
m_pBurningEffect = UTIL_ASW_CreateFireEffect( this );
|
||||
}
|
||||
EmitSound( "ASWFire.BurningFlesh" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_pBurningEffect )
|
||||
{
|
||||
ParticleProp()->StopEmission( m_pBurningEffect );
|
||||
m_pBurningEffect = NULL;
|
||||
}
|
||||
StopSound("ASWFire.BurningFlesh");
|
||||
if ( C_BaseEntity::IsAbsQueriesValid() )
|
||||
EmitSound("ASWFire.StopBurning");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Egg::ClientThink()
|
||||
{
|
||||
BaseClass::ClientThink();
|
||||
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if ( pPlayer && pPlayer->IsSniperScopeActive() )
|
||||
{
|
||||
m_GlowObject.SetRenderFlags( true, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_GlowObject.SetRenderFlags( false, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Material proxy for egg line glow
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// sinePeriod: time that it takes to go through whole sine wave in seconds (default: 1.0f)
|
||||
// sineMax : the max value for the sine wave (default: 1.0f )
|
||||
// sineMin: the min value for the sine wave (default: 0.0f )
|
||||
class CASW_Egg_Proxy : public CResultProxy
|
||||
{
|
||||
public:
|
||||
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
|
||||
virtual void OnBind( void *pC_BaseEntity );
|
||||
|
||||
private:
|
||||
CFloatInput m_SinePeriod;
|
||||
CFloatInput m_SineMax;
|
||||
CFloatInput m_SineMin;
|
||||
CFloatInput m_SineTimeOffset;
|
||||
};
|
||||
|
||||
|
||||
bool CASW_Egg_Proxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
|
||||
{
|
||||
if (!CResultProxy::Init( pMaterial, pKeyValues ))
|
||||
return false;
|
||||
|
||||
if (!m_SinePeriod.Init( pMaterial, pKeyValues, "sinePeriod", 1.0f ))
|
||||
return false;
|
||||
if (!m_SineMax.Init( pMaterial, pKeyValues, "sineMax", 1.0f ))
|
||||
return false;
|
||||
if (!m_SineMin.Init( pMaterial, pKeyValues, "sineMin", 0.0f ))
|
||||
return false;
|
||||
if (!m_SineTimeOffset.Init( pMaterial, pKeyValues, "timeOffset", 0.0f ))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CASW_Egg_Proxy::OnBind( void *pC_BaseEntity )
|
||||
{
|
||||
Assert( m_pResult );
|
||||
|
||||
C_ASW_Egg *pEgg = static_cast<C_ASW_Egg*>( BindArgToEntity( pC_BaseEntity ) );
|
||||
|
||||
float flValue;
|
||||
float flSineTimeOffset = m_SineTimeOffset.GetFloat();
|
||||
float flSineMax = m_SineMax.GetFloat();
|
||||
float flSineMin = m_SineMin.GetFloat();
|
||||
float flSinePeriod = m_SinePeriod.GetFloat();
|
||||
if (flSinePeriod == 0)
|
||||
flSinePeriod = 1;
|
||||
|
||||
// get a value in [0,1]
|
||||
flValue = ( sin( 2.0f * M_PI * (gpGlobals->curtime - flSineTimeOffset) / flSinePeriod ) * 0.5f ) + 0.5f;
|
||||
// get a value in [min,max]
|
||||
flValue = ( flSineMax - flSineMin ) * flValue + flSineMin;
|
||||
|
||||
flValue *= pEgg->m_fEggAwake;
|
||||
|
||||
SetFloatResult( flValue );
|
||||
}
|
||||
|
||||
EXPOSE_INTERFACE( CASW_Egg_Proxy, IMaterialProxy, "EggAwakeSine" IMATERIAL_PROXY_INTERFACE_VERSION );
|
||||
|
||||
void C_ASW_Egg::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr )
|
||||
{
|
||||
CTakeDamageInfo subInfo = info;
|
||||
|
||||
Assert( m_nForceBone > -255 && m_nForceBone < 256 );
|
||||
|
||||
if ( subInfo.GetDamage() >= 1.0 && !(subInfo.GetDamageType() & DMG_SHOCK )
|
||||
&& !( subInfo.GetDamageType() & DMG_BURN ) )
|
||||
{
|
||||
Bleed( subInfo, ptr->endpos, vecDir, ptr );
|
||||
}
|
||||
|
||||
if( !info.GetInflictor() )
|
||||
{
|
||||
subInfo.SetInflictor( info.GetAttacker() );
|
||||
}
|
||||
|
||||
AddMultiDamage( subInfo, this );
|
||||
UTIL_ASW_ClientFloatingDamageNumber( subInfo );
|
||||
}
|
||||
|
||||
void C_ASW_Egg::Bleed( const CTakeDamageInfo &info, const Vector &vecPos, const Vector &vecDir, trace_t *ptr )
|
||||
{
|
||||
UTIL_ASW_DroneBleed( vecPos, -vecDir, 4 );
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef _INCLUDED_C_ASW_EGG_H
|
||||
#define _INCLUDED_C_ASW_EGG_H
|
||||
|
||||
#include "iasw_client_aim_target.h"
|
||||
#include "asw_shareddefs.h"
|
||||
#include "glow_outline_effect.h"
|
||||
|
||||
class CNewParticleEffect;
|
||||
|
||||
class C_ASW_Egg : public C_BaseFlex, public IASW_Client_Aim_Target
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Egg, C_BaseFlex );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Egg();
|
||||
virtual ~C_ASW_Egg();
|
||||
|
||||
// aim target interface
|
||||
IMPLEMENT_AUTO_LIST_GET();
|
||||
virtual float GetRadius() { return 20; }
|
||||
virtual bool IsAimTarget() { return true; }
|
||||
virtual const Vector& GetAimTargetPos(const Vector &vecFiringSrc, bool bWeaponPrefersFlatAiming) { return WorldSpaceCenter(); }
|
||||
virtual const Vector& GetAimTargetRadiusPos(const Vector &vecFiringSrc) { return WorldSpaceCenter(); }
|
||||
|
||||
virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr );
|
||||
virtual void Bleed( const CTakeDamageInfo &info, const Vector &vecPos, const Vector &vecDir, trace_t *ptr );
|
||||
|
||||
Class_T Classify( void ) { return (Class_T) CLASS_ASW_EGG; }
|
||||
virtual void OnDataChanged( DataUpdateType_t type );
|
||||
virtual void UpdateFireEmitters();
|
||||
virtual void UpdateOnRemove();
|
||||
virtual void ClientThink();
|
||||
|
||||
CGlowObject m_GlowObject;
|
||||
bool m_bClientOnFire;
|
||||
CNetworkVar(bool, m_bOnFire);
|
||||
CNewParticleEffect *m_pBurningEffect;
|
||||
float m_fEggAwake; // controls green lines on the outside
|
||||
|
||||
private:
|
||||
C_ASW_Egg( const C_ASW_Egg & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif // _INCLUDED_C_ASW_EGG_H
|
||||
@@ -0,0 +1,765 @@
|
||||
#include "cbase.h"
|
||||
|
||||
#include "IViewRender.h"
|
||||
#include "view.h"
|
||||
#include "studio.h"
|
||||
#include "bone_setup.h"
|
||||
#include "model_types.h"
|
||||
#include "beamdraw.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
#include "iviewrender_beams.h"
|
||||
#include "fx.h"
|
||||
#include "IEffects.h"
|
||||
#include "C_ASW_Entity_Dissolve.h"
|
||||
#include "movevars_shared.h"
|
||||
#include "precache_register.h"
|
||||
#include "asw_fx_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// ASW - Custom version of the entity dissolve effect, used by alien goo when it fades out (doesn't have sparks, etc.)
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Entity_Dissolve, DT_ASW_Entity_Dissolve, CASW_Entity_Dissolve )
|
||||
RecvPropTime(RECVINFO(m_flStartTime)),
|
||||
RecvPropFloat(RECVINFO(m_flFadeOutStart)),
|
||||
RecvPropFloat(RECVINFO(m_flFadeOutLength)),
|
||||
RecvPropFloat(RECVINFO(m_flFadeOutModelStart)),
|
||||
RecvPropFloat(RECVINFO(m_flFadeOutModelLength)),
|
||||
RecvPropFloat(RECVINFO(m_flFadeInStart)),
|
||||
RecvPropFloat(RECVINFO(m_flFadeInLength)),
|
||||
RecvPropInt(RECVINFO(m_nDissolveType)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
C_ASW_Entity_Dissolve::C_ASW_Entity_Dissolve( void )
|
||||
{
|
||||
m_bLinkedToServerEnt = true;
|
||||
m_pController = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Entity_Dissolve::GetRenderBounds( Vector& theMins, Vector& theMaxs )
|
||||
{
|
||||
if ( GetMoveParent() )
|
||||
{
|
||||
GetMoveParent()->GetRenderBounds( theMins, theMaxs );
|
||||
}
|
||||
else
|
||||
{
|
||||
theMins = GetAbsOrigin();
|
||||
theMaxs = theMaxs;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// On data changed
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Entity_Dissolve::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
m_flNextSparkTime = m_flStartTime;
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Cleanup
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Entity_Dissolve::UpdateOnRemove( void )
|
||||
{
|
||||
if ( m_pController )
|
||||
{
|
||||
physenv->DestroyMotionController( m_pController );
|
||||
m_pController = NULL;
|
||||
}
|
||||
|
||||
BaseClass::UpdateOnRemove();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Apply the forces to the entity
|
||||
//------------------------------------------------------------------------------
|
||||
IMotionEvent::simresult_e C_ASW_Entity_Dissolve::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular )
|
||||
{
|
||||
linear.Init();
|
||||
angular.Init();
|
||||
|
||||
// Make it zero g
|
||||
linear.z -= -1.02 * sv_gravity.GetFloat();
|
||||
|
||||
Vector vel;
|
||||
AngularImpulse angVel;
|
||||
pObject->GetVelocity( &vel, &angVel );
|
||||
vel += linear * deltaTime; // account for gravity scale
|
||||
|
||||
Vector unitVel = vel;
|
||||
Vector unitAngVel = angVel;
|
||||
|
||||
float speed = VectorNormalize( unitVel );
|
||||
float flLinearLimit = 50;
|
||||
float flLinearLimitDelta = 40;
|
||||
if ( speed > flLinearLimit )
|
||||
{
|
||||
float flDeltaVel = (flLinearLimit - speed) / deltaTime;
|
||||
if ( flLinearLimitDelta != 0.0f )
|
||||
{
|
||||
float flMaxDeltaVel = -flLinearLimitDelta / deltaTime;
|
||||
if ( flDeltaVel < flMaxDeltaVel )
|
||||
{
|
||||
flDeltaVel = flMaxDeltaVel;
|
||||
}
|
||||
}
|
||||
VectorMA( linear, flDeltaVel, unitVel, linear );
|
||||
}
|
||||
|
||||
return SIM_GLOBAL_ACCELERATION;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tesla effect
|
||||
//-----------------------------------------------------------------------------
|
||||
static void FX_BuildTesla( C_BaseEntity *pEntity, Vector &vecOrigin, Vector &vecEnd )
|
||||
{
|
||||
BeamInfo_t beamInfo;
|
||||
beamInfo.m_pStartEnt = pEntity;
|
||||
beamInfo.m_nStartAttachment = 0;
|
||||
beamInfo.m_pEndEnt = NULL;
|
||||
beamInfo.m_nEndAttachment = 0;
|
||||
beamInfo.m_nType = TE_BEAMTESLA;
|
||||
beamInfo.m_vecStart = vecOrigin;
|
||||
beamInfo.m_vecEnd = vecEnd;
|
||||
beamInfo.m_pszModelName = "sprites/lgtning.vmt";
|
||||
beamInfo.m_flHaloScale = 0.0;
|
||||
beamInfo.m_flLife = random->RandomFloat( 0.25f, 1.0f );
|
||||
beamInfo.m_flWidth = random->RandomFloat( 8.0f, 14.0f );
|
||||
beamInfo.m_flEndWidth = 1.0f;
|
||||
beamInfo.m_flFadeLength = 0.5f;
|
||||
beamInfo.m_flAmplitude = 24;
|
||||
beamInfo.m_flBrightness = 255.0;
|
||||
beamInfo.m_flSpeed = 150.0f;
|
||||
beamInfo.m_nStartFrame = 0.0;
|
||||
beamInfo.m_flFrameRate = 30.0;
|
||||
beamInfo.m_flRed = 255.0;
|
||||
beamInfo.m_flGreen = 255.0;
|
||||
beamInfo.m_flBlue = 255.0;
|
||||
beamInfo.m_nSegments = 18;
|
||||
beamInfo.m_bRenderable = true;
|
||||
beamInfo.m_nFlags = 0; //FBEAM_ONLYNOISEONCE;
|
||||
|
||||
beams->CreateBeamEntPoint( beamInfo );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Tesla effect
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Entity_Dissolve::BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset )
|
||||
{
|
||||
Vector vecOrigin;
|
||||
QAngle vecAngles;
|
||||
MatrixGetColumn( hitboxToWorld, 3, vecOrigin );
|
||||
MatrixAngles( hitboxToWorld, vecAngles.Base() );
|
||||
C_BaseEntity *pEntity = GetMoveParent();
|
||||
|
||||
// Make a couple of tries at it
|
||||
int iTries = -1;
|
||||
Vector vecForward;
|
||||
trace_t tr;
|
||||
do
|
||||
{
|
||||
iTries++;
|
||||
|
||||
// Some beams are deliberatly aimed around the point, the rest are random.
|
||||
if ( !bRandom )
|
||||
{
|
||||
QAngle vecTemp = vecAngles;
|
||||
vecTemp[YAW] += flYawOffset;
|
||||
AngleVectors( vecTemp, &vecForward );
|
||||
|
||||
// Randomly angle it up or down
|
||||
vecForward.z = RandomFloat( -1, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
vecForward = RandomVector( -1, 1 );
|
||||
}
|
||||
|
||||
UTIL_TraceLine( vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr );
|
||||
} while ( tr.fraction >= 1.0 && iTries < 3 );
|
||||
|
||||
Vector vecEnd = tr.endpos - (vecForward * 8);
|
||||
|
||||
// Only spark & glow if we hit something
|
||||
if ( tr.fraction < 1.0 )
|
||||
{
|
||||
if ( !EffectOccluded( tr.endpos ) )
|
||||
{
|
||||
ASSERT_LOCAL_PLAYER_RESOLVABLE();
|
||||
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
|
||||
|
||||
// Move it towards the camera
|
||||
Vector vecFlash = tr.endpos;
|
||||
Vector vecForward;
|
||||
AngleVectors( MainViewAngles(nSlot), &vecForward );
|
||||
vecFlash -= (vecForward * 8);
|
||||
|
||||
g_pEffects->EnergySplash( vecFlash, -vecForward, false );
|
||||
|
||||
// End glow
|
||||
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" );
|
||||
pSimple->SetSortOrigin( vecFlash );
|
||||
SimpleParticle *pParticle;
|
||||
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/blood" ), vecFlash ); // "effects/tesla_glow_noz"
|
||||
if ( pParticle != NULL )
|
||||
{
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
pParticle->m_flDieTime = RandomFloat( 0.5, 1 );
|
||||
pParticle->m_vecVelocity = vec3_origin;
|
||||
Vector color( 1,1,1 );
|
||||
float colorRamp = RandomFloat( 0.75f, 1.25f );
|
||||
pParticle->m_uchColor[0] = 0; //MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
|
||||
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
|
||||
pParticle->m_uchColor[2] = 0; //MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
|
||||
pParticle->m_uchStartSize = RandomFloat( 6,13 );
|
||||
pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2;
|
||||
pParticle->m_uchStartAlpha = 255;
|
||||
pParticle->m_uchEndAlpha = 10;
|
||||
pParticle->m_flRoll = RandomFloat( 0,360 );
|
||||
pParticle->m_flRollDelta = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the tesla
|
||||
FX_BuildTesla( pEntity, vecOrigin, tr.endpos );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sorts the components of a vector
|
||||
//-----------------------------------------------------------------------------
|
||||
static inline void SortAbsVectorComponents( const Vector& src, int* pVecIdx )
|
||||
{
|
||||
Vector absVec( fabs(src[0]), fabs(src[1]), fabs(src[2]) );
|
||||
|
||||
int maxIdx = (absVec[0] > absVec[1]) ? 0 : 1;
|
||||
if (absVec[2] > absVec[maxIdx])
|
||||
{
|
||||
maxIdx = 2;
|
||||
}
|
||||
|
||||
// always choose something right-handed....
|
||||
switch( maxIdx )
|
||||
{
|
||||
case 0:
|
||||
pVecIdx[0] = 1;
|
||||
pVecIdx[1] = 2;
|
||||
pVecIdx[2] = 0;
|
||||
break;
|
||||
case 1:
|
||||
pVecIdx[0] = 2;
|
||||
pVecIdx[1] = 0;
|
||||
pVecIdx[2] = 1;
|
||||
break;
|
||||
case 2:
|
||||
pVecIdx[0] = 0;
|
||||
pVecIdx[1] = 1;
|
||||
pVecIdx[2] = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compute the bounding box's center, size, and basis
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Entity_Dissolve::ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
|
||||
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec )
|
||||
{
|
||||
// Compute the center of the hitbox in worldspace
|
||||
Vector vecHitboxCenter;
|
||||
VectorAdd( pHitBox->bbmin, pHitBox->bbmax, vecHitboxCenter );
|
||||
vecHitboxCenter *= 0.5f;
|
||||
VectorTransform( vecHitboxCenter, hitboxToWorld, *pVecAbsOrigin );
|
||||
|
||||
// Get the object's basis
|
||||
Vector vec[3];
|
||||
MatrixGetColumn( hitboxToWorld, 0, vec[0] );
|
||||
MatrixGetColumn( hitboxToWorld, 1, vec[1] );
|
||||
MatrixGetColumn( hitboxToWorld, 2, vec[2] );
|
||||
// vec[1] *= -1.0f;
|
||||
|
||||
Vector vecViewDir;
|
||||
VectorSubtract( CurrentViewOrigin(), *pVecAbsOrigin, vecViewDir );
|
||||
VectorNormalize( vecViewDir );
|
||||
|
||||
// Project the shadow casting direction into the space of the hitbox
|
||||
Vector localViewDir;
|
||||
localViewDir[0] = DotProduct( vec[0], vecViewDir );
|
||||
localViewDir[1] = DotProduct( vec[1], vecViewDir );
|
||||
localViewDir[2] = DotProduct( vec[2], vecViewDir );
|
||||
|
||||
// Figure out which vector has the largest component perpendicular
|
||||
// to the view direction...
|
||||
// Sort by how perpendicular it is
|
||||
int vecIdx[3];
|
||||
SortAbsVectorComponents( localViewDir, vecIdx );
|
||||
|
||||
// Here's our hitbox basis vectors; namely the ones that are
|
||||
// most perpendicular to the view direction
|
||||
*pXVec = vec[vecIdx[0]];
|
||||
*pYVec = vec[vecIdx[1]];
|
||||
|
||||
// Project them into a plane perpendicular to the view direction
|
||||
*pXVec -= vecViewDir * DotProduct( vecViewDir, *pXVec );
|
||||
*pYVec -= vecViewDir * DotProduct( vecViewDir, *pYVec );
|
||||
VectorNormalize( *pXVec );
|
||||
VectorNormalize( *pYVec );
|
||||
|
||||
// Compute the hitbox size
|
||||
Vector boxSize;
|
||||
VectorSubtract( pHitBox->bbmax, pHitBox->bbmin, boxSize );
|
||||
|
||||
// We project the two longest sides into the vectors perpendicular
|
||||
// to the projection direction, then add in the projection of the perp direction
|
||||
Vector2D size( boxSize[vecIdx[0]], boxSize[vecIdx[1]] );
|
||||
size.x *= fabs( DotProduct( vec[vecIdx[0]], *pXVec ) );
|
||||
size.y *= fabs( DotProduct( vec[vecIdx[1]], *pYVec ) );
|
||||
|
||||
// Add the third component into x and y
|
||||
size.x += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pXVec ) );
|
||||
size.y += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pYVec ) );
|
||||
|
||||
// Bloat a bit, since the shadow wants to extend outside the model a bit
|
||||
size *= 2.0f;
|
||||
|
||||
// Clamp the minimum size
|
||||
Vector2DMax( size, Vector2D(10.0f, 10.0f), size );
|
||||
|
||||
// Factor the size into the xvec + yvec
|
||||
(*pXVec) *= size.x * 0.5f;
|
||||
(*pYVec) *= size.y * 0.5f;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sparks!
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Entity_Dissolve::DoSparks( mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES] )
|
||||
{
|
||||
if ( m_flNextSparkTime > gpGlobals->curtime )
|
||||
return;
|
||||
|
||||
float dt = m_flStartTime + m_flFadeOutStart - gpGlobals->curtime;
|
||||
dt = clamp( dt, 0.0f, m_flFadeOutStart );
|
||||
|
||||
float flNextTime;
|
||||
if (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL)
|
||||
{
|
||||
flNextTime = SimpleSplineRemapVal( dt, 0.0f, m_flFadeOutStart, 2.0f * TICK_INTERVAL, 0.4f );
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT);
|
||||
flNextTime = SimpleSplineRemapVal( dt, 0.0f, m_flFadeOutStart, 0.3f, 1.0f );
|
||||
}
|
||||
|
||||
m_flNextSparkTime = gpGlobals->curtime + flNextTime;
|
||||
|
||||
// Send out beams around us
|
||||
int iNumBeamsAround = 2;
|
||||
int iNumRandomBeams = 1;
|
||||
int iTotalBeams = iNumBeamsAround + iNumRandomBeams;
|
||||
float flYawOffset = RandomFloat(0,360);
|
||||
for ( int i = 0; i < iTotalBeams; i++ )
|
||||
{
|
||||
int nHitbox = random->RandomInt( 0, set->numhitboxes - 1 );
|
||||
mstudiobbox_t *pBox = set->pHitbox(nHitbox);
|
||||
|
||||
float flActualYawOffset = 0;
|
||||
bool bRandom = ( i >= iNumBeamsAround );
|
||||
if ( !bRandom )
|
||||
{
|
||||
flActualYawOffset = anglemod( flYawOffset + ((360 / iTotalBeams) * i) );
|
||||
}
|
||||
|
||||
BuildTeslaEffect( pBox, *hitboxbones[pBox->bone], bRandom, flActualYawOffset );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Entity_Dissolve::SetupEmitter( void )
|
||||
{
|
||||
if ( !m_pEmitter )
|
||||
{
|
||||
m_pEmitter = CSimpleEmitter::Create( "C_ASW_Entity_Dissolve" );
|
||||
m_pEmitter->SetSortOrigin( GetAbsOrigin() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float C_ASW_Entity_Dissolve::GetFadeInPercentage( void )
|
||||
{
|
||||
float dt = gpGlobals->curtime - m_flStartTime;
|
||||
|
||||
if ( dt > m_flFadeOutStart )
|
||||
return 1.0f;
|
||||
|
||||
if ( dt < m_flFadeInStart )
|
||||
return 0.0f;
|
||||
|
||||
if ( (dt > m_flFadeInStart) && (dt < m_flFadeInStart + m_flFadeInLength) )
|
||||
{
|
||||
dt -= m_flFadeInStart;
|
||||
|
||||
return ( dt / m_flFadeInLength );
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float C_ASW_Entity_Dissolve::GetFadeOutPercentage( void )
|
||||
{
|
||||
float dt = gpGlobals->curtime - m_flStartTime;
|
||||
|
||||
if ( dt < m_flFadeInStart )
|
||||
return 1.0f;
|
||||
|
||||
if ( dt > m_flFadeOutStart )
|
||||
{
|
||||
dt -= m_flFadeOutStart;
|
||||
|
||||
if ( dt > m_flFadeOutLength )
|
||||
return 0.0f;
|
||||
|
||||
return 1.0f - ( dt / m_flFadeOutLength );
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float C_ASW_Entity_Dissolve::GetModelFadeOutPercentage( void )
|
||||
{
|
||||
float dt = gpGlobals->curtime - m_flStartTime;
|
||||
|
||||
if ( dt < m_flFadeOutModelStart )
|
||||
return 1.0f;
|
||||
|
||||
if ( dt > m_flFadeOutModelStart )
|
||||
{
|
||||
dt -= m_flFadeOutModelStart;
|
||||
|
||||
if ( dt > m_flFadeOutModelLength )
|
||||
return 0.0f;
|
||||
|
||||
return 1.0f - ( dt / m_flFadeOutModelLength );
|
||||
}
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Entity_Dissolve::ClientThink( void )
|
||||
{
|
||||
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
|
||||
if (!pAnimating)
|
||||
return;
|
||||
|
||||
// NOTE: IsRagdoll means *client-side* ragdoll. We shouldn't be trying to fight
|
||||
// the server ragdoll (or any server physics) on the client
|
||||
if (( !m_pController ) && ( m_nDissolveType == ENTITY_DISSOLVE_NORMAL ) && pAnimating->IsRagdoll())
|
||||
{
|
||||
IPhysicsObject *ppList[32];
|
||||
int nCount = pAnimating->VPhysicsGetObjectList( ppList, 32 );
|
||||
if ( nCount > 0 )
|
||||
{
|
||||
m_pController = physenv->CreateMotionController( this );
|
||||
for ( int i = 0; i < nCount; ++i )
|
||||
{
|
||||
m_pController->AttachObject( ppList[i], true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
color32 color;
|
||||
|
||||
color.r = color.g = color.b = ( 1.0f - GetFadeInPercentage() ) * 255.0f;
|
||||
color.a = GetModelFadeOutPercentage() * 255.0f;
|
||||
|
||||
// Setup the entity fade
|
||||
pAnimating->SetRenderMode( kRenderTransColor );
|
||||
pAnimating->SetRenderColor( color.r, color.g, color.b );
|
||||
pAnimating->SetRenderAlpha( color.a );
|
||||
|
||||
// If we're dead, fade out
|
||||
if ( GetFadeOutPercentage() <= 0.0f )
|
||||
{
|
||||
// spawn some splurts
|
||||
//BloodSpurts();
|
||||
|
||||
ClientThinkList()->RemoveThinkable( GetClientHandle() );
|
||||
|
||||
// Do NOT remove from the client entity list. It'll confuse the local network backdoor, and the entity will never get destroyed
|
||||
// because when the server says to destroy it, the client won't be able to find it.
|
||||
// ClientEntityList().RemoveEntity( GetClientHandle() );
|
||||
|
||||
partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() );
|
||||
|
||||
RemoveFromLeafSystem();
|
||||
|
||||
//FIXME: Ick!
|
||||
//Adrian: I'll assume we don't need the ragdoll either so I'll remove that too.
|
||||
if ( m_bLinkedToServerEnt == false )
|
||||
{
|
||||
Release();
|
||||
|
||||
C_ClientRagdoll *pRagdoll = dynamic_cast <C_ClientRagdoll *> ( pAnimating );
|
||||
|
||||
if ( pRagdoll )
|
||||
{
|
||||
pRagdoll->ReleaseRagdoll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int C_ASW_Entity_Dissolve::DrawModel( int flags )
|
||||
{
|
||||
if ( gpGlobals->frametime == 0 )
|
||||
return 0;
|
||||
|
||||
// See if we should draw
|
||||
if ( m_bReadyToDraw == false )
|
||||
return 0;
|
||||
|
||||
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
|
||||
if (!pAnimating)
|
||||
return 0;
|
||||
|
||||
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
|
||||
if ( !pAnimating->HitboxToWorldTransforms( hitboxbones ) )
|
||||
return 0;
|
||||
|
||||
studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
|
||||
if (!pStudioHdr)
|
||||
return false;
|
||||
|
||||
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
|
||||
if ( !set )
|
||||
return false;
|
||||
|
||||
SetupEmitter();
|
||||
|
||||
int i;
|
||||
|
||||
float fadeInPerc = GetFadeInPercentage();
|
||||
float fadeOutPerc = GetFadeOutPercentage();
|
||||
|
||||
float fadePerc = ( fadeInPerc >= 1.0f ) ? fadeOutPerc : fadeInPerc;
|
||||
|
||||
Vector vecSkew = vec3_origin;
|
||||
|
||||
if ( ( fadePerc < 0.99f ) && ( (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) )
|
||||
{
|
||||
DoSparks( set, hitboxbones );
|
||||
}
|
||||
|
||||
fadePerc = GetModelFadeOutPercentage();
|
||||
|
||||
// Skew the particles in front or in back of their targets
|
||||
vecSkew = CurrentViewForward() * ( 8.0f - ( ( 1.0f - fadePerc ) * 32.0f ) );
|
||||
|
||||
float spriteScale = ( ( gpGlobals->curtime - m_flStartTime ) / m_flFadeOutLength );
|
||||
spriteScale = clamp( spriteScale, 0.75f, 1.0f );
|
||||
|
||||
SimpleParticle *sParticle;
|
||||
|
||||
for ( i = 0; i < set->numhitboxes; ++i )
|
||||
{
|
||||
Vector vecAbsOrigin, xvec, yvec;
|
||||
mstudiobbox_t *pBox = set->pHitbox(i);
|
||||
ComputeRenderInfo( pBox, *hitboxbones[pBox->bone], &vecAbsOrigin, &xvec, &yvec );
|
||||
|
||||
Vector offset;
|
||||
Vector xDir, yDir;
|
||||
|
||||
xDir = xvec;
|
||||
float xScale = VectorNormalize( xDir ) * 0.75f;
|
||||
|
||||
yDir = yvec;
|
||||
float yScale = VectorNormalize( yDir ) * 0.75f;
|
||||
|
||||
int numParticles = clamp( 3.0f * fadePerc, 0, 3 );
|
||||
|
||||
// smoke
|
||||
for ( int j = 0; j < 4; j++ ) // was 2
|
||||
{
|
||||
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
|
||||
offset += vecSkew;
|
||||
|
||||
if ( random->RandomInt( 0, 2 ) != 0 )
|
||||
continue;
|
||||
|
||||
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "swarm/sprites/smoke" ), vecAbsOrigin + offset ); //"effects/spark"
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return 1;
|
||||
|
||||
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( 16.0f, 64.0f ) );
|
||||
|
||||
if ( sParticle->m_vecVelocity.z > 0 )
|
||||
{
|
||||
sParticle->m_uchStartSize = random->RandomFloat( 4, 6 ) * spriteScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
sParticle->m_uchStartSize = 2 * spriteScale;
|
||||
}
|
||||
|
||||
sParticle->m_flDieTime = random->RandomFloat( 0.4f, 0.5f );
|
||||
|
||||
// If we're the last particles, last longer
|
||||
if ( numParticles == 0 )
|
||||
{
|
||||
sParticle->m_flDieTime *= 2.0f;
|
||||
sParticle->m_uchStartSize = 2 * spriteScale * 2;
|
||||
sParticle->m_flRollDelta = 0; //Helper_RandomFloat( -4.0f, 4.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
sParticle->m_flRollDelta = 0; //Helper_RandomFloat( -8.0f, 8.0f );
|
||||
}
|
||||
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
|
||||
float alpha = 255;
|
||||
|
||||
sParticle->m_uchColor[0] = alpha*(108.0f/255.0f);
|
||||
sParticle->m_uchColor[1] = alpha*(88.0f/255.0f);
|
||||
sParticle->m_uchColor[2] = alpha*(83.0f/255.0f);
|
||||
sParticle->m_uchStartAlpha = alpha;
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchEndSize = sParticle->m_uchStartSize * 2.0f;
|
||||
}
|
||||
|
||||
// big shrinking soft sparkles
|
||||
/*
|
||||
for ( int j = 0; j < numParticles; j++ )
|
||||
{
|
||||
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
|
||||
offset += vecSkew;
|
||||
|
||||
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( "effects/combinemuzzle2" ), vecAbsOrigin + offset ); //
|
||||
//sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_pEmitter->GetPMaterial( VarArgs("sprites/flamelet%d", Helper_RandomInt( 1, 5 ) ) ), vecAbsOrigin + offset );
|
||||
|
||||
if ( sParticle == NULL )
|
||||
return 1;
|
||||
|
||||
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -64.0f, 128.0f ) );
|
||||
sParticle->m_uchStartSize = random->RandomFloat( 8, 12 ) * spriteScale;
|
||||
sParticle->m_flDieTime = 0.1f;
|
||||
sParticle->m_flLifetime = 0.0f;
|
||||
|
||||
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
|
||||
sParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f );
|
||||
|
||||
float alpha = 255;
|
||||
|
||||
sParticle->m_uchColor[0] = 0;//alpha;
|
||||
sParticle->m_uchColor[1] = alpha;
|
||||
sParticle->m_uchColor[2] = 0;//alpha;
|
||||
sParticle->m_uchStartAlpha = alpha;
|
||||
sParticle->m_uchEndAlpha = 0;
|
||||
sParticle->m_uchEndSize = 0;
|
||||
}*/
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void C_ASW_Entity_Dissolve::BloodSpurts()
|
||||
{
|
||||
/*
|
||||
Vector vecSkew = vec3_origin;
|
||||
|
||||
// Skew the particles in front or in back of their targets
|
||||
//vecSkew = CurrentViewForward() * ( 8.0f - ( ( 0.5f ) * 32.0f ) );
|
||||
|
||||
float spriteScale = ( ( gpGlobals->curtime - m_flStartTime ) / m_flFadeOutLength );
|
||||
spriteScale = clamp( spriteScale, 0.75f, 1.0f );
|
||||
|
||||
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
|
||||
if (!pAnimating)
|
||||
return;
|
||||
|
||||
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
|
||||
if ( !pAnimating->HitboxToWorldTransforms( hitboxbones ) )
|
||||
return;
|
||||
|
||||
|
||||
studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
|
||||
if (!pStudioHdr)
|
||||
return;
|
||||
|
||||
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
|
||||
if ( !set )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < set->numhitboxes; ++i )
|
||||
{
|
||||
Vector vecAbsOrigin, xvec, yvec;
|
||||
mstudiobbox_t *pBox = set->pHitbox(i);
|
||||
ComputeRenderInfo( pBox, *hitboxbones[pBox->bone], &vecAbsOrigin, &xvec, &yvec );
|
||||
|
||||
Vector offset;
|
||||
Vector xDir, yDir;
|
||||
|
||||
xDir = xvec;
|
||||
float xScale = VectorNormalize( xDir ) * 0.75f;
|
||||
|
||||
yDir = yvec;
|
||||
float yScale = VectorNormalize( yDir ) * 0.75f;
|
||||
|
||||
//int numParticles = clamp( 3.0f * 0.5f, 0, 3 );
|
||||
|
||||
// blood in each hitbox
|
||||
for ( int j = 0; j < 4; j++ ) // was 2
|
||||
{
|
||||
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
|
||||
//offset += vecSkew;
|
||||
|
||||
if ( random->RandomInt( 0, 2 ) != 0 )
|
||||
continue;
|
||||
|
||||
}
|
||||
}*/
|
||||
UTIL_ASW_BloodDrips( WorldSpaceCenter(), Vector(0,0,1), BLOOD_COLOR_BRIGHTGREEN, 4 );
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef _INCLUDED_C_ASW_ENTITY_DISSOLVE_H
|
||||
#define _INCLUDED_C_ASW_ENTITY_DISSOLVE_H
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ASW - Custom version of the entity dissolve effect, used by alien goo when it fades out (doesn't have sparks, etc.)
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_ASW_Entity_Dissolve : public C_BaseEntity, public IMotionEvent
|
||||
{
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_CLASS( C_ASW_Entity_Dissolve, C_BaseEntity );
|
||||
|
||||
C_ASW_Entity_Dissolve( void );
|
||||
|
||||
// Inherited from C_BaseEntity
|
||||
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
|
||||
virtual int DrawModel( int flags );
|
||||
virtual bool ShouldDraw() { return true; }
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void UpdateOnRemove( void );
|
||||
|
||||
virtual void BloodSpurts();
|
||||
|
||||
// Inherited from IMotionEvent
|
||||
virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular );
|
||||
|
||||
void SetupEmitter( void );
|
||||
|
||||
void ClientThink( void );
|
||||
|
||||
void SetServerLinkState( bool state ) { m_bLinkedToServerEnt = state; }
|
||||
|
||||
float m_flStartTime;
|
||||
float m_flFadeOutStart;
|
||||
float m_flFadeOutLength;
|
||||
float m_flFadeOutModelStart;
|
||||
float m_flFadeOutModelLength;
|
||||
float m_flFadeInStart;
|
||||
float m_flFadeInLength;
|
||||
int m_nDissolveType;
|
||||
float m_flNextSparkTime;
|
||||
|
||||
protected:
|
||||
|
||||
float GetFadeInPercentage( void ); // Fade in amount (entity fading to black)
|
||||
float GetFadeOutPercentage( void ); // Fade out amount (particles fading away)
|
||||
float GetModelFadeOutPercentage( void );// Mode fade out amount
|
||||
|
||||
// Compute the bounding box's center, size, and basis
|
||||
void ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
|
||||
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec );
|
||||
void BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset );
|
||||
|
||||
void DoSparks( mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES] );
|
||||
|
||||
private:
|
||||
|
||||
CSmartPtr<CSimpleEmitter> m_pEmitter;
|
||||
|
||||
bool m_bLinkedToServerEnt;
|
||||
IPhysicsMotionController *m_pController;
|
||||
};
|
||||
|
||||
#endif // _INCLUDED_C_ASW_ENTITY_DISSOLVE_H
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_extinguisher_projectile.h"
|
||||
#include "iefx.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Extinguisher_Projectile, DT_ASW_Extinguisher_Projectile, CASW_Extinguisher_Projectile)
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_ASW_Extinguisher_Projectile )
|
||||
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
|
||||
C_ASW_Extinguisher_Projectile::C_ASW_Extinguisher_Projectile()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Extinguisher_Projectile::~C_ASW_Extinguisher_Projectile()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef C_ASW_EXTINGUISHER_PROJECTILE_H
|
||||
#define C_ASW_EXTINGUISHER_PROJECTILE_H
|
||||
|
||||
#include "c_basecombatcharacter.h"
|
||||
|
||||
|
||||
class C_ASW_Extinguisher_Projectile : public C_BaseCombatCharacter
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Extinguisher_Projectile, C_BaseCombatCharacter );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
C_ASW_Extinguisher_Projectile();
|
||||
virtual ~C_ASW_Extinguisher_Projectile();
|
||||
|
||||
private:
|
||||
C_ASW_Extinguisher_Projectile( const C_ASW_Extinguisher_Projectile & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif /* C_ASW_EXTINGUISHER_PROJECTILE_H */
|
||||
@@ -0,0 +1,161 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
//---------------------------------------------------------
|
||||
//---------------------------------------------------------
|
||||
#include "cbase.h"
|
||||
#include "c_asw_fire.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
|
||||
//==================================================
|
||||
// C_Fire
|
||||
//==================================================
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_Fire, DT_ASW_Fire, CFire )
|
||||
RecvPropInt( RECVINFO( m_nFireType ) ),
|
||||
RecvPropFloat( RECVINFO( m_flFireSize ) ),
|
||||
RecvPropFloat( RECVINFO( m_flHeatLevel ) ),
|
||||
RecvPropFloat( RECVINFO( m_flMaxHeat ) ),
|
||||
RecvPropBool( RECVINFO( m_bEnabled ) ),
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
|
||||
//==================================================
|
||||
// C_Fire
|
||||
//==================================================
|
||||
|
||||
C_Fire::C_Fire()
|
||||
{
|
||||
m_nFireType = 0;
|
||||
m_flFireSize = 0.1f;
|
||||
m_flHeatLevel = 0;
|
||||
m_flMaxHeat = 64;
|
||||
m_bEnabled = false;
|
||||
}
|
||||
|
||||
|
||||
C_Fire::~C_Fire()
|
||||
{
|
||||
if ( m_hFire )
|
||||
{
|
||||
m_hFire->StopEmission(false, false , true);
|
||||
m_hFire = NULL;
|
||||
}
|
||||
|
||||
if ( m_hFireTop )
|
||||
{
|
||||
m_hFireTop->StopEmission(false, false , true);
|
||||
m_hFireTop = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void C_Fire::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
CreateFireParticles();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_flHeatLevel > 0 && m_bEnabled && !m_hFire )
|
||||
{
|
||||
CreateFireParticles();
|
||||
}
|
||||
}
|
||||
|
||||
void C_Fire::CreateFireParticles()
|
||||
{
|
||||
if ( !m_bEnabled )
|
||||
return;
|
||||
|
||||
if ( m_nFireType == 1 )
|
||||
m_hFire = ParticleProp()->Create( "mine_fire", PATTACH_ABSORIGIN_FOLLOW );
|
||||
else
|
||||
{
|
||||
if ( m_flFireSize < 24 )
|
||||
{
|
||||
m_hFire = ParticleProp()->Create( "ground_fire_small", PATTACH_ABSORIGIN_FOLLOW );
|
||||
m_hFireTop = ParticleProp()->Create( "ground_fire_small_top", PATTACH_ABSORIGIN_FOLLOW );
|
||||
}
|
||||
else if ( m_flFireSize < 92 )
|
||||
{
|
||||
m_hFire = ParticleProp()->Create( "ground_fire", PATTACH_ABSORIGIN_FOLLOW );
|
||||
m_hFireTop = ParticleProp()->Create( "ground_fire_top", PATTACH_ABSORIGIN_FOLLOW );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hFire = ParticleProp()->Create( "ground_fire_large", PATTACH_ABSORIGIN_FOLLOW );
|
||||
m_hFireTop = ParticleProp()->Create( "ground_fire_large_top", PATTACH_ABSORIGIN_FOLLOW );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( m_hFire )
|
||||
{
|
||||
UpdateFireParticles();
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning("Failed to create a fire emitter\n");
|
||||
}
|
||||
}
|
||||
|
||||
void C_Fire::UpdateFireParticles()
|
||||
{
|
||||
if ( m_hFire )
|
||||
{
|
||||
//m_hFire->SetSortOrigin( GetAbsOrigin() );
|
||||
m_hFire->SetControlPoint( 0, GetAbsOrigin() );
|
||||
Vector vecForward, vecRight, vecUp;
|
||||
AngleVectors( GetAbsAngles(), &vecForward, &vecRight, &vecUp );
|
||||
m_hFire->SetControlPointOrientation( 0, vecForward, vecRight, vecUp );
|
||||
|
||||
float flSize = 1.0f;
|
||||
if ( m_flFireSize < 24 )
|
||||
flSize = m_flFireSize / 12;
|
||||
else if ( m_flFireSize < 92 )
|
||||
flSize = m_flFireSize / 42;
|
||||
else
|
||||
flSize = MAX( m_flFireSize / 128, 0.25);
|
||||
|
||||
float strength = (m_flHeatLevel / m_flMaxHeat) * MAX( flSize, 0.1);
|
||||
m_hFire->SetControlPoint( 1, Vector( strength, strength, 0 ) );
|
||||
m_hFire->SetControlPoint( 5, Vector( flSize, flSize, flSize ) );
|
||||
|
||||
if ( m_nFireType != 1 && m_hFireTop )
|
||||
{
|
||||
m_hFireTop->SetControlPoint( 0, GetAbsOrigin() );
|
||||
m_hFireTop->SetControlPoint( 1, Vector( strength, strength, 0 ) );
|
||||
m_hFireTop->SetControlPoint( 5, Vector( flSize, flSize, flSize ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_Fire::ClientThink()
|
||||
{
|
||||
BaseClass::ClientThink();
|
||||
|
||||
UpdateFireParticles();
|
||||
|
||||
if ( (m_flHeatLevel <= 0 || !m_bEnabled) && m_hFire )
|
||||
{
|
||||
m_hFire->StopEmission(false, false , true);
|
||||
m_hFire = NULL;
|
||||
|
||||
if ( m_nFireType != 1 && m_hFireTop )
|
||||
{
|
||||
m_hFireTop->StopEmission(false, false , true);
|
||||
m_hFireTop = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef C_ASW_FIRE_H
|
||||
#define C_ASW_FIRE_H
|
||||
|
||||
//#include "entityoutput.h"
|
||||
//#include "fire_smoke.h"
|
||||
//#include "plasma.h"
|
||||
#include "c_baseentity.h"
|
||||
|
||||
|
||||
//==================================================
|
||||
|
||||
class C_Fire : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_Fire, CBaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_Fire();
|
||||
virtual ~C_Fire();
|
||||
|
||||
virtual void ClientThink();
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void CreateFireParticles();
|
||||
void UpdateFireParticles();
|
||||
CUtlReference<CNewParticleEffect> m_hFire;
|
||||
CUtlReference<CNewParticleEffect> m_hFireTop;
|
||||
int m_nFireType;
|
||||
float m_flFireSize;
|
||||
float m_flHeatLevel;
|
||||
float m_flMaxHeat;
|
||||
bool m_bEnabled;
|
||||
};
|
||||
|
||||
#endif // C_ASW_FIRE_H
|
||||
@@ -0,0 +1,67 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_firewall_piece.h"
|
||||
#include "c_asw_generic_emitter.h"
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Firewall_Piece, DT_ASW_Firewall_Piece, CASW_Firewall_Piece)
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_ASW_Firewall_Piece )
|
||||
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
|
||||
|
||||
C_ASW_Firewall_Piece::C_ASW_Firewall_Piece()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Firewall_Piece::~C_ASW_Firewall_Piece()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void C_ASW_Firewall_Piece::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// NOTE: Removed this - instead firewall pieces use FireSystem_StartFire on the server,
|
||||
// which creates normal fires with their own emitters
|
||||
//CreateFireEmitter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Firewall_Piece::CreateFireEmitter()
|
||||
{
|
||||
m_hFireEmitter = CASWGenericEmitter::Create( "asw_emitter" );
|
||||
|
||||
if ( m_hFireEmitter.IsValid() )
|
||||
{
|
||||
m_hFireEmitter->UseTemplate("incendiary");
|
||||
m_hFireEmitter->SetActive(true);
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning("Failed to create a firewall's fire emitter\n");
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Firewall_Piece::ClientThink()
|
||||
{
|
||||
BaseClass::ClientThink();
|
||||
if ( m_hFireEmitter.IsValid() )
|
||||
{
|
||||
m_hFireEmitter->Think(gpGlobals->frametime, GetAbsOrigin(), GetAbsAngles());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef _DEFINED_C_ASW_FIREWALL_PIECE_H
|
||||
#define _DEFINED_C_ASW_FIREWALL_PIECE_H
|
||||
|
||||
class CASWGenericEmitter;
|
||||
|
||||
class C_ASW_Firewall_Piece : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Firewall_Piece, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
C_ASW_Firewall_Piece();
|
||||
virtual ~C_ASW_Firewall_Piece();
|
||||
|
||||
virtual void ClientThink();
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void CreateFireEmitter();
|
||||
CSmartPtr<CASWGenericEmitter> m_hFireEmitter;
|
||||
|
||||
private:
|
||||
C_ASW_Firewall_Piece( const C_ASW_Firewall_Piece & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_FIREWALL_PIECE_H */
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_flamer_projectile.h"
|
||||
#include "dlight.h"
|
||||
#include "iefx.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Flamer_Projectile, DT_ASW_Flamer_Projectile, CASW_Flamer_Projectile)
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_ASW_Flamer_Projectile )
|
||||
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
ConVar asw_flamer_light_scale("asw_flamer_light_scale", "0.7f", FCVAR_CHEAT, "Alters the size of the flamer dynamic light");
|
||||
ConVar asw_flamer_light_r("asw_flamer_light_r", "255", FCVAR_CHEAT, "Alters the colour of the flamer dynamic light");
|
||||
ConVar asw_flamer_light_g("asw_flamer_light_g", "192", FCVAR_CHEAT, "Alters the colour of the flamer dynamic light");
|
||||
ConVar asw_flamer_light_b("asw_flamer_light_b", "160", FCVAR_CHEAT, "Alters the colour of the flamer dynamic light");
|
||||
ConVar asw_flamer_light_exponent("asw_flamer_light_exponent", "5", FCVAR_CHEAT, "Alters the flamer dynamic light");
|
||||
|
||||
C_ASW_Flamer_Projectile::C_ASW_Flamer_Projectile()
|
||||
{
|
||||
m_pDynamicLight = 0;
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Flamer_Projectile::~C_ASW_Flamer_Projectile()
|
||||
{
|
||||
if (m_pDynamicLight)
|
||||
{
|
||||
m_pDynamicLight->die = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Flamer_Projectile::CreateLight()
|
||||
{
|
||||
m_pDynamicLight = effects->CL_AllocDlight( index );
|
||||
m_pDynamicLight->origin = GetAbsOrigin();
|
||||
m_pDynamicLight->radius = 61.6 * asw_flamer_light_scale.GetFloat();
|
||||
m_pDynamicLight->decay = 0 / 0.05f;
|
||||
m_pDynamicLight->die = gpGlobals->curtime + 1.0f;
|
||||
m_pDynamicLight->color.r = asw_flamer_light_r.GetFloat();
|
||||
m_pDynamicLight->color.g = asw_flamer_light_g.GetFloat();
|
||||
m_pDynamicLight->color.b = asw_flamer_light_b.GetFloat();
|
||||
m_pDynamicLight->color.exponent = asw_flamer_light_exponent.GetInt();
|
||||
}
|
||||
|
||||
void C_ASW_Flamer_Projectile::ClientThink(void)
|
||||
{
|
||||
if (m_pDynamicLight)
|
||||
{
|
||||
m_pDynamicLight->radius += 78.4f * gpGlobals->frametime * asw_flamer_light_scale.GetFloat(); // was 140 from radius 0
|
||||
m_pDynamicLight->origin = GetAbsOrigin();
|
||||
float f = m_pDynamicLight->die - gpGlobals->curtime;
|
||||
if (f < 0.0f)
|
||||
f = 0.0f;
|
||||
if (f > 1.0f)
|
||||
f = 1.0f;
|
||||
m_pDynamicLight->color.r = asw_flamer_light_r.GetFloat() * f;
|
||||
m_pDynamicLight->color.g = asw_flamer_light_g.GetFloat() * f;
|
||||
m_pDynamicLight->color.b = asw_flamer_light_b.GetFloat() * f;
|
||||
}
|
||||
|
||||
SetNextClientThink(CLIENT_THINK_ALWAYS);//gpGlobals->curtime + 0.001
|
||||
}
|
||||
|
||||
void C_ASW_Flamer_Projectile::OnDataChanged(DataUpdateType_t updateType)
|
||||
{
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
CreateLight();
|
||||
SetNextClientThink(CLIENT_THINK_ALWAYS);
|
||||
}
|
||||
BaseClass::OnDataChanged(updateType);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef C_ASW_FLAMER_PROJECTILE_H
|
||||
#define C_ASW_FLAMER_PROJECTILE_H
|
||||
|
||||
#include "c_basecombatcharacter.h"
|
||||
#include "asw_shareddefs.h"
|
||||
|
||||
struct dlight_t;
|
||||
|
||||
class C_ASW_Flamer_Projectile : public C_BaseCombatCharacter
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Flamer_Projectile, C_BaseCombatCharacter );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
C_ASW_Flamer_Projectile();
|
||||
virtual ~C_ASW_Flamer_Projectile();
|
||||
void ClientThink(void);
|
||||
void OnDataChanged(DataUpdateType_t updateType);
|
||||
void CreateLight();
|
||||
dlight_t* m_pDynamicLight;
|
||||
|
||||
// Classification
|
||||
virtual Class_T Classify( void ) { return (Class_T)CLASS_ASW_FLAMER_PROJECTILE; }
|
||||
|
||||
private:
|
||||
C_ASW_Flamer_Projectile( const C_ASW_Flamer_Projectile & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif /* C_ASW_FLAMER_PROJECTILE_H */
|
||||
@@ -0,0 +1,251 @@
|
||||
#include "cbase.h"
|
||||
#include "precache_register.h"
|
||||
#include "particles_simple.h"
|
||||
#include "iefx.h"
|
||||
#include "dlight.h"
|
||||
#include "view.h"
|
||||
#include "fx.h"
|
||||
#include "clientsideeffects.h"
|
||||
#include "c_pixel_visibility.h"
|
||||
#include "c_asw_flare_projectile.h"
|
||||
#include "soundenvelope.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//Precahce the effects
|
||||
PRECACHE_REGISTER_BEGIN( GLOBAL, ASWPrecacheEffectFlares )
|
||||
PRECACHE_REGISTER_END()
|
||||
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Flare_Projectile, DT_ASW_Flare_Projectile, CASW_Flare_Projectile )
|
||||
RecvPropFloat( RECVINFO( m_flTimeBurnOut ) ),
|
||||
RecvPropFloat( RECVINFO( m_flScale ) ),
|
||||
RecvPropInt( RECVINFO( m_bLight ) ),
|
||||
RecvPropInt( RECVINFO( m_bSmoke ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
// flares maintain a linked list of themselves, for quick checking for autoaim
|
||||
C_ASW_Flare_Projectile* g_pHeadFlare = NULL;
|
||||
|
||||
ConVar asw_flare_r("asw_flare_r", "240", 0, "Colour of flares");
|
||||
ConVar asw_flare_g("asw_flare_g", "255", 0, "Colour of flares");
|
||||
ConVar asw_flare_b("asw_flare_b", "200", 0, "Colour of flares");
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
C_ASW_Flare_Projectile::C_ASW_Flare_Projectile()
|
||||
{
|
||||
m_flTimeBurnOut = 0.0f;
|
||||
m_pDLight = NULL;
|
||||
|
||||
m_bLight = true;
|
||||
m_bSmoke = true;
|
||||
|
||||
//SetDynamicallyAllocated( false );
|
||||
m_queryHandle = 0;
|
||||
m_fStartLightTime = 0;
|
||||
m_fLightRadius = 0;
|
||||
|
||||
m_pFlareEffect = NULL;
|
||||
|
||||
// keep a linked list of flares (used for autoaim)
|
||||
if (g_pHeadFlare)
|
||||
{
|
||||
m_pNextFlare = g_pHeadFlare;
|
||||
g_pHeadFlare = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pHeadFlare = this;
|
||||
m_pNextFlare = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
C_ASW_Flare_Projectile::~C_ASW_Flare_Projectile( void )
|
||||
{
|
||||
// remove ourselves from the linked list of flares
|
||||
if (g_pHeadFlare == this)
|
||||
{
|
||||
g_pHeadFlare = m_pNextFlare;
|
||||
}
|
||||
else
|
||||
{
|
||||
C_ASW_Flare_Projectile* pFlare = g_pHeadFlare;
|
||||
int k=0;
|
||||
while (pFlare != this && pFlare != NULL && k < 256) // some paranoid checks (should always break out of the while anyway)
|
||||
{
|
||||
k++;
|
||||
if (pFlare->m_pNextFlare == this)
|
||||
{
|
||||
pFlare->m_pNextFlare = m_pNextFlare; // pulled ourselves out of the list
|
||||
break;
|
||||
}
|
||||
pFlare = pFlare->m_pNextFlare;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_pDLight)
|
||||
{
|
||||
m_pDLight->die = gpGlobals->curtime;
|
||||
m_pDLight = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : state -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Flare_Projectile::NotifyShouldTransmit( ShouldTransmitState_t state )
|
||||
{
|
||||
if ( state == SHOULDTRANSMIT_END )
|
||||
{
|
||||
AddEffects( EF_NODRAW );
|
||||
}
|
||||
else if ( state == SHOULDTRANSMIT_START )
|
||||
{
|
||||
RemoveEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
BaseClass::NotifyShouldTransmit( state );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : bool -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Flare_Projectile::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
SetNextClientThink(gpGlobals->curtime);
|
||||
//SetSortOrigin( GetAbsOrigin() );
|
||||
SoundInit();
|
||||
}
|
||||
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
}
|
||||
|
||||
const Vector& C_ASW_Flare_Projectile::GetEffectOrigin()
|
||||
{
|
||||
static Vector s_vecEffectPos;
|
||||
Vector forward, right, up;
|
||||
AngleVectors(GetAbsAngles(), &forward, &right, &up);
|
||||
s_vecEffectPos = GetAbsOrigin() + up * 5;
|
||||
return s_vecEffectPos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : timeDelta -
|
||||
//-----------------------------------------------------------------------------
|
||||
//void C_ASW_Flare_Projectile::Update( float timeDelta )
|
||||
void C_ASW_Flare_Projectile::ClientThink( void )
|
||||
{
|
||||
if ( m_pFlareEffect.GetObject() == NULL )
|
||||
{
|
||||
//m_flTimePulse = gpGlobals->curtime + asw_buffgrenade_pulse_interval.GetFloat();
|
||||
|
||||
m_pFlareEffect = ParticleProp()->Create( "flare_fx_main", PATTACH_ABSORIGIN_FOLLOW, -1, GetEffectOrigin() - GetAbsOrigin() );
|
||||
//flare_fx_main
|
||||
}
|
||||
|
||||
float baseScale = m_flScale;
|
||||
|
||||
//Account for fading out
|
||||
if ( ( m_flTimeBurnOut != -1.0f ) && ( ( m_flTimeBurnOut - gpGlobals->curtime ) <= 10.0f ) )
|
||||
{
|
||||
baseScale *= ( ( m_flTimeBurnOut - gpGlobals->curtime ) / 10.0f );
|
||||
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pBurnSound, clamp<float>(0.6f * baseScale, 0.0f, 0.6f), 0 );
|
||||
}
|
||||
|
||||
if ( baseScale < 0.01f )
|
||||
return;
|
||||
//
|
||||
// Dynamic light
|
||||
//
|
||||
|
||||
if ( m_bLight )
|
||||
{
|
||||
if (m_fStartLightTime == 0)
|
||||
{
|
||||
m_fStartLightTime = gpGlobals->curtime;
|
||||
}
|
||||
if (!m_pDLight)
|
||||
{
|
||||
m_pDLight = effects->CL_AllocDlight( index );
|
||||
m_pDLight->color.r = asw_flare_r.GetInt();
|
||||
m_pDLight->color.g = asw_flare_g.GetInt();
|
||||
m_pDLight->color.b = asw_flare_b.GetInt();
|
||||
m_pDLight->color.exponent = 3;
|
||||
}
|
||||
|
||||
m_pDLight->origin = GetAbsOrigin() + Vector(0, 0, 5); // make the dlight slightly higher than the flare, so it doesn't bury the light being so close to the ground
|
||||
|
||||
float flTimeLeft = MAX( 2.0, m_flTimeBurnOut - gpGlobals->curtime );
|
||||
if (m_fLightRadius < 8.0f)
|
||||
{
|
||||
m_fLightRadius += flTimeLeft * (1.0f + random->RandomFloat() * 36.0f);
|
||||
if (m_fLightRadius > 8.0f)
|
||||
m_fLightRadius = 8.0f;
|
||||
}
|
||||
m_pDLight->radius = MAX( 64.0, baseScale * 120 * (m_fLightRadius/8.0f) );
|
||||
|
||||
if ( ( m_flTimeBurnOut != -1.0f ) && ( ( m_flTimeBurnOut - gpGlobals->curtime ) <= 4.0f ) )
|
||||
{
|
||||
// flicker as we're going out
|
||||
//m_pDLight->die = gpGlobals->curtime;
|
||||
//m_pDLight = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pDLight->die = gpGlobals->curtime + 30.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fStartLightTime = 0;
|
||||
}
|
||||
|
||||
SetNextClientThink(gpGlobals->curtime + 0.1f);
|
||||
}
|
||||
|
||||
void C_ASW_Flare_Projectile::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
SoundInit();
|
||||
}
|
||||
|
||||
void C_ASW_Flare_Projectile::UpdateOnRemove()
|
||||
{
|
||||
BaseClass::UpdateOnRemove();
|
||||
SoundShutdown();
|
||||
}
|
||||
|
||||
void C_ASW_Flare_Projectile::SoundInit()
|
||||
{
|
||||
// play flare start sound!!
|
||||
CPASAttenuationFilter filter( this );
|
||||
|
||||
EmitSound("ASW_Flare.IgniteFlare");
|
||||
|
||||
// Bring up the flare burning loop sound
|
||||
if( !m_pBurnSound )
|
||||
{
|
||||
m_pBurnSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "ASW_Flare.FlareLoop" );
|
||||
CSoundEnvelopeController::GetController().Play( m_pBurnSound, 0.0, 100 );
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pBurnSound, 0.6, 2.0 );
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Flare_Projectile::SoundShutdown()
|
||||
{
|
||||
if ( m_pBurnSound )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_pBurnSound );
|
||||
m_pBurnSound = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef _INCLUDED_C_ASW_FLARE_PROJECTILE_H
|
||||
#define _INCLUDED_C_ASW_FLARE_PROJECTILE_H
|
||||
#pragma once
|
||||
|
||||
struct dlight_t;
|
||||
|
||||
#include "c_pixel_visibility.h"
|
||||
|
||||
class C_ASW_Flare_Projectile : public C_BaseCombatCharacter
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Flare_Projectile, C_BaseCombatCharacter );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Flare_Projectile();
|
||||
virtual ~C_ASW_Flare_Projectile();
|
||||
|
||||
virtual Class_T Classify() { return CLASS_FLARE; }
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
//void Update( float timeDelta );
|
||||
virtual void ClientThink( void );
|
||||
void NotifyShouldTransmit( ShouldTransmitState_t state );
|
||||
const Vector& GetEffectOrigin();
|
||||
|
||||
float m_flTimeBurnOut;
|
||||
float m_flScale;
|
||||
bool m_bLight;
|
||||
dlight_t *m_pDLight;
|
||||
float m_fStartLightTime;
|
||||
float m_fLightRadius;
|
||||
bool m_bSmoke;
|
||||
pixelvis_handle_t m_queryHandle;
|
||||
|
||||
// sound
|
||||
void SoundShutdown();
|
||||
void SoundInit();
|
||||
virtual void UpdateOnRemove();
|
||||
virtual void OnRestore();
|
||||
CSoundPatch *m_pBurnSound;
|
||||
|
||||
|
||||
private:
|
||||
C_ASW_Flare_Projectile( const C_ASW_Flare_Projectile & );
|
||||
|
||||
CUtlReference<CNewParticleEffect> m_pFlareEffect;
|
||||
|
||||
public:
|
||||
C_ASW_Flare_Projectile* m_pNextFlare; // next flare in the linked list of live flares
|
||||
};
|
||||
|
||||
extern C_ASW_Flare_Projectile* g_pHeadFlare; // access to a linked list of live flares
|
||||
|
||||
#endif // _INCLUDED_C_ASW_FLARE_PROJECTILE_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,220 @@
|
||||
// Clientside version of the vehicle physics
|
||||
|
||||
#ifndef C_ASW_FOUR_WHEEL_VEHICLE_PHYSICS_H
|
||||
#define C_ASW_FOUR_WHEEL_VEHICLE_PHYSICS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "vphysics/vehicles.h"
|
||||
#include "vcollide_parse.h"
|
||||
#include "datamap.h"
|
||||
//#include "vehicle_sounds.h"
|
||||
|
||||
// in/sec to miles/hour
|
||||
#define INS2MPH_SCALE ( 3600 * (1/5280.0f) * (1/12.0f) )
|
||||
#define INS2MPH(x) ( (x) * INS2MPH_SCALE )
|
||||
#define MPH2INS(x) ( (x) * (1/INS2MPH_SCALE) )
|
||||
|
||||
class C_BaseAnimating;
|
||||
//class CFourWheelServerVehicle; // asw comment
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class C_ASW_FourWheelVehiclePhysics
|
||||
{
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
|
||||
C_ASW_FourWheelVehiclePhysics( C_BaseAnimating *pOuter );
|
||||
virtual ~C_ASW_FourWheelVehiclePhysics ();
|
||||
|
||||
// Call Precache + Spawn from the containing entity's Precache + Spawn methods
|
||||
void Spawn();
|
||||
//void SetOuter( C_BaseAnimating *pOuter, CFourWheelServerVehicle *pServerVehicle ); // asw comment
|
||||
void SetOuter( C_BaseAnimating *pOuter );
|
||||
|
||||
// Initializes the vehicle physics so we can drive it
|
||||
bool Initialize( const char *pScriptName, unsigned int nVehicleType );
|
||||
|
||||
void Teleport( matrix3x4_t& relativeTransform );
|
||||
bool VPhysicsUpdate( IPhysicsObject *pPhysics );
|
||||
bool Think(float fTime);
|
||||
void PlaceWheelDust( int wheelIndex, bool ignoreSpeed = false );
|
||||
|
||||
void DrawDebugGeometryOverlays();
|
||||
int DrawDebugTextOverlays( int nOffset );
|
||||
|
||||
// Updates the controls based on user input
|
||||
void UpdateDriverControls( CUserCmd *cmd, float flFrameTime );
|
||||
|
||||
// Various steering parameters
|
||||
void SetThrottle( float flThrottle );
|
||||
void SetMaxThrottle( float flMaxThrottle );
|
||||
void SetMaxReverseThrottle( float flMaxThrottle );
|
||||
void SetSteering( float flSteering, float flSteeringRate );
|
||||
void SetSteeringDegrees( float flDegrees );
|
||||
void SetAction( float flAction );
|
||||
void TurnOn( );
|
||||
void TurnOff();
|
||||
void ReleaseHandbrake();
|
||||
void SetHandbrake( bool bBrake );
|
||||
bool IsOn() const { return m_bIsOn; }
|
||||
void ResetControls();
|
||||
void SetBoost( float flBoost );
|
||||
bool UpdateBooster( float flFrameTime );
|
||||
void SetHasBrakePedal( bool bHasBrakePedal );
|
||||
|
||||
// Engine
|
||||
void SetDisableEngine( bool bDisable );
|
||||
bool IsEngineDisabled( void ) { return m_pVehicle->IsEngineDisabled(); }
|
||||
|
||||
// Enable/Disable Motion
|
||||
void EnableMotion( void );
|
||||
void DisableMotion( void );
|
||||
|
||||
// Shared code to compute the vehicle view position
|
||||
void GetVehicleViewPosition( const char *pViewAttachment, float flPitchFactor, Vector *pAbsPosition, QAngle *pAbsAngles );
|
||||
|
||||
IPhysicsObject *GetWheel( int iWheel ) { return m_pWheels[iWheel]; }
|
||||
|
||||
int GetSpeed() const;
|
||||
int GetMaxSpeed() const;
|
||||
int GetRPM() const;
|
||||
float GetThrottle() const;
|
||||
bool HasBoost() const;
|
||||
int BoostTimeLeft() const;
|
||||
bool IsBoosting( void );
|
||||
float GetHLSpeed() const;
|
||||
float GetSteering() const;
|
||||
float GetSteeringDegrees() const;
|
||||
IPhysicsVehicleController* GetVehicle(void) { return m_pVehicle; }
|
||||
float GetWheelBaseHeight(int wheelIndex) { return m_wheelBaseHeight[wheelIndex]; }
|
||||
float GetWheelTotalHeight(int wheelIndex) { return m_wheelTotalHeight[wheelIndex]; }
|
||||
|
||||
const vehicleparams_t &GetVehicleParams( void ) { return m_pVehicle->GetVehicleParams(); }
|
||||
const vehicle_controlparams_t &GetVehicleControls( void ) { return m_controls; }
|
||||
|
||||
int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax );
|
||||
|
||||
void AddThrottleReduction( float flPercentage );
|
||||
void RemoveThrottleReduction( float flPercentage );
|
||||
|
||||
private:
|
||||
// engine sounds
|
||||
void CalcWheelData( vehicleparams_t &vehicle );
|
||||
|
||||
void SteeringRest( float carSpeed, const vehicleparams_t &vehicleData, float flFrameTime );
|
||||
void SteeringTurn( float carSpeed, const vehicleparams_t &vehicleData, bool bTurnLeft, float flFrameTime );
|
||||
void SteeringTurnAnalog( float carSpeed, const vehicleparams_t &vehicleData, float sidemove, float flFrameTime );
|
||||
|
||||
// A couple wrapper methods to perform common operations
|
||||
int LookupPoseParameter( const char *szName );
|
||||
float GetPoseParameter( int iParameter );
|
||||
float SetPoseParameter( int iParameter, float flValue );
|
||||
bool GetAttachment ( const char *szName, Vector &origin, QAngle &angles );
|
||||
|
||||
void InitializePoseParameters();
|
||||
bool ParseVehicleScript( const char *pScriptName, solid_t &solid, vehicleparams_t &vehicle );
|
||||
|
||||
private:
|
||||
// This is the entity that contains this class
|
||||
CHandle<C_BaseAnimating> m_pOuter;
|
||||
//CFourWheelServerVehicle *m_pOuterServerVehicle; // asw comment
|
||||
|
||||
vehicle_controlparams_t m_controls;
|
||||
IPhysicsVehicleController *m_pVehicle;
|
||||
|
||||
// Vehicle state info
|
||||
int m_nSpeed;
|
||||
int m_nLastSpeed;
|
||||
int m_nRPM;
|
||||
float m_fLastBoost;
|
||||
int m_nBoostTimeLeft;
|
||||
int m_nHasBoost;
|
||||
|
||||
float m_maxThrottle;
|
||||
float m_flMaxRevThrottle;
|
||||
float m_flThrottleReduction;
|
||||
float m_flMaxSpeed;
|
||||
float m_actionSpeed;
|
||||
IPhysicsObject *m_pWheels[4];
|
||||
|
||||
int m_wheelCount;
|
||||
|
||||
Vector m_wheelPosition[4];
|
||||
QAngle m_wheelRotation[4];
|
||||
float m_wheelBaseHeight[4];
|
||||
float m_wheelTotalHeight[4];
|
||||
int m_poseParameters[12];
|
||||
float m_actionValue;
|
||||
float m_actionScale;
|
||||
float m_debugRadius;
|
||||
float m_throttleRate;
|
||||
float m_throttleStartTime;
|
||||
float m_throttleActiveTime;
|
||||
float m_turboTimer;
|
||||
|
||||
float m_flVehicleVolume; // NPC driven vehicles used louder sounds
|
||||
bool m_bIsOn;
|
||||
bool m_bLastThrottle;
|
||||
bool m_bLastBoost;
|
||||
bool m_bLastSkid;
|
||||
|
||||
int m_nTurnLeftCount;
|
||||
int m_nTurnRightCount;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Physics state..
|
||||
//-----------------------------------------------------------------------------
|
||||
inline int C_ASW_FourWheelVehiclePhysics::GetSpeed() const
|
||||
{
|
||||
return m_nSpeed;
|
||||
}
|
||||
|
||||
inline int C_ASW_FourWheelVehiclePhysics::GetMaxSpeed() const
|
||||
{
|
||||
return INS2MPH(m_pVehicle->GetVehicleParams().engine.maxSpeed);
|
||||
}
|
||||
|
||||
inline int C_ASW_FourWheelVehiclePhysics::GetRPM() const
|
||||
{
|
||||
return m_nRPM;
|
||||
}
|
||||
|
||||
inline float C_ASW_FourWheelVehiclePhysics::GetThrottle() const
|
||||
{
|
||||
return m_controls.throttle;
|
||||
}
|
||||
|
||||
inline bool C_ASW_FourWheelVehiclePhysics::HasBoost() const
|
||||
{
|
||||
return m_nHasBoost != 0;
|
||||
}
|
||||
|
||||
inline int C_ASW_FourWheelVehiclePhysics::BoostTimeLeft() const
|
||||
{
|
||||
return m_nBoostTimeLeft;
|
||||
}
|
||||
|
||||
//inline void C_ASW_FourWheelVehiclePhysics::SetOuter( C_BaseAnimating *pOuter, CFourWheelServerVehicle *pServerVehicle ) // asw comment
|
||||
inline void C_ASW_FourWheelVehiclePhysics::SetOuter( C_BaseAnimating *pOuter )
|
||||
{
|
||||
m_pOuter = pOuter;
|
||||
// m_pOuterServerVehicle = pServerVehicle; // asw comment
|
||||
}
|
||||
|
||||
float RemapAngleRange( float startInterval, float endInterval, float value );
|
||||
|
||||
#define ROLL_CURVE_ZERO 5 // roll less than this is clamped to zero
|
||||
#define ROLL_CURVE_LINEAR 45 // roll greater than this is copied out
|
||||
|
||||
#define PITCH_CURVE_ZERO 10 // pitch less than this is clamped to zero
|
||||
#define PITCH_CURVE_LINEAR 45 // pitch greater than this is copied out
|
||||
|
||||
#endif // C_ASW_FOUR_WHEEL_VEHICLE_PHYSICS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
#ifndef _INCLUDED_C_ASW_FX_H
|
||||
#define _INCLUDED_C_ASW_FX_H
|
||||
|
||||
#include "c_gib.h"
|
||||
|
||||
class C_ASW_Marine;
|
||||
|
||||
// Optional tracer types
|
||||
enum ASW_FX_TracerType_t
|
||||
{
|
||||
ASW_FX_TRACER_DUAL_LEFT = 0x00000001, // fire from left dual attachment point
|
||||
ASW_FX_TRACER_DUAL_RIGHT = 0x00000002, // fire from right dual attachment point
|
||||
};
|
||||
|
||||
class CDroneGibManager : public CAutoGameSystem
|
||||
{
|
||||
public:
|
||||
// Methods of IGameSystem
|
||||
virtual void Update( float frametime );
|
||||
virtual void LevelInitPreEntity( void );
|
||||
|
||||
void AddGib( C_BaseEntity *pEntity );
|
||||
void RemoveGib( C_BaseEntity *pEntity );
|
||||
|
||||
private:
|
||||
typedef CHandle<C_BaseEntity> CGibHandle;
|
||||
CUtlLinkedList< CGibHandle > m_LRU;
|
||||
};
|
||||
|
||||
void ASW_FX_BloodBulletImpact( const Vector &origin, const Vector &normal, float scale, unsigned char r, unsigned char g, unsigned char b );
|
||||
void FX_DroneBleed( const Vector &origin, const Vector &direction, float scale );
|
||||
void FX_GibMeshEmitter( const char *szModel, const char *szTemplate, const Vector &origin, const Vector &direction, int skinm, float fScale=1.0f, bool bFrozen = false );
|
||||
void FX_GrubGib( const Vector &origin, const Vector &direction, float scale, bool bOnFire );
|
||||
void FX_DroneGib( const Vector &origin, const Vector &direction, float scale, int skin, bool bOnFire );
|
||||
void FX_HarvesterGib( const Vector &origin, const Vector &direction, float scale, int skin, bool bOnFire );
|
||||
void FX_ParasiteGib( const Vector &origin, const Vector &direction, float scale, int skin, bool bUseGibImpactSounds, bool bOnFire );
|
||||
void FX_EggGibs( const Vector &origin, int flags, int iEntIndex );
|
||||
void FX_QueenSpitBurst( const Vector &origin, const Vector &direction, float scale, int skin );
|
||||
|
||||
void FX_ProbeStunElectroBeam( CBaseEntity *pEntity, mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset );
|
||||
void FX_ElectroStun(C_BaseAnimating *pAnimating);
|
||||
void FX_ElectroStunSplash( const Vector &pos, const Vector &normal, int nFlags );
|
||||
void FX_QueenDie(C_BaseAnimating *pAnimating);
|
||||
|
||||
void FX_ASW_RGEffect(const Vector &vecStart, const Vector &vecEnd);
|
||||
void FX_ASWTracer( const Vector& start, const Vector& end, int velocity, bool makeWhiz, bool bRedTracer, int iForceStyle=-1 );
|
||||
// user message based tracers
|
||||
void ASWUTracer( C_ASW_Marine *pMarine, const Vector& vecEnd, int iAttributeEffects = 0 );
|
||||
void ASWUTracerless( C_ASW_Marine *pMarine, const Vector& vecEnd, int iAttributeEffects = 0 ); // just muzzle flash and impact, no tracer line
|
||||
void ASWUTracerDual( C_ASW_Marine *pMarine, const Vector& vecEnd, int nDualType = (ASW_FX_TRACER_DUAL_LEFT | ASW_FX_TRACER_DUAL_RIGHT), int iAttributeEffects = 0 );
|
||||
void ASWUTracerUnattached( C_ASW_Marine *pMarine, const Vector &vecStart, const Vector &vecEnd, int iAttributeEffects = 0 );
|
||||
void ASWUTracerRG( C_ASW_Marine *pMarine, const Vector& vecEnd, int iAttributeEffects = 0 );
|
||||
void FX_ASW_ShotgunSmoke( const Vector& vecOrigin, const QAngle& angFacing );
|
||||
void FX_ASW_MuzzleEffectAttached( float scale, ClientEntityHandle_t hEntity, int attachmentIndex, unsigned char *pFlashColor = NULL, bool bOneFrame = false );
|
||||
void FX_ASW_RedMuzzleEffectAttached( float scale, ClientEntityHandle_t hEntity, int attachmentIndex, unsigned char *pFlashColor = NULL, bool bOneFrame = false );
|
||||
void FX_ASW_ParticleMuzzleFlashAttached( float scale, ClientEntityHandle_t hEntity, int attachmentIndex, bool bIsRed );
|
||||
|
||||
void FX_ASW_StunExplosion(const Vector &origin);
|
||||
void FX_ASW_Potential_Burst_Pipe( const Vector &vecImpactPoint, const Vector &vecReflect, const Vector &vecShotBackward, const Vector &vecNormal );
|
||||
|
||||
void ASW_AttachFireToHitboxes(C_BaseAnimating *pAnimating, int iNumFires, float fMaxScale);
|
||||
|
||||
void FX_ASWWaterRipple( const Vector &origin, float scale, Vector *pColor, float flLifetime=1.5, float flAlpha=1 );
|
||||
void FX_ASWSplash( const Vector &origin, const Vector &normal, float scale );
|
||||
|
||||
void FX_ASWExplodeMap();
|
||||
|
||||
extern CDroneGibManager s_DroneGibManager;
|
||||
|
||||
#endif // _INCLUDED_C_ASW_FX_H
|
||||
@@ -0,0 +1,294 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "c_asw_alien.h"
|
||||
#include "c_asw_physics_prop_statue.h"
|
||||
#include "c_asw_mesh_emitter_entity.h"
|
||||
#include "c_asw_egg.h"
|
||||
#include "c_asw_buzzer.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_clientragdoll.h"
|
||||
|
||||
#include "ProxyEntity.h"
|
||||
#include "materialsystem/IMaterial.h"
|
||||
#include "materialsystem/IMaterialVar.h"
|
||||
#include "materialsystem/IMaterialSystem.h"
|
||||
#include <KeyValues.h>
|
||||
|
||||
#include "imaterialproxydict.h"
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Material proxy for changing the material of aliens
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CASW_Model_FX_Proxy : public CEntityMaterialProxy
|
||||
{
|
||||
public:
|
||||
CASW_Model_FX_Proxy( void );
|
||||
virtual ~CASW_Model_FX_Proxy( void );
|
||||
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
|
||||
virtual void OnBind( C_BaseEntity *pEnt );
|
||||
void UpdateEffects( bool bShockBig, bool bOnFire, float flFrozen );
|
||||
void TextureTransform( float flSpeed = 0, float flScale = 6.0f );
|
||||
virtual IMaterial * GetMaterial();
|
||||
|
||||
private:
|
||||
ITexture* m_pFXTexture;
|
||||
|
||||
// "$detailscale" "5"
|
||||
//"$detailblendfactor" 1.0
|
||||
// "$detailblendmode" 6
|
||||
IMaterialVar *m_pDetailMaterial;
|
||||
IMaterialVar *m_pDetailScale;
|
||||
IMaterialVar *m_pDetailBlendFactor;
|
||||
IMaterialVar *m_pDetailBlendMode;
|
||||
IMaterialVar *m_pTextureScrollVar;
|
||||
bool m_bOnFire;
|
||||
bool m_bFrozen;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CASW_Model_FX_Proxy::CASW_Model_FX_Proxy( void )
|
||||
{
|
||||
m_pFXTexture = NULL;
|
||||
m_pDetailMaterial = NULL;
|
||||
m_pDetailScale = NULL;
|
||||
m_pDetailBlendFactor = NULL;
|
||||
m_pDetailBlendMode = NULL;
|
||||
m_pTextureScrollVar = NULL;
|
||||
m_bOnFire = false;
|
||||
m_bFrozen = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CASW_Model_FX_Proxy::~CASW_Model_FX_Proxy( void )
|
||||
{
|
||||
}
|
||||
|
||||
bool CASW_Model_FX_Proxy::Init( IMaterial *pMaterial, KeyValues* pKeyValues )
|
||||
{
|
||||
Assert( pMaterial );
|
||||
|
||||
m_bFrozen = false;
|
||||
m_bOnFire = false;
|
||||
|
||||
// Need to get the material var
|
||||
bool bDetail;
|
||||
m_pDetailMaterial = pMaterial->FindVar( "$detail", &bDetail );
|
||||
|
||||
bool bScale;
|
||||
m_pDetailScale = pMaterial->FindVar( "$detailscale", &bScale );
|
||||
|
||||
bool bBlendFact;
|
||||
m_pDetailBlendFactor = pMaterial->FindVar( "$detailblendfactor", &bBlendFact );
|
||||
|
||||
bool bBlendMode;
|
||||
m_pDetailBlendMode = pMaterial->FindVar( "$detailblendmode", &bBlendMode );
|
||||
|
||||
char const* pScrollVarName = pKeyValues->GetString( "texturescrollvar" );
|
||||
if( !pScrollVarName )
|
||||
return false;
|
||||
|
||||
bool bScrollVar;
|
||||
m_pTextureScrollVar = pMaterial->FindVar( "$detailtexturetransform", &bScrollVar );
|
||||
|
||||
return ( bDetail && bScale && bBlendFact && bBlendMode && bScrollVar );
|
||||
}
|
||||
|
||||
void CASW_Model_FX_Proxy::OnBind( C_BaseEntity *pEnt )
|
||||
{
|
||||
// crashing here because pC_BaseEntity is passed as null?
|
||||
if ( !pEnt )
|
||||
return;
|
||||
|
||||
C_ASW_Mesh_Emitter *pGib = dynamic_cast<C_ASW_Mesh_Emitter*>( pEnt );
|
||||
if ( pGib && pGib->m_bFrozen )
|
||||
{
|
||||
m_pFXTexture = materials->FindTexture( "effects/model_layer_ice_1", TEXTURE_GROUP_MODEL );//
|
||||
if ( m_pFXTexture )
|
||||
{
|
||||
m_pDetailMaterial->SetTextureValue( m_pFXTexture );
|
||||
}
|
||||
m_pDetailBlendFactor->SetFloatValue( 0.4f );
|
||||
TextureTransform( 0 /*speed*/, 5.0f );
|
||||
return;
|
||||
}
|
||||
|
||||
C_ASWStatueProp *pStatue = dynamic_cast<C_ASWStatueProp*>( pEnt );
|
||||
if ( pStatue )
|
||||
{
|
||||
m_pFXTexture = materials->FindTexture( "effects/model_layer_ice_1", TEXTURE_GROUP_MODEL );//
|
||||
if ( m_pFXTexture )
|
||||
{
|
||||
m_pDetailMaterial->SetTextureValue( m_pFXTexture );
|
||||
}
|
||||
m_pDetailBlendFactor->SetFloatValue( 0.4f );
|
||||
TextureTransform( 0, 5.0f );
|
||||
return;
|
||||
}
|
||||
|
||||
bool bShockBig = false;
|
||||
bool bOnFire = false;
|
||||
float flFrozen = 0;
|
||||
|
||||
//C_ASW_ClientRagdoll
|
||||
C_ASW_Alien *pAlien = dynamic_cast<C_ASW_Alien*>( pEnt );
|
||||
if ( pAlien )
|
||||
{
|
||||
bShockBig = pAlien->m_bElectroStunned;
|
||||
bOnFire = pAlien->m_bOnFire;
|
||||
flFrozen = pAlien->GetMoveType() == MOVETYPE_NONE ? 0.0f : pAlien->GetFrozenAmount();
|
||||
//Msg( " alien %d shock = %d fire = %d frozen = %f\n", pAlien->entindex(), bShockBig, bOnFire, flFrozen );
|
||||
UpdateEffects( bShockBig, bOnFire, flFrozen );
|
||||
return;
|
||||
}
|
||||
|
||||
C_ASW_Marine *pMarine = C_ASW_Marine::AsMarine( pEnt );
|
||||
if ( pMarine )
|
||||
{
|
||||
//bShockBig = pMarine->m_bElectroStunned;
|
||||
bOnFire = pMarine->m_bOnFire;
|
||||
flFrozen = pMarine->GetFrozenAmount();
|
||||
UpdateEffects( false, bOnFire, flFrozen );
|
||||
return;
|
||||
}
|
||||
|
||||
C_ASW_Egg *pEgg = dynamic_cast<C_ASW_Egg*>( pEnt );
|
||||
if ( pEgg )
|
||||
{
|
||||
bOnFire = pEgg->m_bOnFire;
|
||||
flFrozen = pEgg->GetFrozenAmount();
|
||||
UpdateEffects( false, bOnFire, flFrozen );
|
||||
return;
|
||||
}
|
||||
|
||||
C_ASW_Buzzer *pBuzzer = dynamic_cast<C_ASW_Buzzer*>( pEnt );
|
||||
if ( pBuzzer )
|
||||
{
|
||||
bShockBig = pBuzzer->m_bElectroStunned;
|
||||
bOnFire = pBuzzer->m_bOnFire;
|
||||
flFrozen = pBuzzer->GetMoveType() == MOVETYPE_NONE ? 0.0f : pBuzzer->GetFrozenAmount();
|
||||
UpdateEffects( bShockBig, bOnFire, flFrozen );
|
||||
return;
|
||||
}
|
||||
|
||||
C_ASW_ClientRagdoll *pRagDoll = dynamic_cast<C_ASW_ClientRagdoll*>( pEnt );
|
||||
if ( pRagDoll )
|
||||
{
|
||||
bShockBig = pRagDoll->m_bElectroShock;
|
||||
bOnFire = !!(pRagDoll->GetFlags() & FL_ONFIRE);
|
||||
UpdateEffects( bShockBig, bOnFire, false );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
C_BaseAnimating *pBaseAnimating = dynamic_cast<C_BaseAnimating*>( pEnt );
|
||||
if ( pBaseAnimating )
|
||||
{
|
||||
flFrozen = pBaseAnimating->GetFrozenAmount();
|
||||
UpdateEffects( false, false, flFrozen );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
m_pDetailBlendFactor->SetFloatValue( 0.0f );
|
||||
}
|
||||
|
||||
void CASW_Model_FX_Proxy::UpdateEffects( bool bShockBig, bool bOnFire, float flFrozen )
|
||||
{
|
||||
if ( bShockBig || bOnFire || flFrozen > 0 )
|
||||
{
|
||||
if ( bShockBig )
|
||||
{
|
||||
m_pFXTexture = materials->FindTexture( "effects/model_layer_shock_1", TEXTURE_GROUP_MODEL );//
|
||||
if ( m_pFXTexture )
|
||||
{
|
||||
float flBlend = 0.75f;
|
||||
m_pDetailBlendFactor->SetFloatValue( flBlend );
|
||||
m_pDetailMaterial->SetTextureValue( m_pFXTexture );
|
||||
TextureTransform( 80, 4.0f );
|
||||
}
|
||||
}
|
||||
else if ( flFrozen > 0 )
|
||||
{
|
||||
m_pFXTexture = materials->FindTexture( "effects/model_layer_ice_1", TEXTURE_GROUP_MODEL );//
|
||||
if ( m_pFXTexture )
|
||||
{
|
||||
m_pDetailBlendFactor->SetFloatValue( MIN( 0.4f, flFrozen/4) );
|
||||
m_pDetailMaterial->SetTextureValue( m_pFXTexture );
|
||||
TextureTransform( 0, 5.0f );
|
||||
}
|
||||
}
|
||||
else if ( bOnFire )
|
||||
{
|
||||
m_pFXTexture = materials->FindTexture( "effects/TiledFire/fire_tiled", TEXTURE_GROUP_MODEL );//
|
||||
if ( m_pFXTexture )
|
||||
{
|
||||
m_pDetailBlendFactor->SetFloatValue( 0.3f );
|
||||
m_pDetailMaterial->SetTextureValue( m_pFXTexture );
|
||||
TextureTransform( 24, 6.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pDetailBlendFactor->SetFloatValue( 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Model_FX_Proxy::TextureTransform( float flSpeed, float flScale )
|
||||
{
|
||||
// scrolling of the detail material
|
||||
float flRate = abs( flSpeed ) / 128.0;
|
||||
float flAngle = (flSpeed >= 0) ? 180 : 0;
|
||||
|
||||
float sOffset = gpGlobals->curtime * cos( flAngle * ( M_PI / 180.0f ) ) * flRate;
|
||||
float tOffset = gpGlobals->curtime * sin( flAngle * ( M_PI / 180.0f ) ) * flRate;
|
||||
|
||||
// make sure that we are positive
|
||||
if( sOffset < 0.0f )
|
||||
{
|
||||
sOffset += 1.0f + -( int )sOffset;
|
||||
}
|
||||
if( tOffset < 0.0f )
|
||||
{
|
||||
tOffset += 1.0f + -( int )tOffset;
|
||||
}
|
||||
|
||||
// make sure that we are in a [0,1] range
|
||||
sOffset = sOffset - ( int )sOffset;
|
||||
tOffset = tOffset - ( int )tOffset;
|
||||
|
||||
if (m_pTextureScrollVar->GetType() == MATERIAL_VAR_TYPE_MATRIX)
|
||||
{
|
||||
VMatrix mat;
|
||||
MatrixBuildTranslation( mat, sOffset, tOffset, 0.0f );
|
||||
m_pTextureScrollVar->SetMatrixValue( mat );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTextureScrollVar->SetVecValue( sOffset, tOffset, 0.0f );
|
||||
}
|
||||
|
||||
m_pDetailScale->SetFloatValue( flScale );
|
||||
}
|
||||
|
||||
IMaterial *CASW_Model_FX_Proxy::GetMaterial()
|
||||
{
|
||||
if ( !m_pDetailMaterial )
|
||||
return NULL;
|
||||
|
||||
return m_pDetailMaterial->GetOwningMaterial();
|
||||
}
|
||||
|
||||
EXPOSE_MATERIAL_PROXY( CASW_Model_FX_Proxy, AlienSurfaceFX );
|
||||
@@ -0,0 +1,208 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_game_resource.h"
|
||||
#include "c_asw_objective.h"
|
||||
#include "c_asw_marine_resource.h"
|
||||
#include "c_asw_scanner_info.h"
|
||||
#include "c_asw_campaign_save.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "asw_input.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Game_Resource, DT_ASW_Game_Resource, CASW_Game_Resource)
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_MarineResources), RecvPropEHandle( RECVINFO( m_MarineResources[0] ) ) ),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_Objectives), RecvPropEHandle( RECVINFO( m_Objectives[0] ) ) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iRosterSelected), RecvPropInt( RECVINFO(m_iRosterSelected[0])) ),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_bPlayerReady), RecvPropBool( RECVINFO(m_bPlayerReady[0])) ),
|
||||
|
||||
RecvPropEHandle (RECVINFO(m_Leader) ),
|
||||
RecvPropInt(RECVINFO(m_iLeaderIndex)),
|
||||
RecvPropEHandle (RECVINFO(m_hScannerInfo) ),
|
||||
RecvPropEHandle (RECVINFO(m_hCampaignSave) ),
|
||||
RecvPropInt(RECVINFO(m_iCampaignGame)),
|
||||
RecvPropBool(RECVINFO(m_bOneMarineEach)),
|
||||
RecvPropInt(RECVINFO(m_iMaxMarines)),
|
||||
RecvPropBool(RECVINFO(m_bOfflineGame)),
|
||||
|
||||
// marine skills
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iSkillSlot0), RecvPropInt( RECVINFO(m_iSkillSlot0[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iSkillSlot1), RecvPropInt( RECVINFO(m_iSkillSlot1[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iSkillSlot2), RecvPropInt( RECVINFO(m_iSkillSlot2[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iSkillSlot3), RecvPropInt( RECVINFO(m_iSkillSlot3[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iSkillSlot4), RecvPropInt( RECVINFO(m_iSkillSlot4[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iSkillSlotSpare), RecvPropInt( RECVINFO(m_iSkillSlotSpare[0]))),
|
||||
|
||||
RecvPropArray( RecvPropString( RECVINFO( m_iszPlayerMedals[0]) ), m_iszPlayerMedals ),
|
||||
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iKickVotes), RecvPropInt( RECVINFO(m_iKickVotes[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iLeaderVotes), RecvPropInt( RECVINFO(m_iLeaderVotes[0]))),
|
||||
|
||||
RecvPropInt(RECVINFO(m_iMoney)),
|
||||
RecvPropInt(RECVINFO(m_iNextCampaignMission)),
|
||||
|
||||
RecvPropInt(RECVINFO(m_nDifficultySuggestion)),
|
||||
|
||||
RecvPropFloat( RECVINFO(m_fMapGenerationProgress) ),
|
||||
RecvPropString( RECVINFO(m_szMapGenerationStatus) ),
|
||||
RecvPropInt( RECVINFO(m_iRandomMapSeed) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Game_Resource *g_pASWGameResource = NULL;
|
||||
|
||||
C_ASW_Game_Resource::C_ASW_Game_Resource()
|
||||
{
|
||||
g_pASWGameResource = this;
|
||||
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
m_MarineResources.Set(i, NULL);
|
||||
}
|
||||
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
|
||||
{
|
||||
m_Objectives.Set(i, NULL);
|
||||
}
|
||||
for (int i=0;i<ASW_NUM_MARINE_PROFILES;i++)
|
||||
{
|
||||
m_iRosterSelected.Set(i, 0);
|
||||
}
|
||||
m_iCampaignGame = -1;
|
||||
m_iNumEnumeratedMarines = NULL;
|
||||
m_pCampaignInfo = NULL;
|
||||
}
|
||||
|
||||
C_ASW_Game_Resource::~C_ASW_Game_Resource()
|
||||
{
|
||||
if ( g_pASWGameResource == this )
|
||||
{
|
||||
g_pASWGameResource = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
C_ASW_Objective* C_ASW_Game_Resource::GetObjective(int i)
|
||||
{
|
||||
if (i<0 || i>=ASW_MAX_OBJECTIVES)
|
||||
return NULL;
|
||||
|
||||
if (m_Objectives[i] == NULL)
|
||||
return NULL;
|
||||
|
||||
C_BaseEntity* c = m_Objectives[i];
|
||||
return static_cast<C_ASW_Objective*>(c);
|
||||
}
|
||||
|
||||
C_ASW_Marine_Resource* C_ASW_Game_Resource::GetMarineResource(int i)
|
||||
{
|
||||
if (i<0 || i>11)
|
||||
return NULL;
|
||||
|
||||
if (m_MarineResources[i] == NULL)
|
||||
return NULL;
|
||||
|
||||
C_BaseEntity* c = m_MarineResources[i];
|
||||
return static_cast<C_ASW_Marine_Resource*>(c);
|
||||
}
|
||||
|
||||
int C_ASW_Game_Resource::GetIndexFor(C_ASW_Marine_Resource* pMarineResource)
|
||||
{
|
||||
for (int i=0;i<GetMaxMarineResources();i++)
|
||||
{
|
||||
if (m_MarineResources[i] == pMarineResource)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool C_ASW_Game_Resource::IsRosterSelected(int i)
|
||||
{
|
||||
if (i<0 || i>=ASW_NUM_MARINE_PROFILES)
|
||||
return false;
|
||||
|
||||
return m_iRosterSelected[i] == 1;
|
||||
}
|
||||
|
||||
bool C_ASW_Game_Resource::IsRosterReserved(int i)
|
||||
{
|
||||
if (i<0 || i>=ASW_NUM_MARINE_PROFILES)
|
||||
return false;
|
||||
return m_iRosterSelected[i] == 2;
|
||||
}
|
||||
|
||||
C_ASW_Player* C_ASW_Game_Resource::GetLeader()
|
||||
{
|
||||
return dynamic_cast<C_ASW_Player*>(m_Leader.Get());
|
||||
}
|
||||
|
||||
C_ASW_Scanner_Info* C_ASW_Game_Resource::GetScannerInfo()
|
||||
{
|
||||
return dynamic_cast<C_ASW_Scanner_Info*>(m_hScannerInfo.Get());
|
||||
}
|
||||
|
||||
C_ASW_Campaign_Save* C_ASW_Game_Resource::GetCampaignSave()
|
||||
{
|
||||
return dynamic_cast<C_ASW_Campaign_Save*>(m_hCampaignSave.Get());
|
||||
}
|
||||
|
||||
int C_ASW_Game_Resource::GetNumMarineResources()
|
||||
{
|
||||
int iNum = 0;
|
||||
for (int i=0;i<ASW_MAX_MARINE_RESOURCES;i++)
|
||||
{
|
||||
if (GetMarineResource(i))
|
||||
iNum++;
|
||||
}
|
||||
return iNum;
|
||||
}
|
||||
|
||||
C_ASW_Game_Resource::CMarineToCrosshairInfo::tuple_t C_ASW_Game_Resource::CMarineToCrosshairInfo::tuple_t::INVALID;
|
||||
|
||||
/// @TODO can use integer compares for slightly better speed
|
||||
static int __cdecl MarineTupleComparator( const C_ASW_Game_Resource::CMarineToCrosshairInfo::tuple_t * a, const C_ASW_Game_Resource::CMarineToCrosshairInfo::tuple_t * b )
|
||||
{
|
||||
float dif = a->m_fDistToCursor - b->m_fDistToCursor;
|
||||
// have to do this because just returning a-b will hit rounding issues
|
||||
return ( dif < 0 ? -1 : ( dif > 0 ? 1 : 0 ) );
|
||||
}
|
||||
|
||||
|
||||
int C_ASW_Game_Resource::CMarineToCrosshairInfo::FindIndexForMarine( C_ASW_Marine *pMarine )
|
||||
{
|
||||
CheckCache();
|
||||
for ( int i = 0 ; i < Count() ; ++i )
|
||||
{
|
||||
if ( GetElement(i).m_hMarine.Get() == pMarine )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning( disable : 4706 )
|
||||
/// @TODO can use a more optimal sorting strategy
|
||||
void C_ASW_Game_Resource::CMarineToCrosshairInfo::RecomputeCache()
|
||||
{
|
||||
VPROF("C_ASW_Game_Resource::CMarineToCrosshairInfo::RecomputeCache()");
|
||||
C_ASW_Game_Resource * RESTRICT pGameResource = ASWGameResource();
|
||||
// purge the array.
|
||||
m_tMarines.RemoveAll();
|
||||
|
||||
const Vector vecCrosshairAimingPos = ASWInput()->GetCrosshairAimingPos();
|
||||
|
||||
for ( int i=0; i<pGameResource->GetMaxMarineResources(); i++ )
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
|
||||
C_ASW_Marine *pMarine;
|
||||
if ( pMR && (pMarine = pMR->GetMarineEntity()) )
|
||||
{
|
||||
float dist = (vecCrosshairAimingPos - pMR->GetMarineEntity()->GetAbsOrigin()).Length2D();
|
||||
m_tMarines.AddToTail( tuple_t(pMarine, dist) );
|
||||
}
|
||||
}
|
||||
|
||||
m_tMarines.Sort( &MarineTupleComparator );
|
||||
|
||||
m_iLastFrameCached = gpGlobals->framecount;
|
||||
}
|
||||
#pragma warning(pop)
|
||||
@@ -0,0 +1,192 @@
|
||||
#ifndef C_ASW_GAME_RESOURCE_H
|
||||
#define C_ASW_GAME_RESOURCE_H
|
||||
#pragma once
|
||||
|
||||
#include "c_baseentity.h"
|
||||
#include "asw_shareddefs.h"
|
||||
#include "asw_marine_skills.h"
|
||||
|
||||
class C_ASW_Objective;
|
||||
class C_ASW_Marine_Resource;
|
||||
class C_ASW_Marine;
|
||||
class C_ASW_Player;
|
||||
class C_ASW_Scanner_Info;
|
||||
class CASW_Campaign_Info;
|
||||
class C_ASW_Campaign_Save;
|
||||
class CASW_Marine_Profile;
|
||||
|
||||
// This entity networks various information about the game
|
||||
// such as list of selected marines, which player is leader, marine skills, etc.
|
||||
|
||||
class C_ASW_Game_Resource : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Game_Resource, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Game_Resource();
|
||||
virtual ~C_ASW_Game_Resource();
|
||||
|
||||
CNetworkArray( EHANDLE, m_MarineResources, ASW_MAX_MARINE_RESOURCES );
|
||||
CNetworkArray( EHANDLE, m_Objectives, ASW_MAX_OBJECTIVES );
|
||||
CNetworkArray( int, m_iRosterSelected, ASW_NUM_MARINE_PROFILES);
|
||||
CNetworkVar( bool, m_bOneMarineEach );
|
||||
CNetworkVar( int, m_iMaxMarines );
|
||||
|
||||
// which player is the leader
|
||||
CNetworkHandle (C_ASW_Player, m_Leader);
|
||||
CNetworkVar(int, m_iLeaderIndex);
|
||||
CNetworkArray( bool, m_bPlayerReady, ASW_MAX_READY_PLAYERS );
|
||||
bool IsPlayerReady(C_ASW_Player *pPlayer);
|
||||
bool IsPlayerReady(int iPlayerEntIndex);
|
||||
|
||||
C_ASW_Scanner_Info* GetScannerInfo();
|
||||
CNetworkHandle (C_ASW_Scanner_Info, m_hScannerInfo);
|
||||
|
||||
bool IsOfflineGame() const { return m_bOfflineGame || ( gpGlobals->maxClients == 1 ); }
|
||||
CNetworkVar( bool, m_bOfflineGame );
|
||||
|
||||
int IsCampaignGame() { return m_iCampaignGame; }
|
||||
CNetworkVar(int, m_iCampaignGame); // is this a campaign game? -1 = unknown, 0 = single mission, 1 = campaign
|
||||
|
||||
C_ASW_Objective* GetObjective(int i);
|
||||
C_ASW_Marine_Resource* GetMarineResource(int i);
|
||||
int GetIndexFor(C_ASW_Marine_Resource* pMarineResource);
|
||||
bool IsRosterSelected(int i);
|
||||
bool IsRosterReserved(int i);
|
||||
int GetMarineResourceIndex( C_ASW_Marine_Resource *pMR );
|
||||
bool AtLeastOneMarine(); // is at least one marine selected?
|
||||
|
||||
int GetMaxMarineResources() { return ASW_MAX_MARINE_RESOURCES; }
|
||||
int GetNumMarines(C_ASW_Player *pPlayer, bool bAliveOnly=false); // returns how many marines this player has selected
|
||||
C_ASW_Player* GetLeader();
|
||||
int GetLeaderEntIndex() { return m_iLeaderIndex; }
|
||||
int GetNumMarineResources();
|
||||
C_ASW_Marine_Resource* GetFirstMarineResourceForPlayer( C_ASW_Player *pPlayer ); // returns the first marine resource controlled by this player
|
||||
|
||||
C_ASW_Campaign_Save* GetCampaignSave();
|
||||
CNetworkHandle(C_ASW_Campaign_Save, m_hCampaignSave);
|
||||
|
||||
bool AreAllOtherPlayersReady(int iPlayerEntIndex);
|
||||
|
||||
// skills
|
||||
int GetSlotForSkill( int nProfileIndex, ASW_Skill nSkillIndex );
|
||||
int GetMarineSkill( int iProfileIndex, int nSkillSlot );
|
||||
int GetMarineSkill( C_ASW_Marine_Resource *m, int nSkillSlot );
|
||||
CNetworkArray(int, m_iSkillSlot0, ASW_NUM_MARINE_PROFILES);
|
||||
CNetworkArray(int, m_iSkillSlot1, ASW_NUM_MARINE_PROFILES);
|
||||
CNetworkArray(int, m_iSkillSlot2, ASW_NUM_MARINE_PROFILES);
|
||||
CNetworkArray(int, m_iSkillSlot3, ASW_NUM_MARINE_PROFILES);
|
||||
CNetworkArray(int, m_iSkillSlot4, ASW_NUM_MARINE_PROFILES);
|
||||
CNetworkArray(int, m_iSkillSlotSpare, ASW_NUM_MARINE_PROFILES);
|
||||
|
||||
int m_iKickVotes[ASW_MAX_READY_PLAYERS];
|
||||
int m_iLeaderVotes[ASW_MAX_READY_PLAYERS];
|
||||
|
||||
// player medals
|
||||
char m_iszPlayerMedals[ ASW_MAX_READY_PLAYERS ][255];
|
||||
|
||||
// returns current number of alive (non-KOed players)
|
||||
int CountAllAliveMarines( void );
|
||||
|
||||
// returns count of all marines in these bounds;
|
||||
int EnumerateMarinesInBox(Vector &mins, Vector &maxs);
|
||||
C_ASW_Marine* EnumeratedMarine(int i);
|
||||
C_ASW_Marine* m_pEnumeratedMarines[12];
|
||||
int m_iNumEnumeratedMarines;
|
||||
|
||||
// a convenient means of finding which marines are closest
|
||||
// to the cursor; stores them in a sorted list,
|
||||
// and caches the computation so that it is performed
|
||||
// no more than once per frame.
|
||||
class CMarineToCrosshairInfo
|
||||
{
|
||||
public:
|
||||
// stores a handle to a marine and also that marine's distance to crosshair
|
||||
// (so you don't need to recompute it over and over again)
|
||||
struct tuple_t
|
||||
{
|
||||
tuple_t( C_ASW_Marine *pMarine, float fDist ) : m_hMarine(pMarine), m_fDistToCursor(fDist) {}
|
||||
tuple_t() : m_hMarine(), m_fDistToCursor(-FLT_MAX) {};
|
||||
CHandle<C_ASW_Marine> m_hMarine;
|
||||
float m_fDistToCursor;
|
||||
|
||||
// an invalid handle returned for bad queries
|
||||
static tuple_t INVALID;
|
||||
};
|
||||
|
||||
/// Get info on the closest marine.
|
||||
inline const tuple_t &GetClosestMarine() { return GetElement(0); }
|
||||
|
||||
/// Returns as if a list of marines sorted by distance to crosshair, closest to furthest.
|
||||
/// the actual type of the list is the tuple_t below, which stores a handle
|
||||
/// and also the distance for convenience.
|
||||
inline const tuple_t &GetElement( int e );
|
||||
inline const tuple_t &operator[]( int i ) { return GetElement(i); }
|
||||
|
||||
/// find the index corresponding to a given marine. returns -1 if marine isn't found (which should never happen)
|
||||
int FindIndexForMarine( C_ASW_Marine *pMarine );
|
||||
|
||||
inline int Count();
|
||||
protected:
|
||||
inline void CheckCache(); // and recompute if necessary
|
||||
void RecomputeCache();
|
||||
|
||||
int m_iLastFrameCached; /// the framecount of the last time my info was cached.
|
||||
CUtlVectorFixed< tuple_t, ASW_MAX_MARINE_RESOURCES > m_tMarines; // a list of marines sorted by distance to crosshair, closest to furthest
|
||||
};
|
||||
// access the singleton info struct giving info on marines close to crosshairs
|
||||
inline CMarineToCrosshairInfo *GetMarineCrosshairCache() { return &m_marineToCrosshairInfo; }
|
||||
|
||||
CASW_Campaign_Info* m_pCampaignInfo;
|
||||
|
||||
// money
|
||||
int GetMoney() { return m_iMoney; }
|
||||
CNetworkVar( int, m_iMoney );
|
||||
|
||||
// map generation progress
|
||||
float m_fMapGenerationProgress;
|
||||
char m_szMapGenerationStatus[ 128 ];
|
||||
int m_iRandomMapSeed; // if set clients, will begin generating a random map based on this seed
|
||||
|
||||
int GetNextCampaignMissionIndex() { return m_iNextCampaignMission.Get(); }
|
||||
CNetworkVar( int, m_iNextCampaignMission );
|
||||
|
||||
CNetworkVar( int, m_nDifficultySuggestion );
|
||||
|
||||
protected:
|
||||
CMarineToCrosshairInfo m_marineToCrosshairInfo;
|
||||
|
||||
private:
|
||||
C_ASW_Game_Resource( const C_ASW_Game_Resource & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
extern C_ASW_Game_Resource *g_pASWGameResource;
|
||||
|
||||
inline C_ASW_Game_Resource* ASWGameResource()
|
||||
{
|
||||
return g_pASWGameResource;
|
||||
}
|
||||
|
||||
inline void C_ASW_Game_Resource::CMarineToCrosshairInfo::CheckCache() // and recompute if necessary
|
||||
{
|
||||
if (gpGlobals->framecount != m_iLastFrameCached)
|
||||
RecomputeCache();
|
||||
}
|
||||
|
||||
inline int C_ASW_Game_Resource::CMarineToCrosshairInfo::Count()
|
||||
{
|
||||
CheckCache();
|
||||
return m_tMarines.Count();
|
||||
}
|
||||
|
||||
inline const C_ASW_Game_Resource::CMarineToCrosshairInfo::tuple_t & C_ASW_Game_Resource::CMarineToCrosshairInfo::GetElement( int e )
|
||||
{
|
||||
CheckCache();
|
||||
if ( e < Count() )
|
||||
return m_tMarines[e];
|
||||
else
|
||||
return tuple_t::INVALID;
|
||||
}
|
||||
|
||||
#endif /* C_ASW_GAME_RESOURCE_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,277 @@
|
||||
#ifndef _DEFINED_ASW_GENERIC_EMITTER_H
|
||||
#define _DEFINED_ASW_GENERIC_EMITTER_H
|
||||
|
||||
#include "particles_simple.h"
|
||||
|
||||
enum ASWParticleType
|
||||
{
|
||||
aswpt_normal = 1,
|
||||
aswpt_glow
|
||||
};
|
||||
|
||||
enum ASWParticleDrawType
|
||||
{
|
||||
aswpdt_sprite = 0,
|
||||
aswpdt_tracer,
|
||||
aswpdt_mesh,
|
||||
};
|
||||
|
||||
class C_ASW_Mesh_Emitter;
|
||||
|
||||
// Our custom particle class
|
||||
class ASWParticle : public SimpleParticle
|
||||
{
|
||||
public:
|
||||
ASWParticle() : SimpleParticle() {}
|
||||
virtual ~ASWParticle()
|
||||
{
|
||||
if (m_pPartner) m_pPartner->m_pPartner = NULL; // unlink us from our partner if we have one
|
||||
}
|
||||
|
||||
// AddASWParticle automatically initializes these fields.
|
||||
Vector m_vecAccn; // particle's velocity is affected by this
|
||||
float m_fExtraSimulateTime; // any extra time here will be added to the simulate deltaTime in the next simulation of this particle (used by DoPresimulate)
|
||||
// aswhack: some properties the flamethrower emitter needs to look good
|
||||
ASWParticleType m_ParticleType;
|
||||
float m_fDropTime;
|
||||
ASWParticle* m_pPartner; // glow particles get attached to the main particle
|
||||
bool bPlacedDecal;
|
||||
};
|
||||
|
||||
// different types of collision
|
||||
enum ASWParticleCollision
|
||||
{
|
||||
aswpc_none = 0,
|
||||
aswpc_brush,
|
||||
aswpc_all
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ASW_EMITTER_BEAM_POS_BEHIND,
|
||||
ASW_EMITTER_BEAM_POS_CENTER,
|
||||
ASW_EMITTER_BEAM_POS_FRONT,
|
||||
};
|
||||
|
||||
class CASWGenericEmitter : public CSimpleEmitter
|
||||
{
|
||||
DECLARE_CLASS( CASWGenericEmitter, CSimpleEmitter );
|
||||
public:
|
||||
CASWGenericEmitter( const char *pDebugName );
|
||||
static CSmartPtr<CASWGenericEmitter> Create( const char *pDebugName );
|
||||
|
||||
// call every frame from host object to make this emitter process
|
||||
virtual void Think(float deltaTime, const Vector& Position, const QAngle& Angle); // called by our host object
|
||||
|
||||
// set whether this emitter should spit out particles or not
|
||||
virtual void SetActive(bool b);
|
||||
|
||||
// get whether this emitter thinks it is spitting out particles now
|
||||
inline bool GetActive( void );
|
||||
|
||||
// Causes all particles to be destroyed in the next simulate and the particle spawn timer is reset
|
||||
void ResetEmitter();
|
||||
|
||||
// set which template this emitter should use
|
||||
void UseTemplate(const char* templatename, bool bReset = true, bool bLoadFromCache=true);
|
||||
|
||||
// resize this emitter (applies on top of any settings in the template)
|
||||
void SetEmitterScale(float f) { m_fEmitterScale = f; SetParticleCullRadius(m_fLargestParticleSize * m_fEmitterScale); }
|
||||
float GetEmitterScale() { return m_fEmitterScale; }
|
||||
|
||||
// creates a single particle
|
||||
virtual ASWParticle* SpawnParticle(const Vector& Position, const QAngle& Angle);
|
||||
|
||||
// set the time at which the emitter should kill itself
|
||||
virtual void SetDieTime(float fTime);
|
||||
|
||||
// Runs through the m_fPresimulateTime instantly, creating particles and simulating them over that period of time
|
||||
virtual void DoPresimulate(const Vector& Position, const QAngle& Angle);
|
||||
|
||||
// ==============
|
||||
// internal stuff
|
||||
// ==============
|
||||
|
||||
protected:
|
||||
virtual void StartRender( VMatrix &effectMatrix );
|
||||
virtual void RenderParticles( CParticleRenderIterator *pIterator );
|
||||
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
|
||||
virtual bool SimulateParticle(ASWParticle* pParticle, float timeDelta); // simulate a particle for timeDelta seconds. returns true if particle should be removed
|
||||
virtual ASWParticle* AddASWParticle( PMaterialHandle hMaterial, const Vector &vOrigin, float flDieTime=3, unsigned char uchSize=10 );
|
||||
virtual void Update(); // should be called whenever the emitter's look is changed
|
||||
|
||||
virtual float UpdateAlpha( const SimpleParticle *pParticle );
|
||||
virtual float ASWUpdateScale( const ASWParticle *pParticle );
|
||||
virtual void ASWUpdateVelocity( ASWParticle *pParticle, float timeDelta );
|
||||
virtual Vector UpdateColor( const SimpleParticle *pParticle );
|
||||
|
||||
virtual ASWParticle* SpawnGlowParticle(const Vector& Position, const QAngle& Angle, ASWParticle* pParent);
|
||||
|
||||
// save settings from the specified template
|
||||
void SaveTemplateAs(const char* templatename);
|
||||
const char* GetTemplateName() { return m_szTemplateName; }
|
||||
|
||||
// returns how many particles this emitter has currently
|
||||
int GetNumParticles() { return GetBinding().GetNumActiveParticles(); }
|
||||
|
||||
// to get/set which material this emitter uses
|
||||
void SetMaterial(const char* materialname );
|
||||
const char* GetMaterial() { return m_szMaterialName; }
|
||||
|
||||
public: // asw temp
|
||||
|
||||
// to get/set which template this emitter uses for collision effects
|
||||
void SetCollisionTemplate(const char* templatename );
|
||||
const char* GetCollisionTemplate() { return m_szCollisionTemplateName; }
|
||||
// to get/set which template this emitter uses for droplet effects
|
||||
void SetDropletTemplate(const char* templatename );
|
||||
const char* GetDropletTemplate() { return m_szDropletTemplateName; }
|
||||
|
||||
void SetGlowMaterial(const char* materialname );
|
||||
const char* GetGlowMaterial() { return m_szGlowMaterialName; }
|
||||
float m_fGlowScale;
|
||||
float m_fGlowDeviation;
|
||||
public:
|
||||
// Structs for our nodes, which control transitions of various particle properties over their lifetimes
|
||||
struct ColorNode
|
||||
{
|
||||
bool bUse;
|
||||
float fTime;
|
||||
color32 Color;
|
||||
float fBandLength;
|
||||
};
|
||||
struct ScaleNode
|
||||
{
|
||||
bool bUse;
|
||||
float fTime;
|
||||
float fScale;
|
||||
float fBandLength;
|
||||
};
|
||||
struct AlphaNode
|
||||
{
|
||||
bool bUse;
|
||||
float fTime;
|
||||
float fAlpha;
|
||||
float fBandLength;
|
||||
};
|
||||
|
||||
bool m_bEmit; // Determines whether or not we should emit particles
|
||||
float m_CurrentParticlesPerSecond; // used to track changes to the particlespersecond
|
||||
int m_iResetEmitter;
|
||||
|
||||
// Properties that describe how this emitter looks
|
||||
ColorNode m_Colors[5];
|
||||
ScaleNode m_Scales[5];
|
||||
AlphaNode m_Alphas[5];
|
||||
float m_ParticlesPerSecond;
|
||||
float m_fParticleLifeMin, m_fParticleLifeMax;
|
||||
float m_fPresimulateTime;
|
||||
Vector velocityMin;
|
||||
Vector velocityMax;
|
||||
Vector positionMin;
|
||||
Vector positionMax;
|
||||
Vector accelerationMin;
|
||||
Vector accelerationMax;
|
||||
float fRollMin, fRollMax;
|
||||
float fRollDeltaMin, fRollDeltaMax;
|
||||
float fGravity;
|
||||
ASWParticleDrawType m_DrawType;
|
||||
float m_fBeamLength;
|
||||
bool m_bScaleBeamByVelocity;
|
||||
bool m_bScaleBeamByLifeLeft;
|
||||
int m_iBeamPosition;
|
||||
float m_fDropletChance; // chance of a particular particle spawning a droplet, if our droplet template is set. Scale is 0 to 100.
|
||||
|
||||
float m_fEmitterScale; // our own scale var, applied on top of the template
|
||||
int m_iParticleSupply; // how many particles are left to spawn
|
||||
int m_iInitialParticleSupply; // the initial particle supply
|
||||
int m_iLightingType; // 0 = no lighting 1 = scale color by lighting 2 = scale alpha by lighting 3 = scale alpha and color by lighting
|
||||
float m_fLightApply; // how much to apply lighting (1.0f = fully apply lighting, 0.5f = only apply half of the darkening/coloring)
|
||||
Vector m_vecLighting; // stored lighting vector
|
||||
|
||||
float m_fParticleLocal; // if set to 1.0, the particles will move with the emitter, at 0 they will be unaffected by the emitter's movement once spawned
|
||||
|
||||
Vector m_vecPosition;
|
||||
Vector m_vecLastSimulatePosition;
|
||||
Vector m_vecEmitterPositionDelta;
|
||||
QAngle m_angFacing;
|
||||
float m_fDieTime; // at this time, the emitter will be stop emitting particles and then when all are gone, it'll destroy itself
|
||||
|
||||
public:
|
||||
bool m_bWrapParticlesToSpawnBounds; // on X/Y only (note: only works on emitters with no rotation)
|
||||
bool m_bLocalCoordSpace; // note:bugged - if true, particles are stored in local space and transformed to the position of the emitter when rendered
|
||||
ASWParticleCollision m_UseCollision;
|
||||
EHANDLE m_hCollisionIgnoreEntity;
|
||||
float m_fCollisionDampening;
|
||||
|
||||
// Custom collision stuff - currently accessible only through code on a specific instance, not throught templates
|
||||
void SetCustomCollisionMask(int iMask);
|
||||
void SetCustomCollisionGroup(int iColGroup);
|
||||
bool m_bUseCustomCollisionMask;
|
||||
bool m_bUseCustomCollisionGroup;
|
||||
int m_CustomCollisionMask;
|
||||
int m_CustomCollisionGroup;
|
||||
|
||||
protected:
|
||||
// calculates the times between each node, for quickly picking which nodes to transition between in the update functions
|
||||
virtual void CalcBandLengths();
|
||||
|
||||
PMaterialHandle m_hMaterial; // Material handle used for this entity's particles
|
||||
PMaterialHandle m_hGlowMaterial; // Material handle used for this entity's particles' glow
|
||||
char m_szMaterialName[MAX_PATH];
|
||||
char m_szGlowMaterialName[MAX_PATH];
|
||||
char m_szTemplateName[MAX_PATH];
|
||||
char m_szCollisionTemplateName[MAX_PATH];
|
||||
char m_szDropletTemplateName[MAX_PATH];
|
||||
|
||||
TimedEvent m_tParticleTimer; // Timer used to control particle emission rate
|
||||
|
||||
CSmartPtr<CASWGenericEmitter> m_hCollisionEmitter;
|
||||
CSmartPtr<CASWGenericEmitter> m_hDropletEmitter;
|
||||
|
||||
float m_fLargestParticleSize; // cache this for quick setting of particle cull size during scaling of the emitter
|
||||
|
||||
public:
|
||||
float m_fLifeLostOnCollision;
|
||||
|
||||
void SetMeshEmitter(C_ASW_Mesh_Emitter *pMeshEmitter);
|
||||
CHandle<C_ASW_Mesh_Emitter> m_hMeshEmitter;
|
||||
Vector m_vecTraceMins;
|
||||
Vector m_vecTraceMaxs;
|
||||
bool m_bHullTraces;
|
||||
float m_fReduceRollRateOnCollision;
|
||||
void SetCollisionSound(const char* szSoundName );
|
||||
char m_szCollisionSoundName[128];
|
||||
void SetCollisionDecal(const char* szDecalName );
|
||||
char m_szCollisionDecalName[128];
|
||||
|
||||
private:
|
||||
CASWGenericEmitter( const CASWGenericEmitter & ); // not defined, not accessible
|
||||
|
||||
friend class C_ASW_Emitter;
|
||||
friend class C_ASW_Mesh_Emitter;
|
||||
friend class CASW_VGUI_Edit_Emitter;
|
||||
};
|
||||
|
||||
// this caches templates
|
||||
class CASWGenericEmitterCache
|
||||
{
|
||||
public:
|
||||
virtual ~CASWGenericEmitterCache();
|
||||
KeyValues* FindTemplate(const char* szTemplateName);
|
||||
void ListCachedEmitters();
|
||||
void PrecacheTemplates();
|
||||
|
||||
CUtlVector<KeyValues*> m_Templates;
|
||||
CUtlVector<const char*> m_TemplateNames;
|
||||
};
|
||||
|
||||
extern CASWGenericEmitterCache g_ASWGenericEmitterCache;
|
||||
|
||||
inline bool CASWGenericEmitter::GetActive()
|
||||
{
|
||||
return m_bEmit;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _DEFINED_ASW_GENERIC_EMITTER_H */
|
||||
@@ -0,0 +1,150 @@
|
||||
#include "cbase.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "c_asw_generic_emitter_entity.h"
|
||||
#include "c_asw_generic_emitter.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
LINK_ENTITY_TO_CLASS( client_asw_emitter, C_ASW_Emitter );
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_Emitter, DT_ASW_Emitter, CASW_Emitter )
|
||||
RecvPropInt( RECVINFO( m_bEmit ) ),
|
||||
RecvPropString( RECVINFO(m_szTemplateName) ),
|
||||
RecvPropFloat( RECVINFO(m_fDesiredScale) ),
|
||||
RecvPropFloat( RECVINFO(m_fScaleRate) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Emitter::C_ASW_Emitter()
|
||||
{
|
||||
m_fScale = 1.0f;
|
||||
m_fDieTime = false;
|
||||
|
||||
m_hClientAttach = NULL;
|
||||
m_szAttach[0] = 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Called when data changes on the server
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Emitter::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
// NOTE: We MUST call the base classes' implementation of this function
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
// Setup our entity's particle system on creation
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
CreateEmitter();
|
||||
}
|
||||
m_hEmitter->Update();
|
||||
}
|
||||
|
||||
void C_ASW_Emitter::CreateEmitter()
|
||||
{
|
||||
// Creat the emitter
|
||||
m_hEmitter = CASWGenericEmitter::Create( "asw_emitter" );
|
||||
m_hEmitter->SetSortOrigin(GetAbsOrigin());
|
||||
|
||||
// Obtain a reference handle to our particle's desired material
|
||||
if ( m_hEmitter.IsValid() )
|
||||
{
|
||||
m_hEmitter->UseTemplate(m_szTemplateName);
|
||||
m_hEmitter->SetEmitterScale(m_fScale);
|
||||
m_hEmitter->SetActive(m_bEmit);
|
||||
m_hEmitter->Update();
|
||||
}
|
||||
|
||||
// Call our ClientThink() function once every client frame
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Client-side think function for the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_Emitter::ClientThink( void )
|
||||
{
|
||||
// We must have a valid emitter
|
||||
if ( m_hEmitter == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if we're clientside attached to something, update our position/angle
|
||||
if (m_hClientAttach.Get())
|
||||
{
|
||||
Vector pos;
|
||||
QAngle ang;
|
||||
if (Q_strlen(m_szAttach) <= 0)
|
||||
{
|
||||
pos = m_hClientAttach->WorldSpaceCenter();
|
||||
ang = m_hClientAttach->GetAbsAngles();
|
||||
}
|
||||
else
|
||||
m_hClientAttach->GetAttachment( m_hClientAttach->LookupAttachment( m_szAttach ), pos, ang );
|
||||
SetAbsOrigin(pos);
|
||||
SetAbsAngles(ang);
|
||||
}
|
||||
|
||||
m_hEmitter->Think(gpGlobals->frametime, GetAbsOrigin(), GetAbsAngles());
|
||||
if (m_fScale != m_fDesiredScale)
|
||||
{
|
||||
if (m_fScale < m_fDesiredScale)
|
||||
{
|
||||
m_fScale = MIN(m_fScale + m_fScaleRate * gpGlobals->frametime, m_fDesiredScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fScale = MAX(m_fScale - m_fScaleRate * gpGlobals->frametime, m_fDesiredScale);
|
||||
}
|
||||
}
|
||||
m_hEmitter->SetEmitterScale(m_fScale);
|
||||
m_hEmitter->SetActive(m_bEmit);
|
||||
if (gpGlobals->curtime > m_fDieTime && m_fDieTime != 0)
|
||||
{
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C_ASW_Emitter::UseTemplate(const char* pTemplateName, bool bLoadFromCache)
|
||||
{
|
||||
if (m_hEmitter == NULL)
|
||||
return;
|
||||
|
||||
strcpy(m_szTemplateName, pTemplateName);
|
||||
m_hEmitter->UseTemplate(pTemplateName,true,bLoadFromCache);
|
||||
}
|
||||
|
||||
void C_ASW_Emitter::SaveAsTemplate(const char* pTemplateName)
|
||||
{
|
||||
if (m_hEmitter == NULL)
|
||||
return;
|
||||
|
||||
strcpy(m_szTemplateName, pTemplateName);
|
||||
m_hEmitter->SaveTemplateAs(pTemplateName);
|
||||
}
|
||||
|
||||
void C_ASW_Emitter::SetDieTime(float fDieTime)
|
||||
{
|
||||
m_fDieTime = fDieTime;
|
||||
}
|
||||
|
||||
void C_ASW_Emitter::Die()
|
||||
{
|
||||
// make sure our emitter knows to die
|
||||
if (!(m_hEmitter == NULL))
|
||||
{
|
||||
m_hEmitter->SetDieTime(m_fDieTime);
|
||||
}
|
||||
Release();
|
||||
}
|
||||
|
||||
void C_ASW_Emitter::ClientAttach(C_BaseAnimating *pParent, const char *szAttach)
|
||||
{
|
||||
if (!pParent)
|
||||
return;
|
||||
strcpy(m_szAttach, szAttach);
|
||||
m_hClientAttach = pParent;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef _DEFINED_C_ASW_GENERIC_EMITTER_ENTITY_H
|
||||
#define _DEFINED_C_ASW_GENERIC_EMITTER_ENTITY_H
|
||||
|
||||
class CASW_VGUI_Edit_Emitter;
|
||||
class CASWGenericEmitter;
|
||||
|
||||
class C_ASW_Emitter : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_CLASS( C_ASW_Emitter, C_BaseEntity );
|
||||
|
||||
C_ASW_Emitter();
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType ); // Called when data changes on the server
|
||||
virtual void ClientThink( void ); // Client-side think function for the entity
|
||||
virtual void UseTemplate(const char* pTemplateName, bool bLoadFromCache);
|
||||
virtual void SaveAsTemplate(const char* pTemplateName);
|
||||
virtual void CreateEmitter();
|
||||
virtual void SetDieTime(float fDieTime);
|
||||
virtual void Die();
|
||||
virtual void ClientAttach(C_BaseAnimating *pParent, const char *szAttach); // clientside attach to a specific entity's attachment point
|
||||
|
||||
public:
|
||||
bool m_bEmit; // Determines whether or not we should emit particles
|
||||
float m_fScale;
|
||||
float m_fDesiredScale;
|
||||
float m_fScaleRate;
|
||||
float m_fDieTime;
|
||||
|
||||
CSmartPtr<CASWGenericEmitter> m_hEmitter; // Particle emitter for this entity
|
||||
char m_szTemplateName[MAX_PATH];
|
||||
|
||||
CHandle<C_BaseAnimating> m_hClientAttach;
|
||||
char m_szAttach[64];
|
||||
|
||||
friend class CASW_VGUI_Edit_Emitter;
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_GENERIC_EMITTER_ENTITY_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_grub.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Grub, DT_ASW_Grub, CASW_Grub)
|
||||
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Grub::C_ASW_Grub()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
C_ASW_Grub::~C_ASW_Grub()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _INLCUDE_C_ASW_GRUB_H
|
||||
#define _INLCUDE_C_ASW_GRUB_H
|
||||
|
||||
#include "c_asw_alien.h"
|
||||
|
||||
class C_ASW_Grub : public C_ASW_Alien
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Grub, C_ASW_Alien );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Grub();
|
||||
virtual ~C_ASW_Grub();
|
||||
|
||||
virtual bool IsAimTarget() { return false; }
|
||||
|
||||
private:
|
||||
C_ASW_Grub( const C_ASW_Grub & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif /* _INLCUDE_C_ASW_GRUB_H */
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_gun_smoke_emitter.h"
|
||||
#include "c_asw_generic_emitter.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// a smoke emitter that should be attached to the end of a gun
|
||||
// the gun should notify this when it fires and this class will make smoke get
|
||||
// thicker after you've been firing it for a while and then stopped
|
||||
|
||||
LINK_ENTITY_TO_CLASS( client_asw_gun_smoke_emitter, C_ASW_Gun_Smoke_Emitter );
|
||||
|
||||
#define ASW_SMOKE_DELAY 0.01f
|
||||
|
||||
C_ASW_Gun_Smoke_Emitter::C_ASW_Gun_Smoke_Emitter()
|
||||
{
|
||||
m_fFireCount = 0;
|
||||
m_fLastFireTime = 0;
|
||||
UseTemplate("autogunsmoke", true);
|
||||
}
|
||||
|
||||
void C_ASW_Gun_Smoke_Emitter::ClientThink()
|
||||
{
|
||||
if (gpGlobals->curtime - m_fLastFireTime > ASW_SMOKE_DELAY)
|
||||
{
|
||||
StartSmoking();
|
||||
m_fFireCount -= gpGlobals->frametime * 3;
|
||||
if (m_fFireCount < 0)
|
||||
m_fFireCount = 0;
|
||||
}
|
||||
BaseClass::ClientThink();
|
||||
}
|
||||
|
||||
void C_ASW_Gun_Smoke_Emitter::OnFired()
|
||||
{
|
||||
m_fLastFireTime = gpGlobals->curtime;
|
||||
StopSmoking();
|
||||
m_fFireCount = MIN(m_fFireCount + 0.5f, 10.0f);
|
||||
}
|
||||
|
||||
void C_ASW_Gun_Smoke_Emitter::StopSmoking()
|
||||
{
|
||||
m_bEmit = false;
|
||||
}
|
||||
|
||||
void C_ASW_Gun_Smoke_Emitter::StartSmoking()
|
||||
{
|
||||
m_bEmit = true;
|
||||
|
||||
float density = MIN(80.0f, m_fFireCount * 8.0f);
|
||||
if (m_hEmitter.GetObject())
|
||||
m_hEmitter->m_ParticlesPerSecond = density;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _INCLUDED_C_ASW_GUN_SMOKE_EMITTER_H
|
||||
#define _INCLUDED_C_ASW_GUN_SMOKE_EMITTER_H
|
||||
|
||||
#include "c_asw_generic_emitter_entity.h"
|
||||
|
||||
class C_ASW_Gun_Smoke_Emitter : public C_ASW_Emitter
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( C_ASW_Gun_Smoke_Emitter, C_ASW_Emitter );
|
||||
|
||||
C_ASW_Gun_Smoke_Emitter();
|
||||
virtual void ClientThink();
|
||||
void OnFired(); // our gun calls this when it fires
|
||||
void StartSmoking();
|
||||
void StopSmoking();
|
||||
|
||||
float m_fFireCount;
|
||||
float m_fLastFireTime;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDED_C_ASW_GUN_SMOKE_EMITTER_H */
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_marine_resource.h"
|
||||
#include "asw_marine_profile.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_hack.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Hack, DT_ASW_Hack, CASW_Hack)
|
||||
RecvPropEHandle (RECVINFO(m_hHackerMarineResource)),
|
||||
RecvPropEHandle (RECVINFO(m_hHackTarget)),
|
||||
RecvPropInt (RECVINFO(m_iShowOption)),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_Hack::C_ASW_Hack()
|
||||
{
|
||||
m_hHackerMarineResource = NULL;
|
||||
m_hHackTarget = NULL;
|
||||
}
|
||||
|
||||
C_ASW_Marine_Resource* C_ASW_Hack::GetHackerMarineResource()
|
||||
{
|
||||
return m_hHackerMarineResource.Get();
|
||||
}
|
||||
|
||||
C_BaseEntity* C_ASW_Hack::GetHackTarget()
|
||||
{
|
||||
return m_hHackTarget.Get();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return the player who will predict this entity
|
||||
//-----------------------------------------------------------------------------
|
||||
C_BasePlayer* C_ASW_Hack::GetPredictionOwner()
|
||||
{
|
||||
C_ASW_Marine_Resource *pMR = m_hHackerMarineResource.Get();
|
||||
if ( !pMR )
|
||||
return NULL;
|
||||
|
||||
return pMR->GetCommander();
|
||||
}
|
||||
|
||||
void C_ASW_Hack::PostDataUpdate( DataUpdateType_t updateType )
|
||||
{
|
||||
bool bPredict = ShouldPredict();
|
||||
if ( bPredict )
|
||||
{
|
||||
SetSimulatedEveryTick( true );
|
||||
SetPredictionEligible( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSimulatedEveryTick( false );
|
||||
SetPredictionEligible( false );
|
||||
}
|
||||
|
||||
BaseClass::PostDataUpdate( updateType );
|
||||
|
||||
if ( GetPredictable() && !bPredict )
|
||||
{
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
ShutdownPredictable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef _DEFINED_C_ASW_HACK
|
||||
#define _DEFINED_C_ASW_HACK
|
||||
|
||||
#include "c_asw_marine_resource.h"
|
||||
|
||||
class CUserCmd;
|
||||
class C_ASW_Marine;
|
||||
class C_ASW_Player;
|
||||
namespace vgui {
|
||||
class Panel;
|
||||
};
|
||||
|
||||
class C_ASW_Hack : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
C_ASW_Hack();
|
||||
|
||||
DECLARE_CLASS( C_ASW_Hack, C_BaseEntity );
|
||||
DECLARE_CLIENTCLASS();
|
||||
|
||||
C_ASW_Marine_Resource* GetHackerMarineResource();
|
||||
C_BaseEntity* GetHackTarget();
|
||||
|
||||
virtual void ASWPostThink(C_ASW_Player *pPlayer, C_ASW_Marine *pMarine, CUserCmd *ucmd, float fDeltaTime) { }
|
||||
virtual void ReverseTumbler(int i, C_ASW_Marine *pMarine) { }
|
||||
virtual void FrameDeleted(vgui::Panel *pPanel) { }
|
||||
virtual bool CanOverrideHack() { return false; }
|
||||
virtual float GetTumblerProgress() { return 0; }
|
||||
virtual C_BasePlayer *GetPredictionOwner( void );
|
||||
virtual void PostDataUpdate( DataUpdateType_t updateType );
|
||||
|
||||
CNetworkHandle (C_ASW_Marine_Resource, m_hHackerMarineResource); // marine info of the marine hacking
|
||||
CNetworkHandle (C_BaseEntity, m_hHackTarget);
|
||||
CNetworkVar(int, m_iShowOption);
|
||||
private:
|
||||
C_ASW_Hack( const C_ASW_Hack & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_HACK */
|
||||
@@ -0,0 +1,241 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_marine_resource.h"
|
||||
#include "asw_marine_profile.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_hack_computer.h"
|
||||
#include "c_asw_computer_area.h"
|
||||
#include "asw_vgui_computer_frame.h"
|
||||
#include "asw_vgui_computer_menu.h"
|
||||
#include "asw_vgui_frame.h"
|
||||
#include <vgui/vgui.h>
|
||||
#include <vgui_controls/Controls.h>
|
||||
#include "vgui_controls/frame.h"
|
||||
#include "iclientmode.h"
|
||||
#include <vgui/IScheme.h>
|
||||
#include "asw_input.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Hack_Computer, DT_ASW_Hack_Computer, CASW_Hack_Computer)
|
||||
RecvPropInt (RECVINFO(m_iNumTumblers)),
|
||||
RecvPropInt (RECVINFO(m_iEntriesPerTumbler)),
|
||||
RecvPropBool (RECVINFO(m_bLastAllCorrect)),
|
||||
RecvPropFloat (RECVINFO(m_fMoveInterval)),
|
||||
RecvPropFloat (RECVINFO(m_fNextMoveTime)),
|
||||
RecvPropFloat (RECVINFO(m_fFastFinishTime)),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iTumblerPosition), RecvPropInt( RECVINFO(m_iTumblerPosition[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iTumblerCorrectNumber), RecvPropInt( RECVINFO(m_iTumblerCorrectNumber[0]))),
|
||||
RecvPropArray3( RECVINFO_ARRAY(m_iTumblerDirection), RecvPropInt( RECVINFO(m_iTumblerDirection[0]))),
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_ASW_Hack_Computer )
|
||||
DEFINE_PRED_FIELD( m_fNextMoveTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_bLastAllCorrect, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_ARRAY( m_iTumblerDirection, FIELD_INTEGER, ASW_HACK_COMPUTER_MAX_TUMBLERS, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_ARRAY( m_iTumblerPosition, FIELD_INTEGER, ASW_HACK_COMPUTER_MAX_TUMBLERS, FTYPEDESC_INSENDTABLE ),
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
C_ASW_Hack_Computer::C_ASW_Hack_Computer()
|
||||
{
|
||||
m_hFrame = NULL;
|
||||
m_hComputerFrame = NULL;
|
||||
m_fTumblerDiffTime = -1;
|
||||
m_bLaunchedHackPanel = false;
|
||||
m_iShowOption = 0;
|
||||
m_iOldShowOption = 0;
|
||||
m_bLastAllCorrect = false;
|
||||
m_fStartedHackTime = 0;
|
||||
SetPredictionEligible( true );
|
||||
for (int i=0;i<ASW_HACK_COMPUTER_MAX_TUMBLERS;i++)
|
||||
{
|
||||
m_iNewTumblerDirection[i] = 0;
|
||||
m_iNewTumblerPosition[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
C_ASW_Hack_Computer::~C_ASW_Hack_Computer()
|
||||
{
|
||||
if (m_hFrame.Get() && m_hFrame->m_pNotifyHackOnClose == this)
|
||||
m_hFrame->m_pNotifyHackOnClose = NULL;
|
||||
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Computer::FrameDeleted(vgui::Panel *pPanel)
|
||||
{
|
||||
if (pPanel == m_hFrame.Get())
|
||||
{
|
||||
m_hFrame = NULL;
|
||||
}
|
||||
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Computer::ClientThink()
|
||||
{
|
||||
HACK_GETLOCALPLAYER_GUARD( "Need to support launching multiple hack panels on one machine (1 for each splitscreen player) for this to make sense." );
|
||||
if (m_bLaunchedHackPanel && GetHackerMarineResource() == NULL) // if we've launched our hack window, but the hack has lost its hacking marine, then close our window down
|
||||
{
|
||||
m_bLaunchedHackPanel = false;
|
||||
m_iOldShowOption = 0; // reset our option
|
||||
if (m_hFrame.Get())
|
||||
{
|
||||
m_hFrame->SetVisible(false);
|
||||
m_hFrame->MarkForDeletion();
|
||||
m_hFrame = NULL;
|
||||
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
}
|
||||
}
|
||||
// if we haven't launched the window and data is all present, launch it
|
||||
if (GetHackerMarineResource() != NULL)
|
||||
{
|
||||
if (!m_bLaunchedHackPanel)
|
||||
{
|
||||
if ( C_BasePlayer::IsLocalPlayer( GetHackerMarineResource()->GetCommander() ) )
|
||||
{
|
||||
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew");
|
||||
|
||||
if (GetComputerArea() && GetComputerArea()->IsPDA())
|
||||
m_hFrame = new CASW_VGUI_Computer_Container( GetClientMode()->GetViewport(), "ComputerContainer", "#asw_syntek_pda" );
|
||||
else
|
||||
m_hFrame = new CASW_VGUI_Computer_Container( GetClientMode()->GetViewport(), "ComputerContainer", "#asw_terminal_access" );
|
||||
|
||||
m_hFrame->SetScheme(scheme);
|
||||
|
||||
m_hComputerFrame = new CASW_VGUI_Computer_Frame( m_hFrame.Get(), "VGUIComputerFrame", this );
|
||||
m_hComputerFrame->SetScheme(scheme);
|
||||
m_hComputerFrame->ASWInit();
|
||||
|
||||
m_hFrame->MoveToFront();
|
||||
m_hFrame->RequestFocus();
|
||||
m_hFrame->SetVisible(true);
|
||||
m_hFrame->SetEnabled(true);
|
||||
|
||||
m_bLaunchedHackPanel = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_iOldShowOption != m_iShowOption)
|
||||
{
|
||||
if (m_fStartedHackTime == 0 && m_iShowOption == ASW_HACK_OPTION_OVERRIDE)
|
||||
m_fStartedHackTime = gpGlobals->curtime;
|
||||
Msg("C_ASW_Hack_Computer calling sethackoption as m_iShowOption = %d and m_iOldShowOption = %d\n",
|
||||
m_iShowOption, m_iOldShowOption);
|
||||
if (m_hComputerFrame.Get())
|
||||
m_hComputerFrame->SetHackOption(m_iShowOption);
|
||||
m_iOldShowOption = m_iShowOption;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check for hiding the panel if the player has a different marine selected, or if the selected marine is remote controlling a turret
|
||||
if (m_bLaunchedHackPanel && GetHackerMarineResource() && m_hFrame.Get())
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (!pPlayer)
|
||||
{
|
||||
if (m_hFrame->IsVisible())
|
||||
{
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
m_hFrame->SetVisible(false);
|
||||
//C_BaseEntity::StopSound(-1 /*SOUND_FROM_LOCAL_PLAYER*/, "ASWComputer.Loop");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bLocalPlayerControllingHacker = (GetHackerMarineResource()->IsInhabited() && GetHackerMarineResource()->GetCommanderIndex() == pPlayer->entindex());
|
||||
bool bMarineControllingTurret = (GetHackerMarineResource()->GetMarineEntity() && GetHackerMarineResource()->GetMarineEntity()->IsControllingTurret());
|
||||
|
||||
if ( bLocalPlayerControllingHacker && !bMarineControllingTurret )
|
||||
{
|
||||
ASWInput()->SetCameraFixed( true );
|
||||
|
||||
if ( !m_hFrame->IsVisible() )
|
||||
{
|
||||
m_hFrame->SetVisible(true);
|
||||
//CLocalPlayerFilter filter;
|
||||
//C_BaseEntity::EmitSound( filter, -1 /*SOUND_FROM_LOCAL_PLAYER*/, "ASWComputer.Loop" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
|
||||
if ( m_hFrame->IsVisible() )
|
||||
{
|
||||
m_hFrame->SetVisible(false);
|
||||
//C_BaseEntity::StopSound(-1 /*SOUND_FROM_LOCAL_PLAYER*/, "ASWComputer.Loop");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Computer::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// We want to think every frame.
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// predicted if the marine hacking us is inhabited locally
|
||||
bool C_ASW_Hack_Computer::ShouldPredict()
|
||||
{
|
||||
C_ASW_Marine_Resource * RESTRICT pResource = GetHackerMarineResource();
|
||||
return ( pResource && pResource->IsInhabited() && pResource->IsLocal() );
|
||||
}
|
||||
|
||||
// this returns if we can override the security (checks if the backdrop of the window is red, i.e. is the access denied screen up)
|
||||
// also allows overriding during the splash screen
|
||||
bool C_ASW_Hack_Computer::CanOverrideHack()
|
||||
{
|
||||
if (m_hComputerFrame.Get())
|
||||
{
|
||||
if (GetComputerArea() && GetComputerArea()->IsLocked())
|
||||
{
|
||||
if (m_hComputerFrame->m_iBackdropType == 1 || m_hComputerFrame->m_bPlayingSplash)
|
||||
{
|
||||
if (m_hComputerFrame->m_pMenuPanel && m_hComputerFrame->m_pMenuPanel->IsHacking()) // already hacking
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int C_ASW_Hack_Computer::GetTumblerPosition(int i)
|
||||
{
|
||||
if (i < 0 || i >= ASW_HACK_COMPUTER_MAX_TUMBLERS)
|
||||
return 0;
|
||||
|
||||
if (m_iNewTumblerPosition[i] != -1)
|
||||
return m_iNewTumblerPosition[i];
|
||||
|
||||
return m_iTumblerPosition[i];
|
||||
}
|
||||
|
||||
float C_ASW_Hack_Computer::GetTumblerDiffTime()
|
||||
{
|
||||
if (m_fTumblerDiffTime != -1)
|
||||
{
|
||||
// version used for prediction
|
||||
float fDiff = m_fTumblerDiffTime / 0.5f;
|
||||
if (fDiff >=1.0f)
|
||||
fDiff = 0;
|
||||
return fDiff;
|
||||
}
|
||||
|
||||
float fDiff = (gpGlobals->curtime - GetNextMoveTime()) / 0.5f;
|
||||
if (fDiff > 1.0f)
|
||||
fDiff = 1.0f;
|
||||
return fDiff;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef _DEFINED_C_ASW_HACK_COMPUTER_H
|
||||
#define _DEFINED_C_ASW_HACK_COMPUTER_H
|
||||
|
||||
#include "c_asw_hack.h"
|
||||
#include "asw_shareddefs.h"
|
||||
#include <vgui_controls/PHandle.h>
|
||||
|
||||
class C_ASW_Computer_Area;
|
||||
class CASW_VGUI_Computer_Frame;
|
||||
class CASW_VGUI_Frame;
|
||||
class CASW_Player;
|
||||
|
||||
class C_ASW_Hack_Computer :public C_ASW_Hack
|
||||
{
|
||||
public:
|
||||
C_ASW_Hack_Computer();
|
||||
virtual ~C_ASW_Hack_Computer();
|
||||
|
||||
DECLARE_CLASS( C_ASW_Hack_Computer, C_ASW_Hack );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void ClientThink();
|
||||
bool ShouldPredict();
|
||||
C_ASW_Computer_Area* GetComputerArea();
|
||||
float GetNextMoveTime() { return m_fNextMoveTime.Get(); }
|
||||
float GetTumblerDiffTime();
|
||||
float m_fTumblerDiffTime; // difference between curtime and movetime, calculated in our predicted function (since predicted code seems to run out of time with drawing code)
|
||||
|
||||
virtual void ASWPostThink(C_ASW_Player *pPlayer, C_ASW_Marine *pMarine, CUserCmd *ucmd, float fDeltaTime);
|
||||
virtual void ReverseTumbler(int i, C_ASW_Marine *pMarine);
|
||||
|
||||
CNetworkVar( int, m_iNumTumblers ); // how many tumblers this hack puzzle has
|
||||
CNetworkVar( int, m_iEntriesPerTumbler );
|
||||
CNetworkVar( float, m_fNextMoveTime );
|
||||
CNetworkVar( float, m_fMoveInterval );
|
||||
CNetworkArray( int, m_iTumblerPosition, ASW_HACK_COMPUTER_MAX_TUMBLERS );
|
||||
CNetworkArray( int, m_iTumblerCorrectNumber, ASW_HACK_COMPUTER_MAX_TUMBLERS );
|
||||
CNetworkArray( int, m_iTumblerDirection, ASW_HACK_COMPUTER_MAX_TUMBLERS );
|
||||
int m_iNewTumblerDirection[ASW_HACK_COMPUTER_MAX_TUMBLERS];
|
||||
int m_iNewTumblerPosition[ASW_HACK_COMPUTER_MAX_TUMBLERS];
|
||||
virtual bool CanOverrideHack();
|
||||
|
||||
// returns the tumbler position, using the clientside ones (NewTumblerPosition) if they're set
|
||||
int GetTumblerPosition(int iIndex);
|
||||
|
||||
virtual void FrameDeleted(vgui::Panel *pPanel);
|
||||
|
||||
virtual bool IsTumblerCorrect(int iTumbler);
|
||||
virtual float GetTumblerProgress();
|
||||
bool m_bLastAllCorrect;
|
||||
int m_iLastNumWrong;
|
||||
bool m_bLastHalfCorrect;
|
||||
void UpdateCorrectStatus(CASW_Player *pPlayer, C_ASW_Marine *pMarine, int iNumWrong);
|
||||
|
||||
bool m_bLaunchedHackPanel;
|
||||
int m_iOldShowOption;
|
||||
|
||||
float m_fStartedHackTime;
|
||||
float m_fFastFinishTime;
|
||||
|
||||
vgui::DHANDLE<CASW_VGUI_Frame> m_hFrame;
|
||||
vgui::DHANDLE<CASW_VGUI_Computer_Frame> m_hComputerFrame;
|
||||
|
||||
private:
|
||||
C_ASW_Hack_Computer( const C_ASW_Hack_Computer & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_HACK_COMPUTER_H */
|
||||
@@ -0,0 +1,289 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_marine_resource.h"
|
||||
#include "asw_marine_profile.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_hack_wire_tile.h"
|
||||
#include "vgui/asw_vgui_hack_wire_tile.h"
|
||||
#include "asw_vgui_frame.h"
|
||||
#include "c_asw_button_area.h"
|
||||
#include <vgui/vgui.h>
|
||||
#include <vgui_controls/Controls.h>
|
||||
#include "vgui_controls/frame.h"
|
||||
#include "iclientmode.h"
|
||||
#include <vgui/IScheme.h>
|
||||
#include "asw_input.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_ASW_Hack_Wire_Tile, DT_ASW_Hack_Wire_Tile, CASW_Hack_Wire_Tile)
|
||||
RecvPropInt (RECVINFO(m_iNumColumns) ),
|
||||
RecvPropInt (RECVINFO(m_iNumRows) ),
|
||||
RecvPropInt (RECVINFO(m_iNumWires) ),
|
||||
RecvPropFloat ( RECVINFO( m_fFastFinishTime ) ),
|
||||
RecvPropFloat (RECVINFO(m_fFinishedHackTime) ),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire1TileLit), RecvPropBool( RECVINFO(m_iWire1TileLit[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire2TileLit), RecvPropBool( RECVINFO(m_iWire2TileLit[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire3TileLit), RecvPropBool( RECVINFO(m_iWire3TileLit[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire4TileLit), RecvPropBool( RECVINFO(m_iWire4TileLit[0])) ),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire1TileType), RecvPropInt( RECVINFO(m_iWire1TileType[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire2TileType), RecvPropInt( RECVINFO(m_iWire2TileType[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire3TileType), RecvPropInt( RECVINFO(m_iWire3TileType[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire4TileType), RecvPropInt( RECVINFO(m_iWire4TileType[0])) ),
|
||||
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire1TilePosition), RecvPropInt( RECVINFO(m_iWire1TilePosition[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire2TilePosition), RecvPropInt( RECVINFO(m_iWire2TilePosition[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire3TilePosition), RecvPropInt( RECVINFO(m_iWire3TilePosition[0])) ),
|
||||
RecvPropArray3 ( RECVINFO_ARRAY(m_iWire4TilePosition), RecvPropInt( RECVINFO(m_iWire4TilePosition[0])) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( C_ASW_Hack_Wire_Tile )
|
||||
/*
|
||||
DEFINE_PRED_ARRAY( m_iWire1TilePosition, FIELD_INTEGER, ASW_TILE_ARRAY_SIZE, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_ARRAY( m_iWire2TilePosition, FIELD_INTEGER, ASW_TILE_ARRAY_SIZE, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_ARRAY( m_iWire3TilePosition, FIELD_INTEGER, ASW_TILE_ARRAY_SIZE, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_ARRAY( m_iWire4TilePosition, FIELD_INTEGER, ASW_TILE_ARRAY_SIZE, FTYPEDESC_INSENDTABLE ),
|
||||
*/
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
ConVar asw_hack_cycle_time("asw_hack_cycle_time", "0.5f", FCVAR_CHEAT);
|
||||
|
||||
C_ASW_Hack_Wire_Tile::C_ASW_Hack_Wire_Tile()
|
||||
{
|
||||
m_bLaunchedHackPanel = false;
|
||||
// clear our puzzle data so we know when the server stuff arrives
|
||||
m_iNumColumns = 0;
|
||||
m_iNumRows = 0;
|
||||
m_iNumWires = 0;
|
||||
m_hFrame = NULL;
|
||||
m_fFinishedHackTime = 0;
|
||||
m_fNextLockCycleTime = 0;
|
||||
SetPredictionEligible( true );
|
||||
|
||||
for (int w=0;w<4;w++)
|
||||
{
|
||||
for (int i=0;i<ASW_TILE_ARRAY_SIZE;i++)
|
||||
{
|
||||
m_iTempPredictedTilePosition[w][i] = -1;
|
||||
m_iTempPredictedTilePositionTime[w][i] = 0;
|
||||
m_iTempPredictedTileLit[w][i] = -1;
|
||||
m_iTempPredictedTileLitTime[w][i] = 0;
|
||||
SetTileLocked(w+1, i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
C_ASW_Hack_Wire_Tile::~C_ASW_Hack_Wire_Tile()
|
||||
{
|
||||
if (m_hFrame.Get())
|
||||
{
|
||||
if (m_hFrame->m_pNotifyHackOnClose == this)
|
||||
m_hFrame->m_pNotifyHackOnClose = NULL;
|
||||
}
|
||||
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
}
|
||||
|
||||
// predicted if the marine hacking us is inhabited locally
|
||||
bool C_ASW_Hack_Wire_Tile::ShouldPredict()
|
||||
{
|
||||
C_ASW_Marine_Resource * RESTRICT pResource = GetHackerMarineResource();
|
||||
return ( pResource && pResource->IsInhabited() && pResource->IsLocal() );
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Wire_Tile::FrameDeleted(vgui::Panel *pPanel)
|
||||
{
|
||||
if (pPanel == m_hFrame.Get())
|
||||
{
|
||||
m_hFrame = NULL;
|
||||
}
|
||||
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Wire_Tile::ClientThink()
|
||||
{
|
||||
HACK_GETLOCALPLAYER_GUARD( "Need to support launching multiple hack panels on one machine (1 for each splitscreen player) for this to make sense." );
|
||||
if (m_bLaunchedHackPanel) // if we've launched our hack window, but the hack has lost its hacking marine, then close our window down
|
||||
{
|
||||
bool bStillUsing = true;
|
||||
if (!GetHackerMarineResource())
|
||||
bStillUsing = false;
|
||||
|
||||
if (!bStillUsing)
|
||||
{
|
||||
//Msg("wire hack has lost his hacking marine\n");
|
||||
m_bLaunchedHackPanel = false;
|
||||
if (m_hFrame.Get())
|
||||
{
|
||||
m_hFrame->SetVisible(false);
|
||||
m_hFrame->MarkForDeletion();
|
||||
m_hFrame = NULL;
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we haven't launched the window and data is all present, launch it
|
||||
if (!m_bLaunchedHackPanel && m_iNumWires > 0 && GetHackerMarineResource() != NULL)
|
||||
{
|
||||
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SwarmSchemeNew.res", "SwarmSchemeNew");
|
||||
|
||||
m_hFrame = new CASW_VGUI_Hack_Wire_Tile_Container( GetClientMode()->GetViewport(), "WireTileContainer", this);
|
||||
m_hFrame->SetScheme(scheme);
|
||||
|
||||
CASW_VGUI_Hack_Wire_Tile* pHackWireFrame = new CASW_VGUI_Hack_Wire_Tile( m_hFrame.Get(), "HackWireTile", this );
|
||||
pHackWireFrame->SetScheme(scheme);
|
||||
pHackWireFrame->ASWInit();
|
||||
pHackWireFrame->MoveToFront();
|
||||
pHackWireFrame->RequestFocus();
|
||||
pHackWireFrame->SetVisible(true);
|
||||
pHackWireFrame->SetEnabled(true);
|
||||
m_bLaunchedHackPanel = true;
|
||||
}
|
||||
// check for hiding the panel if the player has a different marine selected, or if the selected marine is remote controlling a turret
|
||||
if (m_bLaunchedHackPanel && GetHackerMarineResource() && m_hFrame.Get())
|
||||
{
|
||||
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
if (!pPlayer)
|
||||
{
|
||||
m_hFrame->SetVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bLocalPlayerControllingHacker = (GetHackerMarineResource()->IsInhabited() && GetHackerMarineResource()->GetCommanderIndex() == pPlayer->entindex());
|
||||
bool bMarineControllingTurret = (GetHackerMarineResource()->GetMarineEntity() && GetHackerMarineResource()->GetMarineEntity()->IsControllingTurret());
|
||||
|
||||
if (bLocalPlayerControllingHacker && !bMarineControllingTurret)
|
||||
{
|
||||
ASWInput()->SetCameraFixed( true );
|
||||
|
||||
m_hFrame->SetVisible(true);
|
||||
|
||||
if (gpGlobals->curtime > m_fNextLockCycleTime)
|
||||
{
|
||||
m_fNextLockCycleTime = gpGlobals->curtime + asw_hack_cycle_time.GetFloat();
|
||||
CycleRows();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASWInput()->SetCameraFixed( false );
|
||||
|
||||
m_hFrame->SetVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Wire_Tile::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( updateType == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// We want to think every frame.
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
m_fNextLockCycleTime = gpGlobals->curtime + asw_hack_cycle_time.GetFloat();
|
||||
return;
|
||||
}
|
||||
if (m_fFastFinishTime != 0 && m_fStartedHackTime == 0)
|
||||
{
|
||||
m_fStartedHackTime = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Wire_Tile::SetTileLocked(int iWire, int iTileIndex, int iLocked)
|
||||
{
|
||||
if (iWire < 1 || iWire > 4)
|
||||
return;
|
||||
|
||||
if (iTileIndex < 0 || iTileIndex >= m_iNumColumns*m_iNumRows)
|
||||
return;
|
||||
|
||||
m_iTileLocked[iWire-1][iTileIndex] = iLocked;
|
||||
}
|
||||
|
||||
int C_ASW_Hack_Wire_Tile::GetTileLocked(int iWire, int iTileIndex)
|
||||
{
|
||||
if (iWire < 1 || iWire > 4)
|
||||
return 0;
|
||||
|
||||
if (iTileIndex < 0 || iTileIndex >= m_iNumColumns*m_iNumRows)
|
||||
return 0;
|
||||
|
||||
return m_iTileLocked[iWire-1][iTileIndex];
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Wire_Tile::InitLockedTiles()
|
||||
{
|
||||
// try creating a 'window' for each row
|
||||
int iWindowSize = m_iNumColumns / 2.0f;
|
||||
for (int wire=1;wire<=m_iNumWires;wire++)
|
||||
{
|
||||
for (int y=0;y<m_iNumRows;y++)
|
||||
{
|
||||
// clear the row
|
||||
for (int k=0;k<m_iNumColumns;k++)
|
||||
{
|
||||
SetTileLocked(wire, y * m_iNumColumns + k, 0);
|
||||
}
|
||||
// pick a random position for the window
|
||||
int iPos = random->RandomFloat() * m_iNumColumns;
|
||||
if (iPos < 0)
|
||||
iPos = m_iNumColumns -1;
|
||||
if (iPos >= m_iNumColumns)
|
||||
iPos = 0;
|
||||
for (int k=0;k<iWindowSize;k++)
|
||||
{
|
||||
int tilex = iPos+k;
|
||||
if (tilex >= m_iNumColumns)
|
||||
tilex -= m_iNumColumns;
|
||||
SetTileLocked(wire, y * m_iNumColumns + tilex, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_ASW_Hack_Wire_Tile::CycleRows()
|
||||
{
|
||||
//CLocalPlayerFilter filter;
|
||||
//C_BaseEntity::EmitSound( filter, -1 /*SOUND_FROM_LOCAL_PLAYER*/, "ASWComputer.ColumnTick" );
|
||||
|
||||
// copy current state shifted one into a new array
|
||||
int iNewTileLocked[4][ASW_TILE_ARRAY_SIZE];
|
||||
for (int wire=1;wire<=m_iNumWires;wire++)
|
||||
{
|
||||
for (int y=0;y<m_iNumRows;y++)
|
||||
{
|
||||
int dir = -1;
|
||||
if ((y % 2) == 0)
|
||||
dir = 1;
|
||||
for (int column=0;column<m_iNumColumns;column++)
|
||||
{
|
||||
int destx = column+dir; //(column + dir) % m_iNumColumns;
|
||||
if (destx >= m_iNumColumns)
|
||||
destx = 0;
|
||||
if (destx < 0)
|
||||
destx = m_iNumColumns -1;
|
||||
int cur = GetTileLocked(wire, y * m_iNumColumns + column);
|
||||
int destindex = y * m_iNumColumns + destx;
|
||||
|
||||
if (destindex >=0 && destindex < (m_iNumColumns*m_iNumRows) && wire>=1 && wire<=4)
|
||||
iNewTileLocked[wire-1][destindex] = cur;
|
||||
//else
|
||||
//Msg("error out of range: wire=%d destindex=%d\n", wire, destindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
// copy the new array back over us
|
||||
for (int wire=0;wire<4;wire++)
|
||||
{
|
||||
for (int i=0;i<ASW_TILE_ARRAY_SIZE;i++)
|
||||
{
|
||||
m_iTileLocked[wire][i] = iNewTileLocked[wire][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef _DEFINED_C_ASW_HACK_WIRE_TILE
|
||||
#define _DEFINED_C_ASW_HACK_WIRE_TILE
|
||||
|
||||
#include "c_asw_hack.h"
|
||||
#include <vgui_controls/PHandle.h>
|
||||
|
||||
#define ASW_MAX_TILE_COLUMNS 8
|
||||
#define ASW_MAX_TILE_ROWS 3
|
||||
#define ASW_TILE_ARRAY_SIZE (ASW_MAX_TILE_COLUMNS*ASW_MAX_TILE_ROWS)
|
||||
|
||||
class CASW_VGUI_Frame;
|
||||
|
||||
class C_ASW_Hack_Wire_Tile : public C_ASW_Hack
|
||||
{
|
||||
public:
|
||||
C_ASW_Hack_Wire_Tile();
|
||||
virtual ~C_ASW_Hack_Wire_Tile();
|
||||
|
||||
DECLARE_CLASS( C_ASW_Hack_Wire_Tile, C_ASW_Hack );
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
bool ShouldPredict();
|
||||
void ClickedNode(int iNodeNum, bool bRightSide);
|
||||
|
||||
void SetTileRotation(int iWire, int x, int y, int iRotation);
|
||||
void SetTileRotation(int iWire, int iTileIndex, int iRotation);
|
||||
|
||||
void UpdateLitTiles(int iWire);
|
||||
void SetTileLit(int iWire, int x, int y, bool bLit);
|
||||
void SetTileLit(int iWire, int iTileIndex, bool bLit);
|
||||
|
||||
CNetworkVar(int, m_iNumColumns);
|
||||
CNetworkVar(int, m_iNumRows);
|
||||
CNetworkVar(int, m_iNumWires);
|
||||
|
||||
CNetworkArray( int, m_iWire1TileType, ASW_TILE_ARRAY_SIZE );
|
||||
CNetworkArray( int, m_iWire1TilePosition, ASW_TILE_ARRAY_SIZE );
|
||||
CNetworkArray( bool, m_iWire1TileLit, ASW_TILE_ARRAY_SIZE );
|
||||
|
||||
CNetworkArray( int, m_iWire2TileType, ASW_TILE_ARRAY_SIZE );
|
||||
CNetworkArray( int, m_iWire2TilePosition, ASW_TILE_ARRAY_SIZE );
|
||||
CNetworkArray( bool, m_iWire2TileLit, ASW_TILE_ARRAY_SIZE );
|
||||
|
||||
CNetworkArray( int, m_iWire3TileType, ASW_TILE_ARRAY_SIZE );
|
||||
CNetworkArray( int, m_iWire3TilePosition, ASW_TILE_ARRAY_SIZE );
|
||||
CNetworkArray( bool, m_iWire3TileLit, ASW_TILE_ARRAY_SIZE );
|
||||
|
||||
CNetworkArray( int, m_iWire4TileType, ASW_TILE_ARRAY_SIZE );
|
||||
CNetworkArray( int, m_iWire4TilePosition, ASW_TILE_ARRAY_SIZE );
|
||||
CNetworkArray( bool, m_iWire4TileLit, ASW_TILE_ARRAY_SIZE );
|
||||
|
||||
void InitLockedTiles();
|
||||
void SetTileLocked(int iWire, int iTileIndex, int iLocked);
|
||||
int GetTileLocked(int iWire, int iTileIndex);
|
||||
int m_iTileLocked[4][ASW_TILE_ARRAY_SIZE];
|
||||
void CycleRows();
|
||||
float m_fNextLockCycleTime;
|
||||
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void ClientThink();
|
||||
virtual void FrameDeleted(vgui::Panel *pPanel);
|
||||
|
||||
// shared functions
|
||||
|
||||
bool AllWiresLit();
|
||||
bool IsWireLit(int iWire);
|
||||
bool StartTileConnected(int iWire);
|
||||
bool EndTileConnected(int iWire);
|
||||
bool TilesConnected(int iWire, int x1, int y1, int x2, int y2);
|
||||
int GetTileRotation(int iWire, int x, int y);
|
||||
int GetTileRotation(int iWire, int iTileIndex);
|
||||
int GetTileType(int iWire, int x, int y);
|
||||
int GetTileType(int iWire, int iTileIndex);
|
||||
bool GetTileLit(int iWire, int x, int y);
|
||||
bool GetTileLit(int iWire, int iTileIndex);
|
||||
float GetWireCharge();
|
||||
|
||||
vgui::DHANDLE<CASW_VGUI_Frame> m_hFrame;
|
||||
|
||||
float m_fFastFinishTime;
|
||||
float m_fStartedHackTime;
|
||||
float m_fFinishedHackTime;
|
||||
|
||||
int m_iTempPredictedTilePosition[4][ASW_TILE_ARRAY_SIZE];
|
||||
int m_iTempPredictedTileLit[4][ASW_TILE_ARRAY_SIZE];
|
||||
float m_iTempPredictedTilePositionTime[4][ASW_TILE_ARRAY_SIZE];
|
||||
float m_iTempPredictedTileLitTime[4][ASW_TILE_ARRAY_SIZE];
|
||||
|
||||
private:
|
||||
bool m_bLaunchedHackPanel;
|
||||
|
||||
C_ASW_Hack_Wire_Tile( const C_ASW_Hack_Wire_Tile & ); // not defined, not accessible
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ASW_WIRE_TILE_HORIZ = 0,
|
||||
ASW_WIRE_TILE_LEFT,
|
||||
ASW_WIRE_TILE_RIGHT,
|
||||
};
|
||||
|
||||
#endif /* _DEFINED_C_ASW_HACK_WIRE_TILE */
|
||||
@@ -0,0 +1,402 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_jeep.h"
|
||||
#include "movevars_shared.h"
|
||||
#include "view.h"
|
||||
#include "flashlighteffect.h"
|
||||
#include "c_baseplayer.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_player.h"
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/Panel.h>
|
||||
#include "asw_util_shared.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern ConVar default_fov;
|
||||
|
||||
ConVar asw_r_JeepViewBlendTo( "asw_r_JeepViewBlendTo", "1", FCVAR_CHEAT );
|
||||
ConVar asw_r_JeepViewBlendToScale( "asw_r_JeepViewBlendToScale", "0.03", FCVAR_CHEAT );
|
||||
ConVar asw_r_JeepViewBlendToTime( "asw_r_JeepViewBlendToTime", "1.5", FCVAR_CHEAT );
|
||||
ConVar asw_r_JeepFOV( "asw_r_JeepFOV", "90", FCVAR_CHEAT );
|
||||
|
||||
//DEFINE_EMBEDDED( m_VehiclePhysics ),
|
||||
|
||||
// These are necessary to save here because the 'owner' of these fields must be the prop_vehicle
|
||||
//DEFINE_PHYSPTR( m_VehiclePhysics.m_pVehicle ),
|
||||
//DEFINE_PHYSPTR_ARRAY( m_VehiclePhysics.m_pWheels ),
|
||||
|
||||
IMPLEMENT_CLIENTCLASS_DT( C_ASW_PropJeep, DT_ASW_PropJeep, CASW_PropJeep )
|
||||
RecvPropBool( RECVINFO( m_bHeadlightIsOn ) ),
|
||||
RecvPropEHandle( RECVINFO( m_hDriver ) ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
C_ASW_PropJeep::C_ASW_PropJeep()
|
||||
{
|
||||
m_vecEyeSpeed.Init();
|
||||
m_flViewAngleDeltaTime = 0.0f;
|
||||
m_pHeadlight = NULL;
|
||||
m_ViewSmoothingData.flFOV = asw_r_JeepFOV.GetFloat();
|
||||
}
|
||||
|
||||
C_ASW_PropJeep::~C_ASW_PropJeep()
|
||||
{
|
||||
if ( m_pHeadlight )
|
||||
{
|
||||
delete m_pHeadlight;
|
||||
}
|
||||
}
|
||||
|
||||
bool C_ASW_PropJeep::Simulate( void )
|
||||
{
|
||||
// The dim light is the flashlight.
|
||||
if ( m_bHeadlightIsOn )
|
||||
{
|
||||
if ( m_pHeadlight == NULL )
|
||||
{
|
||||
// Turned on the headlight; create it.
|
||||
m_pHeadlight = new CHeadlightEffect;
|
||||
|
||||
if ( m_pHeadlight == NULL )
|
||||
return false;
|
||||
|
||||
m_pHeadlight->TurnOn();
|
||||
}
|
||||
|
||||
QAngle vAngle;
|
||||
Vector vVector;
|
||||
Vector vecForward, vecRight, vecUp;
|
||||
|
||||
int iAttachment = LookupAttachment( "headlight" );
|
||||
|
||||
if ( iAttachment != -1 )
|
||||
{
|
||||
GetAttachment( iAttachment, vVector, vAngle );
|
||||
AngleVectors( vAngle, &vecForward, &vecRight, &vecUp );
|
||||
|
||||
m_pHeadlight->UpdateLight( vVector, vecForward, vecRight, vecUp, JEEP_HEADLIGHT_DISTANCE );
|
||||
}
|
||||
}
|
||||
else if ( m_pHeadlight )
|
||||
{
|
||||
// Turned off the flashlight; delete it.
|
||||
delete m_pHeadlight;
|
||||
m_pHeadlight = NULL;
|
||||
}
|
||||
|
||||
BaseClass::Simulate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Blend view angles.
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_PropJeep::UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd )
|
||||
{
|
||||
if ( asw_r_JeepViewBlendTo.GetInt() )
|
||||
{
|
||||
// Check to see if the mouse has been touched in a bit or that we are not throttling.
|
||||
if ( ( pCmd->mousedx != 0 || pCmd->mousedy != 0 ) || ( fabsf( m_flThrottle ) < 0.01f ) )
|
||||
{
|
||||
m_flViewAngleDeltaTime = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flViewAngleDeltaTime += gpGlobals->frametime;
|
||||
}
|
||||
|
||||
if ( m_flViewAngleDeltaTime > asw_r_JeepViewBlendToTime.GetFloat() )
|
||||
{
|
||||
// Blend the view angles.
|
||||
int eyeAttachmentIndex = LookupAttachment( "vehicle_driver_eyes" );
|
||||
Vector vehicleEyeOrigin;
|
||||
QAngle vehicleEyeAngles;
|
||||
GetAttachmentLocal( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
|
||||
|
||||
QAngle outAngles;
|
||||
InterpolateAngles( pCmd->viewangles, vehicleEyeAngles, outAngles, asw_r_JeepViewBlendToScale.GetFloat() );
|
||||
pCmd->viewangles = outAngles;
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::UpdateViewAngles( pLocalPlayer, pCmd );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_PropJeep::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles )
|
||||
{
|
||||
#ifdef HL2_CLIENT_DLL
|
||||
// Get the frametime. (Check to see if enough time has passed to warrent dampening).
|
||||
float flFrameTime = gpGlobals->frametime;
|
||||
|
||||
if ( flFrameTime < JEEP_FRAMETIME_MIN )
|
||||
{
|
||||
vecVehicleEyePos = m_vecLastEyePos;
|
||||
DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, 0.0f );
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep static the sideways motion.
|
||||
// Dampen forward/backward motion.
|
||||
DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
|
||||
|
||||
// Blend up/down motion.
|
||||
DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Use the controller as follows:
|
||||
// speed += ( pCoefficientsOut[0] * ( targetPos - currentPos ) + pCoefficientsOut[1] * ( targetSpeed - currentSpeed ) ) * flDeltaTime;
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_PropJeep::ComputePDControllerCoefficients( float *pCoefficientsOut,
|
||||
float flFrequency, float flDampening,
|
||||
float flDeltaTime )
|
||||
{
|
||||
float flKs = 9.0f * flFrequency * flFrequency;
|
||||
float flKd = 4.5f * flFrequency * flDampening;
|
||||
|
||||
float flScale = 1.0f / ( 1.0f + flKd * flDeltaTime + flKs * flDeltaTime * flDeltaTime );
|
||||
|
||||
pCoefficientsOut[0] = flKs * flScale;
|
||||
pCoefficientsOut[1] = ( flKd + flKs * flDeltaTime ) * flScale;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_PropJeep::DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
|
||||
{
|
||||
// vecVehicleEyePos = real eye position this frame
|
||||
|
||||
// m_vecLastEyePos = eye position last frame
|
||||
// m_vecEyeSpeed = eye speed last frame
|
||||
// vecPredEyePos = predicted eye position this frame (assuming no acceleration - it will get that from the pd controller).
|
||||
// vecPredEyeSpeed = predicted eye speed
|
||||
Vector vecPredEyePos = m_vecLastEyePos + m_vecEyeSpeed * flFrameTime;
|
||||
Vector vecPredEyeSpeed = m_vecEyeSpeed;
|
||||
|
||||
// m_vecLastEyeTarget = real eye position last frame (used for speed calculation).
|
||||
// Calculate the approximate speed based on the current vehicle eye position and the eye position last frame.
|
||||
Vector vecVehicleEyeSpeed = ( vecVehicleEyePos - m_vecLastEyeTarget ) / flFrameTime;
|
||||
m_vecLastEyeTarget = vecVehicleEyePos;
|
||||
if (vecVehicleEyeSpeed.Length() == 0.0)
|
||||
return;
|
||||
|
||||
// Calculate the delta between the predicted eye position and speed and the current eye position and speed.
|
||||
Vector vecDeltaSpeed = vecVehicleEyeSpeed - vecPredEyeSpeed;
|
||||
Vector vecDeltaPos = vecVehicleEyePos - vecPredEyePos;
|
||||
|
||||
// Forward vector.
|
||||
Vector vecForward;
|
||||
AngleVectors( vecVehicleEyeAngles, &vecForward );
|
||||
|
||||
float flDeltaLength = vecDeltaPos.Length();
|
||||
if ( flDeltaLength > JEEP_DELTA_LENGTH_MAX )
|
||||
{
|
||||
// Clamp.
|
||||
float flDelta = flDeltaLength - JEEP_DELTA_LENGTH_MAX;
|
||||
if ( flDelta > 40.0f )
|
||||
{
|
||||
// This part is a bit of a hack to get rid of large deltas (at level load, etc.).
|
||||
m_vecLastEyePos = vecVehicleEyePos;
|
||||
m_vecEyeSpeed = vecVehicleEyeSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Position clamp.
|
||||
float flRatio = JEEP_DELTA_LENGTH_MAX / flDeltaLength;
|
||||
vecDeltaPos *= flRatio;
|
||||
Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
|
||||
vecVehicleEyePos -= vecForwardOffset;
|
||||
m_vecLastEyePos = vecVehicleEyePos;
|
||||
|
||||
// Speed clamp.
|
||||
vecDeltaSpeed *= flRatio;
|
||||
float flCoefficients[2];
|
||||
ComputePDControllerCoefficients( flCoefficients, r_JeepViewDampenFreq.GetFloat(), r_JeepViewDampenDamp.GetFloat(), flFrameTime );
|
||||
m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate an updated (dampening) speed for use in next frames position prediction.
|
||||
float flCoefficients[2];
|
||||
ComputePDControllerCoefficients( flCoefficients, r_JeepViewDampenFreq.GetFloat(), r_JeepViewDampenDamp.GetFloat(), flFrameTime );
|
||||
m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime );
|
||||
|
||||
// Save off data for next frame.
|
||||
m_vecLastEyePos = vecPredEyePos;
|
||||
|
||||
// Move eye forward/backward.
|
||||
Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) );
|
||||
vecVehicleEyePos -= vecForwardOffset;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_PropJeep::DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime )
|
||||
{
|
||||
// Get up vector.
|
||||
Vector vecUp;
|
||||
AngleVectors( vecVehicleEyeAngles, NULL, NULL, &vecUp );
|
||||
vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z );
|
||||
vecVehicleEyePos.z += r_JeepViewZHeight.GetFloat() * vecUp.z;
|
||||
|
||||
// NOTE: Should probably use some damped equation here.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_PropJeep::OnEnteredVehicle( C_BasePlayer *pPlayer )
|
||||
{
|
||||
int eyeAttachmentIndex = LookupAttachment( "vehicle_driver_eyes" );
|
||||
Vector vehicleEyeOrigin;
|
||||
QAngle vehicleEyeAngles;
|
||||
GetAttachment( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
|
||||
|
||||
m_vecLastEyeTarget = vehicleEyeOrigin;
|
||||
m_vecLastEyePos = vehicleEyeOrigin;
|
||||
m_vecEyeSpeed = vec3_origin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ASWWheelDustCallback( const CEffectData &data )
|
||||
{
|
||||
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" );
|
||||
pSimple->SetSortOrigin( data.m_vOrigin );
|
||||
pSimple->SetNearClip( 32, 64 );
|
||||
|
||||
SimpleParticle *pParticle;
|
||||
|
||||
Vector offset;
|
||||
|
||||
//FIXME: Better sampling area
|
||||
offset = data.m_vOrigin + ( data.m_vNormal * data.m_flScale );
|
||||
|
||||
//Find area ambient light color and use it to tint smoke
|
||||
Vector worldLight = WorldGetLightForPoint( offset, true );
|
||||
|
||||
PMaterialHandle hMaterial = pSimple->GetPMaterial("particle/particle_smokegrenade");;
|
||||
|
||||
//Throw puffs
|
||||
offset.Random( -(data.m_flScale*16.0f), data.m_flScale*16.0f );
|
||||
offset.z = 0.0f;
|
||||
offset += data.m_vOrigin + ( data.m_vNormal * data.m_flScale );
|
||||
|
||||
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), hMaterial, offset );
|
||||
|
||||
if ( pParticle != NULL )
|
||||
{
|
||||
pParticle->m_flLifetime = 0.0f;
|
||||
pParticle->m_flDieTime = random->RandomFloat( 0.25f, 0.5f );
|
||||
|
||||
pParticle->m_vecVelocity = RandomVector( -1.0f, 1.0f );
|
||||
VectorNormalize( pParticle->m_vecVelocity );
|
||||
pParticle->m_vecVelocity[2] += random->RandomFloat( 16.0f, 32.0f ) * (data.m_flScale*2.0f);
|
||||
|
||||
int color = random->RandomInt( 100, 150 );
|
||||
|
||||
pParticle->m_uchColor[0] = 16 + ( worldLight[0] * (float) color );
|
||||
pParticle->m_uchColor[1] = 8 + ( worldLight[1] * (float) color );
|
||||
pParticle->m_uchColor[2] = ( worldLight[2] * (float) color );
|
||||
|
||||
pParticle->m_uchStartAlpha = random->RandomInt( 64.0f*data.m_flScale, 128.0f*data.m_flScale );
|
||||
pParticle->m_uchEndAlpha = 0;
|
||||
pParticle->m_uchStartSize = random->RandomInt( 16, 24 ) * data.m_flScale;
|
||||
pParticle->m_uchEndSize = random->RandomInt( 32, 48 ) * data.m_flScale;
|
||||
pParticle->m_flRoll = random->RandomInt( 0, 360 );
|
||||
pParticle->m_flRollDelta = random->RandomFloat( -2.0f, 2.0f );
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_CLIENT_EFFECT( ASWWheelDust, ASWWheelDustCallback );
|
||||
|
||||
// implement driver interface
|
||||
C_ASW_Marine* C_ASW_PropJeep::ASWGetDriver()
|
||||
{
|
||||
return dynamic_cast<C_ASW_Marine*>(m_hDriver.Get());
|
||||
}
|
||||
|
||||
// implement client vehicle interface
|
||||
bool C_ASW_PropJeep::s_bLoadedDriveIconTexture = false;
|
||||
int C_ASW_PropJeep::s_nDriveIconTextureID = -1;
|
||||
bool C_ASW_PropJeep::s_bLoadedRideIconTexture = false;
|
||||
int C_ASW_PropJeep::s_nRideIconTextureID = -1;
|
||||
|
||||
int C_ASW_PropJeep::GetDriveIconTexture()
|
||||
{
|
||||
if (!s_bLoadedDriveIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nDriveIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nDriveIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedDriveIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nDriveIconTextureID;
|
||||
}
|
||||
int C_ASW_PropJeep::GetRideIconTexture()
|
||||
{
|
||||
if (!s_bLoadedRideIconTexture)
|
||||
{
|
||||
// load the portrait textures
|
||||
s_nRideIconTextureID = vgui::surface()->CreateNewTextureID();
|
||||
vgui::surface()->DrawSetTextureFile( s_nRideIconTextureID, "vgui/swarm/UseIcons/PanelUnlocked", true, false);
|
||||
s_bLoadedRideIconTexture = true;
|
||||
}
|
||||
|
||||
return s_nRideIconTextureID;
|
||||
}
|
||||
|
||||
bool C_ASW_PropJeep::MarineInVehicle()
|
||||
{
|
||||
C_ASW_Player* pPlayer = C_ASW_Player::GetLocalASWPlayer();
|
||||
return (pPlayer && pPlayer->GetMarine() && pPlayer->GetMarine()->IsInVehicle());
|
||||
}
|
||||
|
||||
const char* C_ASW_PropJeep::GetDriveIconText()
|
||||
{
|
||||
if (MarineInVehicle())
|
||||
return "Exit Vehicle";
|
||||
|
||||
return "Drive";
|
||||
}
|
||||
|
||||
const char* C_ASW_PropJeep::GetRideIconText()
|
||||
{
|
||||
if (MarineInVehicle())
|
||||
return "Exit Vehicle";
|
||||
|
||||
return "Passenger";
|
||||
}
|
||||
|
||||
bool C_ASW_PropJeep::IsUsable(C_BaseEntity *pUser)
|
||||
{
|
||||
return (pUser && pUser->GetAbsOrigin().DistTo(GetAbsOrigin()) < ASW_MARINE_USE_RADIUS); // near enough?
|
||||
}
|
||||
|
||||
bool C_ASW_PropJeep::GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser)
|
||||
{
|
||||
action.iUseIconTexture = GetDriveIconTexture();
|
||||
TryLocalize( GetDriveIconText(), action.wszText, sizeof( action.wszText ) );
|
||||
action.UseTarget = GetEntity();
|
||||
action.fProgress = -1;
|
||||
action.UseIconRed = 255;
|
||||
action.UseIconGreen = 255;
|
||||
action.UseIconBlue = 255;
|
||||
action.bShowUseKey = true;
|
||||
action.iInventorySlot = -1;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef _INCLUDED_C_ASW_JEEP_H
|
||||
#define _INCLUDED_C_ASW_JEEP_H
|
||||
#pragma once
|
||||
|
||||
#include "c_prop_vehicle.h"
|
||||
#include "c_asw_fourwheelvehiclephysics.h" // asw
|
||||
#include "iasw_client_vehicle.h"
|
||||
#include "c_asw_marine.h"
|
||||
|
||||
#define JEEP_DELTA_LENGTH_MAX 12.0f // 1 foot
|
||||
#define JEEP_FRAMETIME_MIN 1e-6
|
||||
#define JEEP_HEADLIGHT_DISTANCE 1000
|
||||
|
||||
class CHeadlightEffect;
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Client-side Jeep Class
|
||||
//
|
||||
class C_ASW_PropJeep : public C_PropVehicleDriveable, public IASW_Client_Vehicle
|
||||
{
|
||||
|
||||
DECLARE_CLASS( C_ASW_PropJeep, C_PropVehicleDriveable );
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_INTERPOLATION();
|
||||
|
||||
C_ASW_PropJeep();
|
||||
virtual ~C_ASW_PropJeep();
|
||||
|
||||
public:
|
||||
|
||||
void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd );
|
||||
void DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles );
|
||||
|
||||
void OnEnteredVehicle( C_BasePlayer *pPlayer );
|
||||
bool Simulate( void );
|
||||
|
||||
public:
|
||||
|
||||
void DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime );
|
||||
void DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime );
|
||||
void ComputePDControllerCoefficients( float *pCoefficientsOut, float flFrequency, float flDampening, float flDeltaTime );
|
||||
|
||||
// implement our asw vehicle interface
|
||||
virtual int ASWGetNumPassengers() { return 0; } // todo: implement
|
||||
virtual C_ASW_Marine* ASWGetDriver();
|
||||
virtual C_ASW_Marine* ASWGetPassenger(int i) { return NULL; } // todo: implement
|
||||
CNetworkHandle(C_ASW_Marine, m_hDriver);
|
||||
// implement client vehicle interface
|
||||
virtual bool ValidUseTarget() { return true; }
|
||||
virtual int GetDriveIconTexture();
|
||||
virtual int GetRideIconTexture();
|
||||
virtual const char* GetDriveIconText();
|
||||
virtual const char* GetRideIconText();
|
||||
virtual C_BaseEntity* GetEntity() { return this; }
|
||||
static bool s_bLoadedRideIconTexture;
|
||||
static int s_nRideIconTextureID;
|
||||
static bool s_bLoadedDriveIconTexture;
|
||||
static int s_nDriveIconTextureID;
|
||||
// no clientside prediction for this kind of vehicle
|
||||
virtual void SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) { }
|
||||
virtual void ProcessMovement( C_BasePlayer *pPlayer, CMoveData *pMoveData ) { }
|
||||
virtual void ASWStartEngine() { }
|
||||
virtual void ASWStopEngine() { }
|
||||
|
||||
bool MarineInVehicle();
|
||||
|
||||
virtual bool IsUsable(C_BaseEntity *pUser);
|
||||
virtual bool GetUseAction(ASWUseAction &action, C_ASW_Marine *pUser);
|
||||
virtual void CustomPaint(int ix, int iy, int alpha, vgui::Panel *pUseIcon) { }
|
||||
virtual bool ShouldPaintBoxAround() { return (ASWGetDriver() == NULL); }
|
||||
|
||||
protected:
|
||||
|
||||
Vector m_vecSmoothedVelocity;
|
||||
Vector m_vecLastEyePos;
|
||||
Vector m_vecLastEyeTarget;
|
||||
Vector m_vecEyeSpeed;
|
||||
Vector m_vecTargetSpeed;
|
||||
|
||||
float m_flViewAngleDeltaTime;
|
||||
|
||||
float m_flJeepFOV;
|
||||
CHeadlightEffect *m_pHeadlight;
|
||||
bool m_bHeadlightIsOn;
|
||||
};
|
||||
|
||||
#endif // _INCLUDED_C_ASW_JEEP_H
|
||||
@@ -0,0 +1,401 @@
|
||||
#include "cbase.h"
|
||||
#include "c_asw_jeep_clientside.h"
|
||||
#include "props_shared.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "in_buttons.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define SMOOTHING_FACTOR 0.9
|
||||
|
||||
C_ASW_PropJeep_Clientside *C_ASW_PropJeep_Clientside::CreateNew( bool bForce )
|
||||
{
|
||||
C_ASW_PropJeep_Clientside* pVehicle;
|
||||
pVehicle = new C_ASW_PropJeep_Clientside();
|
||||
//pVehicle->Initialize();
|
||||
|
||||
return pVehicle;
|
||||
}
|
||||
|
||||
C_ASW_PropJeep_Clientside::C_ASW_PropJeep_Clientside() : m_VehiclePhysics( this )
|
||||
{
|
||||
m_bInitialisedPhysics = false;
|
||||
|
||||
//m_fDeathTime = -1;
|
||||
//m_impactEnergyScale = 1.0f;
|
||||
m_iHealth = 0;
|
||||
bDestroyVehicle = false;
|
||||
//m_iPhysicsMode = PHYSICS_MULTIPLAYER_AUTODETECT;
|
||||
|
||||
//s_PhysPropList.AddToTail( this );
|
||||
Msg("C_ASW_PropJeep_Clientside created\n");
|
||||
}
|
||||
|
||||
C_ASW_PropJeep_Clientside::~C_ASW_PropJeep_Clientside()
|
||||
{
|
||||
//PhysCleanupFrictionSounds( this );
|
||||
//VPhysicsDestroyObject();
|
||||
//s_PhysPropList.FindAndRemove( this );
|
||||
}
|
||||
|
||||
#define VEHICLE_MODEL "models/buggy.mdl"
|
||||
//#define VEHICLE_MODEL "models/combine_APC.mdl"
|
||||
|
||||
bool C_ASW_PropJeep_Clientside::Initialize()
|
||||
{
|
||||
SetModelName( VEHICLE_MODEL );
|
||||
PrecacheModel(VEHICLE_MODEL);
|
||||
SetModel(VEHICLE_MODEL);
|
||||
if ( InitializeAsClientEntity( STRING(GetModelName()), false ) == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const model_t *mod = GetModel();
|
||||
if ( mod )
|
||||
{
|
||||
Vector mins, maxs;
|
||||
modelinfo->GetModelBounds( mod, mins, maxs );
|
||||
SetCollisionBounds( mins, maxs );
|
||||
}
|
||||
|
||||
solid_t tmpSolid;
|
||||
|
||||
// Create the object in the physics system
|
||||
|
||||
if ( !PhysModelParseSolid( tmpSolid, this, GetModelIndex() ) )
|
||||
{
|
||||
DevMsg("C_ASW_PropJeep_Clientside::Initialize: PhysModelParseSolid failed for entity %i.\n", GetModelIndex() );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pPhysicsObject = VPhysicsInitNormal( SOLID_VPHYSICS, 0, false, &tmpSolid );
|
||||
|
||||
if ( !m_pPhysicsObject )
|
||||
{
|
||||
// failed to create a physics object
|
||||
DevMsg(" C_ASW_PropJeep_Clientside::Initialize: VPhysicsInitNormal() failed for %s.\n", STRING(GetModelName()) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Spawn();
|
||||
|
||||
if ( engine->IsInEditMode() )
|
||||
{
|
||||
// don't spawn in map edit mode
|
||||
return false;
|
||||
}
|
||||
|
||||
// player can push it away
|
||||
SetCollisionGroup( COLLISION_GROUP_VEHICLE );
|
||||
|
||||
UpdatePartitionListEntry();
|
||||
|
||||
CollisionProp()->UpdatePartition();
|
||||
|
||||
//SetBlocksLOS( false ); // this should be a small object
|
||||
|
||||
// Set up shadows; do it here so that objects can change shadowcasting state
|
||||
CreateShadow();
|
||||
|
||||
UpdateVisibility();
|
||||
|
||||
SetNextClientThink( gpGlobals->curtime + 0.4f );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::ClientThink()
|
||||
{
|
||||
if (m_bInitialisedPhysics)
|
||||
{
|
||||
// if we have no driver, then destroy the clientside vehicle
|
||||
if (bDestroyVehicle)
|
||||
{
|
||||
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||
// todo: reveal the dummy?
|
||||
Release();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ThinkTick();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InitPhysics();
|
||||
}
|
||||
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::Spawn()
|
||||
{
|
||||
m_VehiclePhysics.SetOuter( this );
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
//SetModel("models/buggy.mdl");
|
||||
|
||||
m_vecSmoothedVelocity.Init();
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
m_takedamage = DAMAGE_NO;
|
||||
AddSolidFlags( FSOLID_NOT_STANDABLE );
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int C_ASW_PropJeep_Clientside::VPhysicsGetObjectList( IPhysicsObject **pList, int listMax )
|
||||
{
|
||||
return m_VehiclePhysics.VPhysicsGetObjectList( pList, listMax );
|
||||
}
|
||||
|
||||
// pass passenger type questions on to the dummy
|
||||
int C_ASW_PropJeep_Clientside::ASWGetNumPassengers()
|
||||
{
|
||||
if (GetDummy())
|
||||
return GetDummy()->ASWGetNumPassengers();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
C_ASW_Marine* C_ASW_PropJeep_Clientside::ASWGetDriver()
|
||||
{
|
||||
if (GetDummy())
|
||||
return GetDummy()->ASWGetDriver();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
C_ASW_Marine* C_ASW_PropJeep_Clientside::ASWGetPassenger(int i)
|
||||
{
|
||||
if (GetDummy())
|
||||
return GetDummy()->ASWGetPassenger(i);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IASW_Client_Vehicle* C_ASW_PropJeep_Clientside::GetDummy()
|
||||
{
|
||||
C_ASW_Marine* pMarine = ASWGetDriver();
|
||||
if (!pMarine)
|
||||
return NULL;
|
||||
|
||||
return pMarine->GetASWVehicle();
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
|
||||
{
|
||||
if (!m_bInitialisedPhysics)
|
||||
return;
|
||||
//Msg("SetupMove cnum=%d [C] forward=%f side=%f", ucmd->command_number, ucmd->forwardmove, ucmd->sidemove);
|
||||
DriveVehicle( player, ucmd );
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::ProcessMovement( C_BasePlayer *pPlayer, CMoveData *pMoveData )
|
||||
{
|
||||
if (!m_bInitialisedPhysics)
|
||||
return;
|
||||
//Msg("[C] PreProcess \tx=%f\t\ty=%f\t\tz=%f\t\tp=%\t\ty=%\t\tr=%\t\tvx=%f\t\tvy=%f\t\tvz=%f\n",
|
||||
//GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z,
|
||||
//GetAbsAngles().x, GetAbsAngles().y, GetAbsAngles().z,
|
||||
//GetAbsVelocity().x, GetAbsVelocity().y, GetAbsVelocity().z);
|
||||
// Update the steering angles based on speed.
|
||||
UpdateSteeringAngle();
|
||||
|
||||
//ThinkTick();
|
||||
//Msg("[C] PostProcess \tx=%f\t\ty=%f\t\tz=%f\t\tp=%\t\ty=%\t\tr=%\t\tvx=%f\t\tvy=%f\t\tvz=%f\n",
|
||||
//GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z,
|
||||
//GetAbsAngles().x, GetAbsAngles().y, GetAbsAngles().z,
|
||||
//GetAbsVelocity().x, GetAbsVelocity().y, GetAbsVelocity().z);
|
||||
}
|
||||
|
||||
#define JEEP_STEERING_SLOW_ANGLE 50.0f
|
||||
#define JEEP_STEERING_FAST_ANGLE 15.0f
|
||||
|
||||
void C_ASW_PropJeep_Clientside::UpdateSteeringAngle( void )
|
||||
{
|
||||
float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed();
|
||||
float flSpeed = m_VehiclePhysics.GetSpeed();
|
||||
|
||||
float flRatio = 1.0f - ( flSpeed / flMaxSpeed );
|
||||
float flSteeringDegrees = JEEP_STEERING_FAST_ANGLE + ( ( JEEP_STEERING_SLOW_ANGLE - JEEP_STEERING_FAST_ANGLE ) * flRatio );
|
||||
flSteeringDegrees = clamp( flSteeringDegrees, JEEP_STEERING_FAST_ANGLE, JEEP_STEERING_SLOW_ANGLE );
|
||||
m_VehiclePhysics.SetSteeringDegrees( flSteeringDegrees );
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::ThinkTick()
|
||||
{
|
||||
m_VehiclePhysics.Think( gpGlobals->frametime );
|
||||
|
||||
//SetSimulationTime( gpGlobals->curtime );
|
||||
|
||||
//SetAnimatedEveryTick( true );
|
||||
|
||||
StudioFrameAdvance();
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::DriveVehicle( C_BasePlayer *pPlayer, CUserCmd *ucmd )
|
||||
{
|
||||
//Lose control when the player dies
|
||||
if ( pPlayer->IsAlive() == false )
|
||||
return;
|
||||
|
||||
DriveVehicle( TICK_INTERVAL, ucmd, pPlayer->m_afButtonPressed, pPlayer->m_afButtonReleased );
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased )
|
||||
{
|
||||
int iButtons = ucmd->buttons;
|
||||
|
||||
// Only handle the cannon if the vehicle has one
|
||||
/*
|
||||
if ( m_bHasGun )
|
||||
{
|
||||
// If we're holding down an attack button, update our state
|
||||
if ( IsOverturned() == false )
|
||||
{
|
||||
if ( iButtons & IN_ATTACK )
|
||||
{
|
||||
if ( m_bCannonCharging )
|
||||
{
|
||||
FireChargedCannon();
|
||||
}
|
||||
else
|
||||
{
|
||||
FireCannon();
|
||||
}
|
||||
}
|
||||
else if ( iButtons & IN_ATTACK2 )
|
||||
{
|
||||
ChargeCannon();
|
||||
}
|
||||
}
|
||||
|
||||
// If we've released our secondary button, fire off our cannon
|
||||
if ( ( iButtonsReleased & IN_ATTACK2 ) && ( m_bCannonCharging ) )
|
||||
{
|
||||
FireChargedCannon();
|
||||
}
|
||||
}*/
|
||||
|
||||
m_VehiclePhysics.UpdateDriverControls( ucmd, flFrameTime );
|
||||
|
||||
m_nSpeed = m_VehiclePhysics.GetSpeed(); //send speed to client
|
||||
m_nRPM = clamp( m_VehiclePhysics.GetRPM(), 0, 4095 );
|
||||
m_nBoostTimeLeft = m_VehiclePhysics.BoostTimeLeft();
|
||||
m_nHasBoost = m_VehiclePhysics.HasBoost();
|
||||
m_flThrottle = m_VehiclePhysics.GetThrottle();
|
||||
|
||||
m_nScannerDisabledWeapons = false; // off for now, change once we have scanners
|
||||
m_nScannerDisabledVehicle = false; // off for now, change once we have scanners
|
||||
|
||||
//
|
||||
// Fire the appropriate outputs based on button pressed events.
|
||||
//
|
||||
// BUGBUG: m_afButtonPressed is broken - check the player.cpp code!!!
|
||||
float attack = 0, attack2 = 0;
|
||||
|
||||
/*
|
||||
if ( iButtonsDown & IN_ATTACK )
|
||||
{
|
||||
m_pressedAttack.FireOutput( this, this, 0 );
|
||||
}
|
||||
if ( iButtonsDown & IN_ATTACK2 )
|
||||
{
|
||||
m_pressedAttack2.FireOutput( this, this, 0 );
|
||||
}*/
|
||||
|
||||
if ( iButtons & IN_ATTACK )
|
||||
{
|
||||
attack = 1;
|
||||
}
|
||||
if ( iButtons & IN_ATTACK2 )
|
||||
{
|
||||
attack2 = 1;
|
||||
}
|
||||
|
||||
//m_attackaxis.Set( attack, this, this );
|
||||
//m_attack2axis.Set( attack2, this, this );
|
||||
}
|
||||
|
||||
/*
|
||||
void CPropVehicle::DrawDebugGeometryOverlays()
|
||||
{
|
||||
if (m_debugOverlays & OVERLAY_BBOX_BIT)
|
||||
{
|
||||
m_VehiclePhysics.DrawDebugGeometryOverlays();
|
||||
}
|
||||
BaseClass::DrawDebugGeometryOverlays();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void C_ASW_PropJeep_Clientside::VPhysicsUpdate( IPhysicsObject *pPhysics )
|
||||
{
|
||||
if ( IsMarkedForDeletion() )
|
||||
return;
|
||||
|
||||
Vector velocity;
|
||||
VPhysicsGetObject()->GetVelocity( &velocity, NULL );
|
||||
|
||||
//Update our smoothed velocity
|
||||
m_vecSmoothedVelocity = m_vecSmoothedVelocity * SMOOTHING_FACTOR + velocity * ( 1 - SMOOTHING_FACTOR );
|
||||
|
||||
// must be a wheel
|
||||
if (!m_VehiclePhysics.VPhysicsUpdate( pPhysics ))
|
||||
return;
|
||||
|
||||
BaseClass::VPhysicsUpdate( pPhysics );
|
||||
|
||||
if (!m_bInitialisedPhysics)
|
||||
InitPhysics();
|
||||
|
||||
//if (!ASWGetDriver())
|
||||
//SetNextClientThink(gpGlobals->curtime);
|
||||
ThinkTick();
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::InitPhysics()
|
||||
{
|
||||
if (m_bInitialisedPhysics)
|
||||
return;
|
||||
|
||||
m_VehiclePhysics.Spawn();
|
||||
if (!m_VehiclePhysics.Initialize( "scripts/vehicles/jeep_test.txt", VEHICLE_TYPE_CAR_WHEELS ))
|
||||
return;
|
||||
|
||||
ASWStartEngine();
|
||||
m_bInitialisedPhysics = true;
|
||||
}
|
||||
|
||||
void C_ASW_PropJeep_Clientside::ASWStartEngine( void )
|
||||
{
|
||||
//if ( m_bEngineLocked )
|
||||
//{
|
||||
//m_VehiclePhysics.SetHandbrake( true );
|
||||
//return;
|
||||
//}
|
||||
|
||||
m_VehiclePhysics.TurnOn();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_ASW_PropJeep_Clientside::ASWStopEngine( void )
|
||||
{
|
||||
m_VehiclePhysics.TurnOff();
|
||||
|
||||
bDestroyVehicle = true;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef _INCLUDED_C_ASW_JEEP_CLIENTSIDE_H
|
||||
#define _INCLUDED_C_ASW_JEEP_CLIENTSIDE_H
|
||||
#pragma once
|
||||
|
||||
#include "c_asw_jeep.h"
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Client-side Jeep Class
|
||||
//
|
||||
class C_ASW_PropJeep_Clientside : public C_ASW_PropJeep
|
||||
{
|
||||
DECLARE_CLASS( C_ASW_PropJeep_Clientside, C_ASW_PropJeep );
|
||||
|
||||
public:
|
||||
|
||||
C_ASW_PropJeep_Clientside();
|
||||
virtual ~C_ASW_PropJeep_Clientside();
|
||||
virtual void Spawn();
|
||||
bool Initialize();
|
||||
virtual void ClientThink();
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax );
|
||||
static C_ASW_PropJeep_Clientside *CreateNew(bool bForce = false);
|
||||
|
||||
// asw
|
||||
virtual void InitPhysics();
|
||||
virtual void SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move );
|
||||
virtual void ProcessMovement( C_BasePlayer *pPlayer, CMoveData *pMoveData );
|
||||
virtual void DriveVehicle( C_BasePlayer *pPlayer, CUserCmd *ucmd );
|
||||
virtual void DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased );
|
||||
virtual void UpdateSteeringAngle();
|
||||
virtual void ThinkTick();
|
||||
virtual void VPhysicsUpdate( IPhysicsObject *pPhysics );
|
||||
virtual bool ShouldPredict() { return true; }
|
||||
// asw: our clientside physics
|
||||
C_ASW_FourWheelVehiclePhysics m_VehiclePhysics;
|
||||
|
||||
// implement our asw vehicle interface (pass these on to the dummy)
|
||||
virtual int ASWGetNumPassengers();
|
||||
virtual C_ASW_Marine* ASWGetDriver();
|
||||
virtual C_ASW_Marine* ASWGetPassenger(int i);
|
||||
IASW_Client_Vehicle* GetDummy(); // the dummy entity that other players see for our vehicle
|
||||
virtual void ASWStartEngine();
|
||||
virtual void ASWStopEngine(); // destroys the vehicle!
|
||||
virtual bool ValidUseTarget() { return false; }
|
||||
|
||||
bool m_bInitialisedPhysics; // asw
|
||||
bool bDestroyVehicle;
|
||||
};
|
||||
|
||||
#endif // _INCLUDED_C_ASW_JEEP_CLIENTSIDE_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user