mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-07-30 17:11:52 +03:00
commit
6cc2937f5a
7
.gitignore
vendored
7
.gitignore
vendored
@ -19,6 +19,8 @@ ipch
|
||||
*.idb
|
||||
*.vcxproj
|
||||
*.sln
|
||||
*.vcxproj.FileListAbsolute.txt
|
||||
*.pdb
|
||||
|
||||
# OSX/Linux build products
|
||||
*.mak
|
||||
@ -49,6 +51,8 @@ client.dylib.dSYM/
|
||||
server.dylib
|
||||
server.dylib.dSYM/
|
||||
|
||||
sp/game/bin
|
||||
|
||||
# files generated by running a mod
|
||||
config.cfg
|
||||
|
||||
@ -61,6 +65,7 @@ config.cfg
|
||||
*.filters
|
||||
*.vpc_crc
|
||||
*.sentinel
|
||||
*.recipe
|
||||
|
||||
# Backup files
|
||||
*.bak
|
||||
@ -90,4 +95,4 @@ sp/src/vgui2/*.dll
|
||||
sp/src/vgui2/*.pdb
|
||||
|
||||
# Build support files
|
||||
sp/src/devtools/gcc9+support.o
|
||||
sp/src/devtools/gcc9+support.o
|
33
README
33
README
@ -1,6 +1,6 @@
|
||||
//=========================================================================================================================
|
||||
|
||||
Mapbase v7.3 - Source 2013
|
||||
Mapbase v8.0 - Source 2013
|
||||
https://github.com/mapbase-source/source-sdk-2013
|
||||
https://www.moddb.com/mods/mapbase
|
||||
|
||||
@ -52,6 +52,7 @@ Mapbase uses content from the following non-Source SDK 2013 Valve games or SDKs:
|
||||
-- Alien Swarm (Used to port assets from the aforementioned SDK code features, e.g. game instructor icons)
|
||||
-- Left 4 Dead (Used to port certain animations as well as assets from the aforementioned SDK code features, e.g. particle rain)
|
||||
-- Half-Life: Source (Used to port friction tool textures)
|
||||
-- Half-Life 2: Survivor (Used to port Gordon Freeman model)
|
||||
|
||||
Valve allows assets from these titles to be distributed for modding purposes. Note that ported assets are only used in the release build, not the code repository.
|
||||
|
||||
@ -118,7 +119,9 @@ Direct contributions:
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/245 (ViewPunch random fix by Mr0maks)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/248 (soundlevel_t conversation warning fix by Mechami)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/266 ("OnPhysGunPull" output in CPhysicsProp by rlenhub)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/281 (npc_combinedropship DropStrider input by Bronzehawk75)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/292 (env_headcrabcanister random spawn type by arbabf)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/293 (Restore text selection code by SanyaSho)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/294 (SDK_LightmappedGeneric editor blend swap fix by azzyr)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/308 (BlurFilterY fix by Wikot235)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/312 (Zombie improvements by Wikot235)
|
||||
@ -126,17 +129,33 @@ Direct contributions:
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/324 (server-only info/func_null by SirYodaJedi)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/333 (Cvar to transition levels while in MOVETYPE_NOCLIP by Wikot235)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/342 (NaN particle cull radius fix by celisej567)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/360 (.gitignore update by Unusuario2)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/381 (color_correction_volume crash fix by Nbc66)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/385 (VRAD -ultrafast command by Unusuario2)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/391 (VRAD -extrapasses command by Unusuario2)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/393 (Additional VBSP options doc by Unusuario2)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/397 (Viewmodel camera bone by Nbc66)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/412 (Compile tool negative threads support by Unusuario2)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/414 (VRAD %alphatexture by SirYodaJedi)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/415 (Parallax corrected cubemaps optimization and fix by Zeldaboy14 and White_Red_Dragons)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/418 (Server ragdoll death poses by AnOldLady)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/419 (npc_helicopter removal crash fix by Wikot235)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/420 (sk_combine_head_dmg_multiplier cvar by Wikot235)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/422 (Expanded HL2 NPC custom model support by Maestra Fenix [committed by Blixibon])
|
||||
- https://github.com/mapbase-source/mapbase-game-src/pull/1 (Advanced video options duplicate field name fix by arbabf; This is asset-based and not reflected in the code)
|
||||
- https://github.com/mapbase-source/mapbase-game-src/pull/2 (gameinfo.txt typo fix by CarePackage17; This is asset-based and not reflected in the code)
|
||||
- https://github.com/mapbase-source/mapbase-game-src/pull/3 (HudMessage cutoff fix by arbabf; This is asset-based and not reflected in the code)
|
||||
- Demo autorecord code provided by Klems
|
||||
- cc_emit crash fix provided by 1upD
|
||||
- npc_barnacle poison zombie crash fix provided by Agrimar
|
||||
- Custom HL2 ammo crate models created by Rykah (Textures created by Blixibon; This is asset-based and, aside from the SLAM crate, not reflected in the code)
|
||||
- Combine lock hardware on door01_left.mdl created by Kralich (This is asset-based and not reflected in the code)
|
||||
- npc_vehicledriver fixes provided by CrAzY
|
||||
- npc_combine cover behavior patches provided by iohnnyboy
|
||||
- logic_playmovie icon created by URAKOLOUY5 (This is asset-based and not reflected in the code)
|
||||
- Dropship APC save/load fix provided by Cvoxulary
|
||||
- c_arms support on HL2 viewmodels by Inaki and ReverendV92 (This is asset-based and not reflected in the code)
|
||||
- Custom c_arms for HL2 characters by Notewell (This is asset-based and not reflected in the code)
|
||||
|
||||
== Contributions from samisalreadytaken:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/47 (VScript utility/consistency changes)
|
||||
@ -154,11 +173,19 @@ Direct contributions:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/192 (VScript hook manager and fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/206 (Fix CScriptNetMsgHelper::WriteEntity())
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/213 (VScript HUD visibility control, optimizations for 3D skybox angles/fake worldportals)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/221 (VScript serialization rewrite)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/229 (VScript VGUI HUD viewport parenting, game_text and vgui_text_display VScript font fallback)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/260 (CScriptNetPropManager rewrite)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/261 (Misc VScript additions)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/279 (weapon_custom_scripted fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/302 (VScript debugger)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/331 (VScript leak fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/332 (Fix OOB access)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/411 (VScript debugger cleanup)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/423 (GetPropFloatArray Vector indexing fix)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/431 (VScript save/restore and debugger fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/441 (VScript instance helper fallback)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/447 (Update VScript sqdbg)
|
||||
|
||||
== Contributions from z33ky:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux compilation fixes)
|
||||
@ -172,7 +199,10 @@ Direct contributions:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/159 (Additional GCC/Linux compilation fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/162 (VS2019 exception specification fix)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/170 (HL2 non-Episodic build fix)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/320 (Fix ScriptHook_t initialization order)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/321 (Prevent return of dangling Vector/QAngle to VScript)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/322 (Small Mapbase fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/436 (VScript member function call safety)
|
||||
|
||||
== Contributions from Petercov:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/182 (NPCs load dynamic interactions from all animation MDLs)
|
||||
@ -183,6 +213,7 @@ Direct contributions:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/230 (Caption fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/231 (Sentence source bug fix)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/264 (Outputs for vgui_screen)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/427 (CBaseCombatWeapon::WeaponClassFromString typo fix [committed by vizzys])
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -1531,35 +1531,32 @@ float C_BaseAnimating::ClampCycle( float flCycle, bool isLooping )
|
||||
//-----------------------------------------------------------------------------
|
||||
const Vector& C_BaseAnimating::ScriptGetAttachmentOrigin( int iAttachment )
|
||||
{
|
||||
|
||||
static Vector absOrigin;
|
||||
static QAngle qa;
|
||||
QAngle qa;
|
||||
|
||||
C_BaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
|
||||
|
||||
return absOrigin;
|
||||
}
|
||||
|
||||
const Vector& C_BaseAnimating::ScriptGetAttachmentAngles( int iAttachment )
|
||||
const QAngle& C_BaseAnimating::ScriptGetAttachmentAngles( int iAttachment )
|
||||
{
|
||||
|
||||
static Vector absOrigin;
|
||||
static Vector absAngles;
|
||||
static QAngle qa;
|
||||
Vector absOrigin;
|
||||
|
||||
C_BaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
|
||||
absAngles.x = qa.x;
|
||||
absAngles.y = qa.y;
|
||||
absAngles.z = qa.z;
|
||||
return absAngles;
|
||||
return qa;
|
||||
}
|
||||
|
||||
HSCRIPT C_BaseAnimating::ScriptGetAttachmentMatrix( int iAttachment )
|
||||
HSCRIPT_RC C_BaseAnimating::ScriptGetAttachmentMatrix( int iAttachment )
|
||||
{
|
||||
static matrix3x4_t matrix;
|
||||
matrix3x4_t *matrix = new matrix3x4_t;
|
||||
|
||||
C_BaseAnimating::GetAttachment( iAttachment, matrix );
|
||||
return g_pScriptVM->RegisterInstance( &matrix );
|
||||
if ( C_BaseAnimating::GetAttachment( iAttachment, *matrix ) )
|
||||
return g_pScriptVM->RegisterInstance( matrix, true );
|
||||
|
||||
delete matrix;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void C_BaseAnimating::ScriptGetBoneTransform( int iBone, HSCRIPT hTransform )
|
||||
|
@ -464,8 +464,8 @@ public:
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
int ScriptLookupAttachment( const char *pAttachmentName ) { return LookupAttachment( pAttachmentName ); }
|
||||
const Vector& ScriptGetAttachmentOrigin(int iAttachment);
|
||||
const Vector& ScriptGetAttachmentAngles(int iAttachment);
|
||||
HSCRIPT ScriptGetAttachmentMatrix(int iAttachment);
|
||||
const QAngle& ScriptGetAttachmentAngles(int iAttachment);
|
||||
HSCRIPT_RC ScriptGetAttachmentMatrix(int iAttachment);
|
||||
|
||||
void ScriptGetBoneTransform( int iBone, HSCRIPT hTransform );
|
||||
void ScriptSetBoneTransform( int iBone, HSCRIPT hTransform );
|
||||
|
@ -90,11 +90,10 @@ static inline bool ShouldDrawLocalPlayerViewModel( void )
|
||||
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
|
||||
if (localplayer)
|
||||
{
|
||||
if (localplayer->m_bDrawPlayerModelExternally)
|
||||
if (localplayer->DrawingPlayerModelExternally() && localplayer->InFirstPersonView())
|
||||
{
|
||||
// If this isn't the main view, draw the weapon.
|
||||
view_id_t viewID = CurrentViewID();
|
||||
if (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)
|
||||
if (!localplayer->InPerspectiveView())
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -224,8 +223,16 @@ ShadowType_t C_BaseCombatWeapon::ShadowCastType()
|
||||
if (!IsBeingCarried())
|
||||
return SHADOWS_RENDER_TO_TEXTURE;
|
||||
|
||||
if (IsCarriedByLocalPlayer() && !C_BasePlayer::ShouldDrawLocalPlayer())
|
||||
return SHADOWS_NONE;
|
||||
if (IsCarriedByLocalPlayer())
|
||||
{
|
||||
if (!C_BasePlayer::ShouldDrawLocalPlayer())
|
||||
return SHADOWS_NONE;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (C_BasePlayer::GetLocalPlayer() && C_BasePlayer::GetLocalPlayer()->ShadowCastType() == SHADOWS_NONE)
|
||||
return SHADOWS_NONE;
|
||||
#endif
|
||||
}
|
||||
|
||||
return SHADOWS_RENDER_TO_TEXTURE;
|
||||
}
|
||||
@ -458,7 +465,7 @@ bool C_BaseCombatWeapon::ShouldDraw( void )
|
||||
|
||||
#ifdef MAPBASE
|
||||
// We're drawing this in non-main views, handle it in DrawModel()
|
||||
if ( pLocalPlayer->m_bDrawPlayerModelExternally )
|
||||
if ( pLocalPlayer->DrawingPlayerModelExternally() )
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@ -511,11 +518,10 @@ int C_BaseCombatWeapon::DrawModel( int flags )
|
||||
if ( localplayer )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (localplayer->m_bDrawPlayerModelExternally)
|
||||
if (GetOwner() == localplayer && localplayer->DrawingPlayerModelExternally())
|
||||
{
|
||||
// If this isn't the main view, draw the weapon.
|
||||
view_id_t viewID = CurrentViewID();
|
||||
if ( (!localplayer->InFirstPersonView() || (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)) && (viewID != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)) )
|
||||
if ( (!localplayer->InPerspectiveView() || !localplayer->InFirstPersonView()) && (CurrentViewID() != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)))
|
||||
{
|
||||
// TODO: Is this inefficient?
|
||||
int nModelIndex = GetModelIndex();
|
||||
@ -534,6 +540,10 @@ int C_BaseCombatWeapon::DrawModel( int flags )
|
||||
|
||||
return iDraw;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ( localplayer->IsObserver() && GetOwner() )
|
||||
@ -551,6 +561,24 @@ int C_BaseCombatWeapon::DrawModel( int flags )
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_BaseCombatWeapon::DispatchMuzzleEffect( const char *options, bool isFirstPerson )
|
||||
{
|
||||
// Don't show muzzle flashes in first-person
|
||||
C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||||
if (pPlayer)
|
||||
{
|
||||
if (pPlayer->DrawingPlayerModelExternally() && pPlayer->InFirstPersonView())
|
||||
return false;
|
||||
}
|
||||
|
||||
return BaseClass::DispatchMuzzleEffect( options, isFirstPerson );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Allows the client-side entity to override what the network tells it to use for
|
||||
|
@ -433,8 +433,7 @@ ScriptHook_t C_BaseEntity::g_Hook_UpdateOnRemove;
|
||||
ScriptHook_t C_BaseEntity::g_Hook_ModifyEmitSoundParams;
|
||||
#endif
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities" )
|
||||
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT_WITH_HELPER( C_BaseEntity, "Root class of all client-side entities", &g_BaseEntityScriptInstanceHelper )
|
||||
DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetForward, "GetForwardVector", "Get the forward vector of the entity" )
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
|
@ -125,6 +125,16 @@ ConVar demo_fov_override( "demo_fov_override", "0", FCVAR_CLIENTDLL | FCVAR_DONT
|
||||
// This value is found by hand, and a good value depends more on the in-game models than on actual human shapes.
|
||||
ConVar cl_meathook_neck_pivot_ingame_up( "cl_meathook_neck_pivot_ingame_up", "7.0" );
|
||||
ConVar cl_meathook_neck_pivot_ingame_fwd( "cl_meathook_neck_pivot_ingame_fwd", "3.0" );
|
||||
#ifdef MAPBASE
|
||||
ConVar cl_meathook_neck_pivot_override( "cl_meathook_neck_pivot_override", "0", FCVAR_NONE, "Overrides playermodel values for meathook and uses cvars only" );
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
ConVar cl_playermodel_draw_externally_override( "cl_playermodel_draw_externally_override", "-1", FCVAR_ARCHIVE, "Overrides developer-placed options to draw the player's model externally." );
|
||||
|
||||
ConVar cl_playermodel_legs_override( "cl_playermodel_legs_override", "-1", FCVAR_ARCHIVE, "Overrides developer-placed options to draw the player's model below the camera." );
|
||||
ConVar cl_playermodel_legs_scale_bones( "cl_playermodel_legs_scale_bones", "1" );
|
||||
#endif
|
||||
|
||||
void RecvProxy_LocalVelocityX( const CRecvProxyData *pData, void *pStruct, void *pOut );
|
||||
void RecvProxy_LocalVelocityY( const CRecvProxyData *pData, void *pStruct, void *pOut );
|
||||
@ -280,6 +290,7 @@ END_RECV_TABLE()
|
||||
// See baseplayer_shared.h for more details.
|
||||
RecvPropInt ( RECVINFO( m_spawnflags ), 0, RecvProxy_ShiftPlayerSpawnflags ),
|
||||
|
||||
RecvPropBool ( RECVINFO( m_bDrawPlayerLegs ) ),
|
||||
RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ),
|
||||
RecvPropBool ( RECVINFO( m_bInTriggerFall ) ),
|
||||
#endif
|
||||
@ -1486,13 +1497,186 @@ bool C_BasePlayer::ShouldInterpolate()
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool C_BasePlayer::InPerspectiveView() const
|
||||
{
|
||||
// VIEW_NONE is used by the water intersection view, see CAboveWaterView::CIntersectionView::Draw()
|
||||
// (TODO: Consider changing the view ID at the source to VIEW_REFRACTION? VIEW_NONE could be an oversight)
|
||||
view_id_t viewID = CurrentViewID();
|
||||
return (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA || viewID == VIEW_REFRACTION || viewID == VIEW_NONE);
|
||||
}
|
||||
|
||||
bool C_BasePlayer::DrawingPlayerModelExternally() const
|
||||
{
|
||||
if (cl_playermodel_draw_externally_override.GetInt() > -1)
|
||||
return cl_playermodel_draw_externally_override.GetBool();
|
||||
|
||||
return m_bDrawPlayerModelExternally;
|
||||
}
|
||||
|
||||
bool C_BasePlayer::DrawingLegs() const
|
||||
{
|
||||
if (cl_playermodel_legs_override.GetInt() > -1)
|
||||
return cl_playermodel_legs_override.GetBool();
|
||||
|
||||
// For now, don't draw legs if looking up in any way
|
||||
// (fixes issues with some animations causing clipping with chest)
|
||||
if (GetAbsAngles().x < 0.0f)
|
||||
return false;
|
||||
|
||||
return m_bDrawPlayerLegs;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CStudioHdr *C_BasePlayer::OnNewModel( void )
|
||||
{
|
||||
CStudioHdr *hdr = BaseClass::OnNewModel();
|
||||
if (!hdr)
|
||||
return NULL;
|
||||
|
||||
KeyValues *modelKeyValues = new KeyValues( "" );
|
||||
CUtlBuffer buf( 1024, 0, CUtlBuffer::TEXT_BUFFER );
|
||||
|
||||
// Init values
|
||||
m_FirstPersonModelData.Reset();
|
||||
|
||||
if (!modelinfo->GetModelKeyValue( GetModel(), buf ))
|
||||
{
|
||||
modelKeyValues->deleteThis();
|
||||
return hdr;
|
||||
}
|
||||
|
||||
if (modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), buf ))
|
||||
{
|
||||
CUtlVector<string_t> iszUsedNames;
|
||||
for (KeyValues *pkvModelBlock = modelKeyValues; pkvModelBlock != nullptr; pkvModelBlock = pkvModelBlock->GetNextKey())
|
||||
{
|
||||
KeyValues *pkvPlayerModelData = pkvModelBlock->FindKey( "playermodel_data" );
|
||||
if (pkvPlayerModelData)
|
||||
{
|
||||
m_FirstPersonModelData.ParseModelData( this, pkvPlayerModelData );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modelKeyValues->deleteThis();
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BasePlayer::FirstPersonModelData_t::ParseModelData( C_BasePlayer *pPlayer, KeyValues *pkvPlayerModelData )
|
||||
{
|
||||
m_flFirstPersonNeckPivotUp = pkvPlayerModelData->GetFloat( "neck_pivot_up", FLT_MAX );
|
||||
m_flFirstPersonNeckPivotFwd = pkvPlayerModelData->GetFloat( "neck_pivot_fwd", FLT_MAX );
|
||||
|
||||
m_flFirstPersonNeckPivotDuckUp = pkvPlayerModelData->GetFloat( "neck_pivot_duck_up", FLT_MAX );
|
||||
m_flFirstPersonNeckPivotDuckFwd = pkvPlayerModelData->GetFloat( "neck_pivot_duck_fwd", FLT_MAX );
|
||||
|
||||
KeyValues *pkvBoneScales = pkvPlayerModelData->FindKey( "bone_transforms" );
|
||||
if (pkvBoneScales)
|
||||
{
|
||||
KeyValues *pkvSpineTransforms = pkvBoneScales->FindKey( "spine" );
|
||||
if (pkvSpineTransforms)
|
||||
{
|
||||
for (KeyValues *pkvBone = pkvSpineTransforms->GetFirstSubKey(); pkvBone != nullptr; pkvBone = pkvBone->GetNextKey())
|
||||
{
|
||||
int nBone = pPlayer->LookupBone( pkvBone->GetName() );
|
||||
if (nBone == -1)
|
||||
continue;
|
||||
|
||||
m_FirstPersonBoneScales[BoneScales_Spine].Insert(nBone, pkvBone->GetFloat());
|
||||
}
|
||||
}
|
||||
|
||||
KeyValues *pkvArmsTransforms = pkvBoneScales->FindKey( "arms" );
|
||||
if (pkvArmsTransforms)
|
||||
{
|
||||
for (KeyValues *pkvBone = pkvArmsTransforms->GetFirstSubKey(); pkvBone != nullptr; pkvBone = pkvBone->GetNextKey())
|
||||
{
|
||||
int nBone = pPlayer->LookupBone( pkvBone->GetName() );
|
||||
if (nBone == -1)
|
||||
continue;
|
||||
|
||||
m_FirstPersonBoneScales[BoneScales_Arms].Insert( nBone, pkvBone->GetFloat() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: move position and rotation transforms into global matrices
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BasePlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion *q, const matrix3x4_t &cameraTransform, int boneMask, CBoneBitList &boneComputed )
|
||||
{
|
||||
BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed );
|
||||
|
||||
if (DrawingLegs() && InPerspectiveView() && InFirstPersonView())
|
||||
{
|
||||
//BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" );
|
||||
|
||||
if (cl_playermodel_legs_scale_bones.GetBool())
|
||||
{
|
||||
// For now, only do transforms when we have an active weapon
|
||||
// (since we typically just cull stuff influenced by viewmodels and upper-body weapon posture, like arms)
|
||||
if ((GetActiveWeapon() && !GetActiveWeapon()->IsEffectActive( EF_NODRAW )) || GetUseEntity())
|
||||
{
|
||||
matrix3x4_t *pFirstZero = NULL;
|
||||
|
||||
for (int nMap = 0; nMap < FirstPersonModelData_t::BoneScales_Max; nMap++)
|
||||
{
|
||||
const CUtlMap<int, float> &scaleMap = m_FirstPersonModelData.m_FirstPersonBoneScales[nMap];
|
||||
FOR_EACH_MAP( scaleMap, i )
|
||||
{
|
||||
int nBone = scaleMap.Key(i);
|
||||
if (nBone == -1)
|
||||
continue;
|
||||
|
||||
if (!(hdr->boneFlags( nBone ) & boneMask))
|
||||
continue;
|
||||
|
||||
float flScale = scaleMap.Element(i);
|
||||
|
||||
matrix3x4_t &mTransform = GetBoneForWrite( nBone );
|
||||
|
||||
if (flScale == 0.0f)
|
||||
{
|
||||
if (!pFirstZero)
|
||||
{
|
||||
MatrixScaleByZero( mTransform );
|
||||
pFirstZero = &mTransform;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep zeroes in one place
|
||||
MatrixCopy( *pFirstZero, mTransform );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MatrixScaleBy( flScale, mTransform );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool C_BasePlayer::ShouldDraw()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// We have to "always draw" a player with m_bDrawPlayerModelExternally in order to show up in whatever rendering list all of the views use,
|
||||
// but we can't put this in ShouldDrawThisPlayer() because we would have no way of knowing if it stomps the other checks that draw the player model anyway.
|
||||
// As a result, we have to put it here in the central ShouldDraw() function. DrawModel() makes sure we only draw in non-main views and nothing's drawing the model anyway.
|
||||
return (ShouldDrawThisPlayer() || m_bDrawPlayerModelExternally) && BaseClass::ShouldDraw();
|
||||
return (ShouldDrawThisPlayer() || DrawingPlayerModelExternally() || DrawingLegs()) && BaseClass::ShouldDraw();
|
||||
#else
|
||||
return ShouldDrawThisPlayer() && BaseClass::ShouldDraw();
|
||||
#endif
|
||||
@ -1501,12 +1685,16 @@ bool C_BasePlayer::ShouldDraw()
|
||||
int C_BasePlayer::DrawModel( int flags )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (m_bDrawPlayerModelExternally)
|
||||
if (DrawingLegs() && InFirstPersonView() && InPerspectiveView())
|
||||
{
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
if (DrawingPlayerModelExternally())
|
||||
{
|
||||
// Draw the player in any view except the main or "intro" view, both of which are default first-person views.
|
||||
// HACKHACK: Also don't draw in shadow depth textures if the player's flashlight is on, as that causes the playermodel to block it.
|
||||
view_id_t viewID = CurrentViewID();
|
||||
if (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA || (viewID == VIEW_SHADOW_DEPTH_TEXTURE && IsEffectActive(EF_DIMLIGHT)))
|
||||
if (InPerspectiveView() || (CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE && IsEffectActive(EF_DIMLIGHT)))
|
||||
{
|
||||
// Make sure the player model wouldn't draw anyway...
|
||||
if (!ShouldDrawThisPlayer())
|
||||
@ -3057,13 +3245,21 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( !InPerspectiveView() )
|
||||
#else
|
||||
if ( !DrawingMainView() )
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If we aren't drawing the player anyway, don't mess with the bones. This can happen in Portal.
|
||||
#ifdef MAPBASE
|
||||
if ( !ShouldDrawThisPlayer() && !DrawingPlayerModelExternally() && !DrawingLegs() )
|
||||
#else
|
||||
if( !ShouldDrawThisPlayer() )
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -3084,6 +3280,63 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec
|
||||
Vector vHeadTransformTranslation ( mHeadTransform[0][3], mHeadTransform[1][3], mHeadTransform[2][3] );
|
||||
|
||||
|
||||
float flNeckPivotUp = cl_meathook_neck_pivot_ingame_up.GetFloat();
|
||||
float flNeckPivotFwd = cl_meathook_neck_pivot_ingame_fwd.GetFloat();
|
||||
#ifdef MAPBASE
|
||||
if (DrawingLegs() && !cl_meathook_neck_pivot_override.GetBool())
|
||||
{
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotUp != FLT_MAX || m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd != FLT_MAX)
|
||||
{
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotUp != FLT_MAX)
|
||||
flNeckPivotUp = m_FirstPersonModelData.m_flFirstPersonNeckPivotUp;
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd != FLT_MAX)
|
||||
flNeckPivotFwd = m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd;
|
||||
|
||||
if (GetFlags() & FL_DUCKING || m_Local.m_flDucktime > 0.0f)
|
||||
{
|
||||
if (!IsLocalPlayer() || m_Local.m_flDucktime <= 0.0f)
|
||||
{
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX)
|
||||
flNeckPivotUp = m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp;
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX)
|
||||
flNeckPivotFwd = m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bDucking;
|
||||
if (IsLocalPlayer())
|
||||
bDucking = input->GetButtonBits(0) & IN_DUCK;
|
||||
else
|
||||
bDucking = GetCurrentUserCommand()->buttons & IN_DUCK;
|
||||
|
||||
// HACKHACK using constants from game movement
|
||||
float flPerc = SimpleSpline( RemapValClamped( m_Local.m_flDucktime, bDucking ? 600.0f : 800.0f, 1000.0f, 0.0f, 1.0f ) );
|
||||
|
||||
if (bDucking)
|
||||
{
|
||||
// Ducking
|
||||
//Msg( "Ducking with perc %f (%f)\n", flPerc, m_Local.m_flDucktime );
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX)
|
||||
flNeckPivotUp = FLerp( m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp, flNeckPivotUp, flPerc );
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX)
|
||||
flNeckPivotFwd = FLerp( m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd, flNeckPivotFwd, flPerc );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unducking
|
||||
//Msg( "Unducking with perc %f (%f)\n", flPerc, m_Local.m_flDucktime );
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX)
|
||||
flNeckPivotUp = FLerp( flNeckPivotUp, m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp, flPerc );
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX)
|
||||
flNeckPivotFwd = FLerp( flNeckPivotFwd, m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd, flPerc );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Find out where the player's head (driven by the HMD) is in the world.
|
||||
// We can't move this with animations or effects without causing nausea, so we need to move
|
||||
// the whole body so that the animated head is in the right place to match the player-controlled head.
|
||||
@ -3100,7 +3353,7 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec
|
||||
// The head bone is the neck pivot point of the in-game character.
|
||||
|
||||
Vector vRealMidEyePos = mWorldFromMideye.GetTranslation();
|
||||
vRealPivotPoint = vRealMidEyePos - ( mWorldFromMideye.GetUp() * cl_meathook_neck_pivot_ingame_up.GetFloat() ) - ( mWorldFromMideye.GetForward() * cl_meathook_neck_pivot_ingame_fwd.GetFloat() );
|
||||
vRealPivotPoint = vRealMidEyePos - ( mWorldFromMideye.GetUp() * flNeckPivotUp ) - ( mWorldFromMideye.GetForward() * flNeckPivotFwd );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3108,7 +3361,7 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec
|
||||
Vector vForward, vRight, vUp;
|
||||
AngleVectors( MainViewAngles(), &vForward, &vRight, &vUp );
|
||||
|
||||
vRealPivotPoint = MainViewOrigin() - ( vUp * cl_meathook_neck_pivot_ingame_up.GetFloat() ) - ( vForward * cl_meathook_neck_pivot_ingame_fwd.GetFloat() );
|
||||
vRealPivotPoint = MainViewOrigin() - ( vUp * flNeckPivotUp ) - ( vForward * flNeckPivotFwd );
|
||||
}
|
||||
|
||||
Vector vDeltaToAdd = vRealPivotPoint - vHeadTransformTranslation;
|
||||
|
@ -293,6 +293,15 @@ public:
|
||||
|
||||
virtual bool ShouldInterpolate();
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool InPerspectiveView() const; // In a view that renders directly from the player's perspective (and may, for example, render the playermodel)
|
||||
bool DrawingPlayerModelExternally() const;
|
||||
bool DrawingLegs() const;
|
||||
|
||||
virtual CStudioHdr *OnNewModel( void );
|
||||
virtual void BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t &cameraTransform, int boneMask, CBoneBitList &boneComputed );
|
||||
#endif
|
||||
|
||||
virtual bool ShouldDraw();
|
||||
virtual int DrawModel( int flags );
|
||||
|
||||
@ -468,6 +477,9 @@ public:
|
||||
inline void RemoveSpawnFlags( int flags ) { m_spawnflags &= ~flags; }
|
||||
inline void AddSpawnFlags( int flags ) { m_spawnflags |= flags; }
|
||||
|
||||
// Draws the player's model below the camera, visible when the player looks down.
|
||||
bool m_bDrawPlayerLegs;
|
||||
|
||||
// Allows the player's model to draw on non-main views, like monitors or mirrors.
|
||||
bool m_bDrawPlayerModelExternally;
|
||||
|
||||
@ -502,6 +514,10 @@ protected:
|
||||
|
||||
virtual void FireGameEvent( IGameEvent *event );
|
||||
|
||||
#ifdef MAPBASE
|
||||
inline CUtlMap<int, float> &GetFirstPersonArmScales() { return m_FirstPersonModelData.m_FirstPersonBoneScales[FirstPersonModelData_t::BoneScales_Arms]; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Did we just enter a vehicle this frame?
|
||||
bool JustEnteredVehicle();
|
||||
@ -556,6 +572,41 @@ private:
|
||||
|
||||
bool m_bFiredWeapon;
|
||||
|
||||
#ifdef MAPBASE
|
||||
struct FirstPersonModelData_t
|
||||
{
|
||||
void Reset()
|
||||
{
|
||||
m_flFirstPersonNeckPivotUp = m_flFirstPersonNeckPivotFwd = FLT_MAX;
|
||||
m_flFirstPersonNeckPivotDuckUp = m_flFirstPersonNeckPivotDuckFwd = FLT_MAX;
|
||||
|
||||
for (int i = 0; i < BoneScales_Max; i++)
|
||||
{
|
||||
m_FirstPersonBoneScales[i].RemoveAll();
|
||||
m_FirstPersonBoneScales[i].SetLessFunc( DefLessFunc( int ) );
|
||||
}
|
||||
}
|
||||
|
||||
void ParseModelData( C_BasePlayer *pPlayer, KeyValues *pkvPlayerModelData );
|
||||
|
||||
enum
|
||||
{
|
||||
BoneScales_Spine,
|
||||
BoneScales_Arms,
|
||||
|
||||
BoneScales_Max
|
||||
};
|
||||
|
||||
// Values to scale bones by when drawing playermodel in first person
|
||||
CUtlMap<int, float> m_FirstPersonBoneScales[BoneScales_Max];
|
||||
|
||||
float m_flFirstPersonNeckPivotUp, m_flFirstPersonNeckPivotFwd = FLT_MAX;
|
||||
float m_flFirstPersonNeckPivotDuckUp, m_flFirstPersonNeckPivotDuckFwd = FLT_MAX;
|
||||
};
|
||||
|
||||
FirstPersonModelData_t m_FirstPersonModelData;
|
||||
#endif
|
||||
|
||||
|
||||
// Player flashlight dynamic light pointers
|
||||
CFlashlightEffect *m_pFlashlight;
|
||||
|
@ -399,10 +399,38 @@ int C_SpriteRenderer::DrawSprite(
|
||||
if ( group == RENDER_GROUP_VIEW_MODEL_TRANSLUCENT || group == RENDER_GROUP_VIEW_MODEL_OPAQUE )
|
||||
return 0;
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
if (ent->m_iViewHideFlags > 0)
|
||||
{
|
||||
// Hide this entity if it's not supposed to be drawn in this view.
|
||||
if (ent->m_iViewHideFlags & (1 << CurrentViewID()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
QAngle temp;
|
||||
ent->GetAttachment( attachmentindex, effect_origin, temp );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( entity )
|
||||
{
|
||||
C_BaseEntity *ent = entity->GetBaseEntity();
|
||||
if ( ent )
|
||||
{
|
||||
if (ent->m_iViewHideFlags > 0)
|
||||
{
|
||||
// Hide this entity if it's not supposed to be drawn in this view.
|
||||
if (ent->m_iViewHideFlags & (1 << CurrentViewID()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( rendermode != kRenderNormal )
|
||||
{
|
||||
|
@ -47,8 +47,12 @@ $Project
|
||||
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\matchers.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\matchers.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\mapbase_playeranimstate.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\mapbase_playeranimstate.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\game_timer.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\game_timer.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT]
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT]
|
||||
@ -71,6 +75,7 @@ $Project
|
||||
$File "mapbase\c_vgui_text_display.cpp"
|
||||
$File "mapbase\c_weapon_custom_hl2.cpp"
|
||||
$File "mapbase\mapbase_autocubemap.cpp"
|
||||
$File "mapbase\hud_generic_timer.cpp"
|
||||
}
|
||||
|
||||
$Folder "HL2 DLL"
|
||||
|
@ -157,6 +157,22 @@ void CColorCorrectionMgr::CommitColorCorrectionWeights()
|
||||
}
|
||||
m_colorCorrectionWeights.RemoveAll();
|
||||
}
|
||||
|
||||
void CColorCorrectionMgr::LevelShutdownPreEntity()
|
||||
{
|
||||
//Clean up the vectors when shuting down a level
|
||||
//will keep dangling pointers inside of the vector causing a nullptr crash
|
||||
if (g_ColorCorrectionVolumeList.Base())
|
||||
{
|
||||
g_ColorCorrectionVolumeList.Purge();
|
||||
}
|
||||
|
||||
if (g_ColorCorrectionList.Base())
|
||||
{
|
||||
g_ColorCorrectionList.Purge();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight )
|
||||
{
|
||||
|
@ -76,6 +76,8 @@ private:
|
||||
CUtlVector< SetWeightParams_t > m_colorCorrectionWeights;
|
||||
|
||||
void CommitColorCorrectionWeights();
|
||||
|
||||
void LevelShutdownPreEntity();
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -31,8 +31,12 @@ ConVar cl_npc_speedmod_outtime( "cl_npc_speedmod_outtime", "1.5", FCVAR_CLIENTDL
|
||||
IMPLEMENT_CLIENTCLASS_DT(C_BaseHLPlayer, DT_HL2_Player, CHL2_Player)
|
||||
RecvPropDataTable( RECVINFO_DT(m_HL2Local),0, &REFERENCE_RECV_TABLE(DT_HL2Local) ),
|
||||
RecvPropBool( RECVINFO( m_fIsSprinting ) ),
|
||||
#ifdef MAPBASE
|
||||
RecvPropInt( RECVINFO( m_nProtagonistIndex ) ),
|
||||
#endif
|
||||
#ifdef SP_ANIM_STATE
|
||||
RecvPropFloat( RECVINFO( m_flAnimRenderYaw ) ),
|
||||
RecvPropFloat( RECVINFO( m_flAnimRenderZ ) ),
|
||||
#endif
|
||||
END_RECV_TABLE()
|
||||
|
||||
@ -78,6 +82,8 @@ C_BaseHLPlayer::C_BaseHLPlayer()
|
||||
#ifdef MAPBASE
|
||||
ConVarRef scissor("r_flashlightscissor");
|
||||
scissor.SetValue("0");
|
||||
|
||||
m_nProtagonistIndex = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -103,6 +109,22 @@ void C_BaseHLPlayer::OnDataChanged( DataUpdateType_t updateType )
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseHLPlayer::AddEntity( void )
|
||||
{
|
||||
BaseClass::AddEntity();
|
||||
|
||||
#ifdef MAPBASE_MP
|
||||
if (m_pPlayerAnimState)
|
||||
{
|
||||
QAngle angEyeAngles = EyeAngles();
|
||||
m_pPlayerAnimState->Update( angEyeAngles.y, angEyeAngles.x );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -664,24 +686,76 @@ bool C_BaseHLPlayer::CreateMove( float flInputSampleTime, CUserCmd *pCmd )
|
||||
void C_BaseHLPlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed )
|
||||
{
|
||||
BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed );
|
||||
/*#ifdef MAPBASE
|
||||
// BuildFirstPersonMeathookTransformations is used prior to this when drawing legs
|
||||
if (!DrawingLegs() || !InPerspectiveView() || !InFirstPersonView())
|
||||
#endif*/
|
||||
BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" );
|
||||
}
|
||||
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const Vector &C_BaseHLPlayer::GetRenderOrigin()
|
||||
{
|
||||
if (m_flAnimRenderZ != 0.0f)
|
||||
{
|
||||
static Vector vecRender;
|
||||
vecRender = BaseClass::GetRenderOrigin();
|
||||
vecRender.z += m_flAnimRenderZ;
|
||||
return vecRender;
|
||||
}
|
||||
|
||||
return BaseClass::GetRenderOrigin();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const QAngle& C_BaseHLPlayer::GetRenderAngles( void )
|
||||
{
|
||||
#ifdef MAPBASE_MP
|
||||
if ( m_pPlayerAnimState )
|
||||
{
|
||||
return m_pPlayerAnimState->GetRenderAngles();
|
||||
}
|
||||
#else
|
||||
if ( m_flAnimRenderYaw != FLT_MAX )
|
||||
{
|
||||
return m_angAnimRender;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return BaseClass::GetRenderAngles();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: model-change notification. Fires on dynamic load completion as well
|
||||
//-----------------------------------------------------------------------------
|
||||
CStudioHdr *C_BaseHLPlayer::OnNewModel()
|
||||
{
|
||||
CStudioHdr *hdr = BaseClass::OnNewModel();
|
||||
|
||||
#ifdef MAPBASE_MP
|
||||
// Clears the animation state if we already have one.
|
||||
if ( m_pPlayerAnimState != NULL )
|
||||
{
|
||||
m_pPlayerAnimState->Release();
|
||||
m_pPlayerAnimState = NULL;
|
||||
}
|
||||
|
||||
if ( hdr && hdr->HaveSequenceForActivity(ACT_HL2MP_IDLE) /*&& hl2_use_sp_animstate.GetBool()*/ )
|
||||
{
|
||||
// Here we create and init the player animation state.
|
||||
m_pPlayerAnimState = CreatePlayerAnimationState(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
return hdr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "c_hl2_playerlocaldata.h"
|
||||
|
||||
#if !defined( HL2MP ) && defined ( MAPBASE )
|
||||
#include "mapbase/singleplayer_animstate.h"
|
||||
#include "mapbase/mapbase_playeranimstate.h"
|
||||
#endif
|
||||
|
||||
class C_BaseHLPlayer : public C_BasePlayer
|
||||
@ -29,6 +29,7 @@ public:
|
||||
C_BaseHLPlayer();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void AddEntity( void );
|
||||
|
||||
void Weapon_DropPrimary( void );
|
||||
|
||||
@ -62,8 +63,14 @@ public:
|
||||
|
||||
bool IsWeaponLowered( void ) { return m_HL2Local.m_bWeaponLowered; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
int GetProtagonistIndex() const { return m_nProtagonistIndex; }
|
||||
#endif
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
virtual const Vector& GetRenderOrigin();
|
||||
virtual const QAngle& GetRenderAngles( void );
|
||||
virtual CStudioHdr *OnNewModel();
|
||||
#endif
|
||||
|
||||
public:
|
||||
@ -86,11 +93,18 @@ private:
|
||||
bool m_bPlayUseDenySound; // Signaled by PlayerUse, but can be unset by HL2 ladder code...
|
||||
float m_flSpeedMod;
|
||||
float m_flExitSpeedMod;
|
||||
|
||||
#ifdef MAPBASE
|
||||
int m_nProtagonistIndex;
|
||||
#endif
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
#ifdef MAPBASE_MP
|
||||
CSinglePlayerAnimState *m_pPlayerAnimState;
|
||||
#elif MAPBASE
|
||||
// At the moment, we network the render angles since almost none of the player anim stuff is done on the client in SP.
|
||||
// If any of this is ever adapted for MP, this method should be replaced with replicating/moving the anim state to the client.
|
||||
float m_flAnimRenderYaw;
|
||||
float m_flAnimRenderZ;
|
||||
QAngle m_angAnimRender;
|
||||
#endif
|
||||
|
||||
|
@ -100,7 +100,11 @@ void CHudSuitPower::OnThink( void )
|
||||
}
|
||||
|
||||
bool flashlightActive = pPlayer->IsFlashlightActive();
|
||||
#ifdef MAPBASE
|
||||
bool sprintActive = pPlayer->IsSprintActive();
|
||||
#else
|
||||
bool sprintActive = pPlayer->IsSprinting();
|
||||
#endif
|
||||
bool breatherActive = pPlayer->IsBreatherActive();
|
||||
int activeDevices = (int)flashlightActive + (int)sprintActive + (int)breatherActive;
|
||||
|
||||
@ -250,7 +254,11 @@ void CHudSuitPower::Paint()
|
||||
ypos += text2_gap;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (pPlayer->IsSprintActive())
|
||||
#else
|
||||
if (pPlayer->IsSprinting())
|
||||
#endif
|
||||
{
|
||||
tempString = g_pVGuiLocalize->Find("#Valve_Hud_SPRINT");
|
||||
|
||||
|
511
sp/src/game/client/mapbase/hud_generic_timer.cpp
Normal file
511
sp/src/game/client/mapbase/hud_generic_timer.cpp
Normal file
@ -0,0 +1,511 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: Generic timer HUD element for HL2-based mods
|
||||
//
|
||||
// Author: Blixibon
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "hud.h"
|
||||
#include "hud_macros.h"
|
||||
#include "hudelement.h"
|
||||
#include "hud_numericdisplay.h"
|
||||
#include "iclientmode.h"
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/AnimationController.h>
|
||||
#include <vgui_controls/EditablePanel.h>
|
||||
#include "baseviewport.h"
|
||||
#include "mapbase/game_timer.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern bool g_bAnyGameTimerActive;
|
||||
|
||||
ConVar hud_timer_max_bars( "hud_timer_max_bars", "15" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Timer panel
|
||||
//-----------------------------------------------------------------------------
|
||||
class CHudGenericGameTimer : public CHudElement, public vgui::Panel
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CHudGenericGameTimer, vgui::Panel );
|
||||
|
||||
public:
|
||||
CHudGenericGameTimer( const char *pElementName );
|
||||
virtual void Init( void );
|
||||
virtual void VidInit( void );
|
||||
virtual void Reset( void );
|
||||
virtual void OnThink();
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||||
virtual bool ShouldDraw( void );
|
||||
virtual void Paint();
|
||||
|
||||
C_GameTimer *GetTimer();
|
||||
bool FindTimer();
|
||||
|
||||
void SetDisplayValue( int value ) { m_iValue = value; }
|
||||
void SetLabelText( const wchar_t *text );
|
||||
|
||||
virtual void PaintNumbers( vgui::HFont font, int xpos, int ypos );
|
||||
virtual void PaintBars( int xpos, int ypos, int wide );
|
||||
|
||||
int GetTimerIndex() const { return m_iTimerIndex; }
|
||||
|
||||
private:
|
||||
void SetTimerLabel( void );
|
||||
|
||||
private:
|
||||
|
||||
int m_iTimerIndex;
|
||||
|
||||
bool m_bTimerDisplayed;
|
||||
bool m_bPlayingFadeout;
|
||||
float m_flShutoffTime;
|
||||
|
||||
bool m_bTimerPaused;
|
||||
bool m_bTimerWarned;
|
||||
|
||||
int m_iValue;
|
||||
int m_iTimerMaxLength;
|
||||
bool m_bShowTimeRemaining;
|
||||
int m_nProgressBarMax;
|
||||
int m_nProgressBarOverride;
|
||||
float m_flOverrideX, m_flOverrideY;
|
||||
wchar_t m_LabelText[32];
|
||||
|
||||
int m_nLabelWidth, m_nLabelHeight;
|
||||
int m_nTimerWidth, m_nTimerHeight;
|
||||
|
||||
CPanelAnimationVarAliasType( float, m_flMinWidth, "MinWidth", "100", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flBorder, "Border", "24", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flLabelTimerSpacing, "LabelTimerSpacing", "2", "proportional_float" );
|
||||
|
||||
CPanelAnimationVarAliasType( float, m_flBarHeight, "BarHeight", "5", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flBarChunkGap, "BarChunkGap", "3", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flBarVerticalGap, "BarVerticalGap", "8", "proportional_float" );
|
||||
CPanelAnimationVar( int, m_iBarDisabledAlpha, "BarDisabledAlpha", "70" );
|
||||
|
||||
CPanelAnimationVar( float, m_flBlur, "Blur", "0" );
|
||||
|
||||
CPanelAnimationVar( vgui::HFont, m_hNumberFont, "NumberFont", "HudHintTextLarge" );
|
||||
CPanelAnimationVar( vgui::HFont, m_hNumberGlowFont, "NumberGlowFont", "HudHintTextLarge" );
|
||||
CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "HudHintTextSmall" );
|
||||
};
|
||||
|
||||
DECLARE_HUDELEMENT( CHudGenericGameTimer );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CHudGenericGameTimer::CHudGenericGameTimer( const char *pElementName )
|
||||
: CHudElement( pElementName ),
|
||||
BaseClass( NULL, "HudGenericGameTimer" )
|
||||
{
|
||||
Panel *pParent = g_pClientMode->GetViewport();
|
||||
SetParent( pParent );
|
||||
|
||||
SetHiddenBits( HIDEHUD_MISCSTATUS );
|
||||
|
||||
m_iTimerIndex = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::Init()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::Reset()
|
||||
{
|
||||
SetDisplayValue( 0 );
|
||||
SetAlpha( 0 );
|
||||
|
||||
m_flShutoffTime = 0.0f;
|
||||
m_bTimerDisplayed = false;
|
||||
m_iTimerIndex = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::VidInit()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::OnThink()
|
||||
{
|
||||
C_BasePlayer *local = C_BasePlayer::GetLocalPlayer();
|
||||
if ( !local )
|
||||
{
|
||||
// Not ready to init!
|
||||
return;
|
||||
}
|
||||
|
||||
// If our timer has been disabled, close the menu
|
||||
C_GameTimer *pTimer = GetTimer();
|
||||
if ( !pTimer || pTimer->IsDisabled() || pTimer->IsMarkedForDeletion() )
|
||||
{
|
||||
if ( m_flShutoffTime == 0.0f )
|
||||
{
|
||||
m_flShutoffTime = gpGlobals->curtime + 1.0f;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerClose" );
|
||||
}
|
||||
m_iTimerIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check pause state
|
||||
if ( m_bTimerPaused && !pTimer->IsTimerPaused() )
|
||||
{
|
||||
m_bTimerPaused = false;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerPulse" );
|
||||
}
|
||||
else if ( pTimer->IsTimerPaused() )
|
||||
{
|
||||
m_bTimerPaused = true;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerPulseOnce" );
|
||||
}
|
||||
|
||||
float flTimeRemaining = floorf( pTimer->GetTimeRemaining() );
|
||||
|
||||
// Check warn state
|
||||
float flWarnTime = pTimer->GetWarnTime();
|
||||
|
||||
if (flWarnTime > 0.0f)
|
||||
{
|
||||
if ( m_bTimerWarned && flTimeRemaining > flWarnTime )
|
||||
{
|
||||
// Turn back to normal
|
||||
m_bTimerWarned = false;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerUnwarn" );
|
||||
}
|
||||
else if ( flTimeRemaining <= flWarnTime )
|
||||
{
|
||||
// Turn red
|
||||
m_bTimerWarned = true;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerWarn" );
|
||||
}
|
||||
}
|
||||
|
||||
SetDisplayValue( flTimeRemaining );
|
||||
|
||||
m_iTimerMaxLength = pTimer->GetTimerMaxLength();
|
||||
m_bShowTimeRemaining = pTimer->ShowTimeRemaining();
|
||||
|
||||
m_nProgressBarMax = pTimer->GetProgressBarMaxSegments();
|
||||
if (m_nProgressBarMax == -1)
|
||||
{
|
||||
// Default to timer max length
|
||||
m_nProgressBarMax = min( m_iTimerMaxLength, hud_timer_max_bars.GetInt() );
|
||||
}
|
||||
|
||||
m_nProgressBarOverride = pTimer->GetProgressBarOverride();
|
||||
|
||||
pTimer->GetPositionOverride( m_flOverrideX, m_flOverrideY );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: hud scheme settings
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
|
||||
SetPaintBackgroundEnabled( false );
|
||||
|
||||
// set our size
|
||||
int screenWide, screenTall;
|
||||
int x, y;
|
||||
GetPos( x, y );
|
||||
GetHudSize( screenWide, screenTall );
|
||||
SetBounds( 0, y, screenWide, screenTall - y );
|
||||
|
||||
// Start with a 0:00 timer
|
||||
m_nTimerWidth = (vgui::surface()->GetCharacterWidth( m_hNumberFont, '0' ) * 3);
|
||||
m_nTimerWidth += vgui::surface()->GetCharacterWidth( m_hNumberFont, ':' );
|
||||
|
||||
m_nTimerHeight = vgui::surface()->GetFontTall( m_hNumberFont );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudGenericGameTimer::ShouldDraw( void )
|
||||
{
|
||||
if ( !CHudElement::ShouldDraw() )
|
||||
return false;
|
||||
|
||||
if ( !m_bTimerDisplayed )
|
||||
{
|
||||
// Check if we should find a new timer
|
||||
if ( g_bAnyGameTimerActive )
|
||||
{
|
||||
if ( FindTimer() )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for if menu is set to disappear
|
||||
if ( m_flShutoffTime > 0 && m_flShutoffTime <= gpGlobals->curtime )
|
||||
{
|
||||
// times up, shutoff
|
||||
m_bTimerDisplayed = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( m_flOverrideX == -1.0f && m_flOverrideY == -1.0f )
|
||||
{
|
||||
// Don't overlap with the weapon selection HUD
|
||||
vgui::Panel *pWeaponSelection = GetParent()->FindChildByName( "HudWeaponSelection" );
|
||||
if ( pWeaponSelection && pWeaponSelection->IsVisible() )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
inline C_GameTimer *CHudGenericGameTimer::GetTimer()
|
||||
{
|
||||
if (m_iTimerIndex <= 0)
|
||||
return NULL;
|
||||
|
||||
// Need to do a dynamic_cast because this entity index could've been replaced since it was last used
|
||||
return dynamic_cast<C_GameTimer*>(C_BaseEntity::Instance( m_iTimerIndex ));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudGenericGameTimer::FindTimer()
|
||||
{
|
||||
// Find a new timer
|
||||
for ( int i = 0; i < IGameTimerAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
C_GameTimer *pTimer = static_cast<C_GameTimer *>( IGameTimerAutoList::AutoList()[i] );
|
||||
if ( !pTimer->IsDisabled() && !pTimer->IsMarkedForDeletion() )
|
||||
{
|
||||
m_iTimerIndex = pTimer->entindex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
C_GameTimer *pTimer = GetTimer();
|
||||
if ( pTimer )
|
||||
{
|
||||
// New timer selected, set the caption
|
||||
wchar_t wszLabelText[128];
|
||||
const wchar_t *wLocalizedItem = g_pVGuiLocalize->Find( pTimer->GetTimerCaption() );
|
||||
if (wLocalizedItem)
|
||||
{
|
||||
V_wcsncpy( wszLabelText, wLocalizedItem, sizeof( wszLabelText ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pTimer->GetTimerCaption(), wszLabelText, sizeof( wszLabelText ) );
|
||||
}
|
||||
SetLabelText( wszLabelText );
|
||||
|
||||
m_flShutoffTime = 0;
|
||||
m_bTimerDisplayed = true;
|
||||
m_bTimerPaused = pTimer->IsTimerPaused();
|
||||
m_bTimerWarned = false;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_bTimerPaused ? "GenericGameTimerShow" : "GenericGameTimerShowFlash" );
|
||||
|
||||
SetDisplayValue( ceil( pTimer->GetTimeRemaining() ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: data accessor
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::SetLabelText( const wchar_t *text )
|
||||
{
|
||||
wcsncpy( m_LabelText, text, sizeof( m_LabelText ) / sizeof( wchar_t ) );
|
||||
m_LabelText[(sizeof( m_LabelText ) / sizeof( wchar_t )) - 1] = 0;
|
||||
|
||||
m_nLabelWidth = 0;
|
||||
m_nLabelHeight = 0;
|
||||
|
||||
if (m_LabelText[0] != '\0')
|
||||
{
|
||||
int nLabelLen = V_wcslen( m_LabelText );
|
||||
for (int ch = 0; ch < nLabelLen; ch++)
|
||||
{
|
||||
m_nLabelWidth += vgui::surface()->GetCharacterWidth( m_hTextFont, m_LabelText[ch] );
|
||||
}
|
||||
|
||||
m_nLabelHeight = vgui::surface()->GetFontTall( m_hTextFont );
|
||||
m_nLabelHeight += m_flLabelTimerSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: paints a number at the specified position
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::PaintNumbers( vgui::HFont font, int xpos, int ypos )
|
||||
{
|
||||
vgui::surface()->DrawSetTextFont(font);
|
||||
|
||||
int nTimeToDisplay = m_iValue;
|
||||
|
||||
if ( !m_bShowTimeRemaining )
|
||||
{
|
||||
nTimeToDisplay = m_iTimerMaxLength - nTimeToDisplay;
|
||||
}
|
||||
|
||||
int nMinutes = 0;
|
||||
int nSeconds = 0;
|
||||
wchar_t unicode[6];
|
||||
|
||||
if (nTimeToDisplay <= 0)
|
||||
{
|
||||
nMinutes = 0;
|
||||
nSeconds = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nMinutes = nTimeToDisplay / 60;
|
||||
nSeconds = nTimeToDisplay % 60;
|
||||
}
|
||||
|
||||
V_snwprintf( unicode, ARRAYSIZE(unicode), L"%d:%02d", nMinutes, nSeconds );
|
||||
|
||||
vgui::surface()->DrawSetTextPos( xpos, ypos );
|
||||
vgui::surface()->DrawUnicodeString( unicode );
|
||||
|
||||
// draw the overbright blur
|
||||
for (float fl = m_flBlur; fl > 0.0f; fl -= 1.0f)
|
||||
{
|
||||
if (fl >= 1.0f)
|
||||
{
|
||||
vgui::surface()->DrawSetTextPos( xpos, ypos );
|
||||
vgui::surface()->DrawUnicodeString( unicode );
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw a percentage of the last one
|
||||
Color col = GetFgColor();
|
||||
col[3] *= fl;
|
||||
vgui::surface()->DrawSetTextColor( col );
|
||||
vgui::surface()->DrawSetTextPos( xpos, ypos );
|
||||
vgui::surface()->DrawUnicodeString( unicode );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: paints bars at the specified position
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::PaintBars( int xpos, int ypos, int wide )
|
||||
{
|
||||
// get bar chunks
|
||||
int barChunkWidth = (wide / m_nProgressBarMax) - m_flBarChunkGap;
|
||||
|
||||
int enabledChunks;
|
||||
if (m_nProgressBarOverride > -1)
|
||||
enabledChunks = m_nProgressBarOverride;
|
||||
else
|
||||
{
|
||||
enabledChunks = (int)floorf( ((float)m_iValue / (float)m_iTimerMaxLength) * (float)m_nProgressBarMax );
|
||||
if (!m_bShowTimeRemaining)
|
||||
{
|
||||
enabledChunks = m_nProgressBarMax - enabledChunks;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the suit power bar
|
||||
vgui::surface()->DrawSetColor( GetFgColor() );
|
||||
for (int i = 0; i < enabledChunks; i++)
|
||||
{
|
||||
vgui::surface()->DrawFilledRect( xpos, ypos, xpos + barChunkWidth, ypos + m_flBarHeight );
|
||||
xpos += (barChunkWidth + m_flBarChunkGap);
|
||||
}
|
||||
// draw the exhausted portion of the bar.
|
||||
Color clrExhausted = GetFgColor();
|
||||
clrExhausted[3] = ((float)clrExhausted[3] / 255.0f) * m_iBarDisabledAlpha;
|
||||
vgui::surface()->DrawSetColor( clrExhausted );
|
||||
for (int i = enabledChunks; i < m_nProgressBarMax; i++)
|
||||
{
|
||||
vgui::surface()->DrawFilledRect( xpos, ypos, xpos + barChunkWidth, ypos + m_flBarHeight );
|
||||
xpos += (barChunkWidth + m_flBarChunkGap);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: renders the vgui panel
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::Paint()
|
||||
{
|
||||
// Check for 00:00 timer
|
||||
int nTimerWidth = m_nTimerWidth;
|
||||
if (m_iValue > 600)
|
||||
nTimerWidth += vgui::surface()->GetCharacterWidth( m_hNumberFont, '0' );
|
||||
|
||||
// draw the background
|
||||
int wide = max( nTimerWidth, m_nLabelWidth ) + m_flBorder;
|
||||
if (m_flMinWidth > wide)
|
||||
wide = m_flMinWidth;
|
||||
|
||||
int tall = m_nTimerHeight + m_nLabelHeight + (m_flBorder/2);
|
||||
if (m_nProgressBarMax > 0)
|
||||
tall += m_flBarHeight + m_flBarVerticalGap;
|
||||
else
|
||||
tall += (m_flBorder/2);
|
||||
|
||||
int screenW, screenH;
|
||||
GetHudSize( screenW, screenH );
|
||||
|
||||
float flScalarX = (m_flOverrideX != -1.0f ? m_flOverrideX : 0.5f);
|
||||
float flScalarY = (m_flOverrideY != -1.0f ? m_flOverrideY : 0.05f);
|
||||
|
||||
int x = (screenW - wide) * flScalarX;
|
||||
int y = (screenH - tall) * flScalarY;
|
||||
|
||||
DrawBox( x, y, wide, tall, GetBgColor(), 1.0f);
|
||||
|
||||
y += (m_flBorder/2);
|
||||
|
||||
// draw our bars
|
||||
if (m_nProgressBarMax > 0)
|
||||
{
|
||||
int barX = x + (m_flBorder/2);
|
||||
PaintBars( barX, y, wide - m_flBorder );
|
||||
y += m_flBarVerticalGap;
|
||||
}
|
||||
|
||||
if (m_nLabelHeight > 0)
|
||||
{
|
||||
vgui::surface()->DrawSetTextFont( m_hTextFont );
|
||||
vgui::surface()->DrawSetTextColor( GetFgColor() );
|
||||
vgui::surface()->DrawSetTextPos( x + ((wide - m_nLabelWidth) * 0.5f), y );
|
||||
vgui::surface()->DrawUnicodeString( m_LabelText );
|
||||
y += m_nLabelHeight;
|
||||
}
|
||||
|
||||
// draw our numbers
|
||||
vgui::surface()->DrawSetTextColor( GetFgColor() );
|
||||
|
||||
int digitX = x + ((wide - nTimerWidth) * 0.5f);
|
||||
int digitY = y;
|
||||
PaintNumbers( m_hNumberFont, digitX, digitY );
|
||||
}
|
@ -1031,7 +1031,7 @@ void CScriptSurface::DrawColoredTextRect( int font, int x, int y, int w, int h,
|
||||
#define __base() this->_base
|
||||
|
||||
#define BEGIN_SCRIPTDESC_VGUI( panelClass )\
|
||||
BEGIN_SCRIPTDESC_NAMED( CScript_##panelClass##_Helper, IScriptVGUIObject, #panelClass, "" )\
|
||||
BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( CScript_##panelClass##_Helper, IScriptVGUIObject, #panelClass, "", VGUI_SCRIPT_INSTANCE_HELPER )\
|
||||
DEFINE_VGUI_SCRIPTFUNC_##panelClass()
|
||||
|
||||
//
|
||||
@ -1235,9 +1235,9 @@ class CScriptVGUIScriptInstanceHelper : public IScriptInstanceHelper
|
||||
|
||||
static CScriptVGUIScriptInstanceHelper g_ScriptVGUIScriptInstanceHelper;
|
||||
|
||||
#define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER() DEFINE_SCRIPT_INSTANCE_HELPER( &g_ScriptVGUIScriptInstanceHelper )
|
||||
#define VGUI_SCRIPT_INSTANCE_HELPER &g_ScriptVGUIScriptInstanceHelper
|
||||
#else
|
||||
#define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER()
|
||||
#define VGUI_SCRIPT_INSTANCE_HELPER NULL
|
||||
#endif
|
||||
|
||||
|
||||
@ -1866,8 +1866,6 @@ public:
|
||||
};
|
||||
|
||||
#define DEFINE_VGUI_SCRIPTFUNC_Panel()\
|
||||
DEFINE_VGUI_SCRIPT_INSTANCE_HELPER()\
|
||||
\
|
||||
DEFINE_SCRIPTFUNC( Destroy, "" )\
|
||||
DEFINE_SCRIPTFUNC( MakeReadyForUse, "" )\
|
||||
DEFINE_SCRIPTFUNC( GetName, "" )\
|
||||
@ -2612,9 +2610,17 @@ public:
|
||||
|
||||
static inline void SetHScript( HSCRIPT &var, HSCRIPT val )
|
||||
{
|
||||
if ( var && g_pScriptVM )
|
||||
g_pScriptVM->ReleaseScript( var );
|
||||
var = val;
|
||||
if ( g_pScriptVM )
|
||||
{
|
||||
if ( var )
|
||||
g_pScriptVM->ReleaseScript( var );
|
||||
|
||||
var = g_pScriptVM->CopyObject( val );
|
||||
}
|
||||
else
|
||||
{
|
||||
var = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define CheckCallback(s)\
|
||||
|
@ -37,6 +37,9 @@ char g_szPrelocalisedMenuString[MAX_MENU_STRING];
|
||||
|
||||
DECLARE_HUDELEMENT( CHudMenu );
|
||||
DECLARE_HUD_MESSAGE( CHudMenu, ShowMenu );
|
||||
#ifdef MAPBASE
|
||||
DECLARE_HUD_MESSAGE( CHudMenu, ShowMenuComplex );
|
||||
#endif
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
@ -71,6 +74,9 @@ CHudMenu::CHudMenu( const char *pElementName ) :
|
||||
void CHudMenu::Init( void )
|
||||
{
|
||||
HOOK_HUD_MESSAGE( CHudMenu, ShowMenu );
|
||||
#ifdef MAPBASE
|
||||
HOOK_HUD_MESSAGE( CHudMenu, ShowMenuComplex );
|
||||
#endif
|
||||
|
||||
m_bMenuTakesInput = false;
|
||||
m_bMenuDisplayed = false;
|
||||
@ -81,6 +87,24 @@ void CHudMenu::Init( void )
|
||||
Reset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenu::LevelInit()
|
||||
{
|
||||
CHudElement::LevelInit();
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_bMapDefinedMenu)
|
||||
{
|
||||
// Fixes menu retaining on level change/reload
|
||||
// TODO: Would non-map menus benefit from this as well?
|
||||
m_bMenuTakesInput = false;
|
||||
m_bMenuDisplayed = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -114,7 +138,11 @@ void CHudMenu::OnThink()
|
||||
float flSelectionTimeout = MENU_SELECTION_TIMEOUT;
|
||||
|
||||
// If we've been open for a while without input, hide
|
||||
#ifdef MAPBASE
|
||||
if ( m_bMenuDisplayed && ( gpGlobals->curtime - m_flSelectionTime > flSelectionTimeout && !m_bMapDefinedMenu ) )
|
||||
#else
|
||||
if ( m_bMenuDisplayed && ( gpGlobals->curtime - m_flSelectionTime > flSelectionTimeout ) )
|
||||
#endif
|
||||
{
|
||||
m_bMenuDisplayed = false;
|
||||
}
|
||||
@ -130,11 +158,24 @@ bool CHudMenu::ShouldDraw( void )
|
||||
return false;
|
||||
|
||||
// check for if menu is set to disappear
|
||||
if ( m_flShutoffTime > 0 && m_flShutoffTime <= gpGlobals->realtime )
|
||||
if ( m_flShutoffTime > 0 )
|
||||
{
|
||||
// times up, shutoff
|
||||
m_bMenuDisplayed = false;
|
||||
return false;
|
||||
#ifdef MAPBASE
|
||||
if ( m_bMapDefinedMenu && !m_bPlayingFadeout && (m_flShutoffTime - m_flOpenCloseTime) <= GetMenuTime() )
|
||||
{
|
||||
// Begin closing the menu
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MenuClose" );
|
||||
m_bMenuTakesInput = false;
|
||||
m_bPlayingFadeout = true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ( m_flShutoffTime <= GetMenuTime() )
|
||||
{
|
||||
// times up, shutoff
|
||||
m_bMenuDisplayed = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return draw;
|
||||
@ -169,23 +210,21 @@ void CHudMenu::Paint()
|
||||
return;
|
||||
|
||||
// center it
|
||||
int x = 20;
|
||||
int x = m_nBorder;
|
||||
|
||||
Color menuColor = m_MenuColor;
|
||||
Color itemColor = m_ItemColor;
|
||||
|
||||
int c = m_Processed.Count();
|
||||
|
||||
int border = 20;
|
||||
|
||||
int wide = m_nMaxPixels + border;
|
||||
int tall = m_nHeight + border;
|
||||
int wide = m_nMaxPixels + m_nBorder;
|
||||
int tall = m_nHeight + m_nBorder;
|
||||
|
||||
int y = ( ScreenHeight() - tall ) * 0.5f;
|
||||
|
||||
DrawBox( x - border/2, y - border/2, wide, tall, m_BoxColor, m_flSelectionAlphaOverride / 255.0f );
|
||||
DrawBox( x - m_nBorder/2, y - m_nBorder/2, wide, tall, m_BoxColor, m_flSelectionAlphaOverride / 255.0f );
|
||||
|
||||
//DrawTexturedBox( x - border/2, y - border/2, wide, tall, m_BoxColor, m_flSelectionAlphaOverride / 255.0f );
|
||||
//DrawTexturedBox( x - m_nBorder/2, y - m_nBorder/2, wide, tall, m_BoxColor, m_flSelectionAlphaOverride / 255.0f );
|
||||
|
||||
menuColor[3] = menuColor[3] * ( m_flSelectionAlphaOverride / 255.0f );
|
||||
itemColor[3] = itemColor[3] * ( m_flSelectionAlphaOverride / 255.0f );
|
||||
@ -195,7 +234,18 @@ void CHudMenu::Paint()
|
||||
ProcessedLine *line = &m_Processed[ i ];
|
||||
Assert( line );
|
||||
|
||||
Color clr = line->menuitem != 0 ? itemColor : menuColor;
|
||||
#ifdef MAPBASE
|
||||
bool isItem = true;
|
||||
if (line->menuitem == 0 && line->startchar < (MAX_MENU_STRING-1) && g_szMenuString[ line->startchar ] != L'0' && g_szMenuString[ line->startchar+1 ] != L'.')
|
||||
{
|
||||
// Can't use 0 directly because it gets conflated with the cancel item
|
||||
isItem = false;
|
||||
}
|
||||
#else
|
||||
bool isItem = line->menuitem != 0;
|
||||
#endif
|
||||
|
||||
Color clr = isItem ? itemColor : menuColor;
|
||||
|
||||
bool canblur = false;
|
||||
if ( line->menuitem != 0 &&
|
||||
@ -208,15 +258,15 @@ void CHudMenu::Paint()
|
||||
vgui::surface()->DrawSetTextColor( clr );
|
||||
|
||||
int drawLen = line->length;
|
||||
if ( line->menuitem != 0 )
|
||||
if (isItem)
|
||||
{
|
||||
drawLen *= m_flTextScan;
|
||||
}
|
||||
|
||||
vgui::surface()->DrawSetTextFont( line->menuitem != 0 ? m_hItemFont : m_hTextFont );
|
||||
vgui::surface()->DrawSetTextFont( isItem ? m_hItemFont : m_hTextFont );
|
||||
|
||||
PaintString( &g_szMenuString[ line->startchar ], drawLen,
|
||||
line->menuitem != 0 ? m_hItemFont : m_hTextFont, x, y );
|
||||
isItem ? m_hItemFont : m_hTextFont, x, y );
|
||||
|
||||
if ( canblur )
|
||||
{
|
||||
@ -242,6 +292,20 @@ void CHudMenu::Paint()
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
inline float CHudMenu::GetMenuTime( void )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// In singleplayer, use the curtime instead. This fixes issues with menus disappearing after pausing
|
||||
if (gpGlobals->maxClients <= 1)
|
||||
return gpGlobals->curtime;
|
||||
#endif
|
||||
|
||||
return gpGlobals->realtime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: selects an item from the menu
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -260,7 +324,7 @@ void CHudMenu::SelectMenuItem( int menu_item )
|
||||
|
||||
// remove the menu quickly
|
||||
m_bMenuTakesInput = false;
|
||||
m_flShutoffTime = gpGlobals->realtime + m_flOpenCloseTime;
|
||||
m_flShutoffTime = GetMenuTime() + m_flOpenCloseTime;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("MenuClose");
|
||||
}
|
||||
}
|
||||
@ -339,9 +403,20 @@ void CHudMenu::ProcessText( void )
|
||||
{
|
||||
ProcessedLine *l = &m_Processed[ i ];
|
||||
Assert( l );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool isItem = true;
|
||||
if (l->menuitem == 0 && l->startchar < (MAX_MENU_STRING-1) && g_szMenuString[ l->startchar ] != L'0' && g_szMenuString[ l->startchar+1 ] != L'.')
|
||||
{
|
||||
// Can't use 0 directly because it gets conflated with the cancel item
|
||||
isItem = false;
|
||||
}
|
||||
#else
|
||||
bool isItem = l->menuitem != 0;
|
||||
#endif
|
||||
|
||||
int pixels = 0;
|
||||
vgui::HFont font = l->menuitem != 0 ? m_hItemFont : m_hTextFont;
|
||||
vgui::HFont font = isItem ? m_hItemFont : m_hTextFont;
|
||||
|
||||
for ( int ch = 0; ch < l->length; ch++ )
|
||||
{
|
||||
@ -364,7 +439,7 @@ void CHudMenu::ProcessText( void )
|
||||
void CHudMenu::HideMenu( void )
|
||||
{
|
||||
m_bMenuTakesInput = false;
|
||||
m_flShutoffTime = gpGlobals->realtime + m_flOpenCloseTime;
|
||||
m_flShutoffTime = GetMenuTime() + m_flOpenCloseTime;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("MenuClose");
|
||||
}
|
||||
|
||||
@ -381,6 +456,11 @@ void CHudMenu::ShowMenu( const char * menuName, int validSlots )
|
||||
m_flShutoffTime = -1;
|
||||
m_bitsValidSlots = validSlots;
|
||||
m_fWaitingForMore = 0;
|
||||
m_nBorder = 20;
|
||||
#ifdef MAPBASE
|
||||
m_bMapDefinedMenu = false;
|
||||
m_bPlayingFadeout = false;
|
||||
#endif
|
||||
|
||||
Q_strncpy( g_szPrelocalisedMenuString, menuName, sizeof( g_szPrelocalisedMenuString ) );
|
||||
|
||||
@ -408,6 +488,11 @@ void CHudMenu::ShowMenu_KeyValueItems( KeyValues *pKV )
|
||||
m_flShutoffTime = -1;
|
||||
m_fWaitingForMore = 0;
|
||||
m_bitsValidSlots = 0;
|
||||
m_nBorder = 20;
|
||||
#ifdef MAPBASE
|
||||
m_bMapDefinedMenu = false;
|
||||
m_bPlayingFadeout = false;
|
||||
#endif
|
||||
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("MenuOpen");
|
||||
m_nSelectedItem = -1;
|
||||
@ -426,7 +511,11 @@ void CHudMenu::ShowMenu_KeyValueItems( KeyValues *pKV )
|
||||
const char *pszItem = item->GetName();
|
||||
const wchar_t *wLocalizedItem = g_pVGuiLocalize->Find( pszItem );
|
||||
|
||||
#ifdef MAPBASE
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"->%d. %ls\n", i+1, wLocalizedItem );
|
||||
#else
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"%d. %ls\n", i+1, wLocalizedItem );
|
||||
#endif
|
||||
nRemaining -= nCount;
|
||||
pWritePosition += nCount;
|
||||
|
||||
@ -436,7 +525,11 @@ void CHudMenu::ShowMenu_KeyValueItems( KeyValues *pKV )
|
||||
// put a cancel on the end
|
||||
m_bitsValidSlots |= (1<<9);
|
||||
|
||||
#ifdef MAPBASE
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"->0. %ls\n", g_pVGuiLocalize->Find( "#Cancel" ) );
|
||||
#else
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"0. %ls\n", g_pVGuiLocalize->Find( "#Cancel" ) );
|
||||
#endif
|
||||
nRemaining -= nCount;
|
||||
pWritePosition += nCount;
|
||||
|
||||
@ -465,8 +558,7 @@ void CHudMenu::MsgFunc_ShowMenu( bf_read &msg)
|
||||
|
||||
if ( DisplayTime > 0 )
|
||||
{
|
||||
m_flShutoffTime = m_flOpenCloseTime + DisplayTime + gpGlobals->realtime;
|
||||
|
||||
m_flShutoffTime = m_flOpenCloseTime + DisplayTime + GetMenuTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -511,8 +603,131 @@ void CHudMenu::MsgFunc_ShowMenu( bf_read &msg)
|
||||
}
|
||||
|
||||
m_fWaitingForMore = NeedMore;
|
||||
m_nBorder = 20;
|
||||
#ifdef MAPBASE
|
||||
m_bMapDefinedMenu = false;
|
||||
m_bPlayingFadeout = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar hud_menu_complex_border( "hud_menu_complex_border", "30" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Message handler for ShowMenu message with more options for game_menu
|
||||
// takes four values:
|
||||
// short : a bitfield of keys that are valid input
|
||||
// float : the duration, in seconds, the menu should stay up. -1 means it stays until something is chosen.
|
||||
// byte : a boolean, TRUE if there is more string yet to be received before displaying the menu, false if it's the last string
|
||||
// string: menu string to display
|
||||
// if this message is never received, then scores will simply be the combined totals of the players.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenu::MsgFunc_ShowMenuComplex( bf_read &msg)
|
||||
{
|
||||
m_bitsValidSlots = (short)msg.ReadWord();
|
||||
float DisplayTime = msg.ReadFloat();
|
||||
int NeedMore = msg.ReadByte();
|
||||
|
||||
m_nBorder = hud_menu_complex_border.GetInt();
|
||||
m_bMapDefinedMenu = true;
|
||||
m_bPlayingFadeout = false;
|
||||
|
||||
if ( DisplayTime > 0 )
|
||||
{
|
||||
m_flShutoffTime = m_flOpenCloseTime + DisplayTime + GetMenuTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flShutoffTime = -1;
|
||||
}
|
||||
|
||||
if ( m_bitsValidSlots > -1 )
|
||||
{
|
||||
char szString[2048];
|
||||
msg.ReadString( szString, sizeof(szString) );
|
||||
|
||||
if ( !m_fWaitingForMore ) // this is the start of a new menu
|
||||
{
|
||||
Q_strncpy( g_szPrelocalisedMenuString, szString, sizeof( g_szPrelocalisedMenuString ) );
|
||||
}
|
||||
else
|
||||
{ // append to the current menu string
|
||||
Q_strncat( g_szPrelocalisedMenuString, szString, sizeof( g_szPrelocalisedMenuString ), COPY_ALL_CHARACTERS );
|
||||
}
|
||||
|
||||
if ( !NeedMore )
|
||||
{
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("MenuOpenFlash");
|
||||
m_nSelectedItem = -1;
|
||||
|
||||
// we have the whole string, so we can localise it now
|
||||
wchar_t *pWritePosition = g_szMenuString;
|
||||
int nRemaining = sizeof( g_szMenuString ) / sizeof( wchar_t );
|
||||
int nCount;
|
||||
|
||||
char *pszToken = strtok( szString, "\n" );
|
||||
int nCurItem = 0;
|
||||
for (; pszToken != NULL; pszToken = strtok( NULL, "\n" ), nCurItem++)
|
||||
{
|
||||
if (!*pszToken || *pszToken == ' ')
|
||||
continue;
|
||||
|
||||
wchar_t wszMenuItem[128];
|
||||
|
||||
const wchar_t *wLocalizedItem = g_pVGuiLocalize->Find( pszToken );
|
||||
if (wLocalizedItem)
|
||||
{
|
||||
V_wcsncpy( wszMenuItem, wLocalizedItem, sizeof( wszMenuItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pszToken, wszMenuItem, sizeof( wszMenuItem ) );
|
||||
}
|
||||
|
||||
if (nCurItem == 0)
|
||||
{
|
||||
// First item is title
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"%ls\n", wszMenuItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this item isn't valid, skip until it is
|
||||
//while (!(m_bitsValidSlots & (1 << nCurItem)) && nCurItem < 10)
|
||||
//{
|
||||
// nCurItem++;
|
||||
//}
|
||||
|
||||
if (nCurItem == 10)
|
||||
nCurItem = 0;
|
||||
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"->%d. %ls\n", nCurItem, wszMenuItem );
|
||||
}
|
||||
|
||||
nRemaining -= nCount;
|
||||
pWritePosition += nCount;
|
||||
}
|
||||
|
||||
ProcessText();
|
||||
}
|
||||
|
||||
m_bMenuDisplayed = true;
|
||||
|
||||
if (m_bitsValidSlots > 0)
|
||||
m_bMenuTakesInput = true;
|
||||
else
|
||||
m_bMenuTakesInput = false;
|
||||
|
||||
m_flSelectionTime = gpGlobals->curtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
HideMenu();
|
||||
}
|
||||
|
||||
m_fWaitingForMore = NeedMore;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: hud scheme settings
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -26,10 +26,14 @@ class CHudMenu : public CHudElement, public vgui::Panel
|
||||
public:
|
||||
CHudMenu( const char *pElementName );
|
||||
void Init( void );
|
||||
void LevelInit( void );
|
||||
void VidInit( void );
|
||||
void Reset( void );
|
||||
virtual bool ShouldDraw( void );
|
||||
void MsgFunc_ShowMenu( bf_read &msg );
|
||||
#ifdef MAPBASE
|
||||
void MsgFunc_ShowMenuComplex( bf_read &msg );
|
||||
#endif
|
||||
void HideMenu( void );
|
||||
void ShowMenu( const char * menuName, int keySlot );
|
||||
void ShowMenu_KeyValueItems( KeyValues *pKV );
|
||||
@ -42,6 +46,8 @@ private:
|
||||
virtual void Paint();
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
|
||||
private:
|
||||
float GetMenuTime( void );
|
||||
|
||||
void ProcessText( void );
|
||||
|
||||
void PaintString( const wchar_t *text, int textlen, vgui::HFont& font, int x, int y );
|
||||
@ -59,6 +65,7 @@ private:
|
||||
|
||||
int m_nMaxPixels;
|
||||
int m_nHeight;
|
||||
int m_nBorder;
|
||||
|
||||
bool m_bMenuDisplayed;
|
||||
int m_bitsValidSlots;
|
||||
@ -69,6 +76,12 @@ private:
|
||||
|
||||
float m_flSelectionTime;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Indicates this menu is defined by game_menu
|
||||
bool m_bMapDefinedMenu;
|
||||
bool m_bPlayingFadeout;
|
||||
#endif
|
||||
|
||||
CPanelAnimationVar( float, m_flOpenCloseTime, "OpenCloseTime", "1" );
|
||||
|
||||
CPanelAnimationVar( float, m_flBlur, "Blur", "0" );
|
||||
|
@ -855,7 +855,7 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
||||
C_BaseCombatWeapon *weapon = dynamic_cast< C_BaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
|
||||
if ( weapon )
|
||||
{
|
||||
player->SelectItem( weapon->GetClassname(), ucmd->weaponsubtype );
|
||||
player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,7 @@ ConVar gl_clear_randomcolor( "gl_clear_randomcolor", "0", FCVAR_CHEAT, "Clear th
|
||||
static ConVar r_farz( "r_farz", "-1", FCVAR_CHEAT, "Override the far clipping plane. -1 means to use the value in env_fog_controller." );
|
||||
#ifdef MAPBASE
|
||||
static ConVar r_nearz( "r_nearz", "-1", FCVAR_CHEAT, "Override the near clipping plane. -1 means to use the default value (usually 7)." );
|
||||
static ConVar cl_camera_anim_intensity("cl_camera_anim_intensity", "1.0", FCVAR_ARCHIVE, "Intensity of cambone animations");
|
||||
#endif
|
||||
static ConVar cl_demoviewoverride( "cl_demoviewoverride", "0", 0, "Override view during demo playback" );
|
||||
|
||||
@ -1306,6 +1307,37 @@ void CViewRender::Render( vrect_t *rect )
|
||||
g_ClientVirtualReality.OverlayHUDQuadWithUndistort( view, bDoUndistort, g_pClientMode->ShouldBlackoutAroundHUD(), bTranslucent );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//--------------------------------
|
||||
// Handle camera anims
|
||||
//--------------------------------
|
||||
if (!UseVR() && pPlayer && cl_camera_anim_intensity.GetFloat() > 0)
|
||||
{
|
||||
if (pPlayer->GetViewModel(0))
|
||||
{
|
||||
int attachment = pPlayer->GetViewModel(0)->LookupAttachment("camera");
|
||||
if (attachment != -1)
|
||||
{
|
||||
int rootBone = pPlayer->GetViewModel(0)->LookupAttachment("camera_root");
|
||||
Vector cameraOrigin = Vector(0, 0, 0);
|
||||
QAngle cameraAngles = QAngle(0, 0, 0);
|
||||
Vector rootOrigin = Vector(0, 0, 0);
|
||||
QAngle rootAngles = QAngle(0, 0, 0);
|
||||
|
||||
pPlayer->GetViewModel(0)->GetAttachmentLocal(attachment, cameraOrigin, cameraAngles);
|
||||
if (rootBone != -1)
|
||||
{
|
||||
pPlayer->GetViewModel(0)->GetAttachmentLocal(rootBone, rootOrigin, rootAngles);
|
||||
cameraOrigin -= rootOrigin;
|
||||
cameraAngles -= rootAngles;
|
||||
}
|
||||
view.angles += cameraAngles * cl_camera_anim_intensity.GetFloat();
|
||||
view.origin += cameraOrigin * cl_camera_anim_intensity.GetFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // MAPBASE
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,10 @@
|
||||
extern IScriptManager *scriptmanager;
|
||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
ConVar script_connect_debugger_on_mapspawn_client( "script_connect_debugger_on_mapspawn_client", "0" );
|
||||
#endif
|
||||
|
||||
// #define VMPROFILE 1
|
||||
|
||||
#ifdef VMPROFILE
|
||||
@ -234,8 +238,7 @@ class CMaterialProxyScriptInstanceHelper : public IScriptInstanceHelper
|
||||
|
||||
CMaterialProxyScriptInstanceHelper g_MaterialProxyScriptInstanceHelper;
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptMaterialProxy, "CScriptMaterialProxy", "Material proxy for VScript" )
|
||||
DEFINE_SCRIPT_INSTANCE_HELPER( &g_MaterialProxyScriptInstanceHelper )
|
||||
BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( CScriptMaterialProxy, "CScriptMaterialProxy", "Material proxy for VScript", &g_MaterialProxyScriptInstanceHelper )
|
||||
DEFINE_SCRIPTFUNC( GetVarString, "Gets a material var's string value" )
|
||||
DEFINE_SCRIPTFUNC( GetVarInt, "Gets a material var's int value" )
|
||||
DEFINE_SCRIPTFUNC( GetVarFloat, "Gets a material var's float value" )
|
||||
@ -683,6 +686,17 @@ bool VScriptClientInit()
|
||||
//g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" );
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if ( script_connect_debugger_on_mapspawn_client.GetInt() == 2 )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port, 10.0f );
|
||||
}
|
||||
else if ( script_connect_debugger_on_mapspawn_client.GetInt() != 0 )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||
}
|
||||
#endif
|
||||
|
||||
if (scriptLanguage == SL_SQUIRREL)
|
||||
{
|
||||
g_pScriptVM->Run( g_Script_vscript_client );
|
||||
@ -771,11 +785,19 @@ public:
|
||||
VScriptClientTerm();
|
||||
}
|
||||
|
||||
virtual void FrameUpdatePostEntityThink()
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual void Update( float frametime )
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
g_pScriptVM->Frame( frametime );
|
||||
}
|
||||
#else
|
||||
virtual void FrameUpdatePostEntityThink()
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
g_pScriptVM->Frame( gpGlobals->frametime );
|
||||
}
|
||||
#endif
|
||||
|
||||
bool m_bAllowEntityCreationInScripts;
|
||||
};
|
||||
|
@ -16,6 +16,10 @@
|
||||
#include "saverestore_utlvector.h"
|
||||
#include "dt_utlvector_send.h"
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#include "mapbase/vscript_funcs_shared.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
@ -471,7 +475,8 @@ void CAnimationLayer::DispatchAnimEvents( CBaseAnimating *eventHandler, CBaseAni
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (eventHandler->m_ScriptScope.IsInitialized() && eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
|
||||
scriptanimevent_t wrapper( event );
|
||||
if (eventHandler->m_ScriptScope.IsInitialized() && !eventHandler->ScriptHookHandleAnimEvent( wrapper ))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
|
@ -2594,6 +2594,18 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SMG1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_AR2 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_PHYSGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_GRENADE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_RPG );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_MELEE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SLAM );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_REVOLVER );
|
||||
@ -2603,6 +2615,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_REVOLVER );
|
||||
|
||||
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
|
||||
@ -2614,6 +2627,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_AR1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_AR1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_AR1 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_AR3 );
|
||||
@ -2624,6 +2638,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_AR3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_AR3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_AR3 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SMG2 );
|
||||
@ -2634,6 +2649,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SMG2 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SMG2 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SMG2 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SMG3 );
|
||||
@ -2644,6 +2660,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SMG3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SMG3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SMG3 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_HMG1 );
|
||||
@ -2654,6 +2671,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_HMG1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_HMG1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_HMG1 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SNIPER_RIFLE );
|
||||
@ -2664,6 +2682,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SNIPER_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SNIPER_RIFLE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_DUAL_PISTOLS );
|
||||
@ -2674,6 +2693,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_DUAL_PISTOLS );
|
||||
#endif
|
||||
|
||||
|
@ -318,6 +318,14 @@ ScriptHook_t CAI_BaseNPC::g_Hook_TranslateSchedule;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_GetActualShootPosition;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_OverrideMove;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_ShouldPlayFakeSequenceGesture;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_IsValidEnemy;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_CanBeAnEnemyOf;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_UpdateEnemyMemory;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_OnSeeEntity;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_OnListened;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_BuildScheduleTestBits;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_StartTask;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_RunTask;
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -746,10 +754,19 @@ Vector CAI_BaseNPC::VScriptGetEnemyLKP()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptFindEnemyMemory( HSCRIPT pEnemy )
|
||||
int CAI_BaseNPC::VScriptNumEnemies()
|
||||
{
|
||||
return GetEnemies()->NumEnemies();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetFirstEnemyMemory()
|
||||
{
|
||||
HSCRIPT hScript = NULL;
|
||||
AI_EnemyInfo_t *info = GetEnemies()->Find( ToEnt(pEnemy) );
|
||||
|
||||
AIEnemiesIter_t iter;
|
||||
AI_EnemyInfo_t *info = GetEnemies()->GetFirst( &iter );
|
||||
if (info)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( reinterpret_cast<Script_AI_EnemyInfo_t*>(info) );
|
||||
@ -758,6 +775,70 @@ HSCRIPT CAI_BaseNPC::VScriptFindEnemyMemory( HSCRIPT pEnemy )
|
||||
return hScript;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetNextEnemyMemory( HSCRIPT hMemory )
|
||||
{
|
||||
Script_AI_EnemyInfo_t *pCurEMemory = HScriptToClass<Script_AI_EnemyInfo_t>( hMemory );
|
||||
if (!pCurEMemory)
|
||||
return NULL;
|
||||
|
||||
HSCRIPT hScript = NULL;
|
||||
|
||||
AIEnemiesIter_t iter = (AIEnemiesIter_t)GetEnemies()->FindIndex( pCurEMemory->hEnemy );
|
||||
AI_EnemyInfo_t *pEMemory = GetEnemies()->GetNext( &iter );
|
||||
if (pEMemory)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( reinterpret_cast<Script_AI_EnemyInfo_t*>(pEMemory) );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptFindEnemyMemory( HSCRIPT hEnemy )
|
||||
{
|
||||
HSCRIPT hScript = NULL;
|
||||
AI_EnemyInfo_t *info = GetEnemies()->Find( ToEnt(hEnemy) );
|
||||
if (info)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( reinterpret_cast<Script_AI_EnemyInfo_t*>(info) );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::VScriptUpdateEnemyMemory( HSCRIPT hEnemy, const Vector &position, HSCRIPT hInformer )
|
||||
{
|
||||
return UpdateEnemyMemory( ToEnt( hEnemy ), position, ToEnt( hInformer ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::VScriptClearEnemyMemory( HSCRIPT hEnemy )
|
||||
{
|
||||
CBaseEntity *pEnemy = ToEnt( hEnemy );
|
||||
if (!pEnemy)
|
||||
return;
|
||||
|
||||
GetEnemies()->ClearMemory( pEnemy );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::VScriptSetFreeKnowledgeDuration( float flDuration )
|
||||
{
|
||||
GetEnemies()->SetFreeKnowledgeDuration( flDuration );
|
||||
}
|
||||
|
||||
void CAI_BaseNPC::VScriptSetEnemyDiscardTime( float flDuration )
|
||||
{
|
||||
GetEnemies()->SetEnemyDiscardTime( flDuration );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
int CAI_BaseNPC::VScriptGetState()
|
||||
@ -765,6 +846,34 @@ int CAI_BaseNPC::VScriptGetState()
|
||||
return (int)GetState();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
int CAI_BaseNPC::VScriptGetIdealState()
|
||||
{
|
||||
return (int)GetIdealState();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::VScriptSetIdealState( int nNPCState )
|
||||
{
|
||||
SetIdealState( (NPC_STATE)nNPCState );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetTarget()
|
||||
{
|
||||
return ToHScript( GetTarget() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::VScriptSetTarget( HSCRIPT hTarget )
|
||||
{
|
||||
SetTarget( ToEnt( hTarget ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetHintNode()
|
||||
@ -832,7 +941,7 @@ int CAI_BaseNPC::VScriptGetTaskID()
|
||||
const Task_t *pTask = GetTask();
|
||||
int iID = -1;
|
||||
if (pTask)
|
||||
iID = GetTaskID( TaskName( pTask->iTask ) );
|
||||
iID = AI_RemapFromGlobal( GetTaskID( TaskName( pTask->iTask ) ) );
|
||||
|
||||
return iID;
|
||||
}
|
||||
@ -867,6 +976,70 @@ HSCRIPT CAI_BaseNPC::VScriptGetSquad()
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetBestSound( int validTypes )
|
||||
{
|
||||
HSCRIPT hScript = NULL;
|
||||
CSound *pSound = GetBestSound( validTypes );
|
||||
if (pSound)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( pSound );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetFirstHeardSound()
|
||||
{
|
||||
HSCRIPT hScript = NULL;
|
||||
|
||||
AISoundIter_t iter;
|
||||
CSound *pSound = GetSenses()->GetFirstHeardSound( &iter );
|
||||
if (pSound)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( pSound );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetNextHeardSound( HSCRIPT hSound )
|
||||
{
|
||||
CSound *pCurSound = HScriptToClass<CSound>( hSound );
|
||||
if (!pCurSound)
|
||||
return NULL;
|
||||
|
||||
int iCurrent = pCurSound->m_iNextAudible;
|
||||
if ( iCurrent == SOUNDLIST_EMPTY )
|
||||
return NULL;
|
||||
|
||||
HSCRIPT hScript = NULL;
|
||||
|
||||
CSound *pNextSound = CSoundEnt::SoundPointerForIndex( iCurrent );
|
||||
if (pNextSound)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( pNextSound );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetFirstSeenEntity( int nSeenType )
|
||||
{
|
||||
AISightIter_t iter;
|
||||
return ToHScript( GetSenses()->GetFirstSeenEntity( &iter, (seentype_t)nSeenType ) );
|
||||
}
|
||||
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetNextSeenEntity( HSCRIPT hEnt, int nSeenType )
|
||||
{
|
||||
CBaseEntity *pEnt = ToEnt( hEnt );
|
||||
|
||||
AISightIter_t iter;
|
||||
GetSenses()->GetSeenEntityIndex( &iter, pEnt, (seentype_t)nSeenType );
|
||||
|
||||
return ToHScript( GetSenses()->GetNextSeenEntity( &iter ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CAI_BaseNPC::PassesDamageFilter( const CTakeDamageInfo &info )
|
||||
@ -2595,6 +2768,29 @@ void CAI_BaseNPC::OnListened()
|
||||
{
|
||||
m_OnHearCombat.FireOutput(this, this);
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnListened.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
g_Hook_OnListened.Call( m_ScriptScope, &functionReturn, NULL );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CAI_BaseNPC::OnSeeEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnSeeEntity.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// entity
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pEntity ) };
|
||||
g_Hook_OnSeeEntity.Call( m_ScriptScope, &functionReturn, args );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
@ -2847,7 +3043,7 @@ void CAI_BaseNPC::SetHeadDirection( const Vector &vTargetPos, float flInterval)
|
||||
//--------------------------------------
|
||||
// Set head yaw
|
||||
//--------------------------------------
|
||||
float flDesiredYaw = VecToYaw(vTargetPos - GetLocalOrigin()) - GetLocalAngles().y;
|
||||
float flDesiredYaw = VecToYaw(vTargetPos - GetAbsOrigin()) - GetAbsAngles().y;
|
||||
if (flDesiredYaw > 180)
|
||||
flDesiredYaw -= 360;
|
||||
if (flDesiredYaw < -180)
|
||||
@ -6107,6 +6303,22 @@ bool CAI_BaseNPC::UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position
|
||||
|
||||
if ( GetEnemies() )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_UpdateEnemyMemory.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// enemy, position, informer
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pEnemy ), position, ToHScript( pInformer ) };
|
||||
if (g_Hook_UpdateEnemyMemory.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
// Returning false normally indicates this is a known enemy
|
||||
// Most uses of that functionality involve checking for new enemies, so this is acceptable
|
||||
if (functionReturn.m_bool == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// If the was eluding me and allow the NPC to play a sound
|
||||
if (GetEnemies()->HasEludedMe(pEnemy))
|
||||
{
|
||||
@ -7791,7 +8003,7 @@ void CAI_BaseNPC::NPCInit ( void )
|
||||
|
||||
SetGravity(1.0); // Don't change
|
||||
m_takedamage = DAMAGE_YES;
|
||||
GetMotor()->SetIdealYaw( GetLocalAngles().y );
|
||||
GetMotor()->SetIdealYaw( GetAbsAngles().y );
|
||||
m_iMaxHealth = m_iHealth;
|
||||
m_lifeState = LIFE_ALIVE;
|
||||
SetIdealState( NPC_STATE_IDLE );// Assume npc will be idle, until proven otherwise
|
||||
@ -8979,6 +9191,20 @@ bool CAI_BaseNPC::IsValidEnemy( CBaseEntity *pEnemy )
|
||||
if ( m_hEnemyFilter.Get()!= NULL && m_hEnemyFilter->PassesFilter( this, pEnemy ) == false )
|
||||
return false;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_IsValidEnemy.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// enemy
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pEnemy ) };
|
||||
if (g_Hook_IsValidEnemy.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_bool == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8988,6 +9214,20 @@ bool CAI_BaseNPC::CanBeAnEnemyOf( CBaseEntity *pEnemy )
|
||||
if ( GetSleepState() > AISS_WAITING_FOR_THREAT )
|
||||
return false;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_CanBeAnEnemyOf.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// enemy
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pEnemy ) };
|
||||
if (g_Hook_CanBeAnEnemyOf.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_bool == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9404,14 +9644,14 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget )
|
||||
vecProjection.x = -vecTarget.y;
|
||||
vecProjection.y = vecTarget.x;
|
||||
|
||||
return UTIL_VecToYaw( vecProjection - GetLocalOrigin() );
|
||||
return UTIL_VecToYaw( vecProjection - GetAbsOrigin() );
|
||||
}
|
||||
else if ( GetNavigator()->GetMovementActivity() == ACT_STRAFE_RIGHT )
|
||||
{
|
||||
vecProjection.x = vecTarget.y;
|
||||
vecProjection.y = vecTarget.x;
|
||||
|
||||
return UTIL_VecToYaw( vecProjection - GetLocalOrigin() );
|
||||
return UTIL_VecToYaw( vecProjection - GetAbsOrigin() );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
// Allow hint nodes to override the yaw without needing to control AI
|
||||
@ -9422,7 +9662,7 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget )
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return UTIL_VecToYaw ( vecTarget - GetLocalOrigin() );
|
||||
return UTIL_VecToYaw ( vecTarget - GetAbsOrigin() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -9622,7 +9862,7 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
||||
//DevMsg( "Turned!\n" );
|
||||
SetIdealActivity( ACT_IDLE );
|
||||
Forget( bits_MEMORY_TURNING );
|
||||
SetBoneController( 0, GetLocalAngles().y );
|
||||
SetBoneController( 0, GetAbsAngles().y );
|
||||
IncrementInterpolationFrame();
|
||||
break;
|
||||
}
|
||||
@ -10901,7 +11141,7 @@ Vector CAI_BaseNPC::GetShootEnemyDir( const Vector &shootOrigin, bool bNoisy )
|
||||
else
|
||||
{
|
||||
Vector forward;
|
||||
AngleVectors( GetLocalAngles(), &forward );
|
||||
AngleVectors( GetAbsAngles(), &forward );
|
||||
return forward;
|
||||
}
|
||||
}
|
||||
@ -11529,6 +11769,13 @@ float CAI_BaseNPC::GetEnemyLastTimeSeen() const
|
||||
void CAI_BaseNPC::MarkEnemyAsEluded()
|
||||
{
|
||||
GetEnemies()->MarkAsEluded( GetEnemy() );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_pSquad)
|
||||
{
|
||||
m_pSquad->MarkEnemyAsEluded( this, GetEnemy() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CAI_BaseNPC::ClearEnemyMemory()
|
||||
@ -12307,7 +12554,17 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetEnemy, "SetEnemy", "Set the NPC's current enemy." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetEnemyLKP, "GetEnemyLKP", "Get the last known position of the NPC's current enemy." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptNumEnemies, "NumEnemies", "Get the number of enemies this NPC knows about." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetFirstEnemyMemory, "GetFirstEnemyMemory", "Get information about the NPC's first enemy." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetNextEnemyMemory, "GetNextEnemyMemory", "Get information about the NPC's next enemy." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptFindEnemyMemory, "FindEnemyMemory", "Get information about the NPC's current enemy." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptUpdateEnemyMemory, "UpdateEnemyMemory", "Update information on this enemy. First parameter is the enemy, second is the position we now know the enemy is at, third parameter is the informer (e.g. squadmate who sees enemy, null if I see it myself). Returns true if this is a new enemy." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptClearEnemyMemory, "ClearEnemyMemory", "Makes the NPC forget about the specified enemy." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetFreeKnowledgeDuration, "SetFreeKnowledgeDuration", "Sets the amount of time the NPC can always know an enemy's location after losing sight." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetEnemyDiscardTime, "SetEnemyDiscardTime", "Sets the amount of time needed before the NPC discards an unseen enemy's memory." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetLastAttackTime, "Get the last time the NPC has used an attack (e.g. fired a bullet from a gun)." )
|
||||
DEFINE_SCRIPTFUNC( GetLastDamageTime, "Get the last time the NPC has been damaged." )
|
||||
@ -12315,6 +12572,11 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC( GetLastEnemyTime, "Get the last time the NPC has seen an enemy." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetState, "GetNPCState", "Get the NPC's current state." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetIdealState, "GetIdealNPCState", "Get the NPC's ideal state." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetIdealState, "SetIdealNPCState", "Set the NPC's ideal state." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetTarget, "GetNPCTarget", "Get the NPC's AI target." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetTarget, "SetNPCTarget", "Set the NPC's AI target." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptWake, "Wake", "Awakens the NPC if it is currently asleep." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSleep, "Sleep", "Puts the NPC into a sleeping state." )
|
||||
@ -12362,6 +12624,16 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptClearCondition, "ClearCondition", "Clear a condition on the NPC." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ClearCondition, "ClearConditionID", "Clear a condition on the NPC by ID." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetCustomInterruptCondition, "SetCustomInterruptCondition", "Use with BuildScheduleTestBits to define conditions which should interrupt the schedule." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptIsCustomInterruptConditionSet, "IsCustomInterruptConditionSet", "Use with BuildScheduleTestBits to define conditions which should interrupt the schedule." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptClearCustomInterruptCondition, "ClearCustomInterruptCondition", "Use with BuildScheduleTestBits to define conditions which should interrupt the schedule." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptChainStartTask, "ChainStartTask", "Use with StartTask to redirect to the specified task." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptChainRunTask, "ChainRunTask", "Use with RunTask to redirect to the specified task." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptFailTask, "FailTask", "Fails the currently running task with the specified error message." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptCompleteTask, "CompleteTask", "Completes the currently running task." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetTaskStatus, "GetTaskStatus", "Gets the current task's status." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( IsMoving, "Check if the NPC is moving." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetExpresser, "GetExpresser", "Get a handle for this NPC's expresser." )
|
||||
@ -12380,6 +12652,13 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC( IsCrouching, "Returns true if the NPC is crouching." )
|
||||
DEFINE_SCRIPTFUNC( Crouch, "Tells the NPC to crouch." )
|
||||
DEFINE_SCRIPTFUNC( Stand, "Tells the NPC to stand if it is crouching." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetBestSound, "GetBestSound", "Get the NPC's best sound of the specified type(s). Use 'ALL_SOUNDS' to get any sound." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetFirstHeardSound, "GetFirstHeardSound", "Get the NPC's first heard sound." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetNextHeardSound, "GetNextHeardSound", "Get the NPC's next heard sound." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetFirstSeenEntity, "GetFirstSeenEntity", "Get the NPC's first seen entity in the specified 'SEEN_' list." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetNextSeenEntity, "GetNextSeenEntity", "Get the NPC's next seen entity in the specified 'SEEN_' list." )
|
||||
|
||||
//
|
||||
// Hooks
|
||||
@ -12409,6 +12688,32 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTHOOK_PARAM( "activity", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "translatedActivity", FIELD_CSTRING )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_IsValidEnemy, "IsValidEnemy", FIELD_BOOLEAN, "Whether or not the specified enemy should be considered valid." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "enemy", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_CanBeAnEnemyOf, "CanBeAnEnemyOf", FIELD_BOOLEAN, "Whether or not this NPC can be an enemy of another NPC." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "enemy", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_UpdateEnemyMemory, "UpdateEnemyMemory", FIELD_BOOLEAN, "Whether or not this NPC can be an enemy of another NPC." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "enemy", FIELD_HSCRIPT )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "position", FIELD_VECTOR )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "informer", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_OnSeeEntity, "OnSeeEntity", FIELD_VOID, "Called when the NPC sees an entity." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CAI_BaseNPC::g_Hook_OnListened, "OnListened", FIELD_VOID, "Called when the NPC assigns sound conditions after checking for sounds it hears." )
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CAI_BaseNPC::g_Hook_BuildScheduleTestBits, "BuildScheduleTestBits", FIELD_VOID, "Called when the NPC is determining which conditions can interrupt the current schedule." )
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_StartTask, "StartTask", FIELD_VOID, "Called when a task is starting. The task is provided in both string and ID form. Return false to override actual task functionality." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task_id", FIELD_INTEGER )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task_data", FIELD_FLOAT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_RunTask, "RunTask", FIELD_VOID, "Called every think while the task is running. The task is provided in both string and ID form. Return false to override actual task functionality." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task_id", FIELD_INTEGER )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task_data", FIELD_FLOAT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
@ -13874,7 +14179,7 @@ bool CAI_BaseNPC::OverrideMove( float flInterval )
|
||||
float CAI_BaseNPC::VecToYaw( const Vector &vecDir )
|
||||
{
|
||||
if (vecDir.x == 0 && vecDir.y == 0 && vecDir.z == 0)
|
||||
return GetLocalAngles().y;
|
||||
return GetAbsAngles().y;
|
||||
|
||||
return UTIL_VecToYaw( vecDir );
|
||||
}
|
||||
|
@ -1104,7 +1104,7 @@ public:
|
||||
virtual void OnLooked( int iDistance );
|
||||
virtual void OnListened();
|
||||
|
||||
virtual void OnSeeEntity( CBaseEntity *pEntity ) {}
|
||||
virtual void OnSeeEntity( CBaseEntity *pEntity );
|
||||
|
||||
// If true, AI will try to see this entity regardless of distance.
|
||||
virtual bool ShouldNotDistanceCull() { return false; }
|
||||
@ -1180,6 +1180,11 @@ public:
|
||||
|
||||
void SetDeathPose( const int &iDeathPose ) { m_iDeathPose = iDeathPose; }
|
||||
void SetDeathPoseFrame( const int &iDeathPoseFrame ) { m_iDeathFrame = iDeathPoseFrame; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
int GetDeathPose() { return m_iDeathPose; }
|
||||
int GetDeathPoseFrame() { return m_iDeathFrame; }
|
||||
#endif
|
||||
|
||||
void SelectDeathPose( const CTakeDamageInfo &info );
|
||||
virtual bool ShouldPickADeathPose( void ) { return true; }
|
||||
@ -1271,9 +1276,24 @@ private:
|
||||
void VScriptSetEnemy( HSCRIPT pEnemy );
|
||||
Vector VScriptGetEnemyLKP();
|
||||
|
||||
HSCRIPT VScriptFindEnemyMemory( HSCRIPT pEnemy );
|
||||
int VScriptNumEnemies();
|
||||
|
||||
HSCRIPT VScriptGetFirstEnemyMemory();
|
||||
HSCRIPT VScriptGetNextEnemyMemory( HSCRIPT hMemory );
|
||||
|
||||
HSCRIPT VScriptFindEnemyMemory( HSCRIPT hEnemy );
|
||||
bool VScriptUpdateEnemyMemory( HSCRIPT hEnemy, const Vector &position, HSCRIPT hInformer );
|
||||
void VScriptClearEnemyMemory( HSCRIPT hEnemy );
|
||||
|
||||
void VScriptSetFreeKnowledgeDuration( float flDuration );
|
||||
void VScriptSetEnemyDiscardTime( float flDuration );
|
||||
|
||||
int VScriptGetState();
|
||||
int VScriptGetIdealState();
|
||||
void VScriptSetIdealState( int nNPCState );
|
||||
|
||||
HSCRIPT VScriptGetTarget();
|
||||
void VScriptSetTarget( HSCRIPT hTarget );
|
||||
|
||||
void VScriptWake( HSCRIPT hActivator ) { Wake( ToEnt(hActivator) ); }
|
||||
void VScriptSleep() { Sleep(); }
|
||||
@ -1308,12 +1328,29 @@ private:
|
||||
void VScriptSetCondition( const char *szCondition ) { SetCondition( GetConditionID( szCondition ) ); }
|
||||
void VScriptClearCondition( const char *szCondition ) { ClearCondition( GetConditionID( szCondition ) ); }
|
||||
|
||||
void VScriptSetCustomInterruptCondition( const char *szCondition ) { SetCustomInterruptCondition( GetConditionID( szCondition ) ); }
|
||||
bool VScriptIsCustomInterruptConditionSet( const char *szCondition ) { return IsCustomInterruptConditionSet( GetConditionID( szCondition ) ); }
|
||||
void VScriptClearCustomInterruptCondition( const char *szCondition ) { ClearCustomInterruptCondition( GetConditionID( szCondition ) ); }
|
||||
|
||||
void VScriptChainStartTask( const char *szTask, float flTaskData ) { ChainStartTask( AI_RemapFromGlobal( GetTaskID( szTask ) ), flTaskData ); }
|
||||
void VScriptChainRunTask( const char *szTask, float flTaskData ) { ChainRunTask( AI_RemapFromGlobal( GetTaskID( szTask ) ), flTaskData ); }
|
||||
void VScriptFailTask( const char *szFailReason ) { TaskFail( szFailReason ); }
|
||||
void VScriptCompleteTask() { TaskComplete(); }
|
||||
int VScriptGetTaskStatus() { return (int)GetTaskStatus(); }
|
||||
|
||||
HSCRIPT VScriptGetExpresser();
|
||||
|
||||
HSCRIPT VScriptGetCine();
|
||||
int GetScriptState() { return m_scriptState; }
|
||||
|
||||
HSCRIPT VScriptGetSquad();
|
||||
|
||||
HSCRIPT VScriptGetBestSound( int validTypes );
|
||||
HSCRIPT VScriptGetFirstHeardSound();
|
||||
HSCRIPT VScriptGetNextHeardSound( HSCRIPT hSound );
|
||||
|
||||
HSCRIPT VScriptGetFirstSeenEntity( int nSeenType );
|
||||
HSCRIPT VScriptGetNextSeenEntity( HSCRIPT hEnt, int nSeenType );
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------
|
||||
@ -2399,6 +2436,14 @@ public:
|
||||
static ScriptHook_t g_Hook_GetActualShootPosition;
|
||||
static ScriptHook_t g_Hook_OverrideMove;
|
||||
static ScriptHook_t g_Hook_ShouldPlayFakeSequenceGesture;
|
||||
static ScriptHook_t g_Hook_IsValidEnemy;
|
||||
static ScriptHook_t g_Hook_CanBeAnEnemyOf;
|
||||
static ScriptHook_t g_Hook_UpdateEnemyMemory;
|
||||
static ScriptHook_t g_Hook_OnSeeEntity;
|
||||
static ScriptHook_t g_Hook_OnListened;
|
||||
static ScriptHook_t g_Hook_BuildScheduleTestBits;
|
||||
static ScriptHook_t g_Hook_StartTask;
|
||||
static ScriptHook_t g_Hook_RunTask;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -45,6 +45,10 @@ extern ConVar ai_use_think_optimizations;
|
||||
|
||||
ConVar ai_simulate_task_overtime( "ai_simulate_task_overtime", "0" );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_enemy_memory_fixes( "ai_enemy_memory_fixes", "0", FCVAR_NONE, "Toggles Mapbase fixes for certain NPC AI not using enemy memory when it should." );
|
||||
#endif
|
||||
|
||||
#define MAX_TASKS_RUN 10
|
||||
|
||||
struct TaskTimings
|
||||
@ -276,6 +280,14 @@ void CAI_BaseNPC::NextScheduledTask ( void )
|
||||
void CAI_BaseNPC::BuildScheduleTestBits( void )
|
||||
{
|
||||
//NOTENOTE: Always defined in the leaf classes
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_BuildScheduleTestBits.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
g_Hook_BuildScheduleTestBits.Call( m_ScriptScope, &functionReturn, NULL );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -730,6 +742,23 @@ void CAI_BaseNPC::MaintainSchedule ( void )
|
||||
AI_PROFILE_SCOPE_BEGIN_( pszTaskName );
|
||||
AI_PROFILE_SCOPE_BEGIN(CAI_BaseNPC_StartTask);
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_StartTask.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// task, task_id, task_data
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { (bDebugTaskNames) ? pszTaskName : TaskName( pTask->iTask ), pTask->iTask, pTask->flTaskData };
|
||||
if (g_Hook_StartTask.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
// Returning false overrides original functionality
|
||||
if (functionReturn.m_bool != false)
|
||||
StartTask( pTask );
|
||||
}
|
||||
else
|
||||
StartTask( pTask );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
StartTask( pTask );
|
||||
|
||||
AI_PROFILE_SCOPE_END();
|
||||
@ -766,6 +795,23 @@ void CAI_BaseNPC::MaintainSchedule ( void )
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_RunTask.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// task, task_id, task_data
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { (bDebugTaskNames) ? pszTaskName : TaskName( pTask->iTask ), pTask->iTask, pTask->flTaskData };
|
||||
if (g_Hook_RunTask.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
// Returning false overrides original functionality
|
||||
if (functionReturn.m_bool != false)
|
||||
RunTask( pTask );
|
||||
}
|
||||
else
|
||||
RunTask( pTask );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
RunTask( pTask );
|
||||
|
||||
if ( GetTaskInterrupt() == 0 || TaskIsComplete() || HasCondition(COND_TASK_FAILED) )
|
||||
@ -918,7 +964,7 @@ void CAI_BaseNPC::StartTurn( float flDeltaYaw )
|
||||
{
|
||||
float flCurrentYaw;
|
||||
|
||||
flCurrentYaw = UTIL_AngleMod( GetLocalAngles().y );
|
||||
flCurrentYaw = UTIL_AngleMod( GetAbsAngles().y );
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( flCurrentYaw + flDeltaYaw ) );
|
||||
SetTurnActivity();
|
||||
}
|
||||
@ -1111,7 +1157,7 @@ void CAI_BaseNPC::StartScriptMoveToTargetTask( int task )
|
||||
{
|
||||
TaskFail(FAIL_NO_TARGET);
|
||||
}
|
||||
else if ( (m_hTargetEnt->GetAbsOrigin() - GetLocalOrigin()).Length() < 1 )
|
||||
else if ( (m_hTargetEnt->GetAbsOrigin() - GetAbsOrigin()).Length() < 1 )
|
||||
{
|
||||
TaskComplete();
|
||||
}
|
||||
@ -1576,7 +1622,7 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
break;
|
||||
|
||||
case TASK_SET_IDEAL_YAW_TO_CURRENT:
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( GetLocalAngles().y ) );
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( GetAbsAngles().y ) );
|
||||
TaskComplete();
|
||||
break;
|
||||
|
||||
@ -1730,7 +1776,7 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
{
|
||||
TaskFail(FAIL_NO_TARGET);
|
||||
}
|
||||
else if ( (pTarget->GetAbsOrigin() - GetLocalOrigin()).Length() < 1 )
|
||||
else if ( (pTarget->GetAbsOrigin() - GetAbsOrigin()).Length() < 1 )
|
||||
{
|
||||
TaskComplete();
|
||||
}
|
||||
@ -1971,7 +2017,17 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
flMaxRange = m_flDistTooFar;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// By default, TASK_GET_PATH_TO_ENEMY_LKP_LOS acts identical to TASK_GET_PATH_TO_ENEMY_LOS.
|
||||
// Considering the fact TASK_GET_PATH_TO_ENEMY_LKP doesn't use this code, this appears to be a mistake.
|
||||
// In HL2, this task is used by Combine soldiers, metrocops, striders, and hunters.
|
||||
// With this change, these NPCs will establish LOS according to enemy memory instead of where the enemy
|
||||
// actually is. This may make the NPCs more consistent and fair, but their AI and levels built around it
|
||||
// may have been designed around this bug, so this is currently being tied to a cvar.
|
||||
Vector vecEnemy = ( task != TASK_GET_PATH_TO_ENEMY_LKP_LOS || !ai_enemy_memory_fixes.GetBool() ) ? GetEnemy()->GetAbsOrigin() : GetEnemyLKP();
|
||||
#else
|
||||
Vector vecEnemy = ( task != TASK_GET_PATH_TO_ENEMY_LKP ) ? GetEnemy()->GetAbsOrigin() : GetEnemyLKP();
|
||||
#endif
|
||||
Vector vecEnemyEye = vecEnemy + GetEnemy()->GetViewOffset();
|
||||
|
||||
Vector posLos;
|
||||
@ -2965,7 +3021,7 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
{
|
||||
if ( m_hTargetEnt != NULL )
|
||||
{
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( m_hTargetEnt->GetLocalAngles().y ) );
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( m_hTargetEnt->GetAbsAngles().y ) );
|
||||
}
|
||||
|
||||
if ( m_scriptState != SCRIPT_CUSTOM_MOVE_TO_MARK )
|
||||
@ -3294,7 +3350,7 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
||||
pTarget = GetEnemy();
|
||||
if ( pTarget )
|
||||
{
|
||||
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin() , AI_KEEP_YAW_SPEED );
|
||||
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetAbsOrigin(), AI_KEEP_YAW_SPEED );
|
||||
}
|
||||
|
||||
if ( IsActivityFinished() )
|
||||
|
@ -500,6 +500,13 @@ public:
|
||||
g_AI_SensedObjectsManager.Init();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual void RegisterVScript()
|
||||
{
|
||||
g_pScriptVM->RegisterInstance( &g_AI_SensedObjectsManager, "SensedObjectsManager" );
|
||||
}
|
||||
#endif
|
||||
|
||||
void LevelShutdownPreEntity()
|
||||
{
|
||||
CBaseCombatCharacter::ResetVisibilityCache();
|
||||
|
@ -78,6 +78,7 @@ static void DispatchComeback( CAI_ExpresserWithFollowup *pExpress, CBaseEntity *
|
||||
// See DispatchFollowupThroughQueue()
|
||||
criteria.AppendCriteria( "From_idx", CNumStr( pSpeaker->entindex() ) );
|
||||
criteria.AppendCriteria( "From_class", pSpeaker->GetClassname() );
|
||||
pSpeaker->AppendContextToCriteria( criteria, "From_" );
|
||||
#endif
|
||||
// if a SUBJECT criteria is missing, put it back in.
|
||||
if ( criteria.FindCriterionIndex( "Subject" ) == -1 )
|
||||
|
@ -225,6 +225,18 @@ AI_EnemyInfo_t *CAI_Enemies::Find( CBaseEntity *pEntity, bool bTryDangerMemory )
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE
|
||||
unsigned char CAI_Enemies::FindIndex( CBaseEntity *pEntity )
|
||||
{
|
||||
if ( pEntity == AI_UNKNOWN_ENEMY )
|
||||
pEntity = NULL;
|
||||
|
||||
return m_Map.Find( pEntity );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
AI_EnemyInfo_t *CAI_Enemies::GetDangerMemory()
|
||||
|
@ -63,6 +63,9 @@ public:
|
||||
AI_EnemyInfo_t *GetFirst( AIEnemiesIter_t *pIter );
|
||||
AI_EnemyInfo_t *GetNext( AIEnemiesIter_t *pIter );
|
||||
AI_EnemyInfo_t *Find( CBaseEntity *pEntity, bool bTryDangerMemory = false );
|
||||
#ifdef MAPBASE
|
||||
unsigned char FindIndex( CBaseEntity *pEntity );
|
||||
#endif
|
||||
AI_EnemyInfo_t *GetDangerMemory();
|
||||
|
||||
int NumEnemies() const { return m_Map.Count(); }
|
||||
|
@ -298,6 +298,43 @@ CBaseEntity *CAI_Senses::GetNextSeenEntity( AISightIter_t *pIter ) const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool CAI_Senses::GetSeenEntityIndex( AISightIter_t *pIter, CBaseEntity *pSightEnt, seentype_t iSeenType ) const
|
||||
{
|
||||
COMPILE_TIME_ASSERT( sizeof( AISightIter_t ) == sizeof( AISightIterVal_t ) );
|
||||
|
||||
AISightIterVal_t *pIterVal = (AISightIterVal_t *)pIter;
|
||||
|
||||
// If we're searching for a specific type, start in that array
|
||||
pIterVal->SeenArray = (char)iSeenType;
|
||||
int iFirstArray = ( iSeenType == SEEN_ALL ) ? 0 : iSeenType;
|
||||
|
||||
for ( int i = iFirstArray; i < ARRAYSIZE( m_SeenArrays ); i++ )
|
||||
{
|
||||
for ( int j = pIterVal->iNext; j < m_SeenArrays[i]->Count(); j++ )
|
||||
{
|
||||
if ( (*m_SeenArrays[i])[j].Get() == pSightEnt )
|
||||
{
|
||||
pIterVal->array = i;
|
||||
pIterVal->iNext = j+1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
pIterVal->iNext = 0;
|
||||
|
||||
// If we're searching for a specific type, don't move to the next array
|
||||
if ( pIterVal->SeenArray != SEEN_ALL )
|
||||
break;
|
||||
}
|
||||
|
||||
(*pIter) = (AISightIter_t)(-1);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CAI_Senses::BeginGather()
|
||||
@ -749,4 +786,27 @@ void CAI_SensedObjectsManager::AddEntity( CBaseEntity *pEntity )
|
||||
m_SensedObjects.AddToTail( pEntity );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CAI_SensedObjectsManager::RemoveEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
int i = m_SensedObjects.Find( pEntity );
|
||||
if (i == m_SensedObjects.InvalidIndex())
|
||||
return;
|
||||
|
||||
pEntity->RemoveFlag( FL_OBJECT );
|
||||
m_SensedObjects.FastRemove( i );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
BEGIN_SCRIPTDESC_ROOT( CAI_SensedObjectsManager, SCRIPT_SINGLETON "Manager which handles sensed objects." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddEntity, "AddEntity", "Adds an entity to the sensed object list." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptRemoveEntity, "RemoveEntity", "Removes an entity from the sensed object list." )
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
|
@ -82,6 +82,9 @@ public:
|
||||
|
||||
CBaseEntity * GetFirstSeenEntity( AISightIter_t *pIter, seentype_t iSeenType = SEEN_ALL ) const;
|
||||
CBaseEntity * GetNextSeenEntity( AISightIter_t *pIter ) const;
|
||||
#ifdef MAPBASE
|
||||
bool GetSeenEntityIndex( AISightIter_t *pIter, CBaseEntity *pSightEnt, seentype_t iSeenType ) const;
|
||||
#endif
|
||||
|
||||
CSound * GetFirstHeardSound( AISoundIter_t *pIter );
|
||||
CSound * GetNextHeardSound( AISoundIter_t *pIter );
|
||||
@ -152,6 +155,14 @@ public:
|
||||
CBaseEntity * GetNext( int *pIter );
|
||||
|
||||
virtual void AddEntity( CBaseEntity *pEntity );
|
||||
#ifdef MAPBASE
|
||||
virtual void RemoveEntity( CBaseEntity *pEntity );
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
void ScriptAddEntity( HSCRIPT hEnt ) { AddEntity( ToEnt( hEnt ) ); }
|
||||
void ScriptRemoveEntity( HSCRIPT hEnt ) { RemoveEntity( ToEnt( hEnt ) ); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual void OnEntitySpawned( CBaseEntity *pEntity );
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "sceneentity.h"
|
||||
#include "ai_speechqueue.h"
|
||||
#ifdef MAPBASE
|
||||
#include "mapbase/choreosentence.h"
|
||||
#include "ai_squad.h"
|
||||
#endif
|
||||
|
||||
@ -846,6 +847,9 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res
|
||||
case ResponseRules::RESPONSE_NONE:
|
||||
break;
|
||||
|
||||
#ifdef MAPBASE
|
||||
case ResponseRules::RESPONSE_CHOREOSENTENCE:
|
||||
#endif
|
||||
case ResponseRules::RESPONSE_SPEAK:
|
||||
{
|
||||
if ( !result->ShouldntUseScene() )
|
||||
@ -918,7 +922,7 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res
|
||||
textParams.g1 = 255;
|
||||
textParams.b1 = 255;
|
||||
|
||||
if (ai_speech_print_mode.GetBool() && GetOuter()->GetGameTextSpeechParams( textParams ))
|
||||
if (ai_speech_print_mode.GetBool() && GetOuter()->DispatchGetGameTextSpeechParams( textParams ))
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddAllPlayers();
|
||||
@ -1194,6 +1198,15 @@ float CAI_Expresser::GetResponseDuration( AI_Response *result )
|
||||
case ResponseRules::RESPONSE_NONE:
|
||||
case ResponseRules::RESPONSE_ENTITYIO:
|
||||
return 0.0f;
|
||||
#ifdef MAPBASE
|
||||
case ResponseRules::RESPONSE_CHOREOSENTENCE:
|
||||
{
|
||||
const ChoreoSentence_t *pSentence = LookupChoreoSentence( GetOuter(), response );
|
||||
if (pSentence)
|
||||
return GetChoreoSentenceDuration( GetOuter(), *pSentence );
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
|
@ -18,6 +18,10 @@
|
||||
|
||||
CAI_SquadManager g_AI_SquadManager;
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_squad_broadcast_elusion("ai_squad_broadcast_elusion", "0", FCVAR_NONE, "Tells the entire squad when an enemy is eluded");
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAI_SquadManager
|
||||
//
|
||||
@ -740,6 +744,25 @@ void CAI_Squad::UpdateEnemyMemory( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy, c
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CAI_Squad::MarkEnemyAsEluded( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy )
|
||||
{
|
||||
if (!ai_squad_broadcast_elusion.GetBool())
|
||||
return;
|
||||
|
||||
//Broadcast to all members of the squad
|
||||
for ( int i = 0; i < m_SquadMembers.Count(); i++ )
|
||||
{
|
||||
if ( m_SquadMembers[i] != pUpdater )
|
||||
{
|
||||
m_SquadMembers[i]->GetEnemies()->MarkAsEluded( pEnemy );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef PER_ENEMY_SQUADSLOTS
|
||||
|
||||
AISquadEnemyInfo_t *CAI_Squad::FindEnemyInfo( CBaseEntity *pEnemy )
|
||||
@ -883,14 +906,14 @@ void CAI_Squad::ScriptRemoveFromSquad( HSCRIPT hNPC ) { RemoveFromSquad( HScrip
|
||||
|
||||
bool CAI_Squad::ScriptIsSilentMember( HSCRIPT hNPC ) { return IsSilentMember( HScriptToClass<CAI_BaseNPC>( hNPC ) ); }
|
||||
|
||||
void CAI_Squad::ScriptSetSquadData( int iSlot, const char *data )
|
||||
void CAI_Squad::ScriptSetSquadData( int iSlot, int data )
|
||||
{
|
||||
SetSquadData( iSlot, data );
|
||||
}
|
||||
|
||||
const char *CAI_Squad::ScriptGetSquadData( int iSlot )
|
||||
int CAI_Squad::ScriptGetSquadData( int iSlot )
|
||||
{
|
||||
const char *data;
|
||||
int data;
|
||||
GetSquadData( iSlot, &data );
|
||||
return data;
|
||||
}
|
||||
|
@ -107,6 +107,12 @@ public:
|
||||
|
||||
void SquadNewEnemy ( CBaseEntity *pEnemy );
|
||||
void UpdateEnemyMemory( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy, const Vector &position );
|
||||
#ifdef MAPBASE
|
||||
// The idea behind this is that, if one squad member fails to locate the enemy, nobody in the squad knows where the enemy is
|
||||
// Makes combat utilizing elusion a bit smoother
|
||||
// (gated by ai_squad_broadcast_elusion cvar)
|
||||
void MarkEnemyAsEluded( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy );
|
||||
#endif
|
||||
|
||||
bool OccupyStrategySlotRange( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd, int *pSlot );
|
||||
void VacateStrategySlot( CBaseEntity *pEnemy, int slot);
|
||||
@ -186,8 +192,8 @@ private:
|
||||
|
||||
bool ScriptIsSilentMember( HSCRIPT hNPC );
|
||||
|
||||
void ScriptSetSquadData( int iSlot, const char *data );
|
||||
const char *ScriptGetSquadData( int iSlot );
|
||||
void ScriptSetSquadData( int iSlot, int data );
|
||||
int ScriptGetSquadData( int iSlot );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -317,7 +317,7 @@ BEGIN_ENT_SCRIPTDESC( CBaseAnimating, CBaseEntity, "Animating models" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceActivity, "GetSequenceActivity", "Gets the activity ID of the specified sequence index" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSelectWeightedSequence, "SelectWeightedSequence", "Selects a sequence for the specified activity ID" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSelectHeaviestSequence, "SelectHeaviestSequence", "Selects the sequence with the heaviest weight for the specified activity ID" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceKeyValues, "GetSequenceKeyValues", "Get a KeyValue class instance on the specified sequence. WARNING: This uses the same KeyValue pointer as GetModelKeyValues!" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceKeyValues, "GetSequenceKeyValues", "Get a KeyValue class instance on the specified sequence" )
|
||||
DEFINE_SCRIPTFUNC( ResetSequenceInfo, "" )
|
||||
DEFINE_SCRIPTFUNC( StudioFrameAdvance, "" )
|
||||
DEFINE_SCRIPTFUNC( GetPlaybackRate, "" )
|
||||
@ -1261,7 +1261,8 @@ void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler )
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
|
||||
scriptanimevent_t wrapper( event );
|
||||
if (!eventHandler->ScriptHookHandleAnimEvent( wrapper ))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
@ -1299,11 +1300,11 @@ void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseAnimating::ScriptHookHandleAnimEvent( animevent_t *pEvent )
|
||||
bool CBaseAnimating::ScriptHookHandleAnimEvent( scriptanimevent_t &event )
|
||||
{
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_HandleAnimEvent.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( reinterpret_cast<scriptanimevent_t*>(pEvent) );
|
||||
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( &event );
|
||||
|
||||
// event
|
||||
ScriptVariant_t args[] = { hEvent };
|
||||
@ -2305,21 +2306,14 @@ void CBaseAnimating::ScriptGetBoneTransform( int iBone, HSCRIPT hTransform )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// VScript access to sequence's key values
|
||||
// for iteration and value access, use:
|
||||
// ScriptFindKey, ScriptGetFirstSubKey, ScriptGetString,
|
||||
// ScriptGetInt, ScriptGetFloat, ScriptGetNextKey
|
||||
// NOTE: This is recycled from ScriptGetModelKeyValues() and uses its pointer!!!
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseAnimating::ScriptGetSequenceKeyValues( int iSequence )
|
||||
HSCRIPT_RC CBaseAnimating::ScriptGetSequenceKeyValues( int iSequence )
|
||||
{
|
||||
KeyValues *pSeqKeyValues = GetSequenceKeyValues( iSequence );
|
||||
HSCRIPT hScript = NULL;
|
||||
if ( pSeqKeyValues )
|
||||
{
|
||||
// UNDONE: how does destructor get called on this
|
||||
m_pScriptModelKeyValues = hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pSeqKeyValues, true );
|
||||
|
||||
// UNDONE: who calls ReleaseInstance on this??? Does name need to be unique???
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pSeqKeyValues );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include "datacache/idatacache.h"
|
||||
#include "tier0/threadtools.h"
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
struct scriptanimevent_t;
|
||||
#endif
|
||||
|
||||
struct animevent_t;
|
||||
struct matrix3x4_t;
|
||||
@ -146,7 +149,7 @@ public:
|
||||
virtual void DispatchAnimEvents ( CBaseAnimating *eventHandler ); // Handle events that have happend since last time called up until X seconds into the future
|
||||
virtual void HandleAnimEvent( animevent_t *pEvent );
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
bool ScriptHookHandleAnimEvent( animevent_t *pEvent );
|
||||
bool ScriptHookHandleAnimEvent( scriptanimevent_t &event );
|
||||
#endif
|
||||
|
||||
int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName );
|
||||
@ -208,7 +211,7 @@ public:
|
||||
int ScriptSelectHeaviestSequence( int activity ) { return SelectHeaviestSequence( (Activity)activity ); }
|
||||
int ScriptSelectWeightedSequence( int activity, int curSequence ) { return SelectWeightedSequence( (Activity)activity, curSequence ); }
|
||||
|
||||
HSCRIPT ScriptGetSequenceKeyValues( int iSequence );
|
||||
HSCRIPT_RC ScriptGetSequenceKeyValues( int iSequence );
|
||||
|
||||
// For VScript
|
||||
int GetSkin() { return m_nSkin; }
|
||||
|
@ -3482,13 +3482,13 @@ void CBaseCombatCharacter::AddRelationship( const char *pszRelationship, CBaseEn
|
||||
bool bFoundEntity = false;
|
||||
|
||||
// Try to get pointer to an entity of this name
|
||||
CBaseEntity *entity = gEntList.FindEntityByName( NULL, entityString );
|
||||
CBaseEntity *entity = gEntList.FindEntityByName( NULL, entityString, this, pActivator );
|
||||
while( entity )
|
||||
{
|
||||
// make sure you catch all entities of this name.
|
||||
bFoundEntity = true;
|
||||
AddEntityRelationship(entity, disposition, priority );
|
||||
entity = gEntList.FindEntityByName( entity, entityString );
|
||||
entity = gEntList.FindEntityByName( entity, entityString, this, pActivator );
|
||||
}
|
||||
|
||||
if( !bFoundEntity )
|
||||
|
@ -1628,10 +1628,53 @@ void CBaseEntity::TakeDamage( const CTakeDamageInfo &inputInfo )
|
||||
DamageFilterDamageMod(info);
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnTakeDamage.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
HSCRIPT hInfo = g_pScriptVM->RegisterInstance( &info );
|
||||
|
||||
// info
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ScriptVariant_t( hInfo ) };
|
||||
if ( g_Hook_OnTakeDamage.Call( m_ScriptScope, &functionReturn, args ) )
|
||||
{
|
||||
if (functionReturn.m_type == FIELD_BOOLEAN && functionReturn.m_bool == false)
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( hInfo );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_pScriptVM->RemoveInstance( hInfo );
|
||||
}
|
||||
#endif
|
||||
|
||||
OnTakeDamage( info );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Allows entities to be 'invisible' to NPC senses.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseEntity::CanBeSeenBy( CAI_BaseNPC *pNPC )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_CanBeSeenBy.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// npc
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pNPC ) };
|
||||
if (g_Hook_CanBeSeenBy.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_bool == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns a value that scales all damage done by this entity.
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2251,14 +2294,16 @@ ScriptHook_t CBaseEntity::g_Hook_OnEntText;
|
||||
ScriptHook_t CBaseEntity::g_Hook_VPhysicsCollision;
|
||||
ScriptHook_t CBaseEntity::g_Hook_FireBullets;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnDeath;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnTakeDamage;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnKilledOther;
|
||||
ScriptHook_t CBaseEntity::g_Hook_HandleInteraction;
|
||||
ScriptHook_t CBaseEntity::g_Hook_ModifyEmitSoundParams;
|
||||
ScriptHook_t CBaseEntity::g_Hook_ModifySentenceParams;
|
||||
ScriptHook_t CBaseEntity::g_Hook_ModifyOrAppendCriteria;
|
||||
ScriptHook_t CBaseEntity::g_Hook_CanBeSeenBy;
|
||||
#endif
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" )
|
||||
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT_WITH_HELPER( CBaseEntity, "Root class of all server-side entities", &g_BaseEntityScriptInstanceHelper )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ConnectOutputToScript, "ConnectOutput", "Adds an I/O connection that will call the named function when the specified output fires" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( DisconnectOutputFromScript, "DisconnectOutput", "Removes a connected script function from an I/O event." )
|
||||
|
||||
@ -2377,6 +2422,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetContext, "GetContext", "Get a response context value" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddContext, "AddContext", "Add a response context value" )
|
||||
DEFINE_SCRIPTFUNC( RemoveContext, "Remove a response context" )
|
||||
DEFINE_SCRIPTFUNC( GetContextExpireTime, "Get a response context's expiration time" )
|
||||
DEFINE_SCRIPTFUNC( GetContextCount, "Get the number of response contexts" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetContextIndex, "GetContextIndex", "Get a response context at a specific index in the form of a table" )
|
||||
@ -2515,14 +2561,15 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
DEFINE_SCRIPTHOOK_PARAM( "normal", FIELD_VECTOR )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_FireBullets, "FireBullets", FIELD_VOID, "Called for every single VPhysics-related collision experienced by this entity." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "speed", FIELD_FLOAT )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "point", FIELD_VECTOR )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "normal", FIELD_VECTOR )
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_FireBullets, "FireBullets", FIELD_VOID, "Called when the entity fires bullets from itself or from a weapon. The parameter is the associated FireBulletsInfo_t handle. Return false to cancel bullet firing." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_OnDeath, "OnDeath", FIELD_BOOLEAN, "Called when the entity dies (Event_Killed). Returning false makes the entity cancel death, although this could have unforeseen consequences. For hooking any damage instead of just death, see filter_script and PassesFinalDamageFilter." )
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_OnDeath, "OnDeath", FIELD_BOOLEAN, "Called when the entity dies (Event_Killed). Returning false makes the entity cancel death, although this could have unforeseen consequences. For hooking any damage instead of just death, use OnTakeDamage." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_OnTakeDamage, "OnTakeDamage", FIELD_BOOLEAN, "Called when the entity takes damage (OnTakeDamage). Returning false makes the entity cancel the damage, similar to a damage filter. This is called after any damage filter operations." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
@ -2544,6 +2591,12 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_ModifySentenceParams, "ModifySentenceParams", FIELD_VOID, "Called every time a sentence is emitted on this entity, allowing for its parameters to be modified." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "params", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CBaseEntity::g_Hook_ModifyOrAppendCriteria, "ModifyOrAppendCriteria", FIELD_HSCRIPT, "Called when the criteria set is collected for a response. Return a table of keyvalues to add to the criteria set." )
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_CanBeSeenBy, "CanBeSeenBy", FIELD_BOOLEAN, "Whether or not this entity can be seen by the specified NPC." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "npc", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
#endif
|
||||
END_SCRIPTDESC();
|
||||
|
||||
@ -7544,6 +7597,61 @@ void CBaseEntity::ModifyOrAppendCriteria( AI_CriteriaSet& set )
|
||||
set.AppendCriteria("spawnflags", UTIL_VarArgs("%i", GetSpawnFlags()));
|
||||
set.AppendCriteria("flags", UTIL_VarArgs("%i", GetFlags()));
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_ModifyOrAppendCriteria.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
if (g_Hook_ModifyOrAppendCriteria.Call( m_ScriptScope, &functionReturn, NULL ))
|
||||
{
|
||||
if (functionReturn.m_hScript != NULL)
|
||||
{
|
||||
int nIterator = -1;
|
||||
ScriptVariant_t varKey, varValue;
|
||||
while ((nIterator = g_pScriptVM->GetKeyValue( functionReturn.m_hScript, nIterator, &varKey, &varValue )) != -1)
|
||||
{
|
||||
float flWeight = 1.0f;
|
||||
char szValue[128];
|
||||
switch (varValue.m_type)
|
||||
{
|
||||
case FIELD_CSTRING:
|
||||
{
|
||||
char *colon = V_strstr( varValue.m_pszString, ":" );
|
||||
if (colon)
|
||||
{
|
||||
// Use as weight
|
||||
flWeight = atof(colon+1);
|
||||
*colon = NULL;
|
||||
}
|
||||
V_strncpy( szValue, varValue.m_pszString, sizeof( szValue ) );
|
||||
}
|
||||
break;
|
||||
case FIELD_BOOLEAN:
|
||||
V_snprintf( szValue, sizeof( szValue ), "%d", varValue.m_bool );
|
||||
break;
|
||||
case FIELD_INTEGER:
|
||||
V_snprintf( szValue, sizeof( szValue ), "%i", varValue.m_int );
|
||||
break;
|
||||
case FIELD_FLOAT:
|
||||
V_snprintf( szValue, sizeof( szValue ), "%f", varValue.m_float );
|
||||
break;
|
||||
case FIELD_VECTOR:
|
||||
V_snprintf( szValue, sizeof( szValue ), "%f %f %f", varValue.m_pVector->x, varValue.m_pVector->y, varValue.m_pVector->z );
|
||||
break;
|
||||
default:
|
||||
Warning( "ModifyOrAppendCriteria doesn't know how to handle field %i for %s\n", varValue.m_type, varKey.m_pszString );
|
||||
break;
|
||||
}
|
||||
|
||||
set.AppendCriteria( varKey.m_pszString, szValue, flWeight );
|
||||
|
||||
g_pScriptVM->ReleaseValue( varKey );
|
||||
g_pScriptVM->ReleaseValue( varValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -10154,7 +10262,7 @@ void CBaseEntity::SetScriptOwnerEntity(HSCRIPT pOwner)
|
||||
// ScriptFindKey, ScriptGetFirstSubKey, ScriptGetString,
|
||||
// ScriptGetInt, ScriptGetFloat, ScriptGetNextKey
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::ScriptGetModelKeyValues( void )
|
||||
HSCRIPT_RC CBaseEntity::ScriptGetModelKeyValues( void )
|
||||
{
|
||||
KeyValues *pModelKeyValues = new KeyValues("");
|
||||
HSCRIPT hScript = NULL;
|
||||
@ -10163,16 +10271,12 @@ HSCRIPT CBaseEntity::ScriptGetModelKeyValues( void )
|
||||
|
||||
if ( pModelKeyValues->LoadFromBuffer( pszModelName, pBuffer ) )
|
||||
{
|
||||
// UNDONE: how does destructor get called on this
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
m_pScriptModelKeyValues = hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pModelKeyValues, true ); // Allow VScript to delete this when the instance is removed.
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pModelKeyValues );
|
||||
#else
|
||||
// UNDONE: how does destructor get called on this
|
||||
m_pScriptModelKeyValues = new CScriptKeyValues( pModelKeyValues );
|
||||
#endif
|
||||
|
||||
// UNDONE: who calls ReleaseInstance on this??? Does name need to be unique???
|
||||
|
||||
#ifndef MAPBASE_VSCRIPT
|
||||
hScript = g_pScriptVM->RegisterInstance( m_pScriptModelKeyValues );
|
||||
#endif
|
||||
|
||||
|
@ -1440,7 +1440,7 @@ public:
|
||||
virtual bool FVisible ( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
virtual bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
|
||||
virtual bool CanBeSeenBy( CAI_BaseNPC *pNPC ) { return true; } // allows entities to be 'invisible' to NPC senses.
|
||||
virtual bool CanBeSeenBy( CAI_BaseNPC *pNPC ); // allows entities to be 'invisible' to NPC senses.
|
||||
|
||||
// This function returns a value that scales all damage done by this entity.
|
||||
// Use CDamageModifier to hook in damage modifiers on a guy.
|
||||
@ -2114,7 +2114,7 @@ public:
|
||||
#endif
|
||||
|
||||
const char* ScriptGetModelName(void) const;
|
||||
HSCRIPT ScriptGetModelKeyValues(void);
|
||||
HSCRIPT_RC ScriptGetModelKeyValues(void);
|
||||
|
||||
void ScriptStopSound(const char* soundname);
|
||||
void ScriptEmitSound(const char* soundname);
|
||||
@ -2177,10 +2177,13 @@ public:
|
||||
static ScriptHook_t g_Hook_VPhysicsCollision;
|
||||
static ScriptHook_t g_Hook_FireBullets;
|
||||
static ScriptHook_t g_Hook_OnDeath;
|
||||
static ScriptHook_t g_Hook_OnTakeDamage;
|
||||
static ScriptHook_t g_Hook_OnKilledOther;
|
||||
static ScriptHook_t g_Hook_HandleInteraction;
|
||||
static ScriptHook_t g_Hook_ModifyEmitSoundParams;
|
||||
static ScriptHook_t g_Hook_ModifySentenceParams;
|
||||
static ScriptHook_t g_Hook_ModifyOrAppendCriteria;
|
||||
static ScriptHook_t g_Hook_CanBeSeenBy;
|
||||
#endif
|
||||
|
||||
string_t m_iszVScripts;
|
||||
@ -2188,9 +2191,7 @@ public:
|
||||
CScriptScope m_ScriptScope;
|
||||
HSCRIPT m_hScriptInstance;
|
||||
string_t m_iszScriptId;
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
HSCRIPT m_pScriptModelKeyValues;
|
||||
#else
|
||||
#ifndef MAPBASE_VSCRIPT
|
||||
CScriptKeyValues* m_pScriptModelKeyValues;
|
||||
#endif
|
||||
};
|
||||
|
@ -816,7 +816,7 @@ bool CBaseFlex::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CCh
|
||||
textParams.g1 = 255;
|
||||
textParams.b1 = 255;
|
||||
|
||||
if ( GetGameTextSpeechParams( textParams ) )
|
||||
if ( DispatchGetGameTextSpeechParams( textParams ) )
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddAllPlayers();
|
||||
@ -1654,6 +1654,12 @@ bool CBaseFlex::ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, C
|
||||
case CChoreoEvent::SPEAK:
|
||||
return true;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Prevents "unknown type" console spam on players
|
||||
case CChoreoEvent::GENERIC:
|
||||
return true;
|
||||
#endif
|
||||
|
||||
default:
|
||||
{
|
||||
Msg( "unknown type %d in ProcessSceneEvent()\n", event->GetType() );
|
||||
@ -2093,8 +2099,16 @@ float CBaseFlex::PlayScene( const char *pszScene, float flDelay, AI_Response *re
|
||||
#ifdef MAPBASE
|
||||
float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname, float flDelay, AI_Response *response, IRecipientFilter *filter )
|
||||
{
|
||||
if (response && response->GetType() == ResponseRules::RESPONSE_CHOREOSENTENCE)
|
||||
return InstancedChoreoSentenceScene( this, soundname, NULL, flDelay, false, response, false, filter );
|
||||
|
||||
return InstancedAutoGeneratedSoundScene( this, soundname, NULL, flDelay, false, response, false, filter );
|
||||
}
|
||||
|
||||
float CBaseFlex::PlayChoreoSentenceScene( const char *pszSentence, float flDelay, AI_Response *response, IRecipientFilter *filter )
|
||||
{
|
||||
return InstancedChoreoSentenceScene( this, pszSentence, NULL, flDelay, false, response, false, filter );
|
||||
}
|
||||
#else
|
||||
float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname )
|
||||
{
|
||||
@ -2106,11 +2120,17 @@ float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Parameters for scene event AI_GameText
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseFlex::GetGameTextSpeechParams( hudtextparms_t ¶ms )
|
||||
bool CBaseFlex::DispatchGetGameTextSpeechParams( hudtextparms_t ¶ms )
|
||||
{
|
||||
// First, get any default values overridden by this class
|
||||
bool bReturn = GetGameTextSpeechParams( params );
|
||||
|
||||
// Allow VScript to override after
|
||||
ScriptVariant_t varTable;
|
||||
if (g_pScriptVM->GetValue(m_ScriptScope, "m_GameTextSpeechParams", &varTable) && varTable.m_type == FIELD_HSCRIPT)
|
||||
if (g_pScriptVM->GetValue( m_ScriptScope, "m_GameTextSpeechParams", &varTable ) && varTable.m_type == FIELD_HSCRIPT)
|
||||
{
|
||||
bReturn = true;
|
||||
|
||||
int nIterator = -1;
|
||||
ScriptVariant_t varKey, varValue;
|
||||
while ((nIterator = g_pScriptVM->GetKeyValue( varTable.m_hScript, nIterator, &varKey, &varValue )) != -1)
|
||||
@ -2147,13 +2167,18 @@ bool CBaseFlex::GetGameTextSpeechParams( hudtextparms_t ¶ms )
|
||||
{
|
||||
params.fxTime = varValue.m_float;
|
||||
}
|
||||
else if (FStrEq( varKey.m_pszString, "disabled" ))
|
||||
{
|
||||
// Allow the params to disable game_text choreo if needed
|
||||
bReturn = !(varValue.m_int > 0);
|
||||
}
|
||||
|
||||
g_pScriptVM->ReleaseValue( varKey );
|
||||
g_pScriptVM->ReleaseValue( varValue );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return bReturn;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -129,6 +129,7 @@ public:
|
||||
|
||||
virtual float PlayScene( const char *pszScene, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
|
||||
#ifdef MAPBASE
|
||||
virtual float PlayChoreoSentenceScene( const char *pszSentenceName, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
|
||||
virtual float PlayAutoGeneratedSoundScene( const char *soundname, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
|
||||
#else
|
||||
virtual float PlayAutoGeneratedSoundScene( const char *soundname );
|
||||
@ -141,7 +142,8 @@ public:
|
||||
virtual int GetSpecialDSP( void ) { return 0; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual bool GetGameTextSpeechParams( hudtextparms_t ¶ms );
|
||||
bool DispatchGetGameTextSpeechParams( hudtextparms_t ¶ms );
|
||||
virtual bool GetGameTextSpeechParams( hudtextparms_t ¶ms ) { return true; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
@ -42,6 +42,10 @@ virtual void NullThink( void );
|
||||
|
||||
ConVar g_debug_basehelicopter( "g_debug_basehelicopter", "0", FCVAR_CHEAT );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar g_helicopter_use_sight_condition( "g_helicopter_use_sight_condition", "0", 0, "If enabled, helicopters will use the AI sight condition instead of just checking if there's a clear path to the player. This prevents them from cheating." );
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------
|
||||
//---------------------------------------------------------
|
||||
// TODOs
|
||||
@ -702,7 +706,11 @@ void CBaseHelicopter::UpdateEnemy()
|
||||
{
|
||||
CBaseEntity *pEnemy = GetEnemy();
|
||||
GatherEnemyConditions( pEnemy );
|
||||
#ifdef MAPBASE
|
||||
if ( (g_helicopter_use_sight_condition.GetBool() && pEnemy->Classify() != CLASS_BULLSEYE) ? HasCondition( COND_SEE_ENEMY ) : FVisible( pEnemy ) )
|
||||
#else
|
||||
if ( FVisible( pEnemy ) )
|
||||
#endif
|
||||
{
|
||||
if (m_flLastSeen < gpGlobals->curtime - 2)
|
||||
{
|
||||
|
@ -297,6 +297,19 @@ void CSpeaker::DispatchResponse( const char *conceptName )
|
||||
CAI_Expresser::RunScriptResponse( pTarget, response, &set, true );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef MAPBASE
|
||||
case ResponseRules::RESPONSE_CHOREOSENTENCE:
|
||||
{
|
||||
CBaseFlex *pFlex = NULL;
|
||||
if (pTarget != this)
|
||||
{
|
||||
// Attempt to get flex on the target
|
||||
pFlex = dynamic_cast<CBaseFlex*>(pTarget);
|
||||
}
|
||||
InstancedAutoGeneratedSoundScene(pFlex, response);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
|
@ -58,6 +58,7 @@
|
||||
#ifdef MAPBASE
|
||||
#include "triggers.h"
|
||||
#include "mapbase/variant_tools.h"
|
||||
#include "mapbase/protagonist_system.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -121,6 +122,7 @@ ConVar player_autoswitch_enabled( "player_autoswitch_enabled", "1", FCVAR_NONE,
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
ConVar hl2_use_sp_animstate( "hl2_use_sp_animstate", "1", FCVAR_NONE, "Allows SP HL2 players to use HL2:DM animations for custom player models. (changes may not apply until model is reloaded)" );
|
||||
ConVar player_process_scene_events( "player_process_scene_events", "1", FCVAR_NONE, "Allows players to process scene events." );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -267,6 +269,7 @@ public:
|
||||
void InputSetHandModelBodyGroup( inputdata_t &inputdata );
|
||||
|
||||
void InputSetPlayerModel( inputdata_t &inputdata );
|
||||
void InputSetPlayerDrawLegs( inputdata_t &inputdata );
|
||||
void InputSetPlayerDrawExternally( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
@ -591,6 +594,8 @@ BEGIN_DATADESC( CHL2_Player )
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "DisableGeigerCounter", InputDisableGeigerCounter ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ShowSquadHUD", InputShowSquadHUD ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "HideSquadHUD", InputHideSquadHUD ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetProtagonist", InputSetProtagonist ),
|
||||
#endif
|
||||
|
||||
DEFINE_SOUNDPATCH( m_sndLeeches ),
|
||||
@ -605,6 +610,10 @@ BEGIN_DATADESC( CHL2_Player )
|
||||
|
||||
DEFINE_FIELD( m_flTimeNextLadderHint, FIELD_TIME ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_iszProtagonistName, FIELD_STRING, "ProtagonistName" ),
|
||||
#endif
|
||||
|
||||
//DEFINE_FIELD( m_hPlayerProxy, FIELD_EHANDLE ), //Shut up class check!
|
||||
|
||||
END_DATADESC()
|
||||
@ -623,6 +632,9 @@ BEGIN_ENT_SCRIPTDESC( CHL2_Player, CBasePlayer, "The HL2 player entity." )
|
||||
DEFINE_SCRIPTFUNC( RemoveCustomSuitDevice, "Removes a custom suit device ID. (1-3)" )
|
||||
DEFINE_SCRIPTFUNC( IsCustomSuitDeviceActive, "Checks if a custom suit device is active." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetProtagonistName, "Gets the player's protagonist name." )
|
||||
DEFINE_SCRIPTFUNC( SetProtagonist, "Sets the player's protagonist entry." )
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
DEFINE_SCRIPTFUNC( AddAnimStateLayer, "Adds a custom sequence index as a misc. layer for the singleplayer anim state, wtih parameters for blending in/out, setting the playback rate, holding the animation at the end, and only playing when the player is still." )
|
||||
#endif
|
||||
@ -638,6 +650,10 @@ CHL2_Player::CHL2_Player()
|
||||
|
||||
m_flArmorReductionTime = 0.0f;
|
||||
m_iArmorReductionFrom = 0;
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_nProtagonistIndex = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
@ -672,8 +688,12 @@ CSuitPowerDevice SuitDeviceCustom[] =
|
||||
IMPLEMENT_SERVERCLASS_ST(CHL2_Player, DT_HL2_Player)
|
||||
SendPropDataTable(SENDINFO_DT(m_HL2Local), &REFERENCE_SEND_TABLE(DT_HL2Local), SendProxy_SendLocalDataTable),
|
||||
SendPropBool( SENDINFO(m_fIsSprinting) ),
|
||||
#ifdef MAPBASE
|
||||
SendPropInt( SENDINFO( m_nProtagonistIndex ), 8, SPROP_UNSIGNED ),
|
||||
#endif
|
||||
#ifdef SP_ANIM_STATE
|
||||
SendPropFloat( SENDINFO(m_flAnimRenderYaw), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO(m_flAnimRenderZ), 0, SPROP_NOSCALE ),
|
||||
#endif
|
||||
END_SEND_TABLE()
|
||||
|
||||
@ -1166,6 +1186,18 @@ void CHL2_Player::PostThink( void )
|
||||
m_pPlayerAnimState->Update( angEyeAngles.y, angEyeAngles.x );
|
||||
|
||||
m_flAnimRenderYaw.Set( m_pPlayerAnimState->GetRenderAngles().y );
|
||||
|
||||
if (m_pPlayerAnimState->IsJumping() && !m_pPlayerAnimState->IsDuckJumping())
|
||||
{
|
||||
m_flAnimRenderZ.Set( -(GetViewOffset().z) );
|
||||
}
|
||||
else
|
||||
m_flAnimRenderZ.Set( 0.0f );
|
||||
|
||||
if (player_process_scene_events.GetBool())
|
||||
{
|
||||
ProcessSceneEvents();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1244,6 +1276,11 @@ void CHL2_Player::Activate( void )
|
||||
#endif
|
||||
|
||||
GetPlayerProxy();
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_iszProtagonistName != NULL_STRING)
|
||||
SetProtagonist( STRING( m_iszProtagonistName ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1483,7 +1520,10 @@ CStudioHdr *CHL2_Player::OnNewModel()
|
||||
}
|
||||
|
||||
extern char g_szDefaultPlayerModel[MAX_PATH];
|
||||
extern bool g_bDefaultPlayerLegs;
|
||||
extern bool g_bDefaultPlayerDrawExternally;
|
||||
|
||||
extern char g_szDefaultProtagonist[MAX_PROTAGONIST_NAME];
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1515,7 +1555,14 @@ void CHL2_Player::Spawn(void)
|
||||
RemoveEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
SetDrawPlayerLegs( g_bDefaultPlayerLegs );
|
||||
SetDrawPlayerModelExternally( g_bDefaultPlayerDrawExternally );
|
||||
|
||||
if (m_iszProtagonistName == NULL_STRING && *g_szDefaultProtagonist)
|
||||
m_iszProtagonistName = MAKE_STRING( g_szDefaultProtagonist );
|
||||
|
||||
if (m_iszProtagonistName != NULL_STRING)
|
||||
SetProtagonist( STRING( m_iszProtagonistName ) );
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -3349,6 +3396,11 @@ void CHL2_Player::Weapon_Equip( CBaseCombatWeapon *pWeapon )
|
||||
if( GetActiveWeapon() == NULL )
|
||||
{
|
||||
m_HL2Local.m_bWeaponLowered = false;
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
if (m_pPlayerAnimState)
|
||||
m_pPlayerAnimState->StopWeaponRelax();
|
||||
#endif
|
||||
}
|
||||
|
||||
BaseClass::Weapon_Equip( pWeapon );
|
||||
@ -3754,6 +3806,11 @@ bool CHL2_Player::Weapon_Lower( void )
|
||||
|
||||
m_HL2Local.m_bWeaponLowered = true;
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
if (m_pPlayerAnimState)
|
||||
m_pPlayerAnimState->StartWeaponRelax();
|
||||
#endif
|
||||
|
||||
CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon *>(GetActiveWeapon());
|
||||
|
||||
if ( pWeapon == NULL )
|
||||
@ -3776,6 +3833,11 @@ bool CHL2_Player::Weapon_Ready( void )
|
||||
|
||||
m_HL2Local.m_bWeaponLowered = false;
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
if (m_pPlayerAnimState)
|
||||
m_pPlayerAnimState->StopWeaponRelax();
|
||||
#endif
|
||||
|
||||
CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon *>(GetActiveWeapon());
|
||||
|
||||
if ( pWeapon == NULL )
|
||||
@ -3989,6 +4051,21 @@ void CHL2_Player::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
m_pPlayerAISquad = g_AI_SquadManager.FindCreateSquad(AllocPooledString(PLAYER_SQUADNAME));
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
if ( m_pPlayerAnimState == NULL )
|
||||
{
|
||||
if ( GetModelPtr() && GetModelPtr()->HaveSequenceForActivity(ACT_HL2MP_IDLE) && hl2_use_sp_animstate.GetBool() )
|
||||
{
|
||||
// Here we create and init the player animation state.
|
||||
m_pPlayerAnimState = CreatePlayerAnimationState(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flAnimRenderYaw = FLT_MAX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
@ -4040,6 +4117,10 @@ bool CHL2_Player::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex
|
||||
StopZooming();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
RefreshProtagonistWeaponData( pWeapon );
|
||||
#endif
|
||||
|
||||
return BaseClass::Weapon_Switch( pWeapon, viewmodelindex );
|
||||
}
|
||||
|
||||
@ -4435,6 +4516,144 @@ bool CHL2_Player::IsCustomSuitDeviceActive( int iDeviceID )
|
||||
|
||||
return SuitPower_IsDeviceActive( SuitDeviceCustom[iDeviceID] );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets our protagonist name, if we have one
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CHL2_Player::GetProtagonistName() const
|
||||
{
|
||||
return STRING( m_iszProtagonistName );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets our protagonist index, if we have one
|
||||
//-----------------------------------------------------------------------------
|
||||
int CHL2_Player::GetProtagonistIndex() const
|
||||
{
|
||||
return m_nProtagonistIndex;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets our protagonist to the specified entry
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHL2_Player::InputSetProtagonist( inputdata_t &inputdata )
|
||||
{
|
||||
SetProtagonist( inputdata.value.String() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets our protagonist to the specified entry
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHL2_Player::SetProtagonist( const char *pszProtagonist )
|
||||
{
|
||||
if (!pszProtagonist || !*pszProtagonist)
|
||||
{
|
||||
ResetProtagonist();
|
||||
return;
|
||||
}
|
||||
|
||||
int nIndex = g_ProtagonistSystem.FindProtagonistIndex( pszProtagonist );
|
||||
if (nIndex == -1)
|
||||
{
|
||||
Warning( "\"%s\" is not a valid protagonist\n", pszProtagonist );
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_nProtagonistIndex != -1)
|
||||
{
|
||||
// Flush any pre-existing data
|
||||
ResetProtagonist();
|
||||
}
|
||||
|
||||
m_nProtagonistIndex = nIndex;
|
||||
m_iszProtagonistName = AllocPooledString( pszProtagonist );
|
||||
|
||||
RefreshProtagonistData();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Resets protagonist data
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHL2_Player::ResetProtagonist()
|
||||
{
|
||||
SetModel( g_szDefaultPlayerModel );
|
||||
m_nSkin = 0;
|
||||
m_nBody = 0;
|
||||
|
||||
CBaseViewModel *vm = GetViewModel( 1 );
|
||||
if (vm)
|
||||
{
|
||||
extern char g_szDefaultHandsModel[MAX_PATH];
|
||||
vm->SetWeaponModel( g_szDefaultHandsModel, NULL );
|
||||
|
||||
vm->m_nSkin = 0;
|
||||
vm->m_nBody = 0;
|
||||
}
|
||||
|
||||
// RemoveContext will automatically remove contexts by name, regardless of how values are specified
|
||||
char szContexts[128] = { 0 };
|
||||
g_ProtagonistSystem.GetProtagonist_ResponseContexts( this, szContexts, sizeof( szContexts ) );
|
||||
if (szContexts[0])
|
||||
RemoveContext( szContexts );
|
||||
|
||||
m_iszProtagonistName = NULL_STRING;
|
||||
m_nProtagonistIndex = -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Refreshes protagonist data
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHL2_Player::RefreshProtagonistData()
|
||||
{
|
||||
if (m_nProtagonistIndex == -1)
|
||||
return;
|
||||
|
||||
g_ProtagonistSystem.PrecacheProtagonist( this, m_nProtagonistIndex );
|
||||
|
||||
const char *pszProtagModel = g_ProtagonistSystem.GetProtagonist_PlayerModel( this );
|
||||
if (pszProtagModel)
|
||||
SetModel( pszProtagModel );
|
||||
|
||||
m_nSkin = g_ProtagonistSystem.GetProtagonist_PlayerModelSkin( this );
|
||||
m_nBody = g_ProtagonistSystem.GetProtagonist_PlayerModelBody( this );
|
||||
|
||||
char szContexts[128] = { 0 };
|
||||
g_ProtagonistSystem.GetProtagonist_ResponseContexts( this, szContexts, sizeof( szContexts ) );
|
||||
if (szContexts[0])
|
||||
AddContext( szContexts );
|
||||
|
||||
RefreshProtagonistWeaponData( GetActiveWeapon() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Refreshes protagonist data
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHL2_Player::RefreshProtagonistWeaponData( CBaseCombatWeapon *pWeapon )
|
||||
{
|
||||
if (m_nProtagonistIndex == -1)
|
||||
return;
|
||||
|
||||
CBaseViewModel *vm = GetViewModel( 1 );
|
||||
if (vm)
|
||||
{
|
||||
const char *pszHandModel = g_ProtagonistSystem.GetProtagonist_HandModel( this, pWeapon );
|
||||
if (pszHandModel)
|
||||
{
|
||||
vm->SetWeaponModel( pszHandModel, NULL );
|
||||
|
||||
vm->m_nSkin = g_ProtagonistSystem.GetProtagonist_HandModelSkin( this, pWeapon );
|
||||
vm->m_nBody = g_ProtagonistSystem.GetProtagonist_HandModelBody( this, pWeapon );
|
||||
}
|
||||
else
|
||||
{
|
||||
extern char g_szDefaultHandsModel[MAX_PATH];
|
||||
vm->SetWeaponModel( g_szDefaultHandsModel, NULL );
|
||||
|
||||
vm->m_nSkin = 0;
|
||||
vm->m_nBody = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -4594,6 +4813,7 @@ BEGIN_DATADESC( CLogicPlayerProxy )
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelSkin", InputSetHandModelSkin ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelBodyGroup", InputSetHandModelBodyGroup ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetPlayerModel", InputSetPlayerModel ),
|
||||
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawLegs", InputSetPlayerDrawLegs ),
|
||||
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawExternally", InputSetPlayerDrawExternally ),
|
||||
DEFINE_INPUT( m_MaxArmor, FIELD_INTEGER, "SetMaxInputArmor" ),
|
||||
DEFINE_INPUT( m_SuitZoomFOV, FIELD_INTEGER, "SetSuitZoomFOV" ),
|
||||
@ -5072,6 +5292,15 @@ void CLogicPlayerProxy::InputSetPlayerModel( inputdata_t &inputdata )
|
||||
m_hPlayer->SetModel( STRING(iszModel) );
|
||||
}
|
||||
|
||||
void CLogicPlayerProxy::InputSetPlayerDrawLegs( inputdata_t &inputdata )
|
||||
{
|
||||
if (!m_hPlayer)
|
||||
return;
|
||||
|
||||
CBasePlayer *pPlayer = static_cast<CBasePlayer*>(m_hPlayer.Get());
|
||||
pPlayer->SetDrawPlayerLegs( inputdata.value.Bool() );
|
||||
}
|
||||
|
||||
void CLogicPlayerProxy::InputSetPlayerDrawExternally( inputdata_t &inputdata )
|
||||
{
|
||||
if (!m_hPlayer)
|
||||
|
@ -19,7 +19,7 @@
|
||||
#if defined ( HL2MP )
|
||||
#include "basemultiplayerplayer.h"
|
||||
#elif defined ( MAPBASE )
|
||||
#include "mapbase/singleplayer_animstate.h"
|
||||
#include "mapbase/mapbase_playeranimstate.h"
|
||||
#endif
|
||||
|
||||
class CAI_Squad;
|
||||
@ -358,6 +358,15 @@ public:
|
||||
void AddCustomSuitDevice( int iDeviceID );
|
||||
void RemoveCustomSuitDevice( int iDeviceID );
|
||||
bool IsCustomSuitDeviceActive( int iDeviceID );
|
||||
|
||||
// Protagonist system
|
||||
const char *GetProtagonistName() const;
|
||||
int GetProtagonistIndex() const;
|
||||
void InputSetProtagonist( inputdata_t &inputdata );
|
||||
void SetProtagonist( const char *pszProtagonist );
|
||||
void ResetProtagonist();
|
||||
void RefreshProtagonistData();
|
||||
void RefreshProtagonistWeaponData( CBaseCombatWeapon *pWeapon );
|
||||
#endif
|
||||
|
||||
CSoundPatch *m_sndLeeches;
|
||||
@ -442,12 +451,19 @@ private:
|
||||
|
||||
friend class CHL2GameMovement;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Protagonist used by protagonist_system.h
|
||||
string_t m_iszProtagonistName;
|
||||
CNetworkVar( int, m_nProtagonistIndex );
|
||||
#endif
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
CSinglePlayerAnimState* m_pPlayerAnimState;
|
||||
CMapbasePlayerAnimState* m_pPlayerAnimState;
|
||||
|
||||
// At the moment, we network the render angles since almost none of the player anim stuff is done on the client in SP.
|
||||
// If any of this is ever adapted for MP, this method should be replaced with replicating/moving the anim state to the client.
|
||||
CNetworkVar( float, m_flAnimRenderYaw );
|
||||
CNetworkVar( float, m_flAnimRenderZ );
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -63,3 +63,88 @@ BEGIN_DATADESC( CItemBattery )
|
||||
END_DATADESC()
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern ConVar sk_battery;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Custom player battery. Heals the player when picked up.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CItemBatteryCustom : public CItem
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CItemBatteryCustom, CItem );
|
||||
CItemBatteryCustom();
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
bool MyTouch( CBasePlayer *pPlayer );
|
||||
|
||||
float GetItemAmount() { return m_flPowerAmount; }
|
||||
|
||||
void InputSetPowerAmount( inputdata_t &inputdata ) { m_flPowerAmount = inputdata.value.Float(); }
|
||||
|
||||
float m_flPowerAmount;
|
||||
string_t m_iszTouchSound;
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( item_battery_custom, CItemBatteryCustom );
|
||||
|
||||
#ifdef MAPBASE
|
||||
BEGIN_DATADESC( CItemBatteryCustom )
|
||||
|
||||
DEFINE_KEYFIELD( m_flPowerAmount, FIELD_FLOAT, "PowerAmount" ),
|
||||
DEFINE_KEYFIELD( m_iszTouchSound, FIELD_STRING, "TouchSound" ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPowerAmount", InputSetPowerAmount ),
|
||||
|
||||
END_DATADESC()
|
||||
#endif
|
||||
|
||||
|
||||
CItemBatteryCustom::CItemBatteryCustom()
|
||||
{
|
||||
SetModelName( AllocPooledString( "models/items/battery.mdl" ) );
|
||||
m_flPowerAmount = sk_battery.GetFloat();
|
||||
m_iszTouchSound = AllocPooledString( "ItemBattery.Touch" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItemBatteryCustom::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
SetModel( STRING( GetModelName() ) );
|
||||
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItemBatteryCustom::Precache( void )
|
||||
{
|
||||
PrecacheModel( STRING( GetModelName() ) );
|
||||
|
||||
PrecacheScriptSound( STRING( m_iszTouchSound ) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pPlayer -
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CItemBatteryCustom::MyTouch( CBasePlayer *pPlayer )
|
||||
{
|
||||
CHL2_Player *pHL2Player = assert_cast<CHL2_Player *>(pPlayer);
|
||||
if (!pHL2Player || sk_battery.GetFloat() == 0.0f)
|
||||
return false;
|
||||
|
||||
float flPowerMult = m_flPowerAmount / sk_battery.GetFloat();
|
||||
return pHL2Player->ApplyBattery( flPowerMult );
|
||||
}
|
||||
#endif
|
||||
|
@ -256,7 +256,7 @@ END_DATADESC()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_PoisonZombie::Precache( void )
|
||||
{
|
||||
PrecacheModel("models/zombie/poison.mdl");
|
||||
PrecacheModel( DefaultOrCustomModel( "models/zombie/poison.mdl" ) );
|
||||
|
||||
PrecacheScriptSound( "NPC_PoisonZombie.Die" );
|
||||
PrecacheScriptSound( "NPC_PoisonZombie.ThrowWarn" );
|
||||
@ -509,7 +509,7 @@ void CNPC_PoisonZombie::SetZombieModel( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModel( "models/zombie/poison.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/zombie/poison.mdl" ) );
|
||||
SetHullType(HULL_HUMAN);
|
||||
}
|
||||
|
||||
|
@ -472,8 +472,8 @@ void CNPC_Antlion::Precache( void )
|
||||
#ifdef HL2_EPISODIC
|
||||
if ( IsWorker() )
|
||||
{
|
||||
PrecacheModel( ANTLION_WORKER_MODEL );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( ANTLION_WORKER_MODEL ) );
|
||||
PrecacheModel( DefaultOrCustomModel( ANTLION_WORKER_MODEL ) );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( DefaultOrCustomModel( ANTLION_WORKER_MODEL ) ) );
|
||||
UTIL_PrecacheOther( "grenade_spit" );
|
||||
PrecacheParticleSystem( "blood_impact_antlion_worker_01" );
|
||||
PrecacheParticleSystem( "antlion_gib_02" );
|
||||
@ -482,8 +482,8 @@ void CNPC_Antlion::Precache( void )
|
||||
else
|
||||
#endif // HL2_EPISODIC
|
||||
{
|
||||
PrecacheModel( ANTLION_MODEL );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( ANTLION_MODEL ) );
|
||||
PrecacheModel( DefaultOrCustomModel( ANTLION_MODEL ) );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( DefaultOrCustomModel( ANTLION_MODEL ) ) );
|
||||
PrecacheParticleSystem( "blood_impact_antlion_01" );
|
||||
PrecacheParticleSystem( "AntlionGib" );
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#ifdef MAPBASE
|
||||
#include "filters.h"
|
||||
#include "ai_hint.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -164,6 +165,15 @@ ConVar g_helicopter_bullrush_mega_bomb_health( "g_helicopter_bullrush_mega_bomb_
|
||||
|
||||
ConVar g_helicopter_bomb_danger_radius( "g_helicopter_bomb_danger_radius", "120" );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar g_helicopter_crashpoint_nearest( "g_helicopter_crashpoint_nearest", "1", 0, "Selects the nearest crash point instead of just the first in the entity list." );
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
ConVar g_helicopter_phys_follow_while_crashing( "g_helicopter_phys_follow_while_crashing", "0", 0, "Allows the phys_bone_followers to follow the helicopter while flying to crash point" );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Activity ACT_HELICOPTER_DROP_BOMB;
|
||||
Activity ACT_HELICOPTER_CRASHING;
|
||||
|
||||
@ -191,7 +201,60 @@ enum
|
||||
|
||||
#define GRENADE_HELICOPTER_MODEL "models/combine_helicopter/helicopter_bomb01.mdl"
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTargetHelicopterCrash : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CTargetHelicopterCrash, CPointEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void InputEnable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisabled = false;
|
||||
}
|
||||
void InputDisable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisabled = true;
|
||||
}
|
||||
bool IsDisabled( void )
|
||||
{
|
||||
return m_bDisabled;
|
||||
}
|
||||
void HelicopterCrashedOnTarget( CBaseHelicopter *pChopper )
|
||||
{
|
||||
m_OnCrashed.FireOutput( pChopper, this );
|
||||
}
|
||||
void HelicopterAcquiredCrashTarget( CBaseHelicopter *pChopper )
|
||||
{
|
||||
m_OnBeginCrash.FireOutput( pChopper, this );
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_bDisabled;
|
||||
|
||||
COutputEvent m_OnCrashed;
|
||||
COutputEvent m_OnBeginCrash;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( info_target_helicopter_crash, CTargetHelicopterCrash );
|
||||
|
||||
BEGIN_DATADESC( CTargetHelicopterCrash )
|
||||
DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ),
|
||||
DEFINE_OUTPUT( m_OnBeginCrash, "OnBeginCrash" ),
|
||||
END_DATADESC()
|
||||
#else
|
||||
LINK_ENTITY_TO_CLASS( info_target_helicopter_crash, CPointEntity );
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -499,6 +562,13 @@ private:
|
||||
// Death, etc.
|
||||
void InputSelfDestruct( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// This is identical to SelfDestruct, except the helicopter won't throw out chunks while flying to a crash point.
|
||||
// This input is meant to be used when the pilot is killed and there's nothing wrong with the helicopter itself.
|
||||
// If there are no crash points, the helicopter will explode in place as normal.
|
||||
void InputSelfDestructNoFX( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
// Enemy visibility check
|
||||
CBaseEntity *FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos );
|
||||
|
||||
@ -522,6 +592,7 @@ private:
|
||||
|
||||
// Various states of the helicopter firing...
|
||||
bool PoseGunTowardTargetDirection( const Vector &vTargetDir );
|
||||
float GetGunPoseSpeed() const;
|
||||
|
||||
// Compute the position to fire at (vehicle + non-vehicle case)
|
||||
void ComputeFireAtPosition( Vector *pVecActualTargetPosition );
|
||||
@ -533,6 +604,17 @@ private:
|
||||
bool DoGunFiring( const Vector &vBasePos, const Vector &vGunDir, const Vector &vecFireAtPosition );
|
||||
void FireElectricityGun( );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Idle aiming
|
||||
bool FindIdleAimTarget();
|
||||
bool ValidIdleAimTarget( CBaseEntity *pAimTarget );
|
||||
|
||||
bool FValidateHintType( CAI_Hint *pHint );
|
||||
|
||||
inline CBaseEntity *GetIdleAimTarget() const { return m_hIdleAimTarget; }
|
||||
inline void SetIdleAimTarget( CBaseEntity *pNewAimTarget ) { m_hIdleAimTarget = pNewAimTarget; }
|
||||
#endif
|
||||
|
||||
// Chooses a point within the circle of death to fire in
|
||||
void PickDirectionToCircleOfDeath( const Vector &vBasePos, const Vector &vecFireAtPosition, Vector *pResult );
|
||||
|
||||
@ -650,6 +732,7 @@ private:
|
||||
void SpotlightStartup();
|
||||
void SpotlightShutdown();
|
||||
|
||||
CBaseEntity *FindCrashPoint();
|
||||
CBaseEntity *GetCrashPoint() { return m_hCrashPoint.Get(); }
|
||||
|
||||
private:
|
||||
@ -721,6 +804,17 @@ private:
|
||||
bool m_bBombsExplodeOnContact;
|
||||
bool m_bNonCombat;
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool m_bIdleAimAround;
|
||||
EHANDLE m_hIdleAimTarget;
|
||||
Vector m_vecIdleAimDir;
|
||||
float m_flNextIdleAimTime;
|
||||
|
||||
bool m_bDisableSmokeTrails;
|
||||
bool m_bDisableCorpses;
|
||||
bool m_bDisableExplosions;
|
||||
#endif
|
||||
|
||||
int m_nNearShots;
|
||||
int m_nMaxNearShots;
|
||||
|
||||
@ -860,6 +954,15 @@ BEGIN_DATADESC( CNPC_AttackHelicopter )
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_bIdleAimAround, FIELD_BOOLEAN, "IdleAimAround" ),
|
||||
DEFINE_FIELD( m_hIdleAimTarget, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_vecIdleAimDir, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_flNextIdleAimTime, FIELD_TIME ),
|
||||
|
||||
DEFINE_KEYFIELD( m_bDisableSmokeTrails, FIELD_BOOLEAN, "DisableSmokeTrails" ),
|
||||
DEFINE_KEYFIELD( m_bDisableCorpses, FIELD_BOOLEAN, "DisableCorpses" ),
|
||||
DEFINE_KEYFIELD( m_bDisableExplosions, FIELD_BOOLEAN, "DisableExplosions" ),
|
||||
#endif
|
||||
|
||||
DEFINE_FIELD( m_hCrashPoint, FIELD_EHANDLE ),
|
||||
@ -896,6 +999,9 @@ BEGIN_DATADESC( CNPC_AttackHelicopter )
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "EnablePathVisibilityTests", InputEnablePathVisibilityTests ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestruct", InputSelfDestruct ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestructNoFX", InputSelfDestructNoFX ),
|
||||
#endif
|
||||
|
||||
DEFINE_THINKFUNC( BlinkLightsThink ),
|
||||
DEFINE_THINKFUNC( SpotlightThink ),
|
||||
@ -1646,6 +1752,21 @@ void CNPC_AttackHelicopter::InputSelfDestruct( inputdata_t &inputdata )
|
||||
TakeDamage( info );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
void CNPC_AttackHelicopter::InputSelfDestructNoFX( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisableSmokeTrails = true;
|
||||
m_bDisableCorpses = true;
|
||||
m_bDisableExplosions = true;
|
||||
|
||||
m_lifeState = LIFE_ALIVE; // Force to die properly.
|
||||
CTakeDamageInfo info( this, this, Vector(0, 0, 1), WorldSpaceCenter(), GetMaxHealth(), CLASS_MISSILE );
|
||||
TakeDamage( info );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// For scripted times where it *has* to shoot
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2245,21 +2366,23 @@ bool CNPC_AttackHelicopter::PoseGunTowardTargetDirection( const Vector &vTargetD
|
||||
}
|
||||
}
|
||||
|
||||
float flPoseSpeed = GetGunPoseSpeed();
|
||||
|
||||
if (angles.x > m_angGun.x)
|
||||
{
|
||||
m_angGun.x = MIN( angles.x, m_angGun.x + 12 );
|
||||
m_angGun.x = MIN( angles.x, m_angGun.x + flPoseSpeed );
|
||||
}
|
||||
if (angles.x < m_angGun.x)
|
||||
{
|
||||
m_angGun.x = MAX( angles.x, m_angGun.x - 12 );
|
||||
m_angGun.x = MAX( angles.x, m_angGun.x - flPoseSpeed );
|
||||
}
|
||||
if (angles.y > m_angGun.y)
|
||||
{
|
||||
m_angGun.y = MIN( angles.y, m_angGun.y + 12 );
|
||||
m_angGun.y = MIN( angles.y, m_angGun.y + flPoseSpeed );
|
||||
}
|
||||
if (angles.y < m_angGun.y)
|
||||
{
|
||||
m_angGun.y = MAX( angles.y, m_angGun.y - 12 );
|
||||
m_angGun.y = MAX( angles.y, m_angGun.y - flPoseSpeed );
|
||||
}
|
||||
|
||||
SetPoseParameter( m_poseWeapon_Pitch, -m_angGun.x );
|
||||
@ -2269,6 +2392,20 @@ bool CNPC_AttackHelicopter::PoseGunTowardTargetDirection( const Vector &vTargetD
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Various states of the helicopter firing...
|
||||
//------------------------------------------------------------------------------
|
||||
float CNPC_AttackHelicopter::GetGunPoseSpeed() const
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (m_bIdleAimAround && !GetEnemy())
|
||||
return 4.0f;
|
||||
#endif
|
||||
|
||||
return 12.0f;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Compute the enemy position (non-vehicle case)
|
||||
//------------------------------------------------------------------------------
|
||||
@ -2363,6 +2500,87 @@ bool CNPC_AttackHelicopter::DoGunIdle( const Vector &vGunDir, const Vector &vTar
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds an idle aim target. Based on CNPC_PlayerCompanion code
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::FindIdleAimTarget()
|
||||
{
|
||||
CAI_Hint *pHint;
|
||||
CHintCriteria hintCriteria;
|
||||
CBaseEntity *pPriorAimTarget = GetIdleAimTarget();
|
||||
|
||||
hintCriteria.SetHintType( HINT_WORLD_VISUALLY_INTERESTING );
|
||||
hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV | bits_HINT_NODE_USE_GROUP | bits_HINT_NODE_NEAREST );
|
||||
hintCriteria.AddIncludePosition( GetAbsOrigin(), CHOPPER_MAX_GUN_DIST );
|
||||
pHint = CAI_HintManager::FindHint( this, hintCriteria );
|
||||
|
||||
if( pHint )
|
||||
{
|
||||
if ( !ValidIdleAimTarget( pHint ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( pHint != pPriorAimTarget )
|
||||
{
|
||||
// Notify of the change.
|
||||
SetIdleAimTarget( pHint );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find an aim target, or found the same one.
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds an idle aim target. Based on CNPC_PlayerCompanion code
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::ValidIdleAimTarget( CBaseEntity *pAimTarget )
|
||||
{
|
||||
Vector vecTargetOrigin = pAimTarget->GetAbsOrigin();
|
||||
|
||||
Vector vBasePos;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos );
|
||||
|
||||
if ( vecTargetOrigin.z > vBasePos.z || (vecTargetOrigin - vBasePos).Length() < 128.0f )
|
||||
{
|
||||
// Too close!
|
||||
return false;
|
||||
}
|
||||
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( vBasePos, vecTargetOrigin, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 1.0f && tr.m_pEnt != pAimTarget )
|
||||
{
|
||||
// No LOS
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::FValidateHintType( CAI_Hint *pHint )
|
||||
{
|
||||
switch( pHint->HintType() )
|
||||
{
|
||||
case HINT_WORLD_VISUALLY_INTERESTING:
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return BaseClass::FValidateHintType( pHint );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// How easy is the target to hit?
|
||||
//------------------------------------------------------------------------------
|
||||
@ -3653,12 +3871,20 @@ int CNPC_AttackHelicopter::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) && !m_bDisableSmokeTrails )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) )
|
||||
#endif
|
||||
{
|
||||
AddSmokeTrail( info.GetDamagePosition() );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_CORPSES ) && !m_bDisableCorpses )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_CORPSES ) )
|
||||
#endif
|
||||
{
|
||||
if ( nPrevHealth != GetMaxHealth() )
|
||||
{
|
||||
@ -3666,7 +3892,11 @@ int CNPC_AttackHelicopter::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) && !m_bDisableExplosions )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) )
|
||||
#endif
|
||||
{
|
||||
ExplodeAndThrowChunk( info.GetDamagePosition() );
|
||||
}
|
||||
@ -3774,6 +4004,46 @@ void Chopper_BecomeChunks( CBaseEntity *pChopper )
|
||||
pBodyChunk->m_pCockpitConstraint = physenv->CreateFixedConstraint( pBodyObject, pCockpitObject, pGroup, fixed );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Find a valid crash point
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseEntity *CNPC_AttackHelicopter::FindCrashPoint()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
float flNearest = MAX_TRACE_LENGTH * MAX_TRACE_LENGTH;
|
||||
CTargetHelicopterCrash *pNearest = NULL;
|
||||
CBaseEntity *pEnt = NULL;
|
||||
while( (pEnt = gEntList.FindEntityByClassname(pEnt, "info_target_helicopter_crash")) != NULL )
|
||||
{
|
||||
CTargetHelicopterCrash *pCrashTarget = assert_cast<CTargetHelicopterCrash*>(pEnt);
|
||||
if ( pCrashTarget->IsDisabled() )
|
||||
continue;
|
||||
|
||||
if (g_helicopter_crashpoint_nearest.GetBool())
|
||||
{
|
||||
float flDist = ( pEnt->WorldSpaceCenter() - WorldSpaceCenter() ).LengthSqr();
|
||||
if( flDist < flNearest )
|
||||
{
|
||||
pNearest = pCrashTarget;
|
||||
flNearest = flDist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pNearest = pCrashTarget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pNearest)
|
||||
pNearest->HelicopterAcquiredCrashTarget( this );
|
||||
|
||||
return pNearest;
|
||||
#else
|
||||
return gEntList.FindEntityByClassname( NULL, "info_target_helicopter_crash" );
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start us crashing
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -3785,13 +4055,16 @@ void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info )
|
||||
}
|
||||
|
||||
m_lifeState = LIFE_DYING;
|
||||
|
||||
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
|
||||
controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.1f );
|
||||
|
||||
if ( GetSleepState() != AISS_WAITING_FOR_INPUT )
|
||||
{
|
||||
CSoundEnvelopeController& controller = CSoundEnvelopeController::GetController();
|
||||
controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.1f );
|
||||
}
|
||||
|
||||
if( GetCrashPoint() == NULL )
|
||||
{
|
||||
CBaseEntity *pCrashPoint = gEntList.FindEntityByClassname( NULL, "info_target_helicopter_crash" );
|
||||
CBaseEntity *pCrashPoint = FindCrashPoint();
|
||||
if( pCrashPoint != NULL )
|
||||
{
|
||||
m_hCrashPoint.Set( pCrashPoint );
|
||||
@ -3812,6 +4085,12 @@ void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info )
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else
|
||||
{
|
||||
assert_cast<CTargetHelicopterCrash*>( GetCrashPoint() )->HelicopterCrashedOnTarget( this );
|
||||
}
|
||||
#endif
|
||||
|
||||
Chopper_BecomeChunks( this );
|
||||
StopLoopingSounds();
|
||||
@ -3869,7 +4148,11 @@ void CNPC_AttackHelicopter::PrescheduleThink( void )
|
||||
SetDesiredPosition( GetCrashPoint()->WorldSpaceCenter() );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( !m_bDisableExplosions && random->RandomInt( 0, 4 ) == 0 )
|
||||
#else
|
||||
if ( random->RandomInt( 0, 4 ) == 0 )
|
||||
#endif
|
||||
{
|
||||
Vector explodePoint;
|
||||
CollisionProp()->RandomPointInBounds( Vector(0.25,0.25,0.25), Vector(0.75,0.75,0.75), &explodePoint );
|
||||
@ -4821,6 +5104,15 @@ void CNPC_AttackHelicopter::Hunt( void )
|
||||
{
|
||||
Flight();
|
||||
UpdatePlayerDopplerShift( );
|
||||
|
||||
#if defined(MAPBASE) && defined(HL2_EPISODIC)
|
||||
if (g_helicopter_phys_follow_while_crashing.GetBool())
|
||||
{
|
||||
// Update our bone followers
|
||||
m_BoneFollowerManager.UpdateBoneFollowers( this );
|
||||
}
|
||||
#endif // HL2_EPISODIC
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4885,6 +5177,55 @@ void CNPC_AttackHelicopter::Hunt( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_bIdleAimAround)
|
||||
{
|
||||
if (!GetEnemy())
|
||||
{
|
||||
if (GetIdleAimTarget())
|
||||
{
|
||||
if (!ValidIdleAimTarget( GetIdleAimTarget() ))
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
m_flNextIdleAimTime = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flNextIdleAimTime < gpGlobals->curtime)
|
||||
{
|
||||
if (!FindIdleAimTarget())
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
|
||||
// Find a random direction in front of us instead
|
||||
Vector vBasePos, vecForward, vecRight, vecUp;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos, &vecForward, &vecRight, &vecUp );
|
||||
|
||||
m_vecIdleAimDir = vecForward + (vecRight * RandomFloat( -0.25f, 0.25f )) + (vecUp * RandomFloat( -0.8f, -0.25f ));
|
||||
}
|
||||
|
||||
m_flNextIdleAimTime = gpGlobals->curtime + RandomFloat( 4.0f, 6.0f );
|
||||
}
|
||||
|
||||
if (GetIdleAimTarget())
|
||||
{
|
||||
// Get gun attachment points
|
||||
Vector vBasePos;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos );
|
||||
|
||||
m_vecIdleAimDir = GetIdleAimTarget()->GetAbsOrigin() - vBasePos;
|
||||
VectorNormalize( m_vecIdleAimDir );
|
||||
}
|
||||
|
||||
PoseGunTowardTargetDirection( m_vecIdleAimDir );
|
||||
}
|
||||
else if (GetIdleAimTarget())
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
// Update our bone followers
|
||||
m_BoneFollowerManager.UpdateBoneFollowers(this);
|
||||
|
@ -839,6 +839,9 @@ void CNPC_Citizen::SelectModel()
|
||||
}
|
||||
}
|
||||
|
||||
// Models selected this way must be unique to avoid conflicts in save/restore
|
||||
m_Type = CT_UNIQUE;
|
||||
|
||||
// Just set the model right here
|
||||
SetModelName( AllocPooledString( returnValue.m_pszString ) );
|
||||
return;
|
||||
|
@ -2551,6 +2551,24 @@ int CNPC_Combine::TranslateSchedule( int scheduleType )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern ConVar ai_enemy_memory_fixes;
|
||||
|
||||
// SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE uses TASK_GET_PATH_TO_ENEMY_LKP_LOS, a task with a mistake
|
||||
// detailed in CAI_BaseNPC::StartTask and fixed by ai_enemy_memory_fixes.
|
||||
//
|
||||
// However, SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE only stops being used once the NPC has LOS to its target.
|
||||
// Since the fixed task now uses the enemy's last known position instead of the enemy's actual position,
|
||||
// this schedule risks getting stuck in a loop.
|
||||
//
|
||||
// This code makes the soldier run up directly to the last known position if it's visible, allowing the AI
|
||||
// to mark the enemy as eluded.
|
||||
if ( ai_enemy_memory_fixes.GetBool() && FVisible( GetEnemyLKP() ) )
|
||||
{
|
||||
return SCHED_COMBINE_PRESS_ATTACK;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE;
|
||||
}
|
||||
break;
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
int RangeAttack2Conditions( float flDot, float flDist ); // For innate grenade attack
|
||||
int MeleeAttack1Conditions( float flDot, float flDist ); // For kick/punch
|
||||
bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ) { return BaseClass::FVisible( vecTarget, traceMask, ppBlocker ); }
|
||||
virtual bool IsCurTaskContinuousMove();
|
||||
|
||||
virtual float GetJumpGravity() const { return 1.8f; }
|
||||
|
@ -275,7 +275,7 @@ CNPC_CombineCamera::~CNPC_CombineCamera()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_CombineCamera::Precache()
|
||||
{
|
||||
PrecacheModel(COMBINE_CAMERA_MODEL);
|
||||
PrecacheModel( DefaultOrCustomModel( COMBINE_CAMERA_MODEL ) );
|
||||
PrecacheModel(COMBINE_CAMERA_GLOW_SPRITE);
|
||||
PrecacheModel(COMBINE_CAMERA_FLASH_SPRITE);
|
||||
|
||||
@ -304,8 +304,7 @@ void CNPC_CombineCamera::Precache()
|
||||
void CNPC_CombineCamera::Spawn()
|
||||
{
|
||||
Precache();
|
||||
|
||||
SetModel(COMBINE_CAMERA_MODEL);
|
||||
SetModel( DefaultOrCustomModel( COMBINE_CAMERA_MODEL ) );
|
||||
|
||||
m_pEyeFlash = CSprite::SpriteCreate(COMBINE_CAMERA_FLASH_SPRITE, GetLocalOrigin(), FALSE);
|
||||
m_pEyeFlash->SetTransparency(kRenderGlow, 255, 255, 255, 0, kRenderFxNoDissipation);
|
||||
|
@ -134,6 +134,11 @@ enum LandingState_t
|
||||
LANDING_HOVER_DESCEND,
|
||||
LANDING_HOVER_TOUCHDOWN,
|
||||
LANDING_END_HOVER,
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Strider dropoff
|
||||
LANDING_STRIDER,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -295,6 +300,9 @@ private:
|
||||
bool IsHovering();
|
||||
void UpdateGroundRotorWashSound( float flAltitude );
|
||||
void UpdateRotorWashVolume( CSoundPatch *pRotorSound, float flVolume, float flDeltaTime );
|
||||
#ifdef MAPBASE
|
||||
void DeathNotice(CBaseEntity* pVictim);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Timers
|
||||
@ -353,6 +361,12 @@ private:
|
||||
string_t m_sRollermineTemplate;
|
||||
string_t m_sRollermineTemplateData;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Template for strider carried by this dropship
|
||||
string_t m_sStriderTemplate;
|
||||
string_t m_sStriderTemplateData;
|
||||
#endif
|
||||
|
||||
// Cached attachment points
|
||||
int m_iMuzzleAttachment;
|
||||
int m_iMachineGunBaseAttachment;
|
||||
@ -827,6 +841,11 @@ BEGIN_DATADESC( CNPC_CombineDropship )
|
||||
DEFINE_KEYFIELD( m_sRollermineTemplate, FIELD_STRING, "RollermineTemplate" ),
|
||||
DEFINE_FIELD( m_sRollermineTemplateData, FIELD_STRING ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD(m_sStriderTemplate, FIELD_STRING, "StriderTemplate"),
|
||||
DEFINE_FIELD(m_sStriderTemplateData, FIELD_STRING),
|
||||
#endif
|
||||
|
||||
DEFINE_ARRAY( m_sNPCTemplateData, FIELD_STRING, DROPSHIP_MAX_SOLDIERS ),
|
||||
DEFINE_KEYFIELD( m_sNPCTemplate[0], FIELD_STRING, "NPCTemplate" ),
|
||||
DEFINE_KEYFIELD( m_sNPCTemplate[1], FIELD_STRING, "NPCTemplate2" ),
|
||||
@ -902,7 +921,7 @@ CNPC_CombineDropship::~CNPC_CombineDropship(void)
|
||||
void CNPC_CombineDropship::Spawn( void )
|
||||
{
|
||||
Precache( );
|
||||
SetModel( "models/combine_dropship.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/combine_dropship.mdl" ) );
|
||||
|
||||
#ifdef _XBOX
|
||||
AddEffects( EF_NOSHADOW );
|
||||
@ -962,12 +981,60 @@ void CNPC_CombineDropship::Spawn( void )
|
||||
break;
|
||||
|
||||
case CRATE_STRIDER:
|
||||
#ifdef MAPBASE
|
||||
if ( m_sStriderTemplate != NULL_STRING )
|
||||
{
|
||||
m_sStriderTemplateData = Templates_FindByTargetName( STRING( m_sStriderTemplate ) );
|
||||
if (m_sStriderTemplateData == NULL_STRING)
|
||||
{
|
||||
Warning("npc_combinedropship %s: Strider Template %s not found!\n", STRING(GetEntityName()), STRING(m_sStriderTemplate));
|
||||
break;
|
||||
}
|
||||
|
||||
CAI_BaseNPC* pent = NULL;
|
||||
CBaseEntity* pEntity = NULL;
|
||||
MapEntity_ParseEntity( pEntity, STRING( m_sStriderTemplateData ), NULL);
|
||||
if ( pEntity != NULL )
|
||||
{
|
||||
pent = ( CAI_BaseNPC* )pEntity;
|
||||
}
|
||||
|
||||
if ( !FClassnameIs(pent, "npc_strider"))
|
||||
{
|
||||
Warning("npc_combinedropship %s: Strider Template %s is not a strider!\n", STRING(GetEntityName()), STRING(m_sStriderTemplate));
|
||||
break;
|
||||
}
|
||||
|
||||
m_OnSpawnNPC.Set( pEntity, pEntity, this );
|
||||
|
||||
pent->RemoveSpawnFlags( SF_NPC_TEMPLATE );
|
||||
|
||||
pent->SetOwnerEntity( this );
|
||||
|
||||
m_hContainer = pent;
|
||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector(0, 0, 100) );
|
||||
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||
m_hContainer->SetParent( this, 0 );
|
||||
m_hContainer->SetOwnerEntity( this );
|
||||
DispatchSpawn(pent);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hContainer = ( CBaseAnimating* )CreateEntityByName("npc_strider");
|
||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector(0, 0, 100) );
|
||||
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||
m_hContainer->SetParent( this, 0 );
|
||||
m_hContainer->SetOwnerEntity( this );
|
||||
m_hContainer->Spawn();
|
||||
}
|
||||
#else
|
||||
m_hContainer = (CBaseAnimating*)CreateEntityByName( "npc_strider" );
|
||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) );
|
||||
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||
m_hContainer->SetParent(this, 0);
|
||||
m_hContainer->SetOwnerEntity(this);
|
||||
m_hContainer->Spawn();
|
||||
#endif
|
||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) );
|
||||
#ifdef MAPBASE
|
||||
m_OnSpawnNPC.Set( m_hContainer, m_hContainer, this );
|
||||
@ -1121,7 +1188,7 @@ void CNPC_CombineDropship::Activate( void )
|
||||
void CNPC_CombineDropship::Precache( void )
|
||||
{
|
||||
// Models
|
||||
PrecacheModel("models/combine_dropship.mdl");
|
||||
PrecacheModel( DefaultOrCustomModel( "models/combine_dropship.mdl" ) );
|
||||
switch ( m_iCrateType )
|
||||
{
|
||||
case CRATE_SOLDIER:
|
||||
@ -1201,13 +1268,24 @@ void CNPC_CombineDropship::Precache( void )
|
||||
void CNPC_CombineDropship::Flight( void )
|
||||
{
|
||||
// Only run the flight model in some flight states
|
||||
#ifdef MAPBASE
|
||||
bool bRunFlight = ( GetLandingState() == LANDING_NO ||
|
||||
GetLandingState() == LANDING_LEVEL_OUT ||
|
||||
GetLandingState() == LANDING_LIFTOFF ||
|
||||
GetLandingState() == LANDING_SWOOPING ||
|
||||
GetLandingState() == LANDING_DESCEND ||
|
||||
GetLandingState() == LANDING_HOVER_LEVEL_OUT ||
|
||||
GetLandingState() == LANDING_HOVER_DESCEND );
|
||||
GetLandingState() == LANDING_HOVER_DESCEND ||
|
||||
GetLandingState() == LANDING_STRIDER );
|
||||
#else
|
||||
bool bRunFlight = (GetLandingState() == LANDING_NO ||
|
||||
GetLandingState() == LANDING_LEVEL_OUT ||
|
||||
GetLandingState() == LANDING_LIFTOFF ||
|
||||
GetLandingState() == LANDING_SWOOPING ||
|
||||
GetLandingState() == LANDING_DESCEND ||
|
||||
GetLandingState() == LANDING_HOVER_LEVEL_OUT ||
|
||||
GetLandingState() == LANDING_HOVER_DESCEND );
|
||||
#endif
|
||||
|
||||
Vector forward, right, up;
|
||||
GetVectors( &forward, &right, &up );
|
||||
@ -1429,8 +1507,14 @@ void CNPC_CombineDropship::Flight( void )
|
||||
}
|
||||
|
||||
// If we're landing, deliberately tuck in the back end
|
||||
#ifdef MAPBASE
|
||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_TOUCHDOWN ||
|
||||
GetLandingState() == LANDING_UNLOADING || GetLandingState() == LANDING_UNLOADED ||
|
||||
GetLandingState() == LANDING_STRIDER || IsHovering() )
|
||||
#else
|
||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_TOUCHDOWN ||
|
||||
GetLandingState() == LANDING_UNLOADING || GetLandingState() == LANDING_UNLOADED || IsHovering() )
|
||||
#endif
|
||||
{
|
||||
finspeed = -60;
|
||||
}
|
||||
@ -1779,6 +1863,16 @@ void CNPC_CombineDropship::InputDropStrider( inputdata_t &inputdata )
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_iszLandTarget != NULL_STRING)
|
||||
{
|
||||
LandCommon();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLandingState(LANDING_STRIDER);
|
||||
}
|
||||
#else
|
||||
QAngle angles = GetAbsAngles();
|
||||
|
||||
angles.x = 0.0;
|
||||
@ -1790,6 +1884,7 @@ void CNPC_CombineDropship::InputDropStrider( inputdata_t &inputdata )
|
||||
m_hContainer->SetAbsVelocity( vec3_origin );
|
||||
|
||||
m_hContainer = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2016,7 +2111,11 @@ void CNPC_CombineDropship::SetLandingState( LandingState_t landingState )
|
||||
if ( m_pDescendingWarningSound )
|
||||
{
|
||||
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
|
||||
#ifdef MAPBASE
|
||||
if ( ( landingState == LANDING_DESCEND ) || ( landingState == LANDING_TOUCHDOWN ) || ( landingState == LANDING_UNLOADING ) || ( landingState == LANDING_UNLOADED ) || ( landingState == LANDING_HOVER_DESCEND ) || ( landingState == LANDING_STRIDER ) )
|
||||
#else
|
||||
if ( ( landingState == LANDING_DESCEND ) || ( landingState == LANDING_TOUCHDOWN ) || ( landingState == LANDING_UNLOADING ) || ( landingState == LANDING_UNLOADED ) || ( landingState == LANDING_HOVER_DESCEND ) )
|
||||
#endif
|
||||
{
|
||||
controller.SoundChangeVolume( m_pDescendingWarningSound, m_bSuppressSound ? 0.0f : 1.0f, 0.3f );
|
||||
}
|
||||
@ -2112,8 +2211,15 @@ void CNPC_CombineDropship::PrescheduleThink( void )
|
||||
if ( flDistance < 70 && flSpeed < 100 )
|
||||
{
|
||||
m_flLandingSpeed = flSpeed;
|
||||
|
||||
if( IsHovering() )
|
||||
#ifdef MAPBASE
|
||||
if ( m_iCrateType == CRATE_STRIDER )
|
||||
{
|
||||
SetLandingState( LANDING_STRIDER );
|
||||
}
|
||||
else if( IsHovering() )
|
||||
#else
|
||||
if ( IsHovering() )
|
||||
#endif
|
||||
{
|
||||
SetLandingState( LANDING_HOVER_DESCEND );
|
||||
}
|
||||
@ -2315,6 +2421,98 @@ void CNPC_CombineDropship::PrescheduleThink( void )
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef MAPBASE
|
||||
case LANDING_STRIDER:
|
||||
{
|
||||
if (!m_hContainer)
|
||||
{
|
||||
// Strider died, get out of here
|
||||
SetLandingState(LANDING_LIFTOFF);
|
||||
return;
|
||||
}
|
||||
|
||||
// Orient myself to the desired direction
|
||||
bool bStillOrienting = false;
|
||||
Vector targetDir;
|
||||
if (m_hLandTarget)
|
||||
{
|
||||
// We've got a land target, so match it's orientation
|
||||
AngleVectors(m_hLandTarget->GetAbsAngles(), &targetDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No land target.
|
||||
targetDir = GetDesiredPosition() - GetAbsOrigin();
|
||||
}
|
||||
|
||||
// Don't unload until we're facing the way the dropoff point specifies
|
||||
float flTargetYaw = UTIL_VecToYaw(targetDir);
|
||||
float flDeltaYaw = UTIL_AngleDiff(flTargetYaw, GetAbsAngles().y);
|
||||
if (fabs(flDeltaYaw) > 5)
|
||||
{
|
||||
bStillOrienting = true;
|
||||
}
|
||||
|
||||
// Ensure we land on the drop point. Stop dropping if we're still turning.
|
||||
Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin());
|
||||
float flDistance = vecToTarget.Length();
|
||||
float flRampedSpeed = m_flLandingSpeed * (flDistance / 70);
|
||||
Vector vecVelocity = (flRampedSpeed / flDistance) * vecToTarget;
|
||||
|
||||
#define STRIDER_LANDING_HEIGHT 540.0f
|
||||
|
||||
float flFactor = MIN(1.0, MAX(0.1f, (flAltitude - STRIDER_LANDING_HEIGHT) / flAltitude));
|
||||
float flDescendVelocity = MIN(-75, MAX_LAND_VEL * flFactor);
|
||||
|
||||
vecVelocity.z = flDescendVelocity;
|
||||
|
||||
SetAbsVelocity(vecVelocity);
|
||||
|
||||
if (flAltitude < 600)
|
||||
{
|
||||
QAngle angles = GetLocalAngles();
|
||||
|
||||
// Level out quickly.
|
||||
angles.x = UTIL_Approach(0.0, angles.x, 0.2);
|
||||
angles.z = UTIL_Approach(0.0, angles.z, 0.2);
|
||||
|
||||
SetLocalAngles(angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
// randomly move as if buffeted by ground effects
|
||||
// gently flatten ship from starting pitch/yaw
|
||||
m_existPitch = UTIL_Approach(0.0, m_existPitch, 1);
|
||||
m_existRoll = UTIL_Approach(0.0, m_existRoll, 1);
|
||||
|
||||
QAngle angles = GetLocalAngles();
|
||||
angles.x = m_existPitch + (sin(gpGlobals->curtime * 3.5f) * DROPSHIP_MAX_LAND_TILT);
|
||||
angles.z = m_existRoll + (sin(gpGlobals->curtime * 3.75f) * DROPSHIP_MAX_LAND_TILT);
|
||||
SetLocalAngles(angles);
|
||||
}
|
||||
|
||||
DoRotorWash();
|
||||
|
||||
if (!bStillOrienting && flAltitude < STRIDER_LANDING_HEIGHT)
|
||||
{
|
||||
QAngle angles = GetAbsAngles();
|
||||
|
||||
m_hContainer->SetParent(NULL, 0);
|
||||
m_hContainer->SetOwnerEntity(NULL);
|
||||
m_hContainer->SetAbsAngles(angles);
|
||||
m_hContainer->SetAbsVelocity(vec3_origin);
|
||||
|
||||
m_hContainer = NULL;
|
||||
|
||||
m_flTimeTakeOff = gpGlobals->curtime + 3.5f;
|
||||
SetLandingState(LANDING_UNLOADING);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LANDING_UNLOADING:
|
||||
{
|
||||
// If we've got no specified takeoff time, we're still waiting for troops to exit. Idle.
|
||||
@ -2817,7 +3015,11 @@ void CNPC_CombineDropship::UpdatePickupNavigation( void )
|
||||
void CNPC_CombineDropship::UpdateLandTargetNavigation( void )
|
||||
{
|
||||
Vector vecPickup = m_hLandTarget->WorldSpaceCenter();
|
||||
#ifdef MAPBASE
|
||||
vecPickup.z += ( m_iCrateType == CRATE_STRIDER ) ? 732 : 256;
|
||||
#else
|
||||
vecPickup.z += 256;
|
||||
#endif
|
||||
SetDesiredPosition( vecPickup );
|
||||
|
||||
//NDebugOverlay::Cross3D( GetDesiredPosition(), -Vector(32,32,32), Vector(32,32,32), 0, 255, 255, true, 0.1f );
|
||||
@ -2850,7 +3052,11 @@ void CNPC_CombineDropship::Hunt( void )
|
||||
// Face our desired position.
|
||||
m_vecDesiredFaceDir = desiredDir;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_LEVEL_OUT || GetLandingState() == LANDING_STRIDER || IsHovering() )
|
||||
#else
|
||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_LEVEL_OUT || IsHovering() )
|
||||
#endif
|
||||
{
|
||||
if ( m_hLandTarget )
|
||||
{
|
||||
@ -3150,6 +3356,19 @@ void CNPC_CombineDropship::MakeTracer( const Vector &vecTracerSrc, const trace_t
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Need a way to tell if our strider died
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_CombineDropship::DeathNotice( CBaseEntity *pVictim )
|
||||
{
|
||||
if ( m_iCrateType == CRATE_STRIDER && GetLandingState() == LANDING_NO )
|
||||
{
|
||||
m_OnContainerShotDownBeforeDropoff.Set( 1, m_hContainer, this );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
AI_BEGIN_CUSTOM_NPC( npc_combinedropship, CNPC_CombineDropship )
|
||||
|
||||
DECLARE_ACTIVITY( ACT_DROPSHIP_FLY_IDLE );
|
||||
|
@ -187,15 +187,29 @@ public:
|
||||
{
|
||||
return m_bDisabled;
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
void GunshipCrashedOnTarget( CBaseHelicopter *pGunship )
|
||||
{
|
||||
m_OnCrashed.FireOutput( pGunship, this );
|
||||
}
|
||||
void GunshipAcquiredCrashTarget( CBaseHelicopter *pGunship )
|
||||
{
|
||||
m_OnBeginCrash.FireOutput( pGunship, this );
|
||||
}
|
||||
#else
|
||||
void GunshipCrashedOnTarget( void )
|
||||
{
|
||||
m_OnCrashed.FireOutput( this, this );
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_bDisabled;
|
||||
|
||||
COutputEvent m_OnCrashed;
|
||||
#ifdef MAPBASE
|
||||
COutputEvent m_OnBeginCrash;
|
||||
#endif
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( info_target_gunshipcrash, CTargetGunshipCrash );
|
||||
@ -209,6 +223,9 @@ BEGIN_DATADESC( CTargetGunshipCrash )
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_OUTPUT( m_OnBeginCrash, "OnBeginCrash" ),
|
||||
#endif
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
@ -547,11 +564,11 @@ void CNPC_CombineGunship::Spawn( void )
|
||||
|
||||
if ( HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) )
|
||||
{
|
||||
SetModel( "models/combine_helicopter.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/combine_helicopter.mdl" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModel( "models/gunship.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/gunship.mdl" ) );
|
||||
}
|
||||
|
||||
ExtractBbox( SelectHeaviestSequence( ACT_GUNSHIP_PATROL ), m_cullBoxMins, m_cullBoxMaxs );
|
||||
@ -673,12 +690,12 @@ void CNPC_CombineGunship::Precache( void )
|
||||
{
|
||||
if ( HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) )
|
||||
{
|
||||
PrecacheModel( "models/combine_helicopter.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/combine_helicopter.mdl" ) );
|
||||
Chopper_PrecacheChunks( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
PrecacheModel("models/gunship.mdl");
|
||||
PrecacheModel( DefaultOrCustomModel( "models/gunship.mdl" ) );
|
||||
}
|
||||
|
||||
PrecacheModel("sprites/lgtning.vmt");
|
||||
@ -708,7 +725,7 @@ void CNPC_CombineGunship::Precache( void )
|
||||
g_iGunshipEffectIndex = PrecacheModel( "sprites/physbeam.vmt" );
|
||||
}
|
||||
|
||||
PropBreakablePrecacheAll( MAKE_STRING("models/gunship.mdl") );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( DefaultOrCustomModel( "models/gunship.mdl" ) ) );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
@ -1564,7 +1581,11 @@ void CNPC_CombineGunship::PrescheduleThink( void )
|
||||
{
|
||||
BeginDestruct();
|
||||
m_OnCrashed.FireOutput( this, this );
|
||||
#ifdef MAPBASE
|
||||
m_hCrashTarget->GunshipCrashedOnTarget( this );
|
||||
#else
|
||||
m_hCrashTarget->GunshipCrashedOnTarget();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1976,6 +1997,10 @@ bool CNPC_CombineGunship::FindNearestGunshipCrash( void )
|
||||
m_flNextGunshipCrashFind = gpGlobals->curtime + 0.5;
|
||||
m_flEndDestructTime = 0;
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_hCrashTarget->GunshipAcquiredCrashTarget( this );
|
||||
#endif
|
||||
|
||||
if ( g_debug_gunship.GetInt() )
|
||||
{
|
||||
NDebugOverlay::Line(GetAbsOrigin(), m_hCrashTarget->GetAbsOrigin(), 0,255,0, true, 0.5);
|
||||
|
@ -38,6 +38,11 @@ ConVar sk_combine_guard_kick( "sk_combine_guard_kick", "0");
|
||||
ConVar combine_guard_spawn_health( "combine_guard_spawn_health", "1" );
|
||||
|
||||
extern ConVar sk_plr_dmg_buckshot;
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar sk_combine_head_dmg_multiplier( "sk_combine_head_dmg_multiplier", "2" );
|
||||
#endif
|
||||
|
||||
extern ConVar sk_plr_num_shotgun_pellets;
|
||||
|
||||
//Whether or not the combine should spawn health on death
|
||||
@ -222,8 +227,14 @@ float CNPC_CombineS::GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDama
|
||||
{
|
||||
case HITGROUP_HEAD:
|
||||
{
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Now you can change the multiplier of headshot damage in console!
|
||||
return sk_combine_head_dmg_multiplier.GetFloat();
|
||||
#else
|
||||
// Soldiers take double headshot damage
|
||||
return 2.0f;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,7 +455,7 @@ void CNPC_Dog::Spawn( void )
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetModel( "models/dog.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/dog.mdl" ) );
|
||||
|
||||
SetHullType( HULL_WIDE_HUMAN );
|
||||
SetHullSizeNormal();
|
||||
@ -638,7 +638,7 @@ void CNPC_Dog::PullObject( bool bMantain )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Dog::Precache( void )
|
||||
{
|
||||
PrecacheModel( "models/dog.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/dog.mdl" ) );
|
||||
|
||||
PrecacheScriptSound( "Weapon_PhysCannon.Launch" );
|
||||
|
||||
|
@ -396,7 +396,7 @@ static const char *s_pLegsModel = "models/gibs/fast_zombie_legs.mdl";
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFastZombie::Precache( void )
|
||||
{
|
||||
PrecacheModel("models/zombie/fast.mdl");
|
||||
PrecacheModel( DefaultOrCustomModel( "models/zombie/fast.mdl" ) );
|
||||
#ifdef HL2_EPISODIC
|
||||
PrecacheModel("models/zombie/Fast_torso.mdl");
|
||||
PrecacheScriptSound( "NPC_FastZombie.CarEnter1" );
|
||||
@ -773,7 +773,7 @@ void CFastZombie::SetZombieModel( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModel( "models/zombie/fast.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/zombie/fast.mdl" ) );
|
||||
SetHullType(HULL_HUMAN);
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ END_DATADESC()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Fisherman::SelectModel()
|
||||
{
|
||||
SetModelName( AllocPooledString( FISHERMAN_MODEL ) );
|
||||
SetModelName( AllocPooledString( DefaultOrCustomModel( FISHERMAN_MODEL ) ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -97,7 +97,7 @@ void CNPC_GMan::Spawn()
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetModel( "models/gman.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/gman.mdl" ) );
|
||||
|
||||
SetHullType(HULL_HUMAN);
|
||||
SetHullSizeNormal();
|
||||
@ -123,7 +123,7 @@ void CNPC_GMan::Spawn()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_GMan::Precache()
|
||||
{
|
||||
PrecacheModel( "models/gman.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/gman.mdl" ) );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ Activity CNPC_Monk::NPC_TranslateActivity( Activity eNewActivity )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Monk::Precache()
|
||||
{
|
||||
PrecacheModel( "models/Monk.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/Monk.mdl" ) );
|
||||
|
||||
PrecacheScriptSound( "NPC_Citizen.FootstepLeft" );
|
||||
PrecacheScriptSound( "NPC_Citizen.FootstepRight" );
|
||||
@ -317,7 +317,7 @@ void CNPC_Monk::Spawn()
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetModel( "models/Monk.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/Monk.mdl" ) );
|
||||
|
||||
SetHullType(HULL_HUMAN);
|
||||
SetHullSizeNormal();
|
||||
|
@ -99,7 +99,7 @@ void CNPC_Mossman::Spawn()
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetModel( "models/mossman.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/mossman.mdl" ) );
|
||||
|
||||
SetHullType(HULL_HUMAN);
|
||||
SetHullSizeNormal();
|
||||
@ -124,7 +124,7 @@ void CNPC_Mossman::Spawn()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Mossman::Precache()
|
||||
{
|
||||
PrecacheModel( "models/mossman.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/mossman.mdl" ) );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
@ -1327,6 +1327,15 @@ void CNPC_Strider::BuildScheduleTestBits()
|
||||
//---------------------------------------------------------
|
||||
int CNPC_Strider::SelectSchedule()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if( GetMoveType() == MOVETYPE_NONE )
|
||||
{
|
||||
// Dropship just released me.
|
||||
AddFlag(FL_FLY);
|
||||
SetMoveType( MOVETYPE_STEP );
|
||||
return SCHED_STRIDER_FALL_TO_GROUND;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
if( GetMoveType() != MOVETYPE_FLY )
|
||||
{
|
||||
@ -1511,6 +1520,26 @@ int CNPC_Strider::TranslateSchedule( int scheduleType )
|
||||
return SCHED_COMBAT_PATROL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
extern ConVar ai_enemy_memory_fixes;
|
||||
|
||||
// Striders convert TASK_GET_PATH_TO_ENEMY_LOS to TASK_GET_PATH_TO_ENEMY_LKP_LOS, a task which incorrectly
|
||||
// acts identically to the former. This is detailed in CAI_BaseNPC::StartTask and fixed by ai_enemy_memory_fixes.
|
||||
//
|
||||
// However, SCHED_ESTABLISH_LINE_OF_FIRE only stops being used once the NPC has LOS to its target.
|
||||
// Since the fixed task now uses the enemy's last known position instead of the enemy's actual position,
|
||||
// this schedule risks getting stuck in a loop.
|
||||
//
|
||||
// This code chains back up to SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK, which is what's supposed to happen when a
|
||||
// strider is eluded in this way.
|
||||
if ( ai_enemy_memory_fixes.GetBool() && FVisible( GetEnemyLKP() ) )
|
||||
{
|
||||
return TranslateSchedule( SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -5818,6 +5847,18 @@ AI_BEGIN_CUSTOM_NPC( npc_strider, CNPC_Strider )
|
||||
" COND_STRIDER_SHOULD_STAND"
|
||||
)
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_STRIDER_FALL_TO_GROUND,
|
||||
|
||||
" Tasks "
|
||||
" TASK_SOUND_WAKE 0"
|
||||
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_STRIDER_DEPLOY"
|
||||
""
|
||||
" Interrupts "
|
||||
)
|
||||
#else
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_STRIDER_FALL_TO_GROUND,
|
||||
@ -5827,7 +5868,7 @@ AI_BEGIN_CUSTOM_NPC( npc_strider, CNPC_Strider )
|
||||
""
|
||||
" Interrupts "
|
||||
)
|
||||
|
||||
#endif
|
||||
|
||||
AI_END_CUSTOM_NPC()
|
||||
|
||||
|
@ -188,6 +188,7 @@ public:
|
||||
bool HasPass() { return m_PlayerFreePass.HasPass(); }
|
||||
|
||||
bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ) { return BaseClass::FVisible( vecTarget, traceMask, ppBlocker ); }
|
||||
Vector BodyTarget( const Vector &posSrc, bool bNoisy );
|
||||
|
||||
bool IsValidEnemy( CBaseEntity *pTarget );
|
||||
|
@ -250,7 +250,7 @@ void CZombie::Precache( void )
|
||||
{
|
||||
BaseClass::Precache();
|
||||
|
||||
PrecacheModel( "models/zombie/classic.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/zombie/classic.mdl" ) );
|
||||
PrecacheModel( "models/zombie/classic_torso.mdl" );
|
||||
PrecacheModel( "models/zombie/classic_legs.mdl" );
|
||||
|
||||
@ -515,7 +515,7 @@ void CZombie::SetZombieModel( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModel( "models/zombie/classic.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/zombie/classic.mdl" ) );
|
||||
SetHullType( HULL_HUMAN );
|
||||
}
|
||||
|
||||
|
@ -249,7 +249,7 @@ void CNPC_Zombine::Precache( void )
|
||||
{
|
||||
BaseClass::Precache();
|
||||
|
||||
PrecacheModel( "models/zombie/zombie_soldier.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/zombie/zombie_soldier.mdl" ) );
|
||||
|
||||
PrecacheScriptSound( "Zombie.FootstepRight" );
|
||||
PrecacheScriptSound( "Zombie.FootstepLeft" );
|
||||
@ -270,7 +270,7 @@ void CNPC_Zombine::Precache( void )
|
||||
|
||||
void CNPC_Zombine::SetZombieModel( void )
|
||||
{
|
||||
SetModel( "models/zombie/zombie_soldier.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/zombie/zombie_soldier.mdl" ) );
|
||||
SetHullType( HULL_HUMAN );
|
||||
|
||||
SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, !m_fIsHeadless );
|
||||
|
@ -2645,16 +2645,19 @@ Vector CProtoSniper::DesiredBodyTarget( CBaseEntity *pTarget )
|
||||
{
|
||||
// By default, aim for the center
|
||||
Vector vecTarget = pTarget->WorldSpaceCenter();
|
||||
const Vector vecBulletOrigin = GetBulletOrigin();
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope(m_ScriptScope))
|
||||
if ( m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope( m_ScriptScope ) )
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { GetBulletOrigin(), ToHScript( pTarget ) };
|
||||
if (g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ))
|
||||
ScriptVariant_t args[] = { vecBulletOrigin, ToHScript( pTarget ) };
|
||||
if ( g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ) )
|
||||
{
|
||||
if (functionReturn.m_type == FIELD_VECTOR && functionReturn.m_pVector->LengthSqr() != 0.0f)
|
||||
if ( functionReturn.m_type == FIELD_VECTOR && functionReturn.m_pVector->LengthSqr() != 0.0f )
|
||||
{
|
||||
return *functionReturn.m_pVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -2682,12 +2685,12 @@ Vector CProtoSniper::DesiredBodyTarget( CBaseEntity *pTarget )
|
||||
{
|
||||
if( flTimeSinceLastMiss > 0.0f && flTimeSinceLastMiss < 4.0f && hl2_episodic.GetBool() )
|
||||
{
|
||||
vecTarget = pTarget->BodyTarget( GetBulletOrigin(), false );
|
||||
vecTarget = pTarget->BodyTarget( vecBulletOrigin, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shoot zombies in the headcrab
|
||||
vecTarget = pTarget->HeadTarget( GetBulletOrigin() );
|
||||
vecTarget = pTarget->HeadTarget( vecBulletOrigin );
|
||||
}
|
||||
}
|
||||
else if( pTarget->Classify() == CLASS_ANTLION )
|
||||
|
985
sp/src/game/server/mapbase/choreosentence.cpp
Normal file
985
sp/src/game/server/mapbase/choreosentence.cpp
Normal file
@ -0,0 +1,985 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: VCD-based sentences.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "utlhashtable.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "soundchars.h"
|
||||
#include "choreosentence.h"
|
||||
#include "mapbase/matchers.h"
|
||||
#include "ai_speech_new.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define IsVirtualWord(pszWord) (pszWord[0] == 'V' && pszWord[1] == '_')
|
||||
#define RemoveVirtualPrefix(pszWord) IsVirtualWord(pszWord) ? pszWord + 2 : pszWord
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CChoreoSentenceSystem : public CAutoGameSystem
|
||||
{
|
||||
public:
|
||||
|
||||
struct VirtualWord_t;
|
||||
struct VirtualWordDefinition_t;
|
||||
struct VirtualWordDefinitionList_t;
|
||||
struct SentenceContextPrerequisite_t;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CChoreoSentenceSystem() : m_Strings( 256, 0, &StringLessThan ) { }
|
||||
~CChoreoSentenceSystem() { PurgeSentences(); }
|
||||
|
||||
bool Init()
|
||||
{
|
||||
// Load the default choreo sentences files
|
||||
LoadChoreoSentenceManifest( "scripts/choreosentences_manifest.txt" );
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
PurgeSentences();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void LoadChoreoSentenceManifest( const char *pszFile )
|
||||
{
|
||||
KeyValues *pManifest = new KeyValues( "ChoreoSentencesManifest" );
|
||||
if (pManifest->LoadFromFile( filesystem, pszFile ))
|
||||
{
|
||||
FOR_EACH_SUBKEY( pManifest, pSubKey )
|
||||
{
|
||||
LoadChoreoSentenceFile( pSubKey->GetString() );
|
||||
}
|
||||
}
|
||||
pManifest->deleteThis();
|
||||
|
||||
//m_Strings.Compact( true );
|
||||
}
|
||||
|
||||
void LoadChoreoSentenceFile( const char *pszFile )
|
||||
{
|
||||
KeyValues *pManifest = new KeyValues( "ChoreoSentences" );
|
||||
if (pManifest->LoadFromFile( filesystem, pszFile ))
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
// Context Prerequisites
|
||||
//----------------------------------------------------------------------------
|
||||
KeyValues *pSentenceContextPrerequisites = pManifest->FindKey( "SentenceContextPrerequisites" );
|
||||
FOR_EACH_SUBKEY( pSentenceContextPrerequisites, pSubKey )
|
||||
{
|
||||
KeyValues *pCondition = pSubKey->GetFirstSubKey();
|
||||
if (pCondition)
|
||||
{
|
||||
//
|
||||
// Only add if there is a subkey for condition
|
||||
//
|
||||
int i = m_ContextPrerequisites.AddToTail();
|
||||
m_ContextPrerequisites[i].nConditionType = DeduceCondition( pCondition->GetName(), V_strlen( pCondition->GetName() ) );
|
||||
|
||||
m_ContextPrerequisites[i].pszContextName = AllocateString( pSubKey->GetName() );
|
||||
m_ContextPrerequisites[i].pszCondition = AllocateString( pCondition->GetString() );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Virtual Words
|
||||
//----------------------------------------------------------------------------
|
||||
KeyValues *pVirtualWords = pManifest->FindKey( "VirtualWords" );
|
||||
FOR_EACH_SUBKEY( pVirtualWords, pSubKey )
|
||||
{
|
||||
//
|
||||
// Determine if this has nested virtual words or not
|
||||
//
|
||||
KeyValues *pMatches = pSubKey->FindKey( "matches" );
|
||||
if (pMatches)
|
||||
{
|
||||
//
|
||||
// It has nested virtual words
|
||||
//
|
||||
int i = m_VirtualWordLists.Insert( RemoveVirtualPrefix( pSubKey->GetName() ) );
|
||||
m_VirtualWordLists[i].pszCriterion = AllocateString( pSubKey->GetString( "criterion" ) );
|
||||
|
||||
bool bFirst = true;
|
||||
FOR_EACH_SUBKEY( pMatches, pWordList )
|
||||
{
|
||||
if (bFirst)
|
||||
{
|
||||
// First one is always default
|
||||
if (LoadVirtualWordDefinitionFromKV( pWordList, m_VirtualWordLists[i].m_DefaultWordDefinition, pSubKey->GetName() ))
|
||||
bFirst = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = m_VirtualWordLists[i].m_WordDefinitions.Insert( pWordList->GetName() );
|
||||
if (!LoadVirtualWordDefinitionFromKV( pWordList, m_VirtualWordLists[i].m_WordDefinitions[i2], pSubKey->GetName() ))
|
||||
m_VirtualWordLists[i].m_WordDefinitions.RemoveAt( i2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// It is a virtual word
|
||||
//
|
||||
int i = m_VirtualWords.Insert( RemoveVirtualPrefix( pSubKey->GetName() ) );
|
||||
if (!LoadVirtualWordDefinitionFromKV( pSubKey, m_VirtualWords[i], pSubKey->GetName() ))
|
||||
m_VirtualWords.RemoveAt( i );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Sentences
|
||||
//----------------------------------------------------------------------------
|
||||
KeyValues *pSentences = pManifest->FindKey( "Sentences" );
|
||||
FOR_EACH_SUBKEY( pSentences, pSetKey )
|
||||
{
|
||||
FOR_EACH_SUBKEY( pSetKey, pSubKey )
|
||||
{
|
||||
if (pSubKey->GetName() && *pSubKey->GetString())
|
||||
{
|
||||
int i = m_Sentences.Insert( pSubKey->GetName() );
|
||||
|
||||
char szPathName[MAX_PATH];
|
||||
V_strncpy( szPathName, pSetKey->GetName(), sizeof( szPathName ) );
|
||||
V_FixSlashes( szPathName );
|
||||
m_Sentences[i].pszPrefix = AllocateString( szPathName );
|
||||
|
||||
//m_Sentences[i].pszPrefix = AllocateString( pSetKey->GetName() );
|
||||
|
||||
ParseChoreoSentence( NULL, pSubKey->GetString(), m_Sentences[i] );
|
||||
m_Sentences[i].pszName = m_Sentences.GetElementName( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pManifest->deleteThis();
|
||||
}
|
||||
|
||||
bool LoadVirtualWordDefinitionFromKV( KeyValues *pWordList, VirtualWordDefinition_t &wordDefinition, const char *pszWordName )
|
||||
{
|
||||
//
|
||||
// Get the condition for this virtual word
|
||||
//
|
||||
KeyValues *pCondition = pWordList->FindKey( "condition" );
|
||||
if (pCondition)
|
||||
{
|
||||
int nStrLen = V_strlen( pCondition->GetString() );
|
||||
const char *pColon = V_strnchr( pCondition->GetString(), ':', nStrLen );
|
||||
if (pColon)
|
||||
{
|
||||
wordDefinition.pszCondition = AllocateString( pColon + 1 );
|
||||
wordDefinition.nConditionType = DeduceCondition( pCondition->GetString(), pColon - pCondition->GetString() );
|
||||
}
|
||||
else
|
||||
{
|
||||
wordDefinition.nConditionType = DeduceCondition( pCondition->GetString(), nStrLen );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wordDefinition.nConditionType = 0;
|
||||
wordDefinition.pszCondition = "";
|
||||
}
|
||||
|
||||
//
|
||||
// Get the words themselves
|
||||
//
|
||||
KeyValues *pWords = pWordList->FindKey( "words" );
|
||||
if (pWords)
|
||||
{
|
||||
FOR_EACH_SUBKEY( pWords, pWord )
|
||||
{
|
||||
int i = wordDefinition.m_Words.AddToTail();
|
||||
V_strncpy( wordDefinition.m_Words[i].szWord, pWord->GetString(), sizeof( wordDefinition.m_Words[i].szWord ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pWords = pWordList->FindKey( "words_from" );
|
||||
if (pWords)
|
||||
{
|
||||
const char *pszWordsTarget = RemoveVirtualPrefix( pWords->GetString() );
|
||||
|
||||
//
|
||||
// Get from another virtual word
|
||||
//
|
||||
FOR_EACH_DICT_FAST( m_VirtualWords, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWords.GetElementName( i ), pszWordsTarget ))
|
||||
{
|
||||
wordDefinition.m_Words.AddVectorToTail( m_VirtualWords[i].m_Words );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wordDefinition.m_Words.Count() <= 0)
|
||||
{
|
||||
Warning( "WARNING: No words found on virtual word %s\n", pszWordName );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void PurgeSentences()
|
||||
{
|
||||
m_ContextPrerequisites.RemoveAll();
|
||||
m_VirtualWordLists.RemoveAll();
|
||||
m_VirtualWords.RemoveAll();
|
||||
m_Sentences.RemoveAll();
|
||||
|
||||
for (unsigned int i = 0; i < m_Strings.Count(); i++)
|
||||
{
|
||||
delete m_Strings[i];
|
||||
}
|
||||
m_Strings.Purge();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void PrintEverything()
|
||||
{
|
||||
Msg( "CONTEXT PREREQUISITES\n\n" );
|
||||
|
||||
FOR_EACH_VEC( m_ContextPrerequisites, i )
|
||||
{
|
||||
Msg( "\t\"%s\"\n\t\tCondition: %i (\"%s\")\n\n", m_ContextPrerequisites[i].pszContextName, m_ContextPrerequisites[i].nConditionType, m_ContextPrerequisites[i].pszCondition );
|
||||
}
|
||||
|
||||
Msg( "VIRTUAL WORDS\n\n" );
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWords, i )
|
||||
{
|
||||
char szWords[256] = { 0 };
|
||||
FOR_EACH_VEC( m_VirtualWords[i].m_Words, nWord )
|
||||
{
|
||||
V_strncat( szWords, "\t\t\t\"", sizeof( szWords ) );
|
||||
V_strncat( szWords, m_VirtualWords[i].m_Words[nWord].szWord, sizeof( szWords ) );
|
||||
V_strncat( szWords, "\"\n", sizeof( szWords ) );
|
||||
}
|
||||
|
||||
Msg( "\t\"%s\"\n\t\tCondition: %i (\"%s\")\n\t\tWords:\n%s\n\n", m_VirtualWords.GetElementName( i ), m_VirtualWords[i].nConditionType, m_VirtualWords[i].pszCondition, szWords );
|
||||
}
|
||||
|
||||
Msg( "SENTENCES\n\n" );
|
||||
|
||||
FOR_EACH_DICT_FAST( m_Sentences, i )
|
||||
{
|
||||
char szWords[128] = { 0 };
|
||||
FOR_EACH_VEC( m_Sentences[i].m_Words, nWord )
|
||||
{
|
||||
if (m_Sentences[i].m_Words[nWord].nPitch != 100)
|
||||
{
|
||||
V_snprintf( szWords, sizeof( szWords ), "%s(p%i) ", szWords, m_Sentences[i].m_Words[nWord].nPitch );
|
||||
}
|
||||
|
||||
if (m_Sentences[i].m_Words[nWord].nVol != 100)
|
||||
{
|
||||
V_snprintf( szWords, sizeof( szWords ), "%s(v%i) ", szWords, m_Sentences[i].m_Words[nWord].nVol );
|
||||
}
|
||||
|
||||
V_strncat( szWords, "\"", sizeof( szWords ) );
|
||||
V_strncat( szWords, m_Sentences[i].m_Words[nWord].pszWord, sizeof( szWords ) );
|
||||
V_strncat( szWords, "\" ", sizeof( szWords ) );
|
||||
}
|
||||
|
||||
Msg( "\t\"%s\"\n\t\tPrefix: \"%s\"\n\t\tCaption: \"%s\"\n\t\tWords: %s\n\n", m_Sentences.GetElementName( i ), m_Sentences[i].pszPrefix, m_Sentences[i].pszCaption ? m_Sentences[i].pszCaption : "N/A", szWords);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintStrings()
|
||||
{
|
||||
CUtlVector<const char*> strings( 0, m_Strings.Count() );
|
||||
for ( UtlHashHandle_t i = m_Strings.FirstInorder(); i != m_Strings.InvalidIndex(); i = m_Strings.NextInorder(i) )
|
||||
{
|
||||
strings.AddToTail( m_Strings[i] );
|
||||
}
|
||||
|
||||
struct _Local {
|
||||
static int __cdecl F(const char * const *a, const char * const *b) { return strcmp(*a, *b); }
|
||||
};
|
||||
strings.Sort( _Local::F );
|
||||
|
||||
for ( int i = 0; i < strings.Count(); ++i )
|
||||
{
|
||||
Msg( " %d (0x%p) : %s\n", i, strings[i], strings[i] );
|
||||
}
|
||||
Msg( "\n" );
|
||||
Msg( "Size: %d items\n", strings.Count() );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const ChoreoSentence_t *LookupChoreoSentence( CBaseEntity *pSpeaker, const char *pszSentenceName )
|
||||
{
|
||||
FOR_EACH_DICT_FAST( m_Sentences, i )
|
||||
{
|
||||
if (FStrEq( m_Sentences.GetElementName( i ), pszSentenceName ))
|
||||
{
|
||||
return &m_Sentences[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void PrecacheVirtualWord( const char *pszWord, const char *pszPrefix, const char *pszSuffix )
|
||||
{
|
||||
pszWord = RemoveVirtualPrefix( pszWord );
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWords, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWords.GetElementName( i ), pszWord ))
|
||||
{
|
||||
// Precache all words
|
||||
FOR_EACH_VEC( m_VirtualWords[i].m_Words, i2 )
|
||||
{
|
||||
CBaseEntity::PrecacheScriptSound( UTIL_VarArgs( "%s%s%s", pszPrefix, m_VirtualWords[i].m_Words[i2].szWord, pszSuffix ) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWordLists, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWordLists.GetElementName( i ), pszWord ))
|
||||
{
|
||||
// Precache all words in default definition
|
||||
FOR_EACH_VEC( m_VirtualWordLists[i].m_DefaultWordDefinition.m_Words, i2 )
|
||||
{
|
||||
CBaseEntity::PrecacheScriptSound( UTIL_VarArgs( "%s%s%s", pszPrefix, m_VirtualWordLists[i].m_DefaultWordDefinition.m_Words[i2].szWord, pszSuffix));
|
||||
}
|
||||
|
||||
// Precache all words in nested definitions
|
||||
FOR_EACH_DICT( m_VirtualWordLists[i].m_WordDefinitions, i2 )
|
||||
{
|
||||
FOR_EACH_VEC( m_VirtualWordLists[i].m_WordDefinitions[i2].m_Words, i3 )
|
||||
{
|
||||
CBaseEntity::PrecacheScriptSound( UTIL_VarArgs( "%s%s%s", pszPrefix, m_VirtualWordLists[i].m_WordDefinitions[i2].m_Words[i3].szWord, pszSuffix ) );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline const VirtualWord_t &ResolveVirtualWordDefinition( CBaseEntity *pSpeaker, const VirtualWordDefinition_t &wordDefinition )
|
||||
{
|
||||
// Resolve this condition
|
||||
int nIndex = ResolveVirtualCondition( pSpeaker, wordDefinition.nConditionType, wordDefinition.pszCondition, wordDefinition.m_Words.Count() );
|
||||
Assert( nIndex >= 0 && nIndex < wordDefinition.m_Words.Count() );
|
||||
|
||||
return wordDefinition.m_Words[nIndex];
|
||||
}
|
||||
|
||||
const char *ResolveVirtualWord( CBaseEntity *pSpeaker, const char *pszWord )
|
||||
{
|
||||
pszWord = RemoveVirtualPrefix( pszWord );
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWords, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWords.GetElementName( i ), pszWord ))
|
||||
{
|
||||
return ResolveVirtualWordDefinition( pSpeaker, m_VirtualWords[i] ).szWord;
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWordLists, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWordLists.GetElementName( i ), pszWord ))
|
||||
{
|
||||
AI_CriteriaSet set;
|
||||
if (pSpeaker)
|
||||
pSpeaker->ModifyOrAppendCriteria( set );
|
||||
|
||||
int nCriterion = set.FindCriterionIndex( m_VirtualWordLists[i].pszCriterion );
|
||||
if (set.IsValidIndex( nCriterion ))
|
||||
{
|
||||
const char *pszValue = set.GetValue( nCriterion );
|
||||
|
||||
// Find the set of virtual words that matches the criterion
|
||||
FOR_EACH_DICT( m_VirtualWordLists[i].m_WordDefinitions, i2 )
|
||||
{
|
||||
if (Matcher_Match( m_VirtualWordLists[i].m_WordDefinitions.GetElementName(i2), pszValue ))
|
||||
{
|
||||
return ResolveVirtualWordDefinition( pSpeaker, m_VirtualWordLists[i].m_WordDefinitions[i2] ).szWord;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the default
|
||||
return ResolveVirtualWordDefinition( pSpeaker, m_VirtualWordLists[i].m_DefaultWordDefinition ).szWord;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CGWarning( 0, CON_GROUP_CHOREO, "Choreo sentence can't find virtual word \"%s\"\n", pszWord );
|
||||
return "";
|
||||
}
|
||||
|
||||
int ResolveVirtualCondition( CBaseEntity *pSpeaker, int nConditionType, const char *pszCondition, int nWordCount )
|
||||
{
|
||||
switch (nConditionType)
|
||||
{
|
||||
default:
|
||||
case ConditionType_None:
|
||||
// Randomize between each word
|
||||
return RandomInt( 0, nWordCount - 1 );
|
||||
break;
|
||||
|
||||
case ConditionType_Context:
|
||||
// Return context as integer
|
||||
if (pSpeaker)
|
||||
{
|
||||
if (pSpeaker->FindContextByName( pszCondition ) == -1)
|
||||
{
|
||||
// Check if this is a prerequisite, and if it is, then apply it
|
||||
FOR_EACH_VEC( m_ContextPrerequisites, i )
|
||||
{
|
||||
if (FStrEq( m_ContextPrerequisites[i].pszContextName, pszCondition ))
|
||||
{
|
||||
pSpeaker->AddContext( pszCondition, UTIL_VarArgs("%i", ResolveVirtualCondition(pSpeaker, m_ContextPrerequisites[i].nConditionType, m_ContextPrerequisites[i].pszCondition, nWordCount)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nContext = clamp( atoi( pSpeaker->GetContextValue( pszCondition ) ), 0, nWordCount - 1 );
|
||||
return nContext;
|
||||
}
|
||||
break;
|
||||
|
||||
case ConditionType_VScript:
|
||||
{
|
||||
// Return VScript code result
|
||||
g_pScriptVM->SetValue( "_choreo_val", "" );
|
||||
|
||||
HSCRIPT hCreateChainScript = g_pScriptVM->CompileScript( UTIL_VarArgs( "_choreo_val = (%s)", pszCondition ) );
|
||||
g_pScriptVM->Run( hCreateChainScript, pSpeaker ? pSpeaker->GetOrCreatePrivateScriptScope() : NULL );
|
||||
|
||||
ScriptVariant_t scriptVar;
|
||||
g_pScriptVM->GetValue( "_choreo_val", &scriptVar );
|
||||
|
||||
g_pScriptVM->ClearValue( "_choreo_val" );
|
||||
|
||||
if (scriptVar.m_int < 0 || scriptVar.m_int >= nWordCount)
|
||||
{
|
||||
Warning("Choreo sentence script var %i from '%s' out of range\n", scriptVar.m_int, pszCondition );
|
||||
scriptVar.m_int = 0;
|
||||
}
|
||||
|
||||
return scriptVar.m_int;
|
||||
}
|
||||
break;
|
||||
|
||||
case ConditionType_DistTo:
|
||||
case ConditionType_DirTo:
|
||||
case ConditionType_GridX:
|
||||
case ConditionType_GridY:
|
||||
{
|
||||
CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, pszCondition, pSpeaker );
|
||||
if (pSpeaker && pTarget)
|
||||
{
|
||||
if (nConditionType == ConditionType_DistTo)
|
||||
{
|
||||
// Convert to meters
|
||||
return (pSpeaker->GetAbsOrigin() - pTarget->GetAbsOrigin()).Length() / 52.49344;
|
||||
}
|
||||
else if (nConditionType == ConditionType_DirTo)
|
||||
{
|
||||
Vector vecDir = (pSpeaker->GetAbsOrigin() - pTarget->GetAbsOrigin());
|
||||
return vecDir.y;
|
||||
}
|
||||
else if (nConditionType == ConditionType_GridX)
|
||||
{
|
||||
return (int)(pTarget->GetAbsOrigin().x / 10.0f) % 20;
|
||||
}
|
||||
else if (nConditionType == ConditionType_GridY)
|
||||
{
|
||||
return (int)(pTarget->GetAbsOrigin().y / 10.0f) % 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
enum
|
||||
{
|
||||
ConditionType_None, // No condition (random)
|
||||
ConditionType_Context, // Word should match value from specified context
|
||||
ConditionType_VScript, // Word should match value returned from specified VScript code
|
||||
|
||||
// HL2 sentence parameters
|
||||
ConditionType_DistTo, // Word should match distance to specified target
|
||||
ConditionType_DirTo, // Word should match direction to specified target
|
||||
ConditionType_GridX, // Word should match world X axis grid of specified target
|
||||
ConditionType_GridY, // Word should match world Y axis grid of specified target
|
||||
};
|
||||
|
||||
int DeduceCondition( const char *pszCondition, int nNumChars )
|
||||
{
|
||||
if (V_strncmp( pszCondition, "context", nNumChars ) == 0)
|
||||
return ConditionType_Context;
|
||||
else if (V_strncmp( pszCondition, "vscript", nNumChars ) == 0)
|
||||
return ConditionType_VScript;
|
||||
else if (V_strncmp( pszCondition, "dist_to", nNumChars ) == 0)
|
||||
return ConditionType_DistTo;
|
||||
else if (V_strncmp( pszCondition, "dir_to", nNumChars ) == 0)
|
||||
return ConditionType_DirTo;
|
||||
else if (V_strncmp( pszCondition, "gridx", nNumChars ) == 0)
|
||||
return ConditionType_GridX;
|
||||
else if (V_strncmp( pszCondition, "gridy", nNumChars ) == 0)
|
||||
return ConditionType_GridY;
|
||||
|
||||
return ConditionType_None;
|
||||
}
|
||||
|
||||
struct VirtualWord_t
|
||||
{
|
||||
char szWord[MAX_CHOREO_SENTENCE_VIRTUAL_WORD_LEN];
|
||||
};
|
||||
|
||||
struct VirtualWordDefinition_t
|
||||
{
|
||||
VirtualWordDefinition_t() {}
|
||||
VirtualWordDefinition_t( const VirtualWordDefinition_t &src )
|
||||
{
|
||||
pszCondition = src.pszCondition;
|
||||
nConditionType = src.nConditionType;
|
||||
m_Words.RemoveAll();
|
||||
m_Words.AddVectorToTail( src.m_Words );
|
||||
}
|
||||
|
||||
const char *pszCondition;
|
||||
int nConditionType;
|
||||
|
||||
CUtlVector< VirtualWord_t > m_Words;
|
||||
};
|
||||
|
||||
struct VirtualWordDefinitionList_t
|
||||
{
|
||||
VirtualWordDefinitionList_t() {}
|
||||
VirtualWordDefinitionList_t( const VirtualWordDefinitionList_t &src )
|
||||
{
|
||||
pszCriterion = src.pszCriterion;
|
||||
m_DefaultWordDefinition = src.m_DefaultWordDefinition;
|
||||
|
||||
m_WordDefinitions.RemoveAll();
|
||||
m_WordDefinitions.EnsureCapacity( src.m_WordDefinitions.Count() );
|
||||
FOR_EACH_DICT_FAST( src.m_WordDefinitions, i )
|
||||
m_WordDefinitions.Insert( src.m_WordDefinitions.GetElementName( i ), src.m_WordDefinitions[i] );
|
||||
}
|
||||
|
||||
const char *pszCriterion;
|
||||
|
||||
VirtualWordDefinition_t m_DefaultWordDefinition;
|
||||
CUtlDict< VirtualWordDefinition_t, int > m_WordDefinitions;
|
||||
};
|
||||
|
||||
struct SentenceContextPrerequisite_t
|
||||
{
|
||||
SentenceContextPrerequisite_t() {}
|
||||
SentenceContextPrerequisite_t( const SentenceContextPrerequisite_t &src )
|
||||
{
|
||||
pszContextName = src.pszContextName;
|
||||
pszCondition = src.pszCondition;
|
||||
nConditionType = src.nConditionType;
|
||||
}
|
||||
|
||||
const char *pszContextName;
|
||||
const char *pszCondition;
|
||||
int nConditionType;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const char *FindString( const char *string )
|
||||
{
|
||||
unsigned short i = m_Strings.Find( string );
|
||||
return i == m_Strings.InvalidIndex() ? NULL : m_Strings[i];
|
||||
}
|
||||
|
||||
const char *AllocateString( const char *string )
|
||||
{
|
||||
int i = m_Strings.Find( string );
|
||||
if ( i != m_Strings.InvalidIndex() )
|
||||
{
|
||||
return m_Strings[i];
|
||||
}
|
||||
|
||||
int len = Q_strlen( string );
|
||||
char *out = new char[ len + 1 ];
|
||||
Q_memcpy( out, string, len );
|
||||
out[ len ] = 0;
|
||||
|
||||
return m_Strings[ m_Strings.Insert( out ) ];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const CUtlDict< ChoreoSentence_t, int > &GetSentences() { return m_Sentences; }
|
||||
|
||||
private:
|
||||
|
||||
// Context prerequisites to be applied if not already applied
|
||||
CUtlVector< SentenceContextPrerequisite_t > m_ContextPrerequisites;
|
||||
|
||||
// Embedded lists of virtual words based on a criterion
|
||||
CUtlDict< VirtualWordDefinitionList_t, int > m_VirtualWordLists;
|
||||
|
||||
// Lists of virtual words (does not include nested ones)
|
||||
CUtlDict< VirtualWordDefinition_t, int > m_VirtualWords;
|
||||
|
||||
// Sentences themselves
|
||||
CUtlDict< ChoreoSentence_t, int > m_Sentences;
|
||||
|
||||
// Dedicated strings, copied from game string pool
|
||||
CUtlRBTree<const char *> m_Strings;
|
||||
|
||||
};
|
||||
|
||||
static CChoreoSentenceSystem g_ChoreoSentenceSystem;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CON_COMMAND( choreosentence_reload, "Reloads choreo sentences" )
|
||||
{
|
||||
//int nStringCount = g_ChoreoSentenceSystem.GetStringCount();
|
||||
g_ChoreoSentenceSystem.PurgeSentences();
|
||||
|
||||
//g_ChoreoSentenceSystem.ReserveStrings( nStringCount );
|
||||
g_ChoreoSentenceSystem.LoadChoreoSentenceManifest( "scripts/choreosentences_manifest.txt" );
|
||||
}
|
||||
|
||||
CON_COMMAND( choreosentence_dump, "Prints all choreo sentence stuff" )
|
||||
{
|
||||
g_ChoreoSentenceSystem.PrintEverything();
|
||||
}
|
||||
|
||||
CON_COMMAND( choreosentence_dump_strings, "Prints all strings allocated by choreo sentences" )
|
||||
{
|
||||
g_ChoreoSentenceSystem.PrintStrings();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
static int AutoCompleteChoreoSentences(const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0)
|
||||
{
|
||||
FOR_EACH_DICT_FAST( g_ChoreoSentenceSystem.GetSentences(), i )
|
||||
{
|
||||
CUtlString sym = g_ChoreoSentenceSystem.GetSentences().GetElementName( i );
|
||||
|
||||
if (Q_strnicmp( sym, substring, checklen ) != 0)
|
||||
continue;
|
||||
|
||||
int idx = symbols.Find( sym );
|
||||
if (idx == symbols.InvalidIndex())
|
||||
{
|
||||
symbols.Insert( sym );
|
||||
}
|
||||
|
||||
// Too many
|
||||
if (symbols.Count() >= COMMAND_COMPLETION_MAXITEMS)
|
||||
break;
|
||||
}
|
||||
|
||||
// Now fill in the results
|
||||
for (int i = symbols.FirstInorder(); i != symbols.InvalidIndex(); i = symbols.NextInorder(i))
|
||||
{
|
||||
const char *name = symbols[i].String();
|
||||
|
||||
char buf[512];
|
||||
Q_snprintf( buf, sizeof( buf ), "%s %s", cmdname, name );
|
||||
Q_strlower( buf );
|
||||
|
||||
CUtlString command;
|
||||
command = buf;
|
||||
commands.AddToTail(command);
|
||||
}
|
||||
|
||||
return symbols.Count();
|
||||
}
|
||||
|
||||
class CChoreoSentenceAutoCompletionFunctor : public ICommandCallback, public ICommandCompletionCallback
|
||||
{
|
||||
public:
|
||||
virtual void CommandCallback( const CCommand &command )
|
||||
{
|
||||
if (command.ArgC() != 2)
|
||||
{
|
||||
Msg( "Format: choreosentence_play <sentence name>\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
const ChoreoSentence_t *pSentence = LookupChoreoSentence( pPlayer, command.Arg( 1 ) );
|
||||
if (pSentence)
|
||||
PrecacheChoreoSentence( *pSentence );
|
||||
|
||||
pPlayer->PlayChoreoSentenceScene( command.Arg( 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
virtual int CommandCompletionCallback( const char *partial, CUtlVector< CUtlString > &commands )
|
||||
{
|
||||
if ( !g_pGameRules )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *cmdname = "choreosentence_play";
|
||||
|
||||
char *substring = (char *)partial;
|
||||
if ( Q_strstr( partial, cmdname ) )
|
||||
{
|
||||
substring = (char *)partial + strlen( cmdname ) + 1;
|
||||
}
|
||||
|
||||
int checklen = Q_strlen( substring );
|
||||
|
||||
extern bool UtlStringLessFunc( const CUtlString & lhs, const CUtlString & rhs );
|
||||
CUtlRBTree< CUtlString > symbols( 0, 0, UtlStringLessFunc );
|
||||
|
||||
return AutoCompleteChoreoSentences(cmdname, commands, symbols, substring, checklen);
|
||||
}
|
||||
};
|
||||
|
||||
static CChoreoSentenceAutoCompletionFunctor g_ChoreoSentenceAutoComplete;
|
||||
static ConCommand choreosentence_play("choreosentence_play", &g_ChoreoSentenceAutoComplete, "Plays the specified choreo sentence on the player", FCVAR_CHEAT, &g_ChoreoSentenceAutoComplete );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *ChoreoSentence_t::GetWordString( CBaseEntity *pSpeaker, int i ) const
|
||||
{
|
||||
const char *pszExtension = "";
|
||||
if (V_strrchr( pszPrefix, CORRECT_PATH_SEPARATOR ))
|
||||
{
|
||||
// Use waves if our prefix is a path
|
||||
pszExtension = ".wav";
|
||||
}
|
||||
|
||||
// TODO: Something more elaborate than UTIL_VarArgs?
|
||||
if (m_Words[i].bVirtual)
|
||||
{
|
||||
const char *pszVirtualWord = g_ChoreoSentenceSystem.ResolveVirtualWord( pSpeaker, m_Words[i].pszWord );
|
||||
return UTIL_VarArgs( "%s%s%s", pszPrefix, pszVirtualWord, pszExtension );
|
||||
}
|
||||
|
||||
return UTIL_VarArgs( "%s%s%s", pszPrefix, m_Words[i].pszWord, pszExtension );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void LoadChoreoSentenceFile( const char *pszFile )
|
||||
{
|
||||
g_ChoreoSentenceSystem.LoadChoreoSentenceFile( pszFile );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const ChoreoSentence_t *LookupChoreoSentence( CBaseEntity *pSpeaker, const char *pszSentenceName )
|
||||
{
|
||||
return g_ChoreoSentenceSystem.LookupChoreoSentence( pSpeaker, pszSentenceName );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void PrecacheChoreoSentence( const ChoreoSentence_t &sentence )
|
||||
{
|
||||
FOR_EACH_VEC( sentence.m_Words, i )
|
||||
{
|
||||
if (sentence.m_Words[i].bVirtual)
|
||||
{
|
||||
// Precache all virtual words
|
||||
const char *pszExtension = "";
|
||||
if (V_strrchr( sentence.pszPrefix, CORRECT_PATH_SEPARATOR ))
|
||||
pszExtension = ".wav";
|
||||
|
||||
g_ChoreoSentenceSystem.PrecacheVirtualWord( sentence.m_Words[i].pszWord, sentence.pszPrefix, pszExtension );
|
||||
}
|
||||
else
|
||||
{
|
||||
CBaseEntity::PrecacheScriptSound( sentence.GetWordString( NULL, i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ParseChoreoSentence( CBaseEntity *pSpeaker, const char *pszRawSentence, ChoreoSentence_t &sentence )
|
||||
{
|
||||
if (pszRawSentence == NULL || *pszRawSentence == NULL)
|
||||
return false;
|
||||
|
||||
char szSentence[256];
|
||||
|
||||
// First, try getting the prefix
|
||||
const char *pColon = V_strnchr( pszRawSentence, ':', V_strlen( pszRawSentence ) );
|
||||
if (pColon)
|
||||
{
|
||||
// Sentence is everything after colon
|
||||
Q_strncpy( szSentence, pColon + 1, sizeof( szSentence ) );
|
||||
|
||||
// Copy everything before colon for prefix
|
||||
char szPathName[MAX_PATH];
|
||||
V_strncpy( szPathName, pszRawSentence, pColon - pszRawSentence + 1 );
|
||||
V_FixSlashes( szPathName );
|
||||
sentence.pszPrefix = g_ChoreoSentenceSystem.AllocateString( szPathName );
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's all one sentence
|
||||
Q_strncpy( szSentence, pszRawSentence, sizeof( szSentence ) );
|
||||
}
|
||||
|
||||
// Now get any parameters
|
||||
const char *pSemiColon = V_strnchr( szSentence, ';', sizeof( szSentence ) );
|
||||
if (pSemiColon)
|
||||
{
|
||||
// Caption is whatever's after the semicolon
|
||||
const char *pszCaption = pSemiColon+1;
|
||||
if (pszCaption[0] == ' ')
|
||||
pszCaption++;
|
||||
|
||||
sentence.pszCaption = g_ChoreoSentenceSystem.AllocateString( pszCaption );
|
||||
|
||||
// Replace semicolon with null terminator
|
||||
szSentence[pSemiColon - szSentence] = '\0';
|
||||
}
|
||||
|
||||
// Next, split up the sentence itself
|
||||
bool success = ParseChoreoSentenceContents( pSpeaker, szSentence, sentence );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ParseChoreoSentenceContents( CBaseEntity *pSpeaker, char *pszSentence, ChoreoSentence_t &sentence )
|
||||
{
|
||||
int nCurVol = 100, nCurPitch = 100;
|
||||
|
||||
char *pszToken = strtok( pszSentence, " " );
|
||||
for (; pszToken != NULL; pszToken = strtok( NULL, " " ))
|
||||
{
|
||||
if (!pszToken || !*pszToken)
|
||||
continue;
|
||||
|
||||
// Check if this is a command number
|
||||
if (pszToken[0] == '(')
|
||||
{
|
||||
pszToken++;
|
||||
|
||||
// Remove closing parentheses
|
||||
//int end = V_strlen( pszToken )-1;
|
||||
//if (pszToken[end] == ')')
|
||||
// pszToken[end] = '\0';
|
||||
|
||||
int nNum = atoi( pszToken + 1 );
|
||||
if (nNum > 0)
|
||||
{
|
||||
switch (pszToken[0])
|
||||
{
|
||||
// TODO: Recognize e, t, etc.?
|
||||
case 'v': nCurVol = nNum; break;
|
||||
case 'p': nCurPitch = nNum; break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "Zero command number in %s\n", pszSentence );
|
||||
}
|
||||
}
|
||||
|
||||
int nWord = sentence.m_Words.AddToTail();
|
||||
|
||||
sentence.m_Words[nWord].nVol = nCurVol;
|
||||
sentence.m_Words[nWord].nPitch = nCurPitch;
|
||||
|
||||
// Check if this is virtual
|
||||
if (IsVirtualWord( pszToken ))
|
||||
sentence.m_Words[nWord].bVirtual = true;
|
||||
|
||||
// Check for periods or commas
|
||||
int end = V_strlen( pszToken )-1;
|
||||
if (pszToken[end] == ',')
|
||||
{
|
||||
int nWord2 = sentence.m_Words.AddToTail();
|
||||
sentence.m_Words[nWord2].pszWord = g_ChoreoSentenceSystem.AllocateString( "_comma" );
|
||||
sentence.m_Words[nWord2].nVol = nCurVol;
|
||||
sentence.m_Words[nWord2].nPitch = nCurPitch;
|
||||
pszToken[end] = '\0';
|
||||
}
|
||||
else if (pszToken[end] == '.')
|
||||
{
|
||||
int nWord2 = sentence.m_Words.AddToTail();
|
||||
sentence.m_Words[nWord2].pszWord = g_ChoreoSentenceSystem.AllocateString( "_period" );
|
||||
sentence.m_Words[nWord2].nVol = nCurVol;
|
||||
sentence.m_Words[nWord2].nPitch = nCurPitch;
|
||||
pszToken[end] = '\0';
|
||||
}
|
||||
|
||||
sentence.m_Words[nWord].pszWord = g_ChoreoSentenceSystem.AllocateString( pszToken );
|
||||
}
|
||||
|
||||
return sentence.m_Words.Count() > 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float GetChoreoSentenceDuration( CBaseFlex *pSpeaker, const ChoreoSentence_t &sentence )
|
||||
{
|
||||
const char *actormodel = (pSpeaker ? STRING( pSpeaker->GetModelName() ) : NULL);
|
||||
float flLength = 0.0f;
|
||||
|
||||
FOR_EACH_VEC( sentence.m_Words, i )
|
||||
{
|
||||
//float duration = CBaseEntity::GetSoundDuration( sentence.GetWordString(pSpeaker, i), actormodel );
|
||||
|
||||
float duration;
|
||||
const char *pszWord = sentence.GetWordString( pSpeaker, i );
|
||||
|
||||
// For now, call the engine functions manually instead of using CBaseEntity::GetSoundDuration so that we could get around the WaveTrace warning
|
||||
if ( V_stristr( pszWord, ".wav" ) || V_stristr( pszWord, ".mp3" ) )
|
||||
{
|
||||
duration = enginesound->GetSoundDuration( PSkipSoundChars( pszWord ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
extern ISoundEmitterSystemBase *soundemitterbase;
|
||||
duration = enginesound->GetSoundDuration( PSkipSoundChars( soundemitterbase->GetWavFileForSound( pszWord, actormodel ) ) );
|
||||
}
|
||||
|
||||
flLength += duration;
|
||||
}
|
||||
|
||||
return flLength;
|
||||
}
|
67
sp/src/game/server/mapbase/choreosentence.h
Normal file
67
sp/src/game/server/mapbase/choreosentence.h
Normal file
@ -0,0 +1,67 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: VCD-based sentences.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CHOREOSENTENCE_H
|
||||
#define CHOREOSENTENCE_H
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
|
||||
#define MAX_CHOREO_SENTENCE_PREFIX_LEN 64
|
||||
#define MAX_CHOREO_SENTENCE_WORD_LEN 32
|
||||
#define MAX_CHOREO_SENTENCE_CAPTION_LEN 64
|
||||
|
||||
#define MAX_CHOREO_SENTENCE_VIRTUAL_WORD_LEN 32
|
||||
|
||||
struct ChoreoSentenceWord_t
|
||||
{
|
||||
ChoreoSentenceWord_t() {}
|
||||
ChoreoSentenceWord_t( const ChoreoSentenceWord_t &src )
|
||||
{
|
||||
pszWord = src.pszWord;
|
||||
nPitch = src.nPitch; nVol = src.nVol;
|
||||
bVirtual = src.bVirtual;
|
||||
}
|
||||
|
||||
const char *pszWord;
|
||||
int nPitch, nVol = 100;
|
||||
bool bVirtual = false;
|
||||
};
|
||||
|
||||
struct ChoreoSentence_t
|
||||
{
|
||||
ChoreoSentence_t() {}
|
||||
ChoreoSentence_t( const ChoreoSentence_t &src )
|
||||
{
|
||||
pszName = src.pszName;
|
||||
pszPrefix = src.pszPrefix;
|
||||
pszCaption = src.pszCaption;
|
||||
m_Words.RemoveAll();
|
||||
m_Words.AddVectorToTail( src.m_Words );
|
||||
}
|
||||
|
||||
const char *GetWordString( CBaseEntity *pSpeaker, int i ) const;
|
||||
|
||||
CUtlVector< ChoreoSentenceWord_t > m_Words;
|
||||
const char *pszName;
|
||||
const char *pszPrefix;
|
||||
const char *pszCaption;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
extern void LoadChoreoSentenceFile( const char *pszFile );
|
||||
|
||||
extern const ChoreoSentence_t *LookupChoreoSentence( CBaseEntity *pSpeaker, const char *pszSentenceName );
|
||||
|
||||
extern void PrecacheChoreoSentence( const ChoreoSentence_t &sentence );
|
||||
|
||||
bool ParseChoreoSentence( CBaseEntity *pSpeaker, const char *pszRawSentence, ChoreoSentence_t &sentence );
|
||||
bool ParseChoreoSentenceContents( CBaseEntity *pSpeaker, char *pszSentence, ChoreoSentence_t &sentence );
|
||||
|
||||
extern float GetChoreoSentenceDuration( CBaseFlex *pSpeaker, const ChoreoSentence_t &sentence );
|
||||
|
||||
#endif // CHOREOSENTENCE_H
|
@ -38,8 +38,8 @@ public:
|
||||
void InputReload( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
HSCRIPT ScriptGetKeyValues( void );
|
||||
HSCRIPT ScriptGetKeyValueBlock( void );
|
||||
HSCRIPT_RC ScriptGetKeyValues( void );
|
||||
HSCRIPT_RC ScriptGetKeyValueBlock( void );
|
||||
|
||||
void ScriptSetKeyValues( HSCRIPT hKV );
|
||||
void ScriptSetKeyValueBlock( HSCRIPT hKV );
|
||||
@ -275,7 +275,7 @@ void CLogicExternalData::InputReload( inputdata_t &inputdata )
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CLogicExternalData::ScriptGetKeyValues( void )
|
||||
HSCRIPT_RC CLogicExternalData::ScriptGetKeyValues( void )
|
||||
{
|
||||
if (m_bReloadBeforeEachAction)
|
||||
LoadFile();
|
||||
@ -283,8 +283,9 @@ HSCRIPT CLogicExternalData::ScriptGetKeyValues( void )
|
||||
HSCRIPT hScript = NULL;
|
||||
if (m_pRoot)
|
||||
{
|
||||
// Does this need to be destructed or freed? m_pScriptModelKeyValues apparently doesn't.
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, m_pRoot, false );
|
||||
KeyValues *pCopy = new KeyValues( NULL );
|
||||
*pCopy = *m_pRoot;
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pCopy );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
@ -292,7 +293,7 @@ HSCRIPT CLogicExternalData::ScriptGetKeyValues( void )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CLogicExternalData::ScriptGetKeyValueBlock( void )
|
||||
HSCRIPT_RC CLogicExternalData::ScriptGetKeyValueBlock( void )
|
||||
{
|
||||
if (m_bReloadBeforeEachAction)
|
||||
LoadFile();
|
||||
@ -300,8 +301,9 @@ HSCRIPT CLogicExternalData::ScriptGetKeyValueBlock( void )
|
||||
HSCRIPT hScript = NULL;
|
||||
if (m_pBlock)
|
||||
{
|
||||
// Does this need to be destructed or freed? m_pScriptModelKeyValues apparently doesn't.
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, m_pBlock, false );
|
||||
KeyValues *pCopy = new KeyValues( NULL );
|
||||
*pCopy = *m_pBlock;
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pCopy );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
@ -321,7 +323,8 @@ void CLogicExternalData::ScriptSetKeyValues( HSCRIPT hKV )
|
||||
KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hKV );
|
||||
if (pKV)
|
||||
{
|
||||
m_pRoot = pKV;
|
||||
m_pRoot = new KeyValues( NULL );
|
||||
*m_pRoot = *pKV;
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,7 +339,8 @@ void CLogicExternalData::ScriptSetKeyValueBlock( HSCRIPT hKV )
|
||||
KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hKV );
|
||||
if (pKV)
|
||||
{
|
||||
m_pBlock = pKV;
|
||||
m_pBlock = new KeyValues( NULL );
|
||||
*m_pBlock = *pKV;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,7 @@ public:
|
||||
virtual Activity GetPrimaryAttackActivity(void) { return m_CustomData.m_bHitUsesMissAnim ? ACT_VM_MISSCENTER : BaseClass::GetPrimaryAttackActivity(); }
|
||||
|
||||
const char* GetWeaponScriptName() { return m_iszWeaponScriptName.Get(); }
|
||||
const char* GetName( void ) const { return STRING( m_iClassname ); }
|
||||
virtual int GetDamageType() { return g_nDamageClassTypeBits[m_CustomData.m_nDamageClass]; }
|
||||
|
||||
virtual void InitCustomWeaponFromData(const void* pData, const char* pszWeaponScript);
|
||||
@ -381,6 +382,7 @@ public:
|
||||
CHLCustomWeaponGun();
|
||||
virtual void InitCustomWeaponFromData(const void* pData, const char* pszWeaponScript);
|
||||
const char* GetWeaponScriptName() { return m_iszWeaponScriptName.Get(); }
|
||||
const char* GetName( void ) const { return STRING( m_iClassname ); }
|
||||
|
||||
// Weapon behaviour
|
||||
virtual void ItemPostFrame(void); // called each frame by the player PostThink
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "entityoutput.h"
|
||||
#ifdef MAPBASE
|
||||
#include "eventqueue.h"
|
||||
#include "saverestore_utlvector.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -825,3 +826,449 @@ void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TY
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Displays a custom number menu for player(s)
|
||||
//-----------------------------------------------------------------------------
|
||||
LINK_ENTITY_TO_CLASS( game_menu, CGameMenu );
|
||||
|
||||
BEGIN_DATADESC( CGameMenu )
|
||||
|
||||
DEFINE_UTLVECTOR( m_ActivePlayers, FIELD_EHANDLE ),
|
||||
DEFINE_UTLVECTOR( m_ActivePlayerTimes, FIELD_TIME ),
|
||||
|
||||
DEFINE_KEYFIELD( m_flDisplayTime, FIELD_FLOAT, "holdtime" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_iszTitle, FIELD_STRING, "Title" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_iszOption[0], FIELD_STRING, "Case01" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[1], FIELD_STRING, "Case02" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[2], FIELD_STRING, "Case03" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[3], FIELD_STRING, "Case04" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[4], FIELD_STRING, "Case05" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[5], FIELD_STRING, "Case06" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[6], FIELD_STRING, "Case07" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[7], FIELD_STRING, "Case08" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[8], FIELD_STRING, "Case09" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[9], FIELD_STRING, "Case10" ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ShowMenu", InputShowMenu ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "HideMenu", InputHideMenu ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "__DoRestore", InputDoRestore ),
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_OnCase[0], "OnCase01" ),
|
||||
DEFINE_OUTPUT( m_OnCase[1], "OnCase02" ),
|
||||
DEFINE_OUTPUT( m_OnCase[2], "OnCase03" ),
|
||||
DEFINE_OUTPUT( m_OnCase[3], "OnCase04" ),
|
||||
DEFINE_OUTPUT( m_OnCase[4], "OnCase05" ),
|
||||
DEFINE_OUTPUT( m_OnCase[5], "OnCase06" ),
|
||||
DEFINE_OUTPUT( m_OnCase[6], "OnCase07" ),
|
||||
DEFINE_OUTPUT( m_OnCase[7], "OnCase08" ),
|
||||
DEFINE_OUTPUT( m_OnCase[8], "OnCase09" ),
|
||||
DEFINE_OUTPUT( m_OnCase[9], "OnCase10" ),
|
||||
DEFINE_OUTPUT( m_OutValue, "OutValue" ),
|
||||
DEFINE_OUTPUT( m_OnTimeout, "OnTimeout" ),
|
||||
|
||||
DEFINE_THINKFUNC( TimeoutThink ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
IMPLEMENT_AUTO_LIST( IGameMenuAutoList );
|
||||
|
||||
static const char *s_pTimeoutContext = "TimeoutContext";
|
||||
|
||||
#define MENU_INFINITE_TIME -1.0f
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CGameMenu::CGameMenu()
|
||||
{
|
||||
m_flDisplayTime = 5.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
|
||||
// Do this a bit after we restore since the HUD might not be ready yet
|
||||
g_EventQueue.AddEvent( this, "__DoRestore", 0.4f, this, this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::InputDoRestore( inputdata_t &inputdata )
|
||||
{
|
||||
// Check if we should restore the menu on anyone
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get())
|
||||
{
|
||||
if (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME)
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddRecipient( static_cast<CBasePlayer*>( m_ActivePlayers[i].Get() ) );
|
||||
|
||||
ShowMenu( filter, m_ActivePlayerTimes[i] - gpGlobals->curtime );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove this player since it's no longer valid
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::TimeoutThink()
|
||||
{
|
||||
float flNextLowestTime = FLT_MAX;
|
||||
FOR_EACH_VEC( m_ActivePlayerTimes, i )
|
||||
{
|
||||
// If the player is still in our list, then they must not have selected an option
|
||||
if (m_ActivePlayerTimes[i] != MENU_INFINITE_TIME)
|
||||
{
|
||||
if (m_ActivePlayerTimes[i] <= gpGlobals->curtime)
|
||||
{
|
||||
m_OnTimeout.FireOutput( m_ActivePlayers[i], this );
|
||||
|
||||
// Remove this player since it's no longer valid
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
break;
|
||||
}
|
||||
else if (m_ActivePlayerTimes[i] < flNextLowestTime)
|
||||
{
|
||||
flNextLowestTime = m_ActivePlayerTimes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flNextLowestTime < FLT_MAX)
|
||||
{
|
||||
SetNextThink( flNextLowestTime, s_pTimeoutContext );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetContextThink( NULL, TICK_NEVER_THINK, s_pTimeoutContext );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::ShowMenu( CRecipientFilter &filter, float flDisplayTime )
|
||||
{
|
||||
// Before showing the menu, check each menu to see if there's already one being shown to one of our recipients
|
||||
for ( int i = 0; i < IGameMenuAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
CGameMenu *pMenu = static_cast<CGameMenu*>( IGameMenuAutoList::AutoList()[i] );
|
||||
if ( pMenu != this && pMenu->IsActive() )
|
||||
{
|
||||
for ( int j = 0; j < filter.GetRecipientCount(); j++ )
|
||||
{
|
||||
CBaseEntity *ent = CBaseEntity::Instance( filter.GetRecipientIndex( j ) );
|
||||
if ( pMenu->IsActiveOnTarget( ent ) )
|
||||
{
|
||||
Msg( "%s overriding menu %s for player %i\n", GetDebugName(), pMenu->GetDebugName(), j );
|
||||
pMenu->RemoveTarget( ent );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flDisplayTime == 0.0f)
|
||||
{
|
||||
flDisplayTime = m_flDisplayTime;
|
||||
}
|
||||
|
||||
char szString[512] = { 0 };
|
||||
int nBitsValidSlots = 0;
|
||||
|
||||
if (m_iszTitle != NULL_STRING)
|
||||
{
|
||||
V_strncat( szString, STRING( m_iszTitle ), sizeof( szString ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert space to tell menu code to skip
|
||||
V_strncat( szString, " ", sizeof( szString ) );
|
||||
}
|
||||
|
||||
// Insert newline even if there's no string
|
||||
V_strncat( szString, "\n", sizeof( szString ) );
|
||||
|
||||
// Populate the options
|
||||
for (int i = 0; i < MAX_MENU_OPTIONS; i++)
|
||||
{
|
||||
if (m_iszOption[i] != NULL_STRING)
|
||||
{
|
||||
nBitsValidSlots |= (1 << i);
|
||||
|
||||
V_strncat( szString, STRING( m_iszOption[i] ), sizeof( szString ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert space to tell menu code to skip
|
||||
V_strncat( szString, " ", sizeof( szString ) );
|
||||
}
|
||||
|
||||
// Insert newline even if there's no string
|
||||
V_strncat( szString, "\n", sizeof( szString ) );
|
||||
}
|
||||
|
||||
if (nBitsValidSlots <= 0 && m_iszTitle == NULL_STRING)
|
||||
{
|
||||
Warning( "%s ShowMenu: Can't show menu with no options or title\n", GetDebugName() );
|
||||
return;
|
||||
}
|
||||
|
||||
UserMessageBegin( filter, "ShowMenuComplex" );
|
||||
WRITE_WORD( nBitsValidSlots );
|
||||
WRITE_FLOAT( flDisplayTime );
|
||||
WRITE_BYTE( 0 );
|
||||
WRITE_STRING( szString );
|
||||
MessageEnd();
|
||||
|
||||
float flMenuTime;
|
||||
if (flDisplayTime <= 0.0f)
|
||||
{
|
||||
flMenuTime = MENU_INFINITE_TIME;
|
||||
}
|
||||
else
|
||||
{
|
||||
flMenuTime = gpGlobals->curtime + flDisplayTime;
|
||||
}
|
||||
|
||||
for ( int j = 0; j < filter.GetRecipientCount(); j++ )
|
||||
{
|
||||
CBaseEntity *ent = CBaseEntity::Instance( filter.GetRecipientIndex( j ) );
|
||||
|
||||
// Check if we already track this player. If not, make a new one
|
||||
bool bFound = false;
|
||||
FOR_EACH_VEC( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get() == ent)
|
||||
{
|
||||
m_ActivePlayerTimes[i] = flMenuTime;
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
m_ActivePlayers.AddToTail( ent );
|
||||
m_ActivePlayerTimes.AddToTail( flMenuTime );
|
||||
}
|
||||
}
|
||||
|
||||
if (GetNextThink( s_pTimeoutContext ) == TICK_NEVER_THINK)
|
||||
{
|
||||
SetContextThink( &CGameMenu::TimeoutThink, gpGlobals->curtime + flDisplayTime, s_pTimeoutContext );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::HideMenu( CRecipientFilter &filter )
|
||||
{
|
||||
UserMessageBegin( filter, "ShowMenuComplex" );
|
||||
WRITE_WORD( -1 );
|
||||
WRITE_FLOAT( 0.0f );
|
||||
WRITE_BYTE( 0 );
|
||||
WRITE_STRING( "" );
|
||||
MessageEnd();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::MenuSelected( int nSlot, CBaseEntity *pActivator )
|
||||
{
|
||||
if (nSlot <= 0 || nSlot > MAX_MENU_OPTIONS)
|
||||
{
|
||||
Warning( "%s: Invalid slot %i\n", GetDebugName(), nSlot );
|
||||
return;
|
||||
}
|
||||
|
||||
m_OnCase[nSlot-1].FireOutput( pActivator, this );
|
||||
m_OutValue.Set( nSlot, pActivator, this );
|
||||
|
||||
RemoveTarget( pActivator );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CGameMenu::IsActive()
|
||||
{
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get())
|
||||
{
|
||||
if (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove this player since it's no longer valid
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CGameMenu::IsActiveOnTarget( CBaseEntity *pPlayer )
|
||||
{
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get() == pPlayer)
|
||||
{
|
||||
if (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME)
|
||||
return true;
|
||||
|
||||
// Remove this player since it's no longer valid
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::RemoveTarget( CBaseEntity *pPlayer )
|
||||
{
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get() == pPlayer)
|
||||
{
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::InputShowMenu( inputdata_t &inputdata )
|
||||
{
|
||||
if (HasSpawnFlags( SF_GAMEMENU_ALLPLAYERS ))
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddAllPlayers();
|
||||
|
||||
ShowMenu( filter );
|
||||
}
|
||||
else
|
||||
{
|
||||
CBasePlayer *pPlayer = NULL;
|
||||
|
||||
// If we're in singleplayer, show the message to the player.
|
||||
if ( gpGlobals->maxClients == 1 )
|
||||
{
|
||||
pPlayer = UTIL_GetLocalPlayer();
|
||||
}
|
||||
// Otherwise show the message to the player that triggered us.
|
||||
else if ( inputdata.pActivator && inputdata.pActivator->IsNetClient() )
|
||||
{
|
||||
pPlayer = ToBasePlayer( inputdata.pActivator );
|
||||
}
|
||||
|
||||
if (pPlayer)
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddRecipient( pPlayer );
|
||||
|
||||
ShowMenu( filter );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::InputHideMenu( inputdata_t &inputdata )
|
||||
{
|
||||
if (HasSpawnFlags( SF_GAMEMENU_ALLPLAYERS ))
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
// Select all players in our list who are still active, and remove them
|
||||
if (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME)
|
||||
{
|
||||
filter.AddRecipient( static_cast<CBasePlayer*>(m_ActivePlayers[i].Get()) );
|
||||
}
|
||||
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
}
|
||||
|
||||
if (filter.GetRecipientCount() <= 0)
|
||||
return;
|
||||
|
||||
HideMenu( filter );
|
||||
}
|
||||
else
|
||||
{
|
||||
CBasePlayer *pPlayer = NULL;
|
||||
|
||||
// If we're in singleplayer, show the message to the player.
|
||||
if ( gpGlobals->maxClients == 1 )
|
||||
{
|
||||
pPlayer = UTIL_GetLocalPlayer();
|
||||
}
|
||||
// Otherwise show the message to the player that triggered us.
|
||||
else if ( inputdata.pActivator && inputdata.pActivator->IsNetClient() )
|
||||
{
|
||||
pPlayer = ToBasePlayer( inputdata.pActivator );
|
||||
}
|
||||
|
||||
if (!pPlayer)
|
||||
return;
|
||||
|
||||
// Verify that this player is in our list
|
||||
CRecipientFilter filter;
|
||||
FOR_EACH_VEC( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get() == pPlayer && (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME))
|
||||
{
|
||||
filter.AddRecipient( pPlayer );
|
||||
|
||||
// Remove since the player won't have the menu anymore
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.GetRecipientCount() <= 0)
|
||||
return;
|
||||
|
||||
HideMenu( filter );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -9,7 +9,55 @@
|
||||
#ifndef MAPRULES_H
|
||||
#define MAPRULES_H
|
||||
|
||||
#ifdef MAPBASE
|
||||
#define MAX_MENU_OPTIONS 10
|
||||
|
||||
#define SF_GAMEMENU_ALLPLAYERS 0x0001
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Displays a custom number menu for player(s)
|
||||
//-----------------------------------------------------------------------------
|
||||
DECLARE_AUTO_LIST( IGameMenuAutoList );
|
||||
class CGameMenu : public CLogicalEntity, public IGameMenuAutoList
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CGameMenu, CLogicalEntity );
|
||||
DECLARE_DATADESC();
|
||||
CGameMenu();
|
||||
|
||||
void OnRestore();
|
||||
void InputDoRestore( inputdata_t &inputdata );
|
||||
|
||||
void TimeoutThink();
|
||||
|
||||
void ShowMenu( CRecipientFilter &filter, float flDisplayTime = 0.0f );
|
||||
void HideMenu( CRecipientFilter &filter );
|
||||
void MenuSelected( int nSlot, CBaseEntity *pActivator );
|
||||
|
||||
bool IsActive();
|
||||
bool IsActiveOnTarget( CBaseEntity *pPlayer );
|
||||
void RemoveTarget( CBaseEntity *pPlayer );
|
||||
|
||||
// Inputs
|
||||
void InputShowMenu( inputdata_t &inputdata );
|
||||
void InputHideMenu( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
|
||||
CUtlVector<EHANDLE> m_ActivePlayers;
|
||||
CUtlVector<float> m_ActivePlayerTimes;
|
||||
|
||||
float m_flDisplayTime;
|
||||
|
||||
string_t m_iszTitle;
|
||||
string_t m_iszOption[MAX_MENU_OPTIONS];
|
||||
|
||||
// Outputs
|
||||
COutputEvent m_OnCase[MAX_MENU_OPTIONS]; // Fired for the option chosen
|
||||
COutputInt m_OutValue; // Outputs the option chosen
|
||||
COutputEvent m_OnTimeout; // Fires when no option was chosen in time
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // MAPRULES_H
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "hierarchy.h"
|
||||
#ifdef MAPBASE
|
||||
#include "decals.h"
|
||||
#include "death_pose.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -29,6 +30,7 @@
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ragdoll_autointeractions("ragdoll_autointeractions", "1", FCVAR_NONE, "Controls whether we should rely on hardcoded keyvalues or automatic flesh checks for ragdoll physgun interactions.");
|
||||
ConVar ai_death_pose_server_enabled("ai_death_pose_server_enabled", "1", FCVAR_NONE, "Toggles the death pose fix code, but for server ragdolls.");
|
||||
#define IsBody() VPhysicsIsFlesh()
|
||||
|
||||
ConVar ragdoll_always_allow_use( "ragdoll_always_allow_use", "0", FCVAR_NONE, "Allows all ragdolls to be used and, if they aren't explicitly set to prevent pickup, picked up." );
|
||||
@ -788,7 +790,11 @@ void CRagdollProp::SetOverlaySequence( Activity activity )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CRagdollProp::InitRagdoll( const Vector& forceVector, int forceBone, const Vector& forcePos, matrix3x4_t* pPrevBones, matrix3x4_t* pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll, bool bDeathPose )
|
||||
#else
|
||||
void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll )
|
||||
#endif
|
||||
{
|
||||
SetCollisionGroup( collisionGroup );
|
||||
|
||||
@ -811,7 +817,11 @@ void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const
|
||||
params.forceVector = forceVector;
|
||||
params.forceBoneIndex = forceBone;
|
||||
params.forcePosition = forcePos;
|
||||
#ifdef MAPBASE
|
||||
params.pCurrentBones = bDeathPose ? pPrevBones : pBoneToWorld;
|
||||
#else
|
||||
params.pCurrentBones = pBoneToWorld;
|
||||
#endif
|
||||
params.jointFrictionScale = 1.0;
|
||||
params.allowStretch = HasSpawnFlags(SF_RAGDOLLPROP_ALLOW_STRETCH);
|
||||
#ifdef MAPBASE
|
||||
@ -1492,6 +1502,43 @@ CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, con
|
||||
|
||||
float fPreviousCycle = clamp(pAnimating->GetCycle()-( dt * ( 1 / fSequenceDuration ) ),0.f,1.f);
|
||||
float fCurCycle = pAnimating->GetCycle();
|
||||
|
||||
#ifdef MAPBASE
|
||||
int deathpose = ACT_INVALID;
|
||||
int deathframe = 0;
|
||||
if (ai_death_pose_server_enabled.GetBool() && pAnimating->IsNPC()) {
|
||||
CAI_BaseNPC* npc = (CAI_BaseNPC*)pAnimating;
|
||||
if (npc) {
|
||||
deathpose = Activity(npc->GetDeathPose());
|
||||
deathframe = npc->GetDeathPoseFrame();
|
||||
}
|
||||
}
|
||||
if (deathpose != ACT_INVALID) {
|
||||
int currentSequence = pAnimating->GetSequence();
|
||||
|
||||
//Force pAnimating to position the deathpose
|
||||
pAnimating->SetSequence(deathpose);
|
||||
pAnimating->SetCycle((float)deathframe / MAX_DEATHPOSE_FRAMES);
|
||||
|
||||
//Store the position
|
||||
pAnimating->SetupBones(pBoneToWorldNext, BONE_USED_BY_ANYTHING);
|
||||
|
||||
//Restore the current sequence and cycle
|
||||
pAnimating->SetSequence(currentSequence);
|
||||
|
||||
pAnimating->SetCycle(fCurCycle);
|
||||
pAnimating->SetupBones(pBoneToWorld, BONE_USED_BY_ANYTHING);
|
||||
}
|
||||
else {
|
||||
// Get current bones positions
|
||||
pAnimating->SetupBones(pBoneToWorldNext, BONE_USED_BY_ANYTHING);
|
||||
// Get previous bones positions
|
||||
pAnimating->SetCycle(fPreviousCycle);
|
||||
pAnimating->SetupBones(pBoneToWorld, BONE_USED_BY_ANYTHING);
|
||||
// Restore current cycle
|
||||
pAnimating->SetCycle(fCurCycle);
|
||||
}
|
||||
#else
|
||||
// Get current bones positions
|
||||
pAnimating->SetupBones( pBoneToWorldNext, BONE_USED_BY_ANYTHING );
|
||||
// Get previous bones positions
|
||||
@ -1499,6 +1546,7 @@ CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, con
|
||||
pAnimating->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING );
|
||||
// Restore current cycle
|
||||
pAnimating->SetCycle( fCurCycle );
|
||||
#endif
|
||||
|
||||
// Reset previous bone flags
|
||||
pAnimating->ClearBoneCacheFlags( BCF_NO_ANIMATION_SKIP );
|
||||
@ -1573,7 +1621,11 @@ CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, con
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
pRagdoll->InitRagdoll(info.GetDamageForce(), forceBone, info.GetDamagePosition(), pBoneToWorld, pBoneToWorldNext, dt, collisionGroup, true, true, deathpose != ACT_INVALID);
|
||||
#else
|
||||
pRagdoll->InitRagdoll( info.GetDamageForce(), forceBone, info.GetDamagePosition(), pBoneToWorld, pBoneToWorldNext, dt, collisionGroup, true );
|
||||
#endif
|
||||
}
|
||||
|
||||
// Are we dissolving?
|
||||
|
@ -75,7 +75,11 @@ public:
|
||||
|
||||
// locals
|
||||
void InitRagdollAnimation( void );
|
||||
#ifdef MAPBASE
|
||||
void InitRagdoll( const Vector& forceVector, int forceBone, const Vector& forcePos, matrix3x4_t* pPrevBones, matrix3x4_t* pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll = true, bool bDeathPose = false );
|
||||
#else
|
||||
void InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll = true );
|
||||
#endif
|
||||
|
||||
void RecheckCollisionFilter( void );
|
||||
void SetDebrisThink();
|
||||
|
@ -4475,6 +4475,11 @@ void CBasePlayer::SetSuitUpdate(const char *name, int fgroup, int iNoRepeatTime)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( HasContext("silent_suit", "1") )
|
||||
return;
|
||||
#endif
|
||||
|
||||
// if name == NULL, then clear out the queue
|
||||
|
||||
if (!name)
|
||||
@ -7959,7 +7964,7 @@ Activity CBasePlayer::Weapon_TranslateActivity( Activity baseAct, bool *pRequire
|
||||
{
|
||||
Activity weaponTranslation = BaseClass::Weapon_TranslateActivity( baseAct, pRequired );
|
||||
|
||||
if ( GetActiveWeapon() && GetActiveWeapon()->IsEffectActive(EF_NODRAW) && baseAct != ACT_ARM )
|
||||
if ( GetActiveWeapon() && !GetActiveWeapon()->IsWeaponVisible() && baseAct != ACT_ARM )
|
||||
{
|
||||
// Our weapon is holstered. Use the base activity.
|
||||
return baseAct;
|
||||
@ -8866,6 +8871,7 @@ void SendProxy_ShiftPlayerSpawnflags( const SendProp *pProp, const void *pStruct
|
||||
// See baseplayer_shared.h for more details.
|
||||
SendPropInt ( SENDINFO( m_spawnflags ), 3, SPROP_UNSIGNED, SendProxy_ShiftPlayerSpawnflags ),
|
||||
|
||||
SendPropBool ( SENDINFO( m_bDrawPlayerLegs ) ),
|
||||
SendPropBool ( SENDINFO( m_bDrawPlayerModelExternally ) ),
|
||||
SendPropBool ( SENDINFO( m_bInTriggerFall ) ),
|
||||
#endif
|
||||
|
@ -1179,6 +1179,9 @@ public:
|
||||
int m_nNumCrateHudHints;
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool GetDrawPlayerLegs( void ) { return m_bDrawPlayerLegs; }
|
||||
void SetDrawPlayerLegs( bool bToggle ) { m_bDrawPlayerLegs.Set( bToggle ); }
|
||||
|
||||
bool GetDrawPlayerModelExternally( void ) { return m_bDrawPlayerModelExternally; }
|
||||
void SetDrawPlayerModelExternally( bool bToggle ) { m_bDrawPlayerModelExternally.Set( bToggle ); }
|
||||
#endif
|
||||
@ -1222,6 +1225,7 @@ private:
|
||||
char m_szNetname[MAX_PLAYER_NAME_LENGTH];
|
||||
|
||||
#ifdef MAPBASE
|
||||
CNetworkVar( bool, m_bDrawPlayerLegs );
|
||||
CNetworkVar( bool, m_bDrawPlayerModelExternally );
|
||||
#endif
|
||||
|
||||
|
@ -393,7 +393,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
||||
if ( weapon )
|
||||
{
|
||||
VPROF( "player->SelectItem()" );
|
||||
player->SelectItem( weapon->GetClassname(), ucmd->weaponsubtype );
|
||||
player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,10 @@
|
||||
#include "npc_alyx_episodic.h"
|
||||
#endif // HL2_EPISODIC
|
||||
|
||||
#ifdef MAPBASE
|
||||
#include "mapbase/choreosentence.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
@ -57,6 +61,10 @@ class CBaseFlex;
|
||||
static ConVar scene_forcecombined( "scene_forcecombined", "0", 0, "When playing back, force use of combined .wav files even in english." );
|
||||
static ConVar scene_maxcaptionradius( "scene_maxcaptionradius", "1200", 0, "Only show closed captions if recipient is within this many units of speaking actor (0==disabled)." );
|
||||
|
||||
#ifdef MAPBASE
|
||||
static ConVar scene_resume_use_last_speaking( "scene_resume_use_last_speaking", "1", 0, "Uses the last actor who spoke for resume scene calls, rather than the first actor of the scene" );
|
||||
#endif
|
||||
|
||||
// Assume sound system is 100 msec lagged (only used if we can't find snd_mixahead cvar!)
|
||||
#define SOUND_SYSTEM_LATENCY_DEFAULT ( 0.1f )
|
||||
|
||||
@ -412,6 +420,10 @@ public:
|
||||
// If this scene is waiting on an actor, give up and quit trying.
|
||||
void InputStopWaitingForActor( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void InputPauseAtLastInterrupt( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
virtual void StartPlayback( void );
|
||||
virtual void PausePlayback( void );
|
||||
virtual void ResumePlayback( void );
|
||||
@ -482,6 +494,9 @@ public:
|
||||
bool InvolvesActor( CBaseEntity *pActor ); // NOTE: returns false if scene hasn't loaded yet
|
||||
|
||||
void GenerateSoundScene( CBaseFlex *pActor, const char *soundname );
|
||||
#ifdef MAPBASE
|
||||
void GenerateChoreoSentenceScene( CBaseFlex *pActor, const char *pszSentenceName );
|
||||
#endif
|
||||
|
||||
virtual float GetPostSpeakDelay() { return 1.0; }
|
||||
|
||||
@ -489,6 +504,7 @@ public:
|
||||
bool HasFlexAnimation( void );
|
||||
#ifdef MAPBASE
|
||||
bool IsPlayingSpeech( void );
|
||||
CBaseFlex *GetLastSpeakingActor( void );
|
||||
#endif
|
||||
|
||||
void SetCurrentTime( float t, bool forceClientSync );
|
||||
@ -594,6 +610,9 @@ private:
|
||||
void PrecacheScene( CChoreoScene *scene );
|
||||
|
||||
CChoreoScene *GenerateSceneForSound( CBaseFlex *pFlexActor, const char *soundname );
|
||||
#ifdef MAPBASE
|
||||
CChoreoScene *GenerateSceneForSentenceName( CBaseFlex *pFlexActor, const char *pszSentenceName );
|
||||
#endif
|
||||
|
||||
bool CheckActors();
|
||||
|
||||
@ -643,6 +662,9 @@ private:
|
||||
bool m_bGenerated;
|
||||
string_t m_iszSoundName;
|
||||
CHandle< CBaseFlex > m_hActor;
|
||||
#ifdef MAPBASE
|
||||
bool m_bChoreoSentence;
|
||||
#endif
|
||||
|
||||
EHANDLE m_hActivator;
|
||||
|
||||
@ -736,6 +758,9 @@ BEGIN_DATADESC( CSceneEntity )
|
||||
DEFINE_FIELD( m_bGenerated, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_iszSoundName, FIELD_STRING ),
|
||||
DEFINE_FIELD( m_hActor, FIELD_EHANDLE ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_FIELD( m_bChoreoSentence, FIELD_BOOLEAN ),
|
||||
#endif
|
||||
DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ),
|
||||
|
||||
// DEFINE_FIELD( m_bSceneMissing, FIELD_BOOLEAN ),
|
||||
@ -757,8 +782,9 @@ BEGIN_DATADESC( CSceneEntity )
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "InterjectResponse", InputInterjectResponse ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StopWaitingForActor", InputStopWaitingForActor ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "Trigger", InputTriggerEvent ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "PauseAtLastInterrupt", InputPauseAtLastInterrupt ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget1", InputSetTarget1 ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget2", InputSetTarget2 ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget3", InputSetTarget3 ),
|
||||
@ -953,6 +979,146 @@ CChoreoScene *CSceneEntity::GenerateSceneForSound( CBaseFlex *pFlexActor, const
|
||||
return scene;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *actor -
|
||||
// *pszSentenceName -
|
||||
// Output : CChoreoScene
|
||||
//-----------------------------------------------------------------------------
|
||||
CChoreoScene *CSceneEntity::GenerateSceneForSentenceName( CBaseFlex *pFlexActor, const char *pszSentenceName )
|
||||
{
|
||||
const ChoreoSentence_t *pSentence = LookupChoreoSentence( pFlexActor, pszSentenceName );
|
||||
if ( !pSentence )
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Couldn't find sentence '%s'\n", pszSentenceName );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: Raw sentence support?
|
||||
// ChoreoSentence_t sentence;
|
||||
// if ( !ParseChoreoSentence( pFlexActor, pszSentence, sentence ) )
|
||||
// {
|
||||
// Warning( "CSceneEntity::GenerateSceneForSentence: Couldn't parse sentence from '%s'\n", pszSentence );
|
||||
// return NULL;
|
||||
// }
|
||||
|
||||
CChoreoScene *scene = new CChoreoScene( this );
|
||||
if ( !scene )
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Failed to allocated new scene!!!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
scene->SetPrintFunc( LocalScene_Printf );
|
||||
|
||||
CChoreoActor *actor = scene->AllocActor();
|
||||
CChoreoChannel *channel = scene->AllocChannel();
|
||||
|
||||
Assert( actor );
|
||||
Assert( channel );
|
||||
|
||||
if ( !actor || !channel )
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Alloc of actor or channel failed!!!\n" );
|
||||
delete scene;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set us up the actorz
|
||||
actor->SetName( "!self" ); // Could be pFlexActor->GetName()?
|
||||
actor->SetActive( true );
|
||||
|
||||
// Set us up the channelz
|
||||
channel->SetName( STRING( m_iszSceneFile ) );
|
||||
channel->SetActor( actor );
|
||||
|
||||
// Add to actor
|
||||
actor->AddChannel( channel );
|
||||
|
||||
// Set us up the eventz
|
||||
const char *actormodel = (pFlexActor ? STRING( pFlexActor->GetModelName() ) : NULL);
|
||||
float flCurTime = 0.0f;
|
||||
FOR_EACH_VEC( pSentence->m_Words, i )
|
||||
{
|
||||
const char *pszWord = pSentence->GetWordString( pFlexActor, i );
|
||||
|
||||
float duration = CBaseEntity::GetSoundDuration( pszWord, actormodel );
|
||||
if (duration <= 0.0f)
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Couldn't determine duration of %s\n", pszWord );
|
||||
}
|
||||
|
||||
CChoreoEvent *event = scene->AllocEvent();
|
||||
Assert( event );
|
||||
|
||||
if ( !event )
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Alloc of event failed!!!\n" );
|
||||
delete scene;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pSentence->pszCaption)
|
||||
{
|
||||
// First word gets the caption, others fall back to it
|
||||
if (i == 0)
|
||||
{
|
||||
event->SetCloseCaptionType( CChoreoEvent::CC_MASTER );
|
||||
event->SetCloseCaptionToken( pSentence->pszCaption );
|
||||
}
|
||||
else
|
||||
{
|
||||
event->SetCloseCaptionType( CChoreoEvent::CC_SLAVE );
|
||||
}
|
||||
}
|
||||
//else if (pSentence->pszName)
|
||||
//{
|
||||
// // TODO: Caption from name?
|
||||
//}
|
||||
|
||||
if (pSentence->m_Words[i].nVol != 100)
|
||||
{
|
||||
event->SetYaw( pSentence->m_Words[i].nVol );
|
||||
}
|
||||
|
||||
if (pSentence->m_Words[i].nPitch != 100)
|
||||
{
|
||||
duration *= (100.0f / ((float)pSentence->m_Words[i].nPitch));
|
||||
event->SetPitch( pSentence->m_Words[i].nPitch );
|
||||
}
|
||||
|
||||
// HACKHACK: Need to be spaced away from repeated sound to avoid changing the previous sound's pitch instead
|
||||
if (i+1 < pSentence->m_Words.Count() && pSentence->m_Words[i+1].pszWord == pSentence->m_Words[i].pszWord
|
||||
&& pSentence->m_Words[i + 1].nPitch != 100)
|
||||
duration += 0.1f;
|
||||
|
||||
event->SetType( CChoreoEvent::SPEAK );
|
||||
event->SetName( pszWord );
|
||||
event->SetParameters( pszWord );
|
||||
event->SetStartTime( flCurTime );
|
||||
event->SetUsingRelativeTag( false );
|
||||
event->SetEndTime( flCurTime + duration );
|
||||
event->SnapTimes();
|
||||
|
||||
//Msg( "%i %s: %f -> %f (%f)\n", i, pszWord, flCurTime, flCurTime + duration, duration );
|
||||
|
||||
// Add to channel
|
||||
channel->AddEvent( event );
|
||||
|
||||
// Point back to our owners
|
||||
event->SetChannel( channel );
|
||||
event->SetActor( actor );
|
||||
|
||||
flCurTime += duration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return scene;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -960,6 +1126,13 @@ void CSceneEntity::Activate()
|
||||
{
|
||||
if ( m_bGenerated && !m_pScene )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (m_bChoreoSentence)
|
||||
{
|
||||
m_pScene = GenerateSceneForSentenceName( m_hActor, STRING( m_iszSoundName ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
m_pScene = GenerateSceneForSound( m_hActor, STRING( m_iszSoundName ) );
|
||||
}
|
||||
|
||||
@ -1138,6 +1311,22 @@ void CSceneEntity::GenerateSoundScene( CBaseFlex *pActor, const char *soundname
|
||||
m_hActor = pActor;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pActor -
|
||||
// *pszSentenceName -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSceneEntity::GenerateChoreoSentenceScene( CBaseFlex *pActor, const char *pszSentenceName )
|
||||
{
|
||||
m_bGenerated = true;
|
||||
m_iszSoundName = MAKE_STRING( pszSentenceName );
|
||||
m_hActor = pActor;
|
||||
|
||||
m_bChoreoSentence = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
@ -1185,6 +1374,33 @@ bool CSceneEntity::IsPlayingSpeech( void )
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseFlex *CSceneEntity::GetLastSpeakingActor( void )
|
||||
{
|
||||
if ( m_pScene )
|
||||
{
|
||||
CChoreoActor *pLastActor = NULL;
|
||||
float flTime = m_pScene->GetTime();
|
||||
for ( int i = 0; i < m_pScene->GetNumEvents(); i++ )
|
||||
{
|
||||
CChoreoEvent *e = m_pScene->GetEvent( i );
|
||||
if ( e->GetType() == CChoreoEvent::SPEAK )
|
||||
{
|
||||
if ( flTime >= e->GetStartTime() )
|
||||
pLastActor = e->GetActor();
|
||||
}
|
||||
}
|
||||
|
||||
if (pLastActor)
|
||||
return FindNamedActor( pLastActor );
|
||||
}
|
||||
|
||||
// Fall back to the first actor
|
||||
return FindNamedActor( 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -1930,6 +2146,26 @@ void CSceneEntity::DispatchStartSpeak( CChoreoScene *scene, CBaseFlex *actor, CC
|
||||
|
||||
// Warning( "Speak %s\n", soundname );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( m_fPitch != 1.0f || event->GetPitch() != 0 )
|
||||
{
|
||||
if ( es.m_nPitch && es.m_nPitch != 100 )
|
||||
es.m_nPitch = static_cast<float>( es.m_nPitch ) * m_fPitch;
|
||||
else
|
||||
{
|
||||
float flPitch = (event->GetPitch() != 0 ? event->GetPitch() : 100.0f);
|
||||
es.m_nPitch = flPitch * m_fPitch;
|
||||
}
|
||||
|
||||
es.m_nFlags |= SND_CHANGE_PITCH;
|
||||
}
|
||||
|
||||
if ( event->GetYaw() != 0 )
|
||||
{
|
||||
es.m_flVolume = (((float)event->GetYaw()) / 100.0f);
|
||||
es.m_nFlags |= SND_CHANGE_VOL;
|
||||
}
|
||||
#else
|
||||
if ( m_fPitch != 1.0f )
|
||||
{
|
||||
if ( es.m_nPitch )
|
||||
@ -1939,6 +2175,7 @@ void CSceneEntity::DispatchStartSpeak( CChoreoScene *scene, CBaseFlex *actor, CC
|
||||
|
||||
es.m_nFlags |= SND_CHANGE_PITCH;
|
||||
}
|
||||
#endif
|
||||
|
||||
EmitSound( filter2, actor->entindex(), es );
|
||||
actor->AddSceneEvent( scene, event );
|
||||
@ -2468,6 +2705,39 @@ void CSceneEntity::InputInterjectResponse( inputdata_t &inputdata )
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSceneEntity::InputPauseAtLastInterrupt( inputdata_t &inputdata )
|
||||
{
|
||||
PausePlayback();
|
||||
m_bPausedViaInput = true;
|
||||
|
||||
if ( m_pScene )
|
||||
{
|
||||
float flLastInterrupt = 0.0f;
|
||||
float flTime = m_pScene->GetTime();
|
||||
for ( int i = 0; i < m_pScene->GetNumEvents(); i++ )
|
||||
{
|
||||
CChoreoEvent *e = m_pScene->GetEvent( i );
|
||||
if ( e->GetType() == CChoreoEvent::INTERRUPT )
|
||||
{
|
||||
if ( flTime > e->GetEndTime() && e->GetEndTime() > flLastInterrupt )
|
||||
{
|
||||
// Set the scene's time to the last interrupt point's end time
|
||||
flLastInterrupt = e->GetEndTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flLastInterrupt != 0.0f)
|
||||
{
|
||||
// Set the scene's time to the last interrupt point's end time
|
||||
m_pScene->SetTime( flLastInterrupt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSceneEntity::SetTarget( int nTarget, string_t pTargetName, CBaseEntity *pActivator, CBaseEntity *pCaller )
|
||||
@ -3096,13 +3366,22 @@ void CSceneEntity::QueueResumePlayback( void )
|
||||
// If it has ".vcd" somewhere in the string, try using it as a scene file first
|
||||
if ( Q_stristr( STRING(m_iszResumeSceneFile), ".vcd" ) )
|
||||
{
|
||||
bStartedScene = InstancedScriptedScene( NULL, STRING(m_iszResumeSceneFile), &m_hWaitingForThisResumeScene, 0, false ) != 0;
|
||||
#ifdef MAPBASE
|
||||
CBaseFlex *pActor = scene_resume_use_last_speaking.GetBool() ? GetLastSpeakingActor() : FindNamedActor( 0 );
|
||||
#else
|
||||
CBaseFlex *pActor = NULL;
|
||||
#endif
|
||||
bStartedScene = InstancedScriptedScene( pActor, STRING(m_iszResumeSceneFile), &m_hWaitingForThisResumeScene, 0, false ) != 0;
|
||||
}
|
||||
|
||||
// HACKHACK: For now, get the first target, and see if we can find a response for him
|
||||
if ( !bStartedScene )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
CBaseFlex *pActor = scene_resume_use_last_speaking.GetBool() ? GetLastSpeakingActor() : FindNamedActor( 0 );
|
||||
#else
|
||||
CBaseFlex *pActor = FindNamedActor( 0 );
|
||||
#endif
|
||||
if ( pActor )
|
||||
{
|
||||
CAI_BaseActor *pBaseActor = dynamic_cast<CAI_BaseActor*>(pActor);
|
||||
@ -3115,7 +3394,7 @@ void CSceneEntity::QueueResumePlayback( void )
|
||||
if ( result )
|
||||
{
|
||||
const char* szResponse = response.GetResponsePtr();
|
||||
bStartedScene = InstancedScriptedScene( NULL, szResponse, &m_hWaitingForThisResumeScene, 0, false ) != 0;
|
||||
bStartedScene = InstancedScriptedScene( pActor, szResponse, &m_hWaitingForThisResumeScene, 0, false ) != 0;
|
||||
}
|
||||
#else
|
||||
AI_Response *result = pBaseActor->SpeakFindResponse( STRING(m_iszResumeSceneFile), NULL );
|
||||
@ -5667,6 +5946,62 @@ void CInstancedSceneEntity::OnLoaded()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
float InstancedChoreoSentenceScene( CBaseFlex *pActor, const char *pszSentence, EHANDLE *phSceneEnt,
|
||||
float flPostDelay, bool bIsBackground, AI_Response *response,
|
||||
bool bMultiplayer, IRecipientFilter *filter /* = NULL */ )
|
||||
{
|
||||
if ( !pActor )
|
||||
{
|
||||
Warning( "InstancedChoreoSentenceScene: Expecting non-NULL pActor for sound %s\n", pszSentence );
|
||||
return 0;
|
||||
}
|
||||
|
||||
CInstancedSceneEntity *pScene = (CInstancedSceneEntity *)CBaseEntity::CreateNoSpawn( "instanced_scripted_scene", vec3_origin, vec3_angle );
|
||||
|
||||
Q_strncpy( pScene->m_szInstanceFilename, UTIL_VarArgs( "AutoGenerated(%s)", pszSentence ), sizeof( pScene->m_szInstanceFilename ) );
|
||||
pScene->m_iszSceneFile = MAKE_STRING( pScene->m_szInstanceFilename );
|
||||
|
||||
pScene->m_hOwner = pActor;
|
||||
pScene->m_bHadOwner = pActor != NULL;
|
||||
|
||||
pScene->GenerateChoreoSentenceScene( pActor, pszSentence );
|
||||
|
||||
pScene->m_bMultiplayer = bMultiplayer;
|
||||
pScene->SetPostSpeakDelay( flPostDelay );
|
||||
DispatchSpawn( pScene );
|
||||
pScene->Activate();
|
||||
pScene->m_bIsBackground = bIsBackground;
|
||||
|
||||
pScene->SetBackground( bIsBackground );
|
||||
pScene->SetRecipientFilter( filter );
|
||||
|
||||
if ( response )
|
||||
{
|
||||
float flPreDelay = response->GetPreDelay();
|
||||
if ( flPreDelay )
|
||||
{
|
||||
pScene->SetPreDelay( flPreDelay );
|
||||
}
|
||||
}
|
||||
|
||||
pScene->StartPlayback();
|
||||
|
||||
if ( response )
|
||||
{
|
||||
// If the response wants us to abort on NPC state switch, remember that
|
||||
pScene->SetBreakOnNonIdle( response->ShouldBreakOnNonIdle() );
|
||||
}
|
||||
|
||||
if ( phSceneEnt )
|
||||
{
|
||||
*phSceneEnt = pScene;
|
||||
}
|
||||
|
||||
return pScene->EstimateLength();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool g_bClientFlex = true;
|
||||
|
||||
LINK_ENTITY_TO_CLASS( scene_manager, CSceneManager );
|
||||
|
@ -28,6 +28,7 @@ int GetRecentNPCSpeech( recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ] );
|
||||
float InstancedScriptedScene( CBaseFlex *pActor, const char *pszScene, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL );
|
||||
#ifdef MAPBASE
|
||||
float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL );
|
||||
float InstancedChoreoSentenceScene( CBaseFlex *pActor, char const *pszSentence, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL );
|
||||
#else
|
||||
float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt = NULL );
|
||||
#endif
|
||||
|
@ -46,8 +46,12 @@ $Project
|
||||
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\matchers.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\matchers.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\mapbase_playeranimstate.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\mapbase_playeranimstate.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\game_timer.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\game_timer.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT]
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT]
|
||||
@ -63,6 +67,8 @@ $Project
|
||||
$File "mapbase\ai_grenade.h"
|
||||
$File "mapbase\ai_monitor.cpp"
|
||||
$File "mapbase\ai_weaponmodifier.cpp"
|
||||
$File "mapbase\choreosentence.cpp"
|
||||
$File "mapbase\choreosentence.h"
|
||||
$File "mapbase\custom_weapon_factory.cpp"
|
||||
$File "mapbase\custom_weapon_factory.h"
|
||||
$File "mapbase\closecaption_entity.cpp"
|
||||
|
@ -66,6 +66,7 @@ BEGIN_SCRIPTDESC_ROOT( CSound, "A sound NPCs can hear." )
|
||||
DEFINE_SCRIPTFUNC( ValidateOwner, "Returns true if the sound's owner is still valid or if the sound never had an owner in the first place." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetOwner, "GetOwner", "Gets the sound's owner." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetTarget, "GetTarget", "Gets the sound's target." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFreeSound, "FreeSound", "Frees the sound from the sound list." )
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
|
@ -140,6 +140,8 @@ public:
|
||||
// For VScript functions
|
||||
HSCRIPT ScriptGetOwner() const { return ToHScript( m_hOwner ); }
|
||||
HSCRIPT ScriptGetTarget() const { return ToHScript( m_hTarget ); }
|
||||
|
||||
void ScriptFreeSound() { m_flExpireTime = gpGlobals->curtime; m_bNoExpirationTime = false; }
|
||||
#endif
|
||||
|
||||
EHANDLE m_hOwner; // sound's owner
|
||||
|
@ -22,6 +22,10 @@
|
||||
|
||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
ConVar script_connect_debugger_on_mapspawn( "script_connect_debugger_on_mapspawn", "0" );
|
||||
#endif
|
||||
|
||||
// #define VMPROFILE 1
|
||||
|
||||
#ifdef VMPROFILE
|
||||
@ -663,6 +667,17 @@ bool VScriptServerInit()
|
||||
RegisterSharedScriptFunctions();
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if ( script_connect_debugger_on_mapspawn.GetInt() == 2 )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port, 10.0f );
|
||||
}
|
||||
else if ( script_connect_debugger_on_mapspawn.GetInt() != 0 )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||
}
|
||||
#endif
|
||||
|
||||
if (scriptLanguage == SL_SQUIRREL)
|
||||
{
|
||||
g_pScriptVM->Run( g_Script_vscript_server );
|
||||
|
@ -72,16 +72,16 @@ function ImpulseScale( flTargetMass, flDesiredSpeed )
|
||||
}
|
||||
__Documentation.RegisterHelp( "ImpulseScale", "float ImpulseScale(float, float)", "Returns an impulse scale required to push an object." );
|
||||
|
||||
local PrecacheModel = PrecacheModel
|
||||
local PrecacheModel = DoPrecacheModel
|
||||
function PrecacheModel( a, b = true )
|
||||
{
|
||||
return PrecacheModel( a, b )
|
||||
}
|
||||
|
||||
local PrecacheOther = PrecacheOther
|
||||
local PrecacheOther = DoPrecacheOther
|
||||
function PrecacheOther( a, b = "" )
|
||||
{
|
||||
PrecacheOther( a, b )
|
||||
return PrecacheOther( a, b )
|
||||
}
|
||||
|
||||
function __ReplaceClosures( script, scope )
|
||||
@ -106,10 +106,9 @@ function __ReplaceClosures( script, scope )
|
||||
}
|
||||
}
|
||||
|
||||
local __OutputsPattern = regexp("^On.*Output$");
|
||||
|
||||
function ConnectOutputs( table )
|
||||
{
|
||||
local __OutputsPattern = regexp("^On.*Output$");
|
||||
local nCharsToStrip = 6;
|
||||
foreach( key, val in table )
|
||||
{
|
||||
|
@ -2694,6 +2694,18 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_PISTOL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SHOTGUN );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_PHYSGUN );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_GRENADE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_RPG );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_MELEE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SLAM );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_RUN_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_REVOLVER );
|
||||
@ -2702,6 +2714,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_REVOLVER );
|
||||
|
||||
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
|
||||
@ -2713,6 +2726,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_AR1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_AR1 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_AR3 );
|
||||
@ -2723,6 +2737,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_AR3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_AR3 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SMG2 );
|
||||
@ -2733,6 +2748,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SMG2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SMG2 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SMG3 );
|
||||
@ -2743,6 +2759,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SMG3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SMG3 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_HMG1 );
|
||||
@ -2753,6 +2770,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_HMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_HMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_HMG1 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SNIPER_RIFLE );
|
||||
@ -2763,6 +2781,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SNIPER_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SNIPER_RIFLE );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_DUAL_PISTOLS );
|
||||
@ -2773,6 +2792,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_DUAL_PISTOLS );
|
||||
#endif
|
||||
|
||||
|
@ -2598,6 +2598,18 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM,
|
||||
|
||||
ACT_HL2MP_GESTURE_RELAX,
|
||||
ACT_HL2MP_GESTURE_RELAX_PISTOL,
|
||||
ACT_HL2MP_GESTURE_RELAX_SHOTGUN,
|
||||
ACT_HL2MP_GESTURE_RELAX_SMG1,
|
||||
ACT_HL2MP_GESTURE_RELAX_AR2,
|
||||
ACT_HL2MP_GESTURE_RELAX_PHYSGUN,
|
||||
ACT_HL2MP_GESTURE_RELAX_GRENADE,
|
||||
ACT_HL2MP_GESTURE_RELAX_RPG,
|
||||
ACT_HL2MP_GESTURE_RELAX_CROSSBOW,
|
||||
ACT_HL2MP_GESTURE_RELAX_MELEE,
|
||||
ACT_HL2MP_GESTURE_RELAX_SLAM,
|
||||
|
||||
ACT_HL2MP_IDLE_REVOLVER,
|
||||
ACT_HL2MP_RUN_REVOLVER,
|
||||
ACT_HL2MP_WALK_REVOLVER,
|
||||
@ -2606,6 +2618,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER,
|
||||
ACT_HL2MP_GESTURE_RELOAD_REVOLVER,
|
||||
ACT_HL2MP_GESTURE_RELAX_REVOLVER,
|
||||
ACT_HL2MP_JUMP_REVOLVER,
|
||||
|
||||
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
|
||||
@ -2618,6 +2631,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1,
|
||||
ACT_HL2MP_GESTURE_RELOAD_AR1,
|
||||
ACT_HL2MP_GESTURE_RELAX_AR1,
|
||||
ACT_HL2MP_JUMP_AR1,
|
||||
|
||||
ACT_HL2MP_IDLE_AR3,
|
||||
@ -2628,6 +2642,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3,
|
||||
ACT_HL2MP_GESTURE_RELOAD_AR3,
|
||||
ACT_HL2MP_GESTURE_RELAX_AR3,
|
||||
ACT_HL2MP_JUMP_AR3,
|
||||
|
||||
ACT_HL2MP_IDLE_SMG2,
|
||||
@ -2638,6 +2653,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2,
|
||||
ACT_HL2MP_GESTURE_RELOAD_SMG2,
|
||||
ACT_HL2MP_GESTURE_RELAX_SMG2,
|
||||
ACT_HL2MP_JUMP_SMG2,
|
||||
|
||||
ACT_HL2MP_IDLE_SMG3,
|
||||
@ -2648,6 +2664,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3,
|
||||
ACT_HL2MP_GESTURE_RELOAD_SMG3,
|
||||
ACT_HL2MP_GESTURE_RELAX_SMG3,
|
||||
ACT_HL2MP_JUMP_SMG3,
|
||||
|
||||
ACT_HL2MP_IDLE_HMG1,
|
||||
@ -2658,6 +2675,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1,
|
||||
ACT_HL2MP_GESTURE_RELOAD_HMG1,
|
||||
ACT_HL2MP_GESTURE_RELAX_HMG1,
|
||||
ACT_HL2MP_JUMP_HMG1,
|
||||
|
||||
ACT_HL2MP_IDLE_SNIPER_RIFLE,
|
||||
@ -2668,6 +2686,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE,
|
||||
ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE,
|
||||
ACT_HL2MP_GESTURE_RELAX_SNIPER_RIFLE,
|
||||
ACT_HL2MP_JUMP_SNIPER_RIFLE,
|
||||
|
||||
ACT_HL2MP_IDLE_DUAL_PISTOLS,
|
||||
@ -2678,6 +2697,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS,
|
||||
ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS,
|
||||
ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS,
|
||||
ACT_HL2MP_JUMP_DUAL_PISTOLS,
|
||||
#endif
|
||||
|
||||
|
@ -31,6 +31,9 @@
|
||||
|
||||
#ifdef GAME_DLL
|
||||
#include "sceneentity.h"
|
||||
#ifdef MAPBASE
|
||||
#include "mapbase/choreosentence.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "networkstringtabledefs.h"
|
||||
@ -492,6 +495,17 @@ void CGameResponseSystem::Precache()
|
||||
CBaseEntity::PrecacheScriptSound( response.value );
|
||||
}
|
||||
break;
|
||||
#ifdef MAPBASE
|
||||
case RESPONSE_CHOREOSENTENCE:
|
||||
{
|
||||
const ChoreoSentence_t *pSentence = LookupChoreoSentence( NULL, response.value );
|
||||
if (pSentence)
|
||||
PrecacheChoreoSentence( *pSentence );
|
||||
else
|
||||
Msg( "Choreo scene '%s' not found\n", response.value );
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,12 @@
|
||||
#include "c_baseplayer.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
|
||||
ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (client) animation state for the specified entity (-1 for none)." );
|
||||
ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." );
|
||||
ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "Show the (client) animation state for the specified entity (-1 for none)." );
|
||||
ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." );
|
||||
#else
|
||||
#include "player.h"
|
||||
ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (server) animation state for the specified entity (-1 for none)." );
|
||||
ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." );
|
||||
ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "Show the (server) animation state for the specified entity (-1 for none)." );
|
||||
ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." );
|
||||
#endif
|
||||
|
||||
|
||||
@ -654,9 +654,11 @@ void CBasePlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr )
|
||||
|
||||
if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY )
|
||||
{
|
||||
#ifndef MAPBASE // This causes problems with entities that rely on the player having a pitch (TODO: gate behind virtual function?)
|
||||
#ifndef CLIENT_DLL
|
||||
//Adrian: Make the model's angle match the legs so the hitboxes match on both sides.
|
||||
GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int iMoveX = GetOuter()->LookupPoseParameter( pStudioHdr, "move_x" );
|
||||
@ -942,6 +944,15 @@ void CBasePlayerAnimState::GetOuterAbsVelocity( Vector& vel ) const
|
||||
#else
|
||||
vel = GetOuter()->GetAbsVelocity();
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (GetOuter()->IsPlayer())
|
||||
{
|
||||
CBasePlayer *pPlayer = ToBasePlayer( GetOuter() );
|
||||
if (pPlayer->GetLaggedMovementValue() != 1.0f)
|
||||
vel *= pPlayer->GetLaggedMovementValue();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1024,9 +1035,15 @@ void CBasePlayerAnimState::DebugShowAnimState( int iStartLine )
|
||||
(float)pLayer->m_flWeight );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
|
||||
{
|
||||
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( i );
|
||||
#else
|
||||
for ( int i=0; i < m_pOuter->GetNumAnimOverlays()-1; i++ )
|
||||
{
|
||||
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( AIMSEQUENCE_LAYER + i );
|
||||
#endif
|
||||
#ifdef CLIENT_DLL
|
||||
AnimStatePrintf( iLine++, "%s(%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)",
|
||||
!pLayer->IsActive() ? "-- ": (pLayer->m_nSequence == 0 ? "-- " : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ) ),
|
||||
|
@ -507,6 +507,11 @@ bool CBaseCombatWeapon::UsesHands() const
|
||||
{
|
||||
return GetWpnData().m_bUsesHands;
|
||||
}
|
||||
|
||||
int CBaseCombatWeapon::GetHandRig() const
|
||||
{
|
||||
return GetWpnData().m_nHandRig;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1127,7 +1132,7 @@ WeaponClass_t CBaseCombatWeapon::WeaponClassFromString(const char *str)
|
||||
return WEPCLASS_RIFLE;
|
||||
else if (FStrEq(str, "WEPCLASS_SHOTGUN"))
|
||||
return WEPCLASS_SHOTGUN;
|
||||
else if (FStrEq(str, "WEPCLASS_HEAY"))
|
||||
else if (FStrEq(str, "WEPCLASS_HEAVY"))
|
||||
return WEPCLASS_HEAVY;
|
||||
|
||||
else if (FStrEq(str, "WEPCLASS_MELEE"))
|
||||
@ -3127,6 +3132,9 @@ BEGIN_ENT_SCRIPTDESC( CBaseCombatWeapon, CBaseAnimating, "The base class for all
|
||||
DEFINE_SCRIPTFUNC( GetViewModel, "Get the weapon's view model." )
|
||||
DEFINE_SCRIPTFUNC( GetDroppedModel, "Get the weapon's unique dropped model if it has one." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( UsesHands, "" )
|
||||
DEFINE_SCRIPTFUNC( GetHandRig, "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetWeight, "Get the weapon's weight." )
|
||||
DEFINE_SCRIPTFUNC( GetPrintName, "" )
|
||||
|
||||
|
@ -307,6 +307,10 @@ public:
|
||||
virtual bool ShouldBlockPrimaryFire() { return false; }
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#ifdef MAPBASE
|
||||
virtual bool DispatchMuzzleEffect( const char *options, bool isFirstPerson );
|
||||
#endif
|
||||
|
||||
virtual void CreateMove( float flInputSampleTime, CUserCmd *pCmd, const QAngle &vecOldViewAngles ) {}
|
||||
virtual int CalcOverrideModelIndex() OVERRIDE;
|
||||
#endif
|
||||
@ -419,12 +423,13 @@ public:
|
||||
virtual bool UsesClipsForAmmo2( void ) const;
|
||||
bool IsMeleeWeapon() const;
|
||||
#ifdef MAPBASE
|
||||
float GetViewmodelFOVOverride() const;
|
||||
virtual float GetViewmodelFOVOverride() const;
|
||||
float GetBobScale() const;
|
||||
float GetSwayScale() const;
|
||||
float GetSwaySpeedScale() const;
|
||||
virtual const char *GetDroppedModel( void ) const;
|
||||
bool UsesHands( void ) const;
|
||||
virtual bool UsesHands( void ) const;
|
||||
virtual int GetHandRig( void ) const;
|
||||
#endif
|
||||
|
||||
// derive this function if you mod uses encrypted weapon info files
|
||||
|
@ -3033,7 +3033,7 @@ void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, f
|
||||
|
||||
float nextthink = gpGlobals->curtime + flTime;
|
||||
|
||||
pf->m_hfnThink = hFunc;
|
||||
pf->m_hfnThink = g_pScriptVM->CopyObject( hFunc );
|
||||
pf->m_flNextThink = nextthink;
|
||||
|
||||
#ifdef GAME_DLL
|
||||
|
@ -255,7 +255,7 @@ inline HSCRIPT ToHScript(CBaseEntity* pEnt)
|
||||
return (pEnt) ? pEnt->GetScriptInstance() : NULL;
|
||||
}
|
||||
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*);
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*, bool);
|
||||
inline CBaseEntity* ToEnt(HSCRIPT hScript)
|
||||
{
|
||||
return (hScript) ? (CBaseEntity*)g_pScriptVM->GetInstanceValue(hScript, GetScriptDescForClass(CBaseEntity)) : NULL;
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include "player_resource.h"
|
||||
#include "tactical_mission.h"
|
||||
#include "gamestats.h"
|
||||
#ifdef MAPBASE
|
||||
#include "maprules.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -619,6 +622,27 @@ bool CGameRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args )
|
||||
{
|
||||
if( GetVoiceGameMgr()->ClientCommand( static_cast<CBasePlayer*>(pEdict), args ) )
|
||||
return true;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( FStrEq( args[0], "menuselect" ) )
|
||||
{
|
||||
if ( args.ArgC() >= 2 )
|
||||
{
|
||||
int slot = atoi( args[1] );
|
||||
|
||||
// See if this is from a game_menu
|
||||
for ( int i = 0; i < IGameMenuAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
CGameMenu *pMenu = static_cast<CGameMenu*>( IGameMenuAutoList::AutoList()[i] );
|
||||
if ( pMenu->IsActiveOnTarget( pEdict ) )
|
||||
{
|
||||
pMenu->MenuSelected( slot, pEdict );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -6,6 +6,9 @@
|
||||
|
||||
#include "cbase.h"
|
||||
#include "basehlcombatweapon_shared.h"
|
||||
#ifdef MAPBASE
|
||||
#include "mapbase/protagonist_system.h"
|
||||
#endif
|
||||
|
||||
#include "hl2_player_shared.h"
|
||||
|
||||
@ -436,4 +439,66 @@ const WeaponProficiencyInfo_t *CBaseHLCombatWeapon::GetDefaultProficiencyValues(
|
||||
return g_BaseWeaponProficiencyTable;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CBaseHLCombatWeapon::GetViewModel( int viewmodelindex ) const
|
||||
{
|
||||
if (GetOwner() && GetOwner()->IsPlayer() && viewmodelindex == 0)
|
||||
{
|
||||
const char *pszProtagVM = g_ProtagonistSystem.GetProtagonist_ViewModel( static_cast<CBasePlayer *>(GetOwner()), this );
|
||||
if (pszProtagVM)
|
||||
return pszProtagVM;
|
||||
}
|
||||
|
||||
return BaseClass::GetViewModel( viewmodelindex );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CBaseHLCombatWeapon::GetViewmodelFOVOverride() const
|
||||
{
|
||||
if (GetOwner() && GetOwner()->IsPlayer())
|
||||
{
|
||||
float *flVMFOV = g_ProtagonistSystem.GetProtagonist_ViewModelFOV( static_cast<CBasePlayer *>(GetOwner()), this );
|
||||
if (flVMFOV)
|
||||
return *flVMFOV;
|
||||
}
|
||||
|
||||
return BaseClass::GetViewmodelFOVOverride();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseHLCombatWeapon::UsesHands() const
|
||||
{
|
||||
if (GetOwner() && GetOwner()->IsPlayer())
|
||||
{
|
||||
bool *bProtagUsesHands = g_ProtagonistSystem.GetProtagonist_UsesHands( static_cast<CBasePlayer *>(GetOwner()), this );
|
||||
if (bProtagUsesHands)
|
||||
return *bProtagUsesHands;
|
||||
}
|
||||
|
||||
return BaseClass::UsesHands();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CBaseHLCombatWeapon::GetHandRig() const
|
||||
{
|
||||
if (GetOwner() && GetOwner()->IsPlayer())
|
||||
{
|
||||
int *nProtagHandRig = g_ProtagonistSystem.GetProtagonist_HandRig( static_cast<CBasePlayer *>(GetOwner()), this );
|
||||
if (nProtagHandRig)
|
||||
return *nProtagHandRig;
|
||||
}
|
||||
|
||||
return BaseClass::GetHandRig();
|
||||
}
|
||||
#endif
|
||||
|
@ -53,6 +53,13 @@ public:
|
||||
|
||||
virtual void ItemHolsterFrame( void );
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual const char *GetViewModel( int viewmodelindex = 0 ) const;
|
||||
virtual float GetViewmodelFOVOverride() const;
|
||||
virtual bool UsesHands( void ) const;
|
||||
virtual int GetHandRig( void ) const;
|
||||
#endif
|
||||
|
||||
int m_iPrimaryAttacks; // # of primary attacks performed with this weapon
|
||||
int m_iSecondaryAttacks; // # of secondary attacks performed with this weapon
|
||||
|
||||
|
658
sp/src/game/shared/mapbase/game_timer.cpp
Normal file
658
sp/src/game/shared/mapbase/game_timer.cpp
Normal file
@ -0,0 +1,658 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: Generic custom timer entity
|
||||
//
|
||||
// Author: Blixibon
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "game_timer.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern bool IsInCommentaryMode( void );
|
||||
|
||||
ConVar sv_game_menu_default_warn_frac( "sv_game_menu_default_warn_frac", "0.25", FCVAR_REPLICATED );
|
||||
|
||||
LINK_ENTITY_TO_CLASS( game_timer, CGameTimer );
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( GameTimer, DT_GameTimer )
|
||||
|
||||
BEGIN_NETWORK_TABLE_NOBASE( CGameTimer, DT_GameTimer )
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
RecvPropBool( RECVINFO( m_bTimerPaused ) ),
|
||||
RecvPropTime( RECVINFO( m_flTimerInitialLength ) ),
|
||||
RecvPropTime( RECVINFO( m_flTimerMaxLength ) ),
|
||||
RecvPropTime( RECVINFO( m_flTimeRemaining ) ),
|
||||
RecvPropTime( RECVINFO( m_flTimerEndTime ) ),
|
||||
RecvPropTime( RECVINFO( m_flWarnTime ) ),
|
||||
RecvPropBool( RECVINFO( m_bIsDisabled ) ),
|
||||
RecvPropBool( RECVINFO( m_bStartPaused ) ),
|
||||
RecvPropBool( RECVINFO( m_bShowTimeRemaining ) ),
|
||||
RecvPropInt( RECVINFO( m_nProgressBarMaxSegments ) ),
|
||||
RecvPropInt( RECVINFO( m_nProgressBarOverride ) ),
|
||||
RecvPropFloat( RECVINFO( m_flOverrideX ) ),
|
||||
RecvPropFloat( RECVINFO( m_flOverrideY ) ),
|
||||
RecvPropString( RECVINFO( m_szTimerCaption ) ),
|
||||
|
||||
RecvPropInt( RECVINFO( m_iTeamNum ) ),
|
||||
|
||||
#else
|
||||
|
||||
SendPropBool( SENDINFO( m_bTimerPaused ) ),
|
||||
SendPropTime( SENDINFO( m_flTimerInitialLength ) ),
|
||||
SendPropTime( SENDINFO( m_flTimerMaxLength ) ),
|
||||
SendPropTime( SENDINFO( m_flTimeRemaining ) ),
|
||||
SendPropTime( SENDINFO( m_flTimerEndTime ) ),
|
||||
SendPropTime( SENDINFO( m_flWarnTime ) ),
|
||||
SendPropBool( SENDINFO( m_bIsDisabled ) ),
|
||||
SendPropBool( SENDINFO( m_bStartPaused ) ),
|
||||
SendPropBool( SENDINFO( m_bShowTimeRemaining ) ),
|
||||
SendPropInt( SENDINFO( m_nProgressBarMaxSegments ) ),
|
||||
SendPropInt( SENDINFO( m_nProgressBarOverride ) ),
|
||||
SendPropFloat( SENDINFO( m_flOverrideX ) ),
|
||||
SendPropFloat( SENDINFO( m_flOverrideY ) ),
|
||||
SendPropString( SENDINFO( m_szTimerCaption ) ),
|
||||
|
||||
SendPropInt( SENDINFO( m_iTeamNum ), TEAMNUM_NUM_BITS, 0 ),
|
||||
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
BEGIN_DATADESC( CGameTimer )
|
||||
|
||||
DEFINE_KEYFIELD( m_flTimerInitialLength, FIELD_FLOAT, "timer_length" ),
|
||||
DEFINE_KEYFIELD( m_flTimerMaxLength, FIELD_FLOAT, "max_length" ),
|
||||
DEFINE_KEYFIELD( m_flWarnTime, FIELD_FLOAT, "warn_time" ),
|
||||
DEFINE_KEYFIELD( m_bIsDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
||||
DEFINE_KEYFIELD( m_bStartPaused, FIELD_BOOLEAN, "start_paused" ),
|
||||
DEFINE_KEYFIELD( m_bShowTimeRemaining, FIELD_BOOLEAN, "show_time_remaining" ),
|
||||
DEFINE_KEYFIELD( m_bDisableOnFinish, FIELD_BOOLEAN, "disable_on_finish" ),
|
||||
DEFINE_KEYFIELD( m_bShowInHUD, FIELD_BOOLEAN, "show_in_hud" ),
|
||||
DEFINE_KEYFIELD( m_nProgressBarMaxSegments, FIELD_INTEGER, "progress_bar_max" ),
|
||||
DEFINE_KEYFIELD( m_nProgressBarOverride, FIELD_INTEGER, "progress_bar_override" ),
|
||||
DEFINE_KEYFIELD( m_flOverrideX, FIELD_FLOAT, "x" ),
|
||||
DEFINE_KEYFIELD( m_flOverrideY, FIELD_FLOAT, "y" ),
|
||||
DEFINE_AUTO_ARRAY( m_szTimerCaption, FIELD_CHARACTER ),
|
||||
DEFINE_KEYFIELD( m_iszPlayerFilterName, FIELD_STRING, "PlayerFilter" ),
|
||||
DEFINE_FIELD( m_hPlayerFilter, FIELD_EHANDLE ),
|
||||
|
||||
DEFINE_FIELD( m_flTimerEndTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_flTimeRemaining, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_bTimerPaused, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_bStartedWarn, FIELD_BOOLEAN ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Pause", InputPause ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Resume", InputResume ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTime", InputSetTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "AddTime", InputAddTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "RemoveTime", InputRemoveTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Restart", InputRestart ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMaxTime", InputSetMaxTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTimerCaption", InputSetTimerCaption ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetProgressBarMaxSegments", InputSetProgressBarMaxSegments ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetProgressBarOverride", InputSetProgressBarOverride ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetX", InputSetX ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetY", InputSetY ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "GetTimeRemaining", InputGetTimeRemaining ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetPlayerFilter", InputSetPlayerFilter ),
|
||||
|
||||
DEFINE_OUTPUT( m_OnFinished, "OnFinished" ),
|
||||
DEFINE_OUTPUT( m_OnPaused, "OnPaused" ),
|
||||
DEFINE_OUTPUT( m_OnResumed, "OnResumed" ),
|
||||
DEFINE_OUTPUT( m_OnWarned, "OnWarned" ),
|
||||
DEFINE_OUTPUT( m_OnTick, "OnTick" ),
|
||||
DEFINE_OUTPUT( m_OnGetTimeRemaining, "OnGetTimeRemaining" ),
|
||||
|
||||
DEFINE_THINKFUNC( TimerThink ),
|
||||
|
||||
END_DATADESC();
|
||||
#endif
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
IMPLEMENT_AUTO_LIST( IGameTimerAutoList );
|
||||
#else
|
||||
#define TIMER_THINK "GameTimerThink"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CGameTimer::CGameTimer( void )
|
||||
{
|
||||
m_bIsDisabled = true;
|
||||
m_bTimerPaused = true;
|
||||
m_flTimeRemaining = 0;
|
||||
m_flTimerEndTime = 0;
|
||||
m_flWarnTime = -1.0f;
|
||||
m_bStartPaused = false;
|
||||
m_bShowTimeRemaining = true;
|
||||
m_flTimerInitialLength = 0;
|
||||
m_flTimerMaxLength = 0;
|
||||
m_nProgressBarMaxSegments = -1;
|
||||
m_nProgressBarOverride = -1;
|
||||
m_flOverrideX = m_flOverrideY = -1.0f;
|
||||
#ifndef CLIENT_DLL
|
||||
m_bDisableOnFinish = true;
|
||||
m_bShowInHUD = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CGameTimer::~CGameTimer( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::Spawn( void )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
if ( IsDisabled() ) // we need to get the data initialized before actually become disabled
|
||||
{
|
||||
m_bIsDisabled = false;
|
||||
SetTimeRemaining( m_flTimerInitialLength );
|
||||
m_bIsDisabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTimeRemaining( m_flTimerInitialLength );
|
||||
if ( !m_bStartPaused )
|
||||
ResumeTimer();
|
||||
}
|
||||
|
||||
if ( m_iszPlayerFilterName != NULL_STRING )
|
||||
{
|
||||
m_hPlayerFilter = dynamic_cast<CBaseFilter *>(gEntList.FindEntityByName( NULL, m_iszPlayerFilterName, this ));
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
||||
bool CGameTimer::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "timer_caption" ) )
|
||||
{
|
||||
Q_strncpy( m_szTimerCaption.GetForModify(), szValue, MAX_GAME_TIMER_CAPTION );
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameTimer::GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "timer_caption" ) )
|
||||
{
|
||||
Q_snprintf( szValue, iMaxLen, "%s", m_szTimerCaption.Get() );
|
||||
return true;
|
||||
}
|
||||
return BaseClass::GetKeyValue( szKeyName, szValue, iMaxLen );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets the seconds left on the timer, paused or not.
|
||||
//-----------------------------------------------------------------------------
|
||||
float CGameTimer::GetTimeRemaining( void )
|
||||
{
|
||||
float flSecondsRemaining;
|
||||
|
||||
if ( m_bTimerPaused )
|
||||
{
|
||||
flSecondsRemaining = m_flTimeRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
flSecondsRemaining = m_flTimerEndTime - gpGlobals->curtime;
|
||||
}
|
||||
|
||||
if ( flSecondsRemaining < 0 )
|
||||
{
|
||||
flSecondsRemaining = 0.0f;
|
||||
}
|
||||
|
||||
return flSecondsRemaining;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets the timer's warning time
|
||||
//-----------------------------------------------------------------------------
|
||||
float CGameTimer::GetWarnTime( void )
|
||||
{
|
||||
if ( m_flWarnTime < 0 )
|
||||
{
|
||||
// TODO: All of the default warning stuff is on the client!!!
|
||||
return GetTimerMaxLength() * sv_game_menu_default_warn_frac.GetFloat();
|
||||
}
|
||||
|
||||
return m_flWarnTime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CGameTimer::GetTimerMaxLength( void )
|
||||
{
|
||||
if ( m_flTimerMaxLength )
|
||||
return m_flTimerMaxLength;
|
||||
|
||||
return m_flTimerInitialLength;
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
bool g_bAnyGameTimerActive = false;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_GameTimer::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( !m_bIsDisabled )
|
||||
{
|
||||
g_bAnyGameTimerActive = true;
|
||||
}
|
||||
else if ( !m_bOldDisabled )
|
||||
{
|
||||
// Go through all of the timers and mark when one is active
|
||||
g_bAnyGameTimerActive = false;
|
||||
for ( int i = 0; i < IGameTimerAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
C_GameTimer *pTimer = static_cast<C_GameTimer *>( IGameTimerAutoList::AutoList()[i] );
|
||||
if ( !pTimer->IsDisabled() && !pTimer->IsMarkedForDeletion() )
|
||||
{
|
||||
g_bAnyGameTimerActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bOldDisabled = m_bIsDisabled;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_GameTimer::UpdateOnRemove( void )
|
||||
{
|
||||
BaseClass::UpdateOnRemove();
|
||||
|
||||
// Update timer presence state
|
||||
g_bAnyGameTimerActive = false;
|
||||
for ( int i = 0; i < IGameTimerAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
C_GameTimer *pTimer = static_cast<C_GameTimer *>( IGameTimerAutoList::AutoList()[i] );
|
||||
if ( pTimer != this && !pTimer->IsDisabled() && !pTimer->IsMarkedForDeletion() )
|
||||
{
|
||||
g_bAnyGameTimerActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::TimerThink( void )
|
||||
{
|
||||
if ( IsDisabled() /*|| IsInCommentaryMode() || gpGlobals->eLoadType == MapLoad_Background*/ )
|
||||
{
|
||||
SetContextThink( &CGameTimer::TimerThink, gpGlobals->curtime + 0.05, TIMER_THINK );
|
||||
return;
|
||||
}
|
||||
|
||||
float flTime = GetTimeRemaining();
|
||||
|
||||
int nTick = (int)floorf( flTime );
|
||||
if (nTick != m_OnTick.Get())
|
||||
{
|
||||
m_OnTick.Set( nTick, this, this );
|
||||
}
|
||||
|
||||
if ( flTime <= 0.0f )
|
||||
{
|
||||
OnTimerFinished();
|
||||
PauseTimer();
|
||||
if (m_bDisableOnFinish)
|
||||
m_bIsDisabled = true;
|
||||
return;
|
||||
}
|
||||
else if ( flTime <= GetWarnTime() && !m_bStartedWarn)
|
||||
{
|
||||
OnTimerWarned();
|
||||
m_bStartedWarn = true;
|
||||
}
|
||||
|
||||
SetContextThink( &CGameTimer::TimerThink, gpGlobals->curtime + 0.05, TIMER_THINK );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: To set the initial timer duration
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::SetTimeRemaining( float flTime )
|
||||
{
|
||||
// make sure we don't go over our max length
|
||||
flTime = m_flTimerMaxLength > 0 ? MIN( flTime, m_flTimerMaxLength ) : flTime;
|
||||
|
||||
m_flTimeRemaining = flTime;
|
||||
m_flTimerEndTime = gpGlobals->curtime + m_flTimeRemaining;
|
||||
|
||||
if ( m_flTimeRemaining > m_flWarnTime )
|
||||
{
|
||||
m_bStartedWarn = false;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::OnTimerFinished()
|
||||
{
|
||||
m_OnFinished.FireOutput( this, this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::OnTimerWarned()
|
||||
{
|
||||
m_OnWarned.FireOutput( this, this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Timer is paused at round end, stops the countdown
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::PauseTimer( CBaseEntity *pActivator )
|
||||
{
|
||||
if ( IsDisabled() )
|
||||
return;
|
||||
|
||||
if ( m_bTimerPaused == false )
|
||||
{
|
||||
m_bTimerPaused = true;
|
||||
m_flTimeRemaining = m_flTimerEndTime - gpGlobals->curtime;
|
||||
|
||||
m_OnPaused.FireOutput( pActivator ? pActivator : this, this );
|
||||
|
||||
SetContextThink( NULL, TICK_NEVER_THINK, TIMER_THINK );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: To start or re-start the timer after a pause
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::ResumeTimer( CBaseEntity *pActivator )
|
||||
{
|
||||
if ( IsDisabled() )
|
||||
return;
|
||||
|
||||
if ( m_bTimerPaused == true )
|
||||
{
|
||||
m_bTimerPaused = false;
|
||||
m_flTimerEndTime = gpGlobals->curtime + m_flTimeRemaining;
|
||||
|
||||
m_OnResumed.FireOutput( pActivator ? pActivator : this, this );
|
||||
|
||||
TimerThink();
|
||||
|
||||
SetContextThink( &CGameTimer::TimerThink, gpGlobals->curtime + 0.05, TIMER_THINK );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Add seconds to the timer while it is running or paused
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::AddTimerSeconds( float flTimeToAdd )
|
||||
{
|
||||
if ( IsDisabled() )
|
||||
return;
|
||||
|
||||
if ( m_flTimerMaxLength > 0 )
|
||||
{
|
||||
// will adding this many seconds push us over our max length?
|
||||
if ( GetTimeRemaining() + flTimeToAdd > m_flTimerMaxLength)
|
||||
{
|
||||
// adjust to only add up to our max length
|
||||
flTimeToAdd = m_flTimerMaxLength - GetTimeRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_bTimerPaused )
|
||||
{
|
||||
m_flTimeRemaining += flTimeToAdd;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flTimerEndTime += flTimeToAdd;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Should we transmit it to the client?
|
||||
//-----------------------------------------------------------------------------
|
||||
int CGameTimer::UpdateTransmitState()
|
||||
{
|
||||
if ( !m_bShowInHUD )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_DONTSEND );
|
||||
}
|
||||
|
||||
if ( m_hPlayerFilter || GetTeamNumber() > TEAM_UNASSIGNED )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_FULLCHECK );
|
||||
}
|
||||
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Which clients should we be transmitting to?
|
||||
//-----------------------------------------------------------------------------
|
||||
int CGameTimer::ShouldTransmit( const CCheckTransmitInfo *pInfo )
|
||||
{
|
||||
int result = BaseClass::ShouldTransmit( pInfo );
|
||||
|
||||
if ( result != FL_EDICT_DONTSEND )
|
||||
{
|
||||
CBaseEntity *pClient = (CBaseEntity *)(pInfo->m_pClientEnt->GetUnknown());
|
||||
if ( pClient )
|
||||
{
|
||||
if ( m_hPlayerFilter )
|
||||
{
|
||||
// Don't send to players who don't pass our filter
|
||||
if ( !m_hPlayerFilter->PassesFilter( this, pClient ) )
|
||||
return FL_EDICT_DONTSEND;
|
||||
}
|
||||
else if ( GetTeamNumber() > TEAM_UNASSIGNED )
|
||||
{
|
||||
// If we don't have an explicit filter, then just check if it's on the same team as us
|
||||
if ( pClient->GetTeamNumber() != GetTeamNumber() )
|
||||
return FL_EDICT_DONTSEND;
|
||||
}
|
||||
|
||||
return FL_EDICT_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputPause( inputdata_t &input )
|
||||
{
|
||||
PauseTimer( input.pActivator );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputResume( inputdata_t &input )
|
||||
{
|
||||
ResumeTimer( input.pActivator );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetTime( inputdata_t &input )
|
||||
{
|
||||
float flTime = input.value.Float();
|
||||
SetTimeRemaining( flTime );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputAddTime( inputdata_t &input )
|
||||
{
|
||||
float flTime = input.value.Float();
|
||||
AddTimerSeconds( flTime );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputRemoveTime( inputdata_t &input )
|
||||
{
|
||||
float flTime = input.value.Float();
|
||||
AddTimerSeconds( -flTime );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetMaxTime( inputdata_t &input )
|
||||
{
|
||||
float flTime = input.value.Float();
|
||||
m_flTimerMaxLength = flTime;
|
||||
|
||||
if (m_flTimerMaxLength > 0)
|
||||
{
|
||||
// make sure our current time is not above the max length
|
||||
if (GetTimeRemaining() > m_flTimerMaxLength)
|
||||
{
|
||||
SetTimeRemaining( m_flTimerMaxLength );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetTimerCaption( inputdata_t &input )
|
||||
{
|
||||
Q_strncpy( m_szTimerCaption.GetForModify(), input.value.String(), MAX_GAME_TIMER_CAPTION );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetProgressBarMaxSegments( inputdata_t &input )
|
||||
{
|
||||
m_nProgressBarMaxSegments = input.value.Int();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetProgressBarOverride( inputdata_t &input )
|
||||
{
|
||||
m_nProgressBarOverride = input.value.Int();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetX( inputdata_t &input )
|
||||
{
|
||||
m_flOverrideX = input.value.Float();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetY( inputdata_t &input )
|
||||
{
|
||||
m_flOverrideY = input.value.Float();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputRestart( inputdata_t &input )
|
||||
{
|
||||
SetTimeRemaining( m_flTimerInitialLength );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputGetTimeRemaining( inputdata_t &input )
|
||||
{
|
||||
m_OnGetTimeRemaining.Set( GetTimeRemaining(), input.pActivator, this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputEnable( inputdata_t &input )
|
||||
{
|
||||
if (GetTimeRemaining() == 0.0f)
|
||||
SetTimeRemaining( m_flTimerInitialLength );
|
||||
|
||||
m_bIsDisabled = false;
|
||||
if ( !m_bStartPaused )
|
||||
ResumeTimer( input.pActivator );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputDisable( inputdata_t &input )
|
||||
{
|
||||
PauseTimer( input.pActivator );
|
||||
m_bIsDisabled = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetPlayerFilter( inputdata_t &inputdata )
|
||||
{
|
||||
m_iszPlayerFilterName = inputdata.value.StringID();
|
||||
if ( m_iszPlayerFilterName != NULL_STRING )
|
||||
{
|
||||
m_hPlayerFilter = dynamic_cast<CBaseFilter *>(gEntList.FindEntityByName( NULL, m_iszPlayerFilterName, this ));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hPlayerFilter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
145
sp/src/game/shared/mapbase/game_timer.h
Normal file
145
sp/src/game/shared/mapbase/game_timer.h
Normal file
@ -0,0 +1,145 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: Generic custom timer entity
|
||||
//
|
||||
// Author: Blixibon
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_baseentity.h"
|
||||
#else
|
||||
#include "filters.h"
|
||||
#endif
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
DECLARE_AUTO_LIST( IGameTimerAutoList );
|
||||
|
||||
#define CGameTimer C_GameTimer
|
||||
#endif
|
||||
|
||||
#define MAX_GAME_TIMER_CAPTION 32
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Displays a custom timer
|
||||
//-----------------------------------------------------------------------------
|
||||
class CGameTimer : public CBaseEntity
|
||||
#ifdef CLIENT_DLL
|
||||
, public IGameTimerAutoList
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CGameTimer, CBaseEntity );
|
||||
DECLARE_NETWORKCLASS();
|
||||
#ifndef CLIENT_DLL
|
||||
DECLARE_DATADESC();
|
||||
#endif
|
||||
|
||||
CGameTimer();
|
||||
~CGameTimer();
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
void Spawn();
|
||||
#ifndef CLIENT_DLL
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
virtual bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen );
|
||||
#endif
|
||||
|
||||
// Based on teamplay_round_timer
|
||||
virtual float GetTimeRemaining( void );
|
||||
virtual float GetTimerMaxLength( void );
|
||||
virtual bool StartPaused( void ) { return m_bStartPaused; }
|
||||
bool ShowTimeRemaining( void ) { return m_bShowTimeRemaining; }
|
||||
float GetWarnTime( void );
|
||||
|
||||
const char *GetTimerCaption( void ) { return m_szTimerCaption.Get(); }
|
||||
|
||||
int GetProgressBarMaxSegments( void ) { return m_nProgressBarMaxSegments; }
|
||||
int GetProgressBarOverride( void ) { return m_nProgressBarOverride; }
|
||||
|
||||
bool OverridesPosition( void ) { return m_flOverrideX != -1.0f || m_flOverrideY != -1.0f; }
|
||||
void GetPositionOverride( float &flX, float &flY ) { flX = m_flOverrideX; flY = m_flOverrideY; }
|
||||
|
||||
bool IsDisabled( void ) { return m_bIsDisabled; }
|
||||
bool IsTimerPaused( void ) { return m_bTimerPaused; }
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
virtual void SetTimeRemaining( float flTime ); // Set the initial length of the timer
|
||||
virtual void AddTimerSeconds( float flTimeToAdd ); // Add time to an already running ( or paused ) timer
|
||||
virtual void OnTimerFinished();
|
||||
virtual void OnTimerWarned();
|
||||
virtual void PauseTimer( CBaseEntity *pActivator = NULL );
|
||||
virtual void ResumeTimer( CBaseEntity *pActivator = NULL );
|
||||
|
||||
void SetProgressBarMaxSegments( int nSegments ) { m_nProgressBarMaxSegments = nSegments; }
|
||||
void SetProgressBarOverride( int nSegments ) { m_nProgressBarOverride = nSegments; }
|
||||
|
||||
int UpdateTransmitState();
|
||||
|
||||
// Inputs
|
||||
void InputEnable( inputdata_t &input );
|
||||
void InputDisable( inputdata_t &input );
|
||||
void InputPause( inputdata_t &input );
|
||||
void InputResume( inputdata_t &input );
|
||||
void InputSetTime( inputdata_t &input );
|
||||
void InputAddTime( inputdata_t &input );
|
||||
void InputRemoveTime( inputdata_t &input );
|
||||
void InputRestart( inputdata_t &input );
|
||||
void InputSetMaxTime( inputdata_t &input );
|
||||
void InputSetTimerCaption( inputdata_t &input );
|
||||
void InputSetProgressBarMaxSegments( inputdata_t &input );
|
||||
void InputSetProgressBarOverride( inputdata_t &input );
|
||||
void InputSetX( inputdata_t &input );
|
||||
void InputSetY( inputdata_t &input );
|
||||
void InputGetTimeRemaining( inputdata_t &input );
|
||||
void InputSetPlayerFilter( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void UpdateOnRemove( void );
|
||||
#else
|
||||
int ShouldTransmit( const CCheckTransmitInfo *pInfo );
|
||||
void TimerThink( void );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
CNetworkVar( bool, m_bIsDisabled );
|
||||
CNetworkVar( float, m_flTimerInitialLength );
|
||||
CNetworkVar( float, m_flTimerMaxLength );
|
||||
CNetworkVar( float, m_flTimerEndTime );
|
||||
CNetworkVar( float, m_flTimeRemaining );
|
||||
CNetworkVar( float, m_flWarnTime ); // Time at which timer turns red, starts ticking loudly, etc.
|
||||
CNetworkVar( int, m_nProgressBarMaxSegments ); // Overrides maximum segments in progress bar if greater than -1
|
||||
CNetworkVar( int, m_nProgressBarOverride ); // Overrides progress bar value if greater than -1
|
||||
CNetworkVar( float, m_flOverrideX );
|
||||
CNetworkVar( float, m_flOverrideY );
|
||||
CNetworkVar( bool, m_bTimerPaused );
|
||||
CNetworkVar( bool, m_bStartPaused );
|
||||
CNetworkVar( bool, m_bShowTimeRemaining );
|
||||
CNetworkString( m_szTimerCaption, MAX_GAME_TIMER_CAPTION );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
bool m_bOldDisabled;
|
||||
#else
|
||||
bool m_bStartedWarn;
|
||||
bool m_bDisableOnFinish;
|
||||
bool m_bShowInHUD; // TODO: ShowInHUD input? Would require client to know it shouldn't show the timer anymore
|
||||
|
||||
string_t m_iszPlayerFilterName;
|
||||
CHandle<CBaseFilter> m_hPlayerFilter;
|
||||
|
||||
// Outputs
|
||||
COutputEvent m_OnFinished;
|
||||
COutputEvent m_OnPaused;
|
||||
COutputEvent m_OnResumed;
|
||||
COutputEvent m_OnWarned;
|
||||
COutputInt m_OnTick;
|
||||
COutputFloat m_OnGetTimeRemaining;
|
||||
#endif
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user