From c5f3fa0778201e24c1b1c192c14b766b10bda5e4 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Wed, 5 Feb 2020 19:08:49 +0000 Subject: [PATCH] Mapbase v3.0 - Overhauled matcher system and added expanded wildcard support, meaning "text", "te?t", "blah_test", etc. are now supported instead of only trailing * - Added support for regular expression matching - Added the missing matrixinvert.h file, which prevented programmers from compiling vbsp - Fixed env_global_light brightness - Added info_player_view_proxy, an entity which mimics a player's view (created for script_intro) - New UnZoomWithRate and SetZoomRate inputs on env_zoom - New "Don't change target's angles" flag on logic_measure_movement - Fixed logic_measure_movement not using ignore origin flags correctly - Fixed filter_damage_mod secondary filter not recognizing mode correctly - Fixed DisableGeigerCounter causing NPCs to ignore player, and possibly fixed other adverse effects in similar code - Added SetEntityName input for setting an entity's targetname - Added "SetTarget" support to point_posecontroller - Added "sk_alyx_health" convar for adjustable npc_alyx health, restored/fixed "sk_barney_health" for adjustable npc_barney health - Added ignore flags and several direction-related inputs to math_vector - Added pose parameter stuff to logic_modelinfo - Fixed ChangeWeapon not changing during combat - Fixed holster/unholster on NPCs without holster/unholster animations - Fixed func_tank and other "player in the way" code ignoring notarget - Added SetPoseParameter input to animating entities - Introduced an experimental chapter system which allows for custom chapter title/restriction management - Added SetChapterTitle input to worldspawn for dynamic title changing - Fixed func_tankairboatgun damage credit, added ability to use its damage keyvalues - Fixed mapbase_rpc_enabled not actually affecting RPC - Moved some newly found Combine soldier grenade code to ai_grenade for other grenade users - Fixed some problems with the new shared activities - Restored an old Mapbase entity as "prop_interactable", an entity which contains all of the functionality of a func_button/func_door in a prop entity - Added env_microphone pitch scale for scaling the pitch of transmitted sounds - Added experimental, long-overdue code for scenes to be able to access !target#'s and other scene-related names through AI_INPUT - Added "mat_specular_disable_on_missing", which "disables" specular reflections when the cubemap texture is missing - Fixed $envmapmasktransform and $bumptransform on VertexLitGeneric and related shaders - Areaportal leaks now stop compilation in leaktest - Replaced "-nodefaultcubemap" with "-defaultcubemap" as the shader changes allow maps to compile without default cubemaps by default with little effect --- sp/src/game/client/c_baseentity.h | 5 + sp/src/game/client/c_baseplayer.cpp | 12 +- sp/src/game/client/c_env_global_light.cpp | 7 + sp/src/game/client/client_mapbase.vpc | 2 + sp/src/game/client/hl2/c_script_intro.cpp | 130 ++++++++- sp/src/game/server/ai_activity.cpp | 73 ++--- sp/src/game/server/ai_baseactor.cpp | 20 +- sp/src/game/server/ai_baseactor.h | 4 + sp/src/game/server/ai_basenpc.cpp | 28 +- sp/src/game/server/baseanimating.cpp | 29 ++ sp/src/game/server/baseanimating.h | 1 + sp/src/game/server/baseentity.cpp | 12 +- sp/src/game/server/baseentity.h | 2 + sp/src/game/server/baseflex.cpp | 12 + sp/src/game/server/baseflex.h | 8 + sp/src/game/server/env_global_light.cpp | 4 + sp/src/game/server/env_zoom.cpp | 34 +++ sp/src/game/server/envmicrophone.cpp | 7 +- sp/src/game/server/envmicrophone.h | 1 + sp/src/game/server/filters.cpp | 4 +- sp/src/game/server/gameinterface.cpp | 124 ++++++++- sp/src/game/server/gameinterface.h | 17 ++ sp/src/game/server/hl2/func_tank.cpp | 13 + sp/src/game/server/hl2/npc_alyx.cpp | 8 + sp/src/game/server/hl2/npc_alyx_episodic.cpp | 21 ++ sp/src/game/server/hl2/npc_barney.cpp | 4 + sp/src/game/server/hl2/npc_combines.cpp | 2 + sp/src/game/server/hl2/npc_combines.h | 2 + sp/src/game/server/hl2/script_intro.cpp | 251 ++++++++++++++++++ sp/src/game/server/logic_measure_movement.cpp | 13 +- sp/src/game/server/logicentities.cpp | 235 +++++++++++++++- sp/src/game/server/mapbase/ai_grenade.h | 27 ++ sp/src/game/server/mapbase/matchers.h | 160 ----------- sp/src/game/server/player.cpp | 13 +- sp/src/game/server/props.cpp | 184 ++++++++++--- sp/src/game/server/rope.cpp | 4 +- sp/src/game/server/sceneentity.cpp | 56 ++++ sp/src/game/server/sceneentity.h | 4 + sp/src/game/server/server_mapbase.vpc | 3 +- sp/src/game/server/world.cpp | 11 + sp/src/game/server/world.h | 2 + sp/src/game/shared/activitylist.cpp | 78 +++--- sp/src/game/shared/baseplayer_shared.h | 9 +- sp/src/game/shared/mapbase/mapbase_rpc.cpp | 19 +- sp/src/game/shared/mapbase/mapbase_shared.cpp | 52 +++- sp/src/game/shared/mapbase/matchers.cpp | 234 ++++++++++++++++ sp/src/game/shared/mapbase/matchers.h | 59 ++++ sp/src/game/shared/point_posecontroller.cpp | 7 + sp/src/game/shared/point_posecontroller.h | 4 + .../stdshaders/BaseVSShader.cpp | 4 + .../materialsystem/stdshaders/BaseVSShader.h | 5 + .../stdshaders/SDK_skin_ps20b.fxc | 5 + ...vertexlit_and_unlit_generic_bump_ps20b.fxc | 5 + ..._vertexlit_and_unlit_generic_bump_ps2x.fxc | 5 + .../SDK_vertexlit_and_unlit_generic_ps20b.fxc | 5 + .../stdshaders/game_shader_dx9_mapbase.vpc | 9 + .../lightmappedgeneric_dx9_helper.cpp | 30 +++ .../lightmappedgeneric_dx9_helper.h | 5 - .../stdshaders/skin_dx9_helper.cpp | 11 + .../vertexlitgeneric_dx9_helper.cpp | 12 + sp/src/utils/vbsp/matrixinvert.h | 117 ++++++++ sp/src/utils/vbsp/portals.cpp | 11 + sp/src/utils/vbsp/vbsp.cpp | 9 +- 63 files changed, 1909 insertions(+), 335 deletions(-) delete mode 100644 sp/src/game/server/mapbase/matchers.h create mode 100644 sp/src/game/shared/mapbase/matchers.cpp create mode 100644 sp/src/game/shared/mapbase/matchers.h create mode 100644 sp/src/utils/vbsp/matrixinvert.h diff --git a/sp/src/game/client/c_baseentity.h b/sp/src/game/client/c_baseentity.h index 4ca3fa49..c68e3868 100644 --- a/sp/src/game/client/c_baseentity.h +++ b/sp/src/game/client/c_baseentity.h @@ -1017,6 +1017,11 @@ public: virtual Vector EyePosition( void ); virtual const QAngle& EyeAngles( void ); // Direction of eyes virtual const QAngle& LocalEyeAngles( void ); // Direction of eyes in local space (pl.v_angle) + +#ifdef MAPBASE + // Created for script_intro and info_player_view_proxy + virtual void GetEyePosition( Vector &vecOrigin, QAngle &angAngles ) { vecOrigin = EyePosition(); angAngles = EyeAngles(); } +#endif // position of ears virtual Vector EarPosition( void ); diff --git a/sp/src/game/client/c_baseplayer.cpp b/sp/src/game/client/c_baseplayer.cpp index 3f8f913a..acbd1ade 100644 --- a/sp/src/game/client/c_baseplayer.cpp +++ b/sp/src/game/client/c_baseplayer.cpp @@ -133,6 +133,16 @@ void RecvProxy_LocalVelocityZ( const CRecvProxyData *pData, void *pStruct, void void RecvProxy_ObserverTarget( const CRecvProxyData *pData, void *pStruct, void *pOut ); void RecvProxy_ObserverMode ( const CRecvProxyData *pData, void *pStruct, void *pOut ); +#ifdef MAPBASE +// Needs to shift bits back +void RecvProxy_ShiftPlayerSpawnflags( const CRecvProxyData *pData, void *pStruct, void *pOut ) +{ + C_BasePlayer *pPlayer = (C_BasePlayer *)pStruct; + + pPlayer->m_spawnflags = (pData->m_Value.m_Int) << 16; +} +#endif + // -------------------------------------------------------------------------------- // // RecvTable for CPlayerState. // -------------------------------------------------------------------------------- // @@ -259,7 +269,7 @@ END_RECV_TABLE() #ifdef MAPBASE // Transmitted from the server for internal player spawnflags. // See baseplayer_shared.h for more details. - RecvPropInt ( RECVINFO( m_spawnflags ) ), + RecvPropInt ( RECVINFO( m_spawnflags ), 0, RecvProxy_ShiftPlayerSpawnflags ), RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ), #endif diff --git a/sp/src/game/client/c_env_global_light.cpp b/sp/src/game/client/c_env_global_light.cpp index 3647fff9..c48803ae 100644 --- a/sp/src/game/client/c_env_global_light.cpp +++ b/sp/src/game/client/c_env_global_light.cpp @@ -251,9 +251,16 @@ void C_GlobalLight::ClientThink() state.m_fLinearAtten = m_flSunDistance * 2.0f; state.m_fConstantAtten = 0.0f; state.m_FarZAtten = m_flSunDistance * 2.0f; +#ifdef MAPBASE + float flAlpha = m_flCurrentLinearFloatLightAlpha * (1.0f / 255.0f); + state.m_Color[0] = (m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale; + state.m_Color[1] = (m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale; + state.m_Color[2] = (m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale; +#else state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha; state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha; state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha; +#endif state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient; state.m_NearZ = 4.0f; state.m_FarZ = m_flSunDistance * 2.0f; diff --git a/sp/src/game/client/client_mapbase.vpc b/sp/src/game/client/client_mapbase.vpc index 9a4645d0..7efb1522 100644 --- a/sp/src/game/client/client_mapbase.vpc +++ b/sp/src/game/client/client_mapbase.vpc @@ -29,6 +29,8 @@ $Project $File "$SRCDIR\game\shared\mapbase\mapbase_game_log.cpp" $File "$SRCDIR\game\shared\mapbase\MapEdit.cpp" $File "$SRCDIR\game\shared\mapbase\MapEdit.h" + $File "$SRCDIR\game\shared\mapbase\matchers.cpp" + $File "$SRCDIR\game\shared\mapbase\matchers.h" $File "mapbase\c_func_clientclip.cpp" } diff --git a/sp/src/game/client/hl2/c_script_intro.cpp b/sp/src/game/client/hl2/c_script_intro.cpp index 0101336f..aaf5349b 100644 --- a/sp/src/game/client/hl2/c_script_intro.cpp +++ b/sp/src/game/client/hl2/c_script_intro.cpp @@ -273,8 +273,7 @@ void C_ScriptIntro::ClientThink( void ) #ifdef MAPBASE if ( m_bUseEyePosition ) { - m_IntroData.m_vecCameraView = m_hCameraEntity->EyePosition(); - m_IntroData.m_vecCameraViewAngles = m_hCameraEntity->EyeAngles(); + m_hCameraEntity->GetEyePosition( m_IntroData.m_vecCameraView, m_IntroData.m_vecCameraViewAngles ); } else { @@ -369,3 +368,130 @@ void C_ScriptIntro::CalculateAlpha( void ) m_IntroData.m_flCurrentFadeColor[3] = flNewAlpha; } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class C_PlayerViewProxy : public C_BaseEntity +{ + DECLARE_CLASS( C_PlayerViewProxy, C_BaseEntity ); +public: + DECLARE_CLIENTCLASS(); + + Vector EyePosition( void ); // position of eyes + const QAngle &EyeAngles( void ); // Direction of eyes in world space + void GetEyePosition( Vector &vecOrigin, QAngle &angAngles ); + const QAngle &LocalEyeAngles( void ); // Direction of eyes + Vector EarPosition( void ); // position of ears + +#ifdef MAPBASE_MP + C_BasePlayer *GetPlayer() { return m_bEnabled ? (m_hPlayer.Get() ? m_hPlayer.Get() : C_BasePlayer::GetLocalPlayer()) : NULL; } +#else + C_BasePlayer *GetPlayer() { return m_bEnabled ? C_BasePlayer::GetLocalPlayer() : NULL; } +#endif + +public: +#ifdef MAPBASE_MP + CHandle m_hPlayer; +#endif + + bool m_bEnabled; +}; + +IMPLEMENT_CLIENTCLASS_DT( C_PlayerViewProxy, DT_PlayerViewProxy, CPlayerViewProxy ) +#ifdef MAPBASE_MP + RecvPropEHandle( RECVINFO( m_hPlayer ) ), +#endif + RecvPropBool( RECVINFO( m_bEnabled ) ), +END_RECV_TABLE() + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Vector C_PlayerViewProxy::EyePosition( void ) +{ + C_BasePlayer *pPlayer = GetPlayer(); + if (pPlayer) + { + //Vector vecPlayerOffset = m_hPlayer.Get()->EyePosition() - m_hPlayer.Get()->GetAbsOrigin(); + //return GetAbsOrigin() + vecPlayerOffset; + + Vector vecOrigin; + QAngle angAngles; + float fldummy; + pPlayer->CalcView( vecOrigin, angAngles, fldummy, fldummy, fldummy ); + + return GetAbsOrigin() + (vecOrigin - pPlayer->GetAbsOrigin()); + } + else + return BaseClass::EyePosition(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const QAngle &C_PlayerViewProxy::EyeAngles( void ) +{ + C_BasePlayer *pPlayer = GetPlayer(); + if (pPlayer) + { + Vector vecOrigin; + static QAngle angAngles; + float fldummy; + pPlayer->CalcView( vecOrigin, angAngles, fldummy, fldummy, fldummy ); + + return angAngles; + + //return m_hPlayer.Get()->EyeAngles(); + } + else + return BaseClass::EyeAngles(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_PlayerViewProxy::GetEyePosition( Vector &vecOrigin, QAngle &angAngles ) +{ + C_BasePlayer *pPlayer = GetPlayer(); + if (pPlayer) + { + float fldummy; + pPlayer->CalcView( vecOrigin, angAngles, fldummy, fldummy, fldummy ); + + vecOrigin = GetAbsOrigin() + (vecOrigin - pPlayer->GetAbsOrigin()); + } + else + { + BaseClass::GetEyePosition( vecOrigin, angAngles ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const QAngle &C_PlayerViewProxy::LocalEyeAngles( void ) +{ + C_BasePlayer *pPlayer = GetPlayer(); + if (pPlayer) + return pPlayer->LocalEyeAngles(); + else + return BaseClass::LocalEyeAngles(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Vector C_PlayerViewProxy::EarPosition( void ) +{ + C_BasePlayer *pPlayer = GetPlayer(); + if (pPlayer) + { + Vector vecPlayerOffset = pPlayer->GetAbsOrigin() - pPlayer->EarPosition(); + return GetAbsOrigin() + vecPlayerOffset; + } + else + return BaseClass::EarPosition(); +} +#endif + diff --git a/sp/src/game/server/ai_activity.cpp b/sp/src/game/server/ai_activity.cpp index ca0c63e3..9190ea7f 100644 --- a/sp/src/game/server/ai_activity.cpp +++ b/sp/src/game/server/ai_activity.cpp @@ -157,10 +157,6 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_RELOAD_LOW ); ADD_ACTIVITY_TO_SR( ACT_ARM ); ADD_ACTIVITY_TO_SR( ACT_DISARM ); -#ifdef COMPANION_HOLSTER_WORKAROUND - ADD_ACTIVITY_TO_SR( ACT_ARM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DISARM_RIFLE ); -#endif ADD_ACTIVITY_TO_SR( ACT_DROP_WEAPON ); ADD_ACTIVITY_TO_SR( ACT_DROP_WEAPON_SHOTGUN ); ADD_ACTIVITY_TO_SR( ACT_PICKUP_GROUND ); @@ -400,11 +396,6 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_SMG2_TOAUTO ); ADD_ACTIVITY_TO_SR( ACT_SMG2_TOBURST ); -#ifdef SHARED_COMBINE_ACTIVITIES - ADD_ACTIVITY_TO_SR( ACT_COMBINE_THROW_GRENADE ); - ADD_ACTIVITY_TO_SR( ACT_COMBINE_AR2_ALTFIRE ); -#endif - // Physcannon special activities ADD_ACTIVITY_TO_SR( ACT_PHYSCANNON_UPGRADE ); @@ -456,10 +447,6 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_IDLE_RIFLE ); ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG1 ); ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SMG1 ); -#if AR2_ACTIVITY_FIX == 1 - ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2 ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_AR2 ); -#endif ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL ); ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_PISTOL ); ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SHOTGUN ); @@ -478,26 +465,10 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_WALK_RIFLE_STIMULATED ); ADD_ACTIVITY_TO_SR( ACT_RUN_RIFLE_STIMULATED ); -#if AR2_ACTIVITY_FIX == 1 - ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2_STIMULATED ); - - ADD_ACTIVITY_TO_SR( ACT_WALK_AR2_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AR2_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AR2_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AR2_STIMULATED ); -#endif - ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_RIFLE_STIMULATED ); ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_RIFLE_STIMULATED ); ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_RIFLE_STIMULATED ); -#if AR2_ACTIVITY_FIX == 1 - ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_AR2_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR2_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2_STIMULATED ); -#endif - ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_RELAXED ); ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_STIMULATED ); ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_AGITATED ); @@ -547,13 +518,6 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_STEALTH_PISTOL ); ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_STEALTH_PISTOL ); -#if AR2_ACTIVITY_FIX == 1 - ADD_ACTIVITY_TO_SR( ACT_WALK_AR2 ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR2 ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AR2 ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2 ); -#endif - ADD_ACTIVITY_TO_SR( ACT_RELOAD_PISTOL ); ADD_ACTIVITY_TO_SR( ACT_RELOAD_PISTOL_LOW ); ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG1 ); @@ -2193,4 +2157,41 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_SPELL_VM_IDLE ); ADD_ACTIVITY_TO_SR( ACT_SPELL_VM_ARM ); ADD_ACTIVITY_TO_SR( ACT_SPELL_VM_FIRE ); + +#if AR2_ACTIVITY_FIX == 1 + ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2 ); + ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_AR2 ); + + ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2_RELAXED ); + ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2_STIMULATED ); + + ADD_ACTIVITY_TO_SR( ACT_WALK_AR2_RELAXED ); + ADD_ACTIVITY_TO_SR( ACT_RUN_AR2_RELAXED ); + ADD_ACTIVITY_TO_SR( ACT_WALK_AR2_STIMULATED ); + ADD_ACTIVITY_TO_SR( ACT_RUN_AR2_STIMULATED ); + + ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_AR2_STIMULATED ); + ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR2_STIMULATED ); + ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2_STIMULATED ); + + ADD_ACTIVITY_TO_SR( ACT_WALK_AR2 ); + ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR2 ); + ADD_ACTIVITY_TO_SR( ACT_RUN_AR2 ); + ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2 ); + + //ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2 ); + //ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2_LOW ); + + ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_AR2 ); +#endif + +#ifdef SHARED_COMBINE_ACTIVITIES + ADD_ACTIVITY_TO_SR( ACT_COMBINE_THROW_GRENADE ); + ADD_ACTIVITY_TO_SR( ACT_COMBINE_AR2_ALTFIRE ); +#endif + +#ifdef COMPANION_HOLSTER_WORKAROUND + ADD_ACTIVITY_TO_SR( ACT_ARM_RIFLE ); + ADD_ACTIVITY_TO_SR( ACT_DISARM_RIFLE ); +#endif } diff --git a/sp/src/game/server/ai_baseactor.cpp b/sp/src/game/server/ai_baseactor.cpp index 03104d49..224cf42d 100644 --- a/sp/src/game/server/ai_baseactor.cpp +++ b/sp/src/game/server/ai_baseactor.cpp @@ -231,13 +231,10 @@ void CAI_BaseActor::SetModel( const char *szModelName ) //----------------------------------------------------------------------------- #ifdef MAPBASE -// Half-Laugh had a nasty way of implementing CSceneEntity into StartSceneEvent and I'm both afraid to do it here -// and I don't remember exactly how I did it. This is extremely important because -// it's the only way we can access !target1, !target2, etc. Please revisit this later. -#define STARTSCENEEVENT_HAS_CSCENEENTITY 0 -#endif - +bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget, CSceneEntity *pSceneEnt ) +#else bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ) +#endif { Assert( info ); Assert( info->m_pScene ); @@ -382,18 +379,13 @@ bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CBaseEntity *pEnt = gEntList.FindEntityByName(NULL, sTarget, this); if (!pEnt) { -#if STARTSCENEEVENT_HAS_CSCENEENTITY DevMsg("%s not found with normal search, slamming to scene ent\n", sTarget); - pEnt = UTIL_FindNamedSceneEntity(sTarget, this, csceneent); + pEnt = UTIL_FindNamedSceneEntity(sTarget, this, pSceneEnt); if (!pEnt) { DevWarning("%s slammed to self!\n", sTarget); pEnt = this; } -#else - DevWarning("%s slammed to self!\n", sTarget); - pEnt = this; -#endif } if (pEnt && sInput) @@ -402,10 +394,9 @@ bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, if (bParameter && sParameter) { const char *strParam = sParameter; -#if STARTSCENEEVENT_HAS_CSCENEENTITY if (strParam[0] == '!') { - CBaseEntity *pParamEnt = UTIL_FindNamedSceneEntity(strParam, this, csceneent); + CBaseEntity *pParamEnt = UTIL_FindNamedSceneEntity(strParam, this, pSceneEnt); if (pParamEnt && pParamEnt->GetEntityName() != NULL_STRING && !gEntList.FindEntityProcedural(strParam)) { // We make sure it's a scene entity that can't be found with entlist procedural so we can translate !target# without messing with !activators, etc. @@ -413,7 +404,6 @@ bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, strParam = pParamEnt->GetEntityName().ToCStr(); } } -#endif if (strParam) { diff --git a/sp/src/game/server/ai_baseactor.h b/sp/src/game/server/ai_baseactor.h index 87d10f50..b2c8c5ca 100644 --- a/sp/src/game/server/ai_baseactor.h +++ b/sp/src/game/server/ai_baseactor.h @@ -101,7 +101,11 @@ public: virtual void SetModel( const char *szModelName ); +#ifdef MAPBASE + virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget, CSceneEntity *pSceneEnt = NULL ); +#else virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ); +#endif virtual bool ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled ); virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event ); diff --git a/sp/src/game/server/ai_basenpc.cpp b/sp/src/game/server/ai_basenpc.cpp index ede98f5b..ad1961d7 100644 --- a/sp/src/game/server/ai_basenpc.cpp +++ b/sp/src/game/server/ai_basenpc.cpp @@ -1374,7 +1374,7 @@ bool CAI_BaseNPC::PlayerInSpread( const Vector &sourcePos, const Vector &targetP #ifdef MAPBASE // "> D_FR" means it isn't D_HT, D_FR, or D_ER (error disposition) - if ( pPlayer && ( !ignoreHatedPlayers || IRelationType( pPlayer ) > D_FR ) ) + if ( pPlayer && ( !ignoreHatedPlayers || IRelationType( pPlayer ) > D_FR ) && !(pPlayer->GetFlags() & FL_NOTARGET) ) #else if ( pPlayer && ( !ignoreHatedPlayers || IRelationType( pPlayer ) != D_HT ) ) #endif @@ -5002,9 +5002,16 @@ void CAI_BaseNPC::PrescheduleThink( void ) if (CapabilitiesGet() & bits_CAP_USE_WEAPONS) { // If we should have our gun out, fetch it - if ( ShouldUnholsterWeapon() && m_iDesiredWeaponState == DESIREDWEAPONSTATE_IGNORE ) + if ( ShouldUnholsterWeapon() ) { - SetDesiredWeaponState( DESIREDWEAPONSTATE_UNHOLSTERED ); + if ( m_iDesiredWeaponState == DESIREDWEAPONSTATE_IGNORE ) + { + SetDesiredWeaponState( DESIREDWEAPONSTATE_UNHOLSTERED ); + } + } + else if (m_iDesiredWeaponState == DESIREDWEAPONSTATE_UNHOLSTERED) + { + SetDesiredWeaponState( DESIREDWEAPONSTATE_IGNORE ); } // If our desired weapon state is not the current, fix it @@ -7675,7 +7682,7 @@ bool CAI_BaseNPC::IsWeaponStateChanging( void ) bool CAI_BaseNPC::DoHolster( void ) { // Cache off the weapon. - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); + CBaseCombatWeapon *pWeapon = GetActiveWeapon(); if (pWeapon) { @@ -7684,7 +7691,10 @@ bool CAI_BaseNPC::DoHolster( void ) { if (m_hMyWeapons[i].Get() == pWeapon) { - m_iLastHolsteredWeapon = i; + // Set to this weapon if we don't have a "target" weapon to unholster + if (m_iLastHolsteredWeapon == -1) + m_iLastHolsteredWeapon = i; + break; } } @@ -7733,6 +7743,9 @@ bool CAI_BaseNPC::DoUnholster( void ) m_Activity = ACT_RESET; } + // Clear last holstered weapon + m_iLastHolsteredWeapon = -1; + return true; } @@ -7786,9 +7799,12 @@ void CAI_BaseNPC::InputChangeWeapon( inputdata_t &inputdata ) return; } + // So the code doesn't try to unholster the wrong weapon + m_iLastHolsteredWeapon = iSwitchTo; + if (!GetActiveWeapon()) { - m_iLastHolsteredWeapon = iSwitchTo; + // Just unholster UnholsterWeapon(); } else diff --git a/sp/src/game/server/baseanimating.cpp b/sp/src/game/server/baseanimating.cpp index 0bca7c42..5fb0ff2f 100644 --- a/sp/src/game/server/baseanimating.cpp +++ b/sp/src/game/server/baseanimating.cpp @@ -210,6 +210,7 @@ BEGIN_DATADESC( CBaseAnimating ) #ifdef MAPBASE DEFINE_INPUTFUNC( FIELD_VOID, "CreateSeparateRagdoll", InputCreateSeparateRagdoll ), DEFINE_INPUTFUNC( FIELD_VOID, "CreateSeparateRagdollClient", InputCreateSeparateRagdollClient ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetPoseParameter", InputSetPoseParameter ), #endif DEFINE_INPUTFUNC( FIELD_STRING, "SetLightingOriginHack", InputSetLightingOriginRelative ), DEFINE_INPUTFUNC( FIELD_STRING, "SetLightingOrigin", InputSetLightingOrigin ), @@ -3679,6 +3680,34 @@ void CBaseAnimating::InputCreateSeparateRagdollClient( inputdata_t &inputdata ) pRagdoll->GetBaseAnimating()->CopyAnimationDataFrom( this ); } } + +void CBaseAnimating::InputSetPoseParameter( inputdata_t &inputdata ) +{ + char token[64]; + Q_strncpy( token, inputdata.value.String(), sizeof(token) ); + char *sChar = strchr( token, ' ' ); + if ( sChar ) + { + *sChar = '\0'; + + // Name + const int index = LookupPoseParameter( token ); + if (index == -1) + { + Warning("SetPoseParameter: Could not find pose parameter \"%s\" on %s\n", token, GetDebugName()); + return; + } + + // Value + const float value = atof( sChar+1 ); + + SetPoseParameter( index, value ); + } + else + { + Warning("SetPoseParameter: \"%s\" is invalid; format is \" \"\n", inputdata.value.String()); + } +} #endif //----------------------------------------------------------------------------- diff --git a/sp/src/game/server/baseanimating.h b/sp/src/game/server/baseanimating.h index abaec974..9ad963bc 100644 --- a/sp/src/game/server/baseanimating.h +++ b/sp/src/game/server/baseanimating.h @@ -300,6 +300,7 @@ public: #ifdef MAPBASE void InputCreateSeparateRagdoll( inputdata_t &inputdata ); void InputCreateSeparateRagdollClient( inputdata_t &inputdata ); + void InputSetPoseParameter( inputdata_t &inputdata ); #endif // Dissolve, returns true if the ragdoll has been created diff --git a/sp/src/game/server/baseentity.cpp b/sp/src/game/server/baseentity.cpp index 2091fa7e..6bc1b6ea 100644 --- a/sp/src/game/server/baseentity.cpp +++ b/sp/src/game/server/baseentity.cpp @@ -2017,6 +2017,8 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity ) DEFINE_OUTPUT( m_OnUser4, "OnUser4" ), #ifdef MAPBASE + DEFINE_INPUTFUNC( FIELD_STRING, "SetEntityName", InputSetEntityName ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget", InputSetTarget ), DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetOwnerEntity", InputSetOwnerEntity ), @@ -7034,7 +7036,7 @@ bool CBaseEntity::HasContext( const char *name, const char *value ) const if (value == NULL) return true; else - return Matcher_Compare(STRING(m_ResponseContexts[i].m_iszValue), value); + return Matcher_Match(STRING(m_ResponseContexts[i].m_iszValue), value); } } @@ -7223,6 +7225,14 @@ void CBaseEntity::InputPassRandomUser( inputdata_t& inputdata ) #ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: Sets the entity's targetname. +//----------------------------------------------------------------------------- +void CBaseEntity::InputSetEntityName( inputdata_t& inputdata ) +{ + SetName( inputdata.value.StringID() ); +} + //----------------------------------------------------------------------------- // Purpose: Sets the generic target field. //----------------------------------------------------------------------------- diff --git a/sp/src/game/server/baseentity.h b/sp/src/game/server/baseentity.h index da619c55..8bccccbc 100644 --- a/sp/src/game/server/baseentity.h +++ b/sp/src/game/server/baseentity.h @@ -680,6 +680,8 @@ public: void InputFireRandomUser( inputdata_t &inputdata ); void InputPassRandomUser( inputdata_t &inputdata ); + void InputSetEntityName( inputdata_t &inputdata ); + virtual void InputSetTarget( inputdata_t &inputdata ); virtual void InputSetOwnerEntity( inputdata_t &inputdata ); diff --git a/sp/src/game/server/baseflex.cpp b/sp/src/game/server/baseflex.cpp index 90c38cdf..e76ce1dd 100644 --- a/sp/src/game/server/baseflex.cpp +++ b/sp/src/game/server/baseflex.cpp @@ -394,7 +394,11 @@ bool CBaseFlex::ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canc // expression - // duration - //----------------------------------------------------------------------------- +#ifdef MAPBASE +void CBaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget, CSceneEntity *pSceneEnt ) +#else void CBaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget ) +#endif { if ( !scene || !event ) { @@ -419,7 +423,11 @@ void CBaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEn info.m_hTarget = pTarget; info.m_bStarted = false; +#ifdef MAPBASE + if (StartSceneEvent( &info, scene, event, actor, pTarget, pSceneEnt )) +#else if (StartSceneEvent( &info, scene, event, actor, pTarget )) +#endif { m_SceneEvents.AddToTail( info ); } @@ -735,7 +743,11 @@ bool CBaseFlex::StartMoveToSceneEvent( CSceneEventInfo *info, CChoreoScene *scen //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- +#ifdef MAPBASE +bool CBaseFlex::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget, CSceneEntity *pSceneEnt ) +#else bool CBaseFlex::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ) +#endif { switch ( event->GetType() ) { diff --git a/sp/src/game/server/baseflex.h b/sp/src/game/server/baseflex.h index 4ac775ea..aaa03c9c 100644 --- a/sp/src/game/server/baseflex.h +++ b/sp/src/game/server/baseflex.h @@ -72,7 +72,11 @@ public: void RemoveChoreoScene( CChoreoScene *scene, bool canceled = false ); // Start the specifics of an scene event +#ifdef MAPBASE + virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget, CSceneEntity *pSceneEnt = NULL ); +#else virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ); +#endif // Manipulation of events for the object // Should be called by think function to process all scene events @@ -91,7 +95,11 @@ public: virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled ); // Add the event to the queue for this actor +#ifdef MAPBASE + void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget = NULL, CSceneEntity *pSceneEnt = NULL ); +#else void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget = NULL ); +#endif // Remove the event from the queue for this actor void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill ); diff --git a/sp/src/game/server/env_global_light.cpp b/sp/src/game/server/env_global_light.cpp index 357e1225..36e8e1ba 100644 --- a/sp/src/game/server/env_global_light.cpp +++ b/sp/src/game/server/env_global_light.cpp @@ -170,7 +170,11 @@ CGlobalLight::CGlobalLight() #else Q_strcpy( m_TextureName.GetForModify(), "effects/flashlight001" ); #endif +#ifdef MAPBASE + m_LightColor.Init( 255, 255, 255, 255 ); +#else m_LightColor.Init( 255, 255, 255, 1 ); +#endif m_flColorTransitionTime = 0.5f; m_flSunDistance = 10000.0f; m_flFOV = 5.0f; diff --git a/sp/src/game/server/env_zoom.cpp b/sp/src/game/server/env_zoom.cpp index 2a9f8478..ec679152 100644 --- a/sp/src/game/server/env_zoom.cpp +++ b/sp/src/game/server/env_zoom.cpp @@ -23,6 +23,10 @@ public: void InputZoom( inputdata_t &inputdata ); void InputUnZoom( inputdata_t &inputdata ); +#ifdef MAPBASE + void InputUnZoomWithRate( inputdata_t &inputdata ); + void InputSetZoomRate( inputdata_t &inputdata ); +#endif int GetFOV( void ) { return m_nFOV; } float GetSpeed( void ) { return m_flSpeed; } @@ -43,6 +47,10 @@ BEGIN_DATADESC( CEnvZoom ) DEFINE_INPUTFUNC( FIELD_VOID, "Zoom", InputZoom ), DEFINE_INPUTFUNC( FIELD_VOID, "UnZoom", InputUnZoom ), +#ifdef MAPBASE + DEFINE_INPUTFUNC( FIELD_VOID, "UnZoomWithRate", InputUnZoomWithRate ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetZoomRate", InputSetZoomRate ), +#endif END_DATADESC() @@ -114,3 +122,29 @@ void CEnvZoom::InputUnZoom( inputdata_t &inputdata ) } } +#ifdef MAPBASE +//----------------------------------------------------------------------------- +// Purpose: +// Input : &inputdata - +//----------------------------------------------------------------------------- +void CEnvZoom::InputUnZoomWithRate( inputdata_t &inputdata ) +{ + CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); + + if ( pPlayer ) + { + // Stuff the values + pPlayer->SetFOV( this, 0, m_flSpeed, m_nFOV ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &inputdata - +//----------------------------------------------------------------------------- +void CEnvZoom::InputSetZoomRate( inputdata_t &inputdata ) +{ + m_flSpeed = inputdata.value.Float(); +} +#endif + diff --git a/sp/src/game/server/envmicrophone.cpp b/sp/src/game/server/envmicrophone.cpp index 0b0fc5ff..14a5d56d 100644 --- a/sp/src/game/server/envmicrophone.cpp +++ b/sp/src/game/server/envmicrophone.cpp @@ -47,6 +47,7 @@ BEGIN_DATADESC( CEnvMicrophone ) #ifdef MAPBASE DEFINE_KEYFIELD(m_iszLandmarkName, FIELD_STRING, "landmark"), DEFINE_FIELD(m_hLandmark, FIELD_EHANDLE), + DEFINE_KEYFIELD(m_flPitchScale, FIELD_FLOAT, "PitchScale"), #endif // DEFINE_FIELD(m_bAvoidFeedback, FIELD_BOOLEAN), // DONT SAVE DEFINE_KEYFIELD(m_iSpeakerDSPPreset, FIELD_INTEGER, "speaker_dsp_preset" ), @@ -526,10 +527,14 @@ MicrophoneResult_t CEnvMicrophone::SoundPlayed( int entindex, const char *soundn ep.m_flVolume = flVolume; ep.m_SoundLevel = soundlevel; ep.m_nFlags = iFlags; - ep.m_nPitch = iPitch; #ifdef MAPBASE + if (m_flPitchScale != 1.0f) + ep.m_nPitch = (int)((float)iPitch * m_flPitchScale); + else + ep.m_nPitch = iPitch; ep.m_pOrigin = &vecOrigin; #else + ep.m_nPitch = iPitch; ep.m_pOrigin = &m_hSpeaker->GetAbsOrigin(); #endif ep.m_flSoundTime = soundtime; diff --git a/sp/src/game/server/envmicrophone.h b/sp/src/game/server/envmicrophone.h index 254486ff..27591f7c 100644 --- a/sp/src/game/server/envmicrophone.h +++ b/sp/src/game/server/envmicrophone.h @@ -85,6 +85,7 @@ private: #ifdef MAPBASE string_t m_iszLandmarkName; EHANDLE m_hLandmark; + float m_flPitchScale = 1.0f; #endif COutputFloat m_SoundLevel; // Fired when the sampled volume level changes. diff --git a/sp/src/game/server/filters.cpp b/sp/src/game/server/filters.cpp index c8d0fd06..c67d6e50 100644 --- a/sp/src/game/server/filters.cpp +++ b/sp/src/game/server/filters.cpp @@ -1908,9 +1908,9 @@ public: switch (m_iSecondaryFilterMode) { case REDIRECT_MUST_PASS_TO_DAMAGE_CALLER: - case REDIRECT_MUST_PASS_TO_ACT: bPass = (RedirectToDamageFilter(pCaller, info)); + case REDIRECT_MUST_PASS_TO_ACT: bPass = (RedirectToDamageFilter( pCaller, info )); break; - case REDIRECT_MUST_PASS_ACTIVATORS: bPass = (info.GetAttacker() && RedirectToFilter(pCaller, info.GetAttacker())); + case REDIRECT_MUST_PASS_ACTIVATORS: bPass = (info.GetAttacker() && RedirectToFilter(pCaller, info.GetAttacker())); break; } if (!bPass) diff --git a/sp/src/game/server/gameinterface.cpp b/sp/src/game/server/gameinterface.cpp index 9da779ca..0a91d34e 100644 --- a/sp/src/game/server/gameinterface.cpp +++ b/sp/src/game/server/gameinterface.cpp @@ -1727,9 +1727,41 @@ static TITLECOMMENT gTitleComments[] = #endif }; +#ifdef MAPBASE +extern CUtlVector *Mapbase_GetChapterMaps(); +extern CUtlVector *Mapbase_GetChapterList(); +#endif + #ifdef _XBOX void CServerGameDLL::GetTitleName( const char *pMapName, char* pTitleBuff, int titleBuffSize ) { +#ifdef MAPBASE + // Check the world entity for a chapter title + if ( CWorld *pWorld = GetWorldEntity() ) + { + const char *pWorldChapter = pWorld->GetChapterTitle(); + if ( pWorldChapter && pWorldChapter[0] != '\0' ) + { + Q_strncpy( chapterTitle, pWorldChapter, sizeof( chapterTitle ) ); + return; + } + } + + // Look in the mod's chapter list + CUtlVector *ModChapterComments = Mapbase_GetChapterMaps(); + if (ModChapterComments->Count() > 0) + { + for ( int i = 0; i < ModChapterComments->Count(); i++ ) + { + if ( !Q_strnicmp( mapname, ModChapterComments->Element(i).pBSPName, strlen(ModChapterComments->Element(i).pBSPName) ) ) + { + Q_strncpy( pTitleBuff, ModChapterComments->Element(i).pTitleName, titleBuffSize ); + return; + } + } + } +#endif + // Try to find a matching title comment for this mapname for ( int i = 0; i < ARRAYSIZE(gTitleComments); i++ ) { @@ -1740,16 +1772,6 @@ void CServerGameDLL::GetTitleName( const char *pMapName, char* pTitleBuff, int t } } -#ifdef MAPBASE - // Check the world entity for a chapter title. - if ( CWorld *pWorld = GetWorldEntity() ) - { - const char *pWorldChapter = pWorld->GetChapterTitle(); - if ( pWorldChapter && pWorldChapter[0] != '\0' ) - Q_strncpy( chapterTitle, pWorldChapter, sizeof( chapterTitle ) ); - } -#endif - Q_strncpy( pTitleBuff, pMapName, titleBuffSize ); } #endif @@ -1789,7 +1811,35 @@ void CServerGameDLL::GetSaveComment( char *text, int maxlength, float flMinutes, } #ifdef MAPBASE - // Check the world entity for a chapter title. + // Look in the mod's chapter list + CUtlVector *ModChapterComments = Mapbase_GetChapterMaps(); + if (ModChapterComments->Count() > 0) + { + for ( int i = 0; i < ModChapterComments->Count(); i++ ) + { + if ( !Q_strnicmp( mapname, ModChapterComments->Element(i).pBSPName, strlen(ModChapterComments->Element(i).pBSPName) ) ) + { + // found one + int j; + + // Got a message, post-process it to be save name friendly + Q_strncpy( comment, ModChapterComments->Element(i).pTitleName, sizeof( comment ) ); + pName = comment; + j = 0; + // Strip out CRs + while ( j < 64 && comment[j] ) + { + if ( comment[j] == '\n' || comment[j] == '\r' ) + comment[j] = 0; + else + j++; + } + break; + } + } + } + + // Check the world entity for a chapter title if ( CWorld *pWorld = GetWorldEntity() ) { const char *pWorldChapter = pWorld->GetChapterTitle(); @@ -2093,6 +2143,58 @@ void UpdateChapterRestrictions( const char *mapname ) } #ifdef MAPBASE + // Look in the mod's chapter list + CUtlVector *ModChapterComments = Mapbase_GetChapterMaps(); + if (ModChapterComments->Count() > 0) + { + for ( int i = 0; i < ModChapterComments->Count(); i++ ) + { + if ( !Q_strnicmp( mapname, ModChapterComments->Element(i).pBSPName, strlen(ModChapterComments->Element(i).pBSPName) ) ) + { + // found + Q_strncpy( chapterTitle, ModChapterComments->Element(i).pTitleName, sizeof( chapterTitle ) ); + int j = 0; + while ( j < 64 && chapterTitle[j] ) + { + if ( chapterTitle[j] == '\n' || chapterTitle[j] == '\r' ) + chapterTitle[j] = 0; + else + j++; + } + + // Mods can order their own custom chapter names, + // allowing for more flexible string name usage, multiple names in one chapter, etc. + CUtlVector *ModChapterList = Mapbase_GetChapterList(); + for ( int i = 0; i < ModChapterList->Count(); i++ ) + { + if ( !Q_strnicmp( chapterTitle, ModChapterList->Element(i).pChapterName, strlen(chapterTitle) ) ) + { + // ok we have the string, see if it's newer + int nNewChapter = ModChapterList->Element(i).iChapter; + int nUnlockedChapter = sv_unlockedchapters.GetInt(); + + if ( nUnlockedChapter < nNewChapter ) + { + // ok we're at a higher chapter, unlock + sv_unlockedchapters.SetValue( nNewChapter ); + + // HACK: Call up through a better function than this? 7/23/07 - jdw + if ( IsX360() ) + { + engine->ServerCommand( "host_writeconfig\n" ); + } + } + + g_nCurrentChapterIndex = nNewChapter; + return; + } + } + + break; + } + } + } + // Check the world entity for a chapter title. if ( CWorld *pWorld = GetWorldEntity() ) { diff --git a/sp/src/game/server/gameinterface.h b/sp/src/game/server/gameinterface.h index c0d7a6da..67805ff6 100644 --- a/sp/src/game/server/gameinterface.h +++ b/sp/src/game/server/gameinterface.h @@ -209,5 +209,22 @@ public: }; EXPOSE_SINGLE_INTERFACE( CServerGameTags, IServerGameTags, INTERFACEVERSION_SERVERGAMETAGS ); +#ifdef MAPBASE +// +// Dynamic mod-based mod title comments +// +typedef struct +{ + char pBSPName[64]; + char pTitleName[64]; +} MODTITLECOMMENT; + +typedef struct +{ + int iChapter; + char pChapterName[64]; +} MODCHAPTER; +#endif + #endif // GAMEINTERFACE_H diff --git a/sp/src/game/server/hl2/func_tank.cpp b/sp/src/game/server/hl2/func_tank.cpp index bec8b1fa..963a0e54 100644 --- a/sp/src/game/server/hl2/func_tank.cpp +++ b/sp/src/game/server/hl2/func_tank.cpp @@ -3369,6 +3369,7 @@ private: #ifdef MAPBASE float m_flHeavyShotInterval = 0.2f; int m_iHeavyShotSpread; + bool m_bUseDamageKV; #endif }; @@ -3388,6 +3389,7 @@ BEGIN_DATADESC( CFuncTankAirboatGun ) #ifdef MAPBASE DEFINE_KEYFIELD( m_flHeavyShotInterval, FIELD_FLOAT, "heavy_shot_interval" ), DEFINE_KEYFIELD( m_iHeavyShotSpread, FIELD_INTEGER, "heavy_shot_spread" ), + DEFINE_KEYFIELD( m_bUseDamageKV, FIELD_BOOLEAN, "use_damage_kv" ), #endif #ifdef MAPBASE @@ -3685,6 +3687,17 @@ void CFuncTankAirboatGun::Fire( int bulletCount, const Vector &barrelEnd, const info.m_flDistance = 4096; info.m_iAmmoType = ammoType; +#ifdef MAPBASE + info.m_pAttacker = pAttacker; + info.m_pAdditionalIgnoreEnt = GetParent(); + + if (m_bUseDamageKV) + { + info.m_flDamage = m_iBulletDamage; + info.m_iPlayerDamage = m_iBulletDamageVsPlayer; + } +#endif + if ( gpGlobals->curtime >= m_flNextHeavyShotTime ) { info.m_iShots = 1; diff --git a/sp/src/game/server/hl2/npc_alyx.cpp b/sp/src/game/server/hl2/npc_alyx.cpp index f9dc1286..72b3f328 100644 --- a/sp/src/game/server/hl2/npc_alyx.cpp +++ b/sp/src/game/server/hl2/npc_alyx.cpp @@ -33,6 +33,10 @@ END_DATADESC() int AE_ALYX_EMPTOOL_ATTACHMENT; int AE_ALYX_EMPTOOL_SEQUENCE; +#ifdef MAPBASE +ConVar sk_alyx_health( "sk_alyx_health", "80" ); +#endif + //========================================================= // Classify - indicates this NPC's place in the // relationship table. @@ -127,7 +131,11 @@ void CNPC_Alyx::Spawn() AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); +#ifdef MAPBASE + m_iHealth = sk_alyx_health.GetInt(); +#else m_iHealth = 80; +#endif NPCInit(); } diff --git a/sp/src/game/server/hl2/npc_alyx_episodic.cpp b/sp/src/game/server/hl2/npc_alyx_episodic.cpp index f512411f..19616e10 100644 --- a/sp/src/game/server/hl2/npc_alyx_episodic.cpp +++ b/sp/src/game/server/hl2/npc_alyx_episodic.cpp @@ -75,6 +75,10 @@ bool IsInCommentaryMode( void ); #define ALYX_MIN_ENEMY_HEALTH_TO_CROUCH 15 #define ALYX_CROUCH_DELAY 5 // Time after crouching before Alyx will crouch again +#ifdef MAPBASE +ConVar sk_alyx_health( "sk_alyx_health", "80" ); +#endif + //----------------------------------------------------------------------------- // Interactions //----------------------------------------------------------------------------- @@ -346,7 +350,11 @@ void CNPC_Alyx::Spawn() AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); +#ifdef MAPBASE + m_iHealth = sk_alyx_health.GetInt(); +#else m_iHealth = 80; +#endif m_bloodColor = DONT_BLEED; NPCInit(); @@ -409,7 +417,15 @@ void CNPC_Alyx::Activate( void ) { // Alyx always kicks her health back up to full after loading a savegame. // Avoids problems with players saving the game in places where she dies immediately afterwards. +#ifdef MAPBASE + // Alyx's health can be >80 thanks to the new convar, and we don't want a 1000-health Alyx to reload + // from 1 health to 1000 health, so this should only kick in if her health is less than her default + // (we also probably don't want this to happen if she's not an ally) + if (IsPlayerAlly() && m_iHealth < 80) + m_iHealth = 80; +#else m_iHealth = 80; +#endif BaseClass::Activate(); @@ -3227,7 +3243,12 @@ bool CNPC_Alyx::PlayerInSpread( const Vector &sourcePos, const Vector &targetPos { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); +#ifdef MAPBASE + // "> D_FR" means it isn't D_HT, D_FR, or D_ER (error disposition) + if ( pPlayer && ( !ignoreHatedPlayers || IRelationType( pPlayer ) > D_FR ) && !(pPlayer->GetFlags() & FL_NOTARGET) ) +#else if ( pPlayer && ( !ignoreHatedPlayers || IRelationType( pPlayer ) != D_HT ) ) +#endif { //If the player is being lifted by a barnacle then go ahead and ignore the player and shoot. #ifdef HL2_EPISODIC diff --git a/sp/src/game/server/hl2/npc_barney.cpp b/sp/src/game/server/hl2/npc_barney.cpp index f4b04074..02afce18 100644 --- a/sp/src/game/server/hl2/npc_barney.cpp +++ b/sp/src/game/server/hl2/npc_barney.cpp @@ -124,7 +124,11 @@ void CNPC_Barney::Spawn( void ) { Precache(); +#ifdef MAPBASE + m_iHealth = sk_barney_health.GetInt(); +#else m_iHealth = 80; +#endif m_iszIdleExpression = MAKE_STRING("scenes/Expressions/BarneyIdle.vcd"); m_iszAlertExpression = MAKE_STRING("scenes/Expressions/BarneyAlert.vcd"); diff --git a/sp/src/game/server/hl2/npc_combines.cpp b/sp/src/game/server/hl2/npc_combines.cpp index 314b26e1..cd4e07b7 100644 --- a/sp/src/game/server/hl2/npc_combines.cpp +++ b/sp/src/game/server/hl2/npc_combines.cpp @@ -136,6 +136,7 @@ void CNPC_CombineS::DeathSound( const CTakeDamageInfo &info ) } +#ifndef MAPBASE // Moved to CAI_GrenadeUser //----------------------------------------------------------------------------- // Purpose: Soldiers use CAN_RANGE_ATTACK2 to indicate whether they can throw // a grenade. Because they check only every half-second or so, this @@ -157,6 +158,7 @@ void CNPC_CombineS::ClearAttackConditions( ) SetCondition( COND_CAN_RANGE_ATTACK2 ); } } +#endif void CNPC_CombineS::PrescheduleThink( void ) { diff --git a/sp/src/game/server/hl2/npc_combines.h b/sp/src/game/server/hl2/npc_combines.h index e9dc75b2..7c7d8fbe 100644 --- a/sp/src/game/server/hl2/npc_combines.h +++ b/sp/src/game/server/hl2/npc_combines.h @@ -35,7 +35,9 @@ public: void Event_Killed( const CTakeDamageInfo &info ); void OnListened(); +#ifndef MAPBASE // Moved to CAI_GrenadeUser void ClearAttackConditions( void ); +#endif bool m_fIsBlocking; diff --git a/sp/src/game/server/hl2/script_intro.cpp b/sp/src/game/server/hl2/script_intro.cpp index 62a126b0..7b15d136 100644 --- a/sp/src/game/server/hl2/script_intro.cpp +++ b/sp/src/game/server/hl2/script_intro.cpp @@ -409,3 +409,254 @@ void CScriptIntro::InputSetFadeColor( inputdata_t &inputdata ) m_flFadeColor.Set( 1, flG ); m_flFadeColor.Set( 2, flB ); } + +#ifdef MAPBASE +class CPlayerViewProxy : public CBaseEntity +{ +public: + DECLARE_CLASS( CPlayerViewProxy, CBaseEntity ); + DECLARE_DATADESC(); + DECLARE_SERVERCLASS(); + + CPlayerViewProxy(); + + void Spawn( void ); + int UpdateTransmitState( void ); + + void ActivateEnt( CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); + void DeactivateEnt(); + void MeasureThink(); + + Vector EyePosition( void ); // position of eyes + const QAngle &EyeAngles( void ); // Direction of eyes in world space + const QAngle &LocalEyeAngles( void ); // Direction of eyes + Vector EarPosition( void ); // position of ears + + // Inputs + void InputActivate( inputdata_t &inputdata ); + void InputDeactivate( inputdata_t &inputdata ); + +#ifdef MAPBASE_MP + // TODO: Mapbase MP should use reception filter or something to determine which player's eye position is offset + CNetworkVar( CHandle, m_hPlayer ); +#else + CHandle m_hPlayer; +#endif + + string_t m_iszMeasureReference; + EHANDLE m_hMeasureReference; + string_t m_iszTargetReference; + EHANDLE m_hTargetReference; + + CNetworkVar( float, m_flScale ); + + CNetworkVar( bool, m_bEnabled ); +}; + +LINK_ENTITY_TO_CLASS( info_player_view_proxy, CPlayerViewProxy ); + +BEGIN_DATADESC( CPlayerViewProxy ) + + // Keys + DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), + DEFINE_KEYFIELD( m_iszMeasureReference, FIELD_STRING, "MeasureReference" ), + DEFINE_FIELD( m_hMeasureReference, FIELD_EHANDLE ), + DEFINE_KEYFIELD( m_iszTargetReference, FIELD_STRING, "TargetReference" ), + DEFINE_FIELD( m_hTargetReference, FIELD_EHANDLE ), + DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "TargetScale" ), + DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "Enabled" ), + + // Inputs + DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), + DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), + + DEFINE_THINKFUNC( MeasureThink ), + +END_DATADESC() + +IMPLEMENT_SERVERCLASS_ST( CPlayerViewProxy, DT_PlayerViewProxy ) +#ifdef MAPBASE_MP + SendPropEHandle( SENDINFO( m_hPlayer ) ), +#endif + SendPropBool( SENDINFO( m_bEnabled ) ), +END_SEND_TABLE() + +CPlayerViewProxy::CPlayerViewProxy() +{ + m_flScale = 1.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPlayerViewProxy::Spawn( void ) +{ + if (m_bEnabled) + ActivateEnt(); +} + +//------------------------------------------------------------------------------ +// Purpose : Send even though we don't have a model. +//------------------------------------------------------------------------------ +int CPlayerViewProxy::UpdateTransmitState() +{ + return SetTransmitState( FL_EDICT_ALWAYS ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPlayerViewProxy::MeasureThink( void ) +{ + if (m_hPlayer.Get() == NULL) + { + // Player has disappeared! Stopping measure + return; + } + + if (m_bEnabled && m_hMeasureReference.Get() && m_hTargetReference.Get()) + { + matrix3x4_t matRefToMeasure, matWorldToMeasure; + MatrixInvert( m_hPlayer.Get()->EntityToWorldTransform(), matWorldToMeasure ); + ConcatTransforms( matWorldToMeasure, m_hMeasureReference.Get()->EntityToWorldTransform(), matRefToMeasure ); + + // Apply the scale factor + if ( ( m_flScale != 0.0f ) && ( m_flScale != 1.0f ) ) + { + Vector vecTranslation; + MatrixGetColumn( matRefToMeasure, 3, vecTranslation ); + vecTranslation /= m_flScale; + MatrixSetColumn( vecTranslation, 3, matRefToMeasure ); + } + + // Now apply the new matrix to the new reference point + matrix3x4_t matMeasureToRef, matNewTargetToWorld; + MatrixInvert( matRefToMeasure, matMeasureToRef ); + ConcatTransforms( m_hTargetReference.Get()->EntityToWorldTransform(), matMeasureToRef, matNewTargetToWorld ); + + Vector vecOrigin; + QAngle angAngles; + MatrixAngles( matNewTargetToWorld, angAngles, vecOrigin ); + Teleport( &vecOrigin, &angAngles, NULL ); + + SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); + } + //else + //{ + // SetAbsOrigin( m_hPlayer.Get()->GetAbsOrigin() ); + // SetAbsAngles( m_hPlayer.Get()->GetAbsAngles() ); + //} +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Vector CPlayerViewProxy::EyePosition( void ) +{ + if (m_hPlayer.Get()) + { + //Vector vecPlayerOffset = m_hPlayer.Get()->EyePosition() - m_hPlayer.Get()->GetAbsOrigin(); + //return GetAbsOrigin() + vecPlayerOffset; + + Vector vecOrigin; + QAngle angAngles; + float fldummy; + m_hPlayer->CalcView( vecOrigin, angAngles, fldummy, fldummy, fldummy ); + + return GetAbsOrigin() + (vecOrigin - m_hPlayer->GetAbsOrigin()); + } + else + return BaseClass::EyePosition(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const QAngle &CPlayerViewProxy::EyeAngles( void ) +{ + if (m_hPlayer.Get()) + { + Vector vecOrigin; + static QAngle angAngles; + float fldummy; + m_hPlayer->CalcView( vecOrigin, angAngles, fldummy, fldummy, fldummy ); + + return angAngles; + + //return m_hPlayer.Get()->EyeAngles(); + } + else + return BaseClass::EyeAngles(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +const QAngle &CPlayerViewProxy::LocalEyeAngles( void ) +{ + if (m_hPlayer.Get()) + return m_hPlayer.Get()->LocalEyeAngles(); + else + return BaseClass::LocalEyeAngles(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Vector CPlayerViewProxy::EarPosition( void ) +{ + if (m_hPlayer.Get()) + { + Vector vecPlayerOffset = m_hPlayer.Get()->EarPosition() - m_hPlayer.Get()->GetAbsOrigin(); + return GetAbsOrigin() + vecPlayerOffset; + } + else + return BaseClass::EarPosition(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPlayerViewProxy::ActivateEnt( CBaseEntity *pActivator, CBaseEntity *pCaller ) +{ + m_bEnabled = true; + + m_hMeasureReference = gEntList.FindEntityByName( NULL, m_iszMeasureReference, this, pActivator, pCaller ); + m_hTargetReference = gEntList.FindEntityByName( NULL, m_iszTargetReference, this, pActivator, pCaller ); + + // Do something else in Mapbase MP + m_hPlayer = UTIL_GetLocalPlayer(); + + SetThink( &CPlayerViewProxy::MeasureThink ); + SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPlayerViewProxy::DeactivateEnt( void ) +{ + m_bEnabled = false; + + m_hMeasureReference = NULL; + m_hTargetReference = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &inputdata - +//----------------------------------------------------------------------------- +void CPlayerViewProxy::InputActivate( inputdata_t &inputdata ) +{ + ActivateEnt(inputdata.pActivator, inputdata.pCaller); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &inputdata - +//----------------------------------------------------------------------------- +void CPlayerViewProxy::InputDeactivate( inputdata_t &inputdata ) +{ + DeactivateEnt(); +} +#endif diff --git a/sp/src/game/server/logic_measure_movement.cpp b/sp/src/game/server/logic_measure_movement.cpp index 9ceba13d..06c3da45 100644 --- a/sp/src/game/server/logic_measure_movement.cpp +++ b/sp/src/game/server/logic_measure_movement.cpp @@ -27,6 +27,9 @@ // Uses "Teleport" instead of "SetAbsOrigin" for smoother movement #define SF_LOGIC_MEASURE_MOVEMENT_TELEPORT ( 1 << 4 ) + +// Specifically refuse to set the target's angles, rather than just turning them to 0 +#define SF_LOGIC_MEASURE_MOVEMENT_DONT_SET_ANGLES ( 1 << 5 ) #endif //----------------------------------------------------------------------------- @@ -281,12 +284,14 @@ void CLogicMeasureMovement::MeasureThink( ) if (HasSpawnFlags( SF_LOGIC_MEASURE_MOVEMENT_TELEPORT )) { - m_hTarget->Teleport( &vecNewOrigin, &vecNewAngles, NULL ); + m_hTarget->Teleport( &vecNewOrigin, !HasSpawnFlags(SF_LOGIC_MEASURE_MOVEMENT_DONT_SET_ANGLES) ? &vecNewAngles : NULL, NULL ); } else { m_hTarget->SetAbsOrigin( vecNewOrigin ); - m_hTarget->SetAbsAngles( vecNewAngles ); + + if (!HasSpawnFlags(SF_LOGIC_MEASURE_MOVEMENT_DONT_SET_ANGLES)) + m_hTarget->SetAbsAngles( vecNewAngles ); } #else matrix3x4_t matRefToMeasure, matWorldToMeasure; @@ -388,11 +393,11 @@ void CLogicMeasureMovement::DoMeasure( Vector &vecOrigin, QAngle &angAngles ) { // Get the position from the matrix's column directly and re-assign it Vector vecPosition; - MatrixGetColumn( matRefToMeasure, 3, vecPosition ); + MatrixGetColumn( matMeasureToRef, 3, vecPosition ); HandleIgnoreFlags( vecPosition.Base() ); - MatrixSetColumn( vecPosition, 3, matRefToMeasure ); + MatrixSetColumn( vecPosition, 3, matMeasureToRef ); } ConcatTransforms( m_hTargetReference->EntityToWorldTransform(), matMeasureToRef, matNewTargetToWorld ); diff --git a/sp/src/game/server/logicentities.cpp b/sp/src/game/server/logicentities.cpp index d4a49bf2..0f524464 100644 --- a/sp/src/game/server/logicentities.cpp +++ b/sp/src/game/server/logicentities.cpp @@ -2466,7 +2466,7 @@ void CLogicCase::InputValue( inputdata_t &inputdata ) for (int i = 0; i < MAX_LOGIC_CASES; i++) { #ifdef MAPBASE - if ((m_nCase[i] != NULL_STRING) && Matcher_Compare(STRING(m_nCase[i]), pszValue)) + if ((m_nCase[i] != NULL_STRING) && Matcher_Match(STRING(m_nCase[i]), pszValue)) { m_OnCase[i].FireOutput( inputdata.pActivator, this ); @@ -3787,7 +3787,7 @@ void CLogicConvar::InputTest( inputdata_t &inputdata ) const char *pCVarString = GetConVarString(inputdata); if (pCVarString) { - if (Matcher_Compare( STRING( m_iszCompareValue ), pCVarString )) + if (Matcher_Match( STRING( m_iszCompareValue ), pCVarString )) { m_OnTrue.FireOutput(inputdata.pActivator, this); } @@ -4611,6 +4611,11 @@ int CMathBits::DrawDebugTextOverlays( void ) return text_offset; } +// These spawnflags control math_vector dimensions. +#define SF_MATH_VECTOR_DISABLE_X ( 1 << 0 ) +#define SF_MATH_VECTOR_DISABLE_Y ( 1 << 1 ) +#define SF_MATH_VECTOR_DISABLE_Z ( 1 << 2 ) + //----------------------------------------------------------------------------- // Purpose: Vector calculations. //----------------------------------------------------------------------------- @@ -4639,8 +4644,16 @@ private: void InputEnable( inputdata_t &inputdata ); void InputDisable( inputdata_t &inputdata ); + void PointAt( Vector &origin, Vector &target, Vector &out ); + void InputPointAtLocation( inputdata_t &inputdata ); + void InputPointAtEntity( inputdata_t &inputdata ); + void InputNormalize( inputdata_t &inputdata ); void InputNormalizeAngles( inputdata_t &inputdata ); + void InputVectorAngles( inputdata_t &inputdata ); + void InputAngleVectorForward( inputdata_t &inputdata ); + void InputAngleVectorRight( inputdata_t &inputdata ); + void InputAngleVectorUp( inputdata_t &inputdata ); void SetCoordinate(float value, char coord, CBaseEntity *pActivator); void GetCoordinate(char coord, CBaseEntity *pActivator); @@ -4693,8 +4706,15 @@ BEGIN_DATADESC( CMathVector ) DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), + DEFINE_INPUTFUNC( FIELD_VECTOR, "PointAtLocation", InputPointAtLocation ), + DEFINE_INPUTFUNC( FIELD_EHANDLE, "PointAtEntity", InputPointAtEntity ), + DEFINE_INPUTFUNC(FIELD_VOID, "Normalize", InputNormalize), DEFINE_INPUTFUNC(FIELD_VOID, "NormalizeAngles", InputNormalizeAngles), + DEFINE_INPUTFUNC(FIELD_VOID, "VectorAngles", InputVectorAngles), + DEFINE_INPUTFUNC(FIELD_VOID, "AngleVectorForward", InputAngleVectorForward), + DEFINE_INPUTFUNC(FIELD_VOID, "AngleVectorRight", InputAngleVectorRight), + DEFINE_INPUTFUNC(FIELD_VOID, "AngleVectorUp", InputAngleVectorUp), DEFINE_INPUTFUNC(FIELD_FLOAT, "SetX", InputSetX), DEFINE_INPUTFUNC(FIELD_FLOAT, "SetY", InputSetY), @@ -4918,6 +4938,68 @@ void CMathVector::InputDisable( inputdata_t &inputdata ) m_bDisabled = true; } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMathVector::PointAt( Vector &origin, Vector &target, Vector &out ) +{ + out = origin - target; + VectorNormalize( out ); + + QAngle ang; + VectorAngles( out, ang ); + + out[0] = ang[0]; + out[1] = ang[1]; + out[2] = ang[2]; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMathVector::InputPointAtLocation( inputdata_t &inputdata ) +{ + if( m_bDisabled ) + { + DevMsg("Math Vector %s ignoring POINTATLOCATION because it is disabled\n", GetDebugName() ); + return; + } + + Vector cur; + m_OutValue.Get(cur); + + Vector location; + inputdata.value.Vector3D( location ); + + PointAt( cur, location, cur ); + + UpdateOutValue( inputdata.pActivator, cur ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMathVector::InputPointAtEntity( inputdata_t &inputdata ) +{ + if( m_bDisabled ) + { + DevMsg("Math Vector %s ignoring POINTATENTITY because it is disabled\n", GetDebugName() ); + return; + } + + if (!inputdata.value.Entity()) + { + Warning("%s received no entity to point at\n", GetDebugName()); + return; + } + + Vector cur; + m_OutValue.Get(cur); + + Vector location = inputdata.value.Entity()->GetAbsOrigin(); + + PointAt( cur, location, cur ); + + UpdateOutValue( inputdata.pActivator, cur ); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CMathVector::InputNormalize( inputdata_t &inputdata ) @@ -4952,6 +5034,71 @@ void CMathVector::InputNormalizeAngles( inputdata_t &inputdata ) UpdateOutValue( inputdata.pActivator, cur ); } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMathVector::InputVectorAngles( inputdata_t &inputdata ) +{ + if( m_bDisabled ) + { + DevMsg("Math Vector %s ignoring VECTORANGLES because it is disabled\n", GetDebugName() ); + return; + } + + Vector cur; + QAngle ang; + m_OutValue.Get(cur); + VectorAngles(cur, ang); + UpdateOutValue( inputdata.pActivator, Vector(ang.x, ang.y, ang.z) ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMathVector::InputAngleVectorForward( inputdata_t &inputdata ) +{ + if( m_bDisabled ) + { + DevMsg("Math Vector %s ignoring ANGLEVECTORFORWARD because it is disabled\n", GetDebugName() ); + return; + } + + Vector cur; + m_OutValue.Get(cur); + AngleVectors(QAngle(cur.x, cur.y, cur.z), &cur); + UpdateOutValue( inputdata.pActivator, cur ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMathVector::InputAngleVectorRight( inputdata_t &inputdata ) +{ + if( m_bDisabled ) + { + DevMsg("Math Vector %s ignoring ANGLEVECTORRIGHT because it is disabled\n", GetDebugName() ); + return; + } + + Vector cur; + m_OutValue.Get(cur); + AngleVectors(QAngle(cur.x, cur.y, cur.z), NULL, &cur, NULL); + UpdateOutValue( inputdata.pActivator, cur ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMathVector::InputAngleVectorUp( inputdata_t &inputdata ) +{ + if( m_bDisabled ) + { + DevMsg("Math Vector %s ignoring ANGLEVECTORUP because it is disabled\n", GetDebugName() ); + return; + } + + Vector cur; + m_OutValue.Get(cur); + AngleVectors(QAngle(cur.x, cur.y, cur.z), NULL, NULL, &cur); + UpdateOutValue( inputdata.pActivator, cur ); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CMathVector::SetCoordinate(float value, char coord, CBaseEntity *pActivator) @@ -5041,6 +5188,13 @@ void CMathVector::SubtractCoordinate(float value, char coord, CBaseEntity *pActi //----------------------------------------------------------------------------- void CMathVector::UpdateOutValue(CBaseEntity *pActivator, Vector &vecNewValue) { + if (HasSpawnFlags( SF_MATH_VECTOR_DISABLE_X )) + vecNewValue.x = 0; + if (HasSpawnFlags( SF_MATH_VECTOR_DISABLE_Y )) + vecNewValue.y = 0; + if (HasSpawnFlags( SF_MATH_VECTOR_DISABLE_Z )) + vecNewValue.z = 0; + m_OutValue.Set(vecNewValue, pActivator, this); m_OutX.Set(vecNewValue.x, pActivator, this); @@ -5422,6 +5576,7 @@ class CLogicModelInfo : public CLogicalEntity private: CBaseAnimating *GetTarget(inputdata_t &inputdata); + int GetPoseParameterIndex(CBaseAnimating *pTarget); // Inputs //void InputSetTarget( inputdata_t &inputdata ) { BaseClass::InputSetTarget(inputdata); m_hTarget = NULL; } @@ -5429,11 +5584,22 @@ private: void InputLookupSequence( inputdata_t &inputdata ); void InputLookupActivity( inputdata_t &inputdata ); + void InputSetPoseParameterName( inputdata_t &inputdata ); + void InputSetPoseParameterValue( inputdata_t &inputdata ); + void InputGetPoseParameter( inputdata_t &inputdata ); + // Outputs COutputInt m_OutNumSkins; COutputInt m_OnHasSequence; COutputEvent m_OnLacksSequence; + COutputFloat m_OutPoseParameterValue; + + // KeyValues + + string_t m_iszPoseParameterName; + int m_iPoseParameterIndex = -1; + DECLARE_DATADESC(); }; @@ -5442,15 +5608,22 @@ LINK_ENTITY_TO_CLASS(logic_modelinfo, CLogicModelInfo); BEGIN_DATADESC( CLogicModelInfo ) + DEFINE_KEYFIELD( m_iszPoseParameterName, FIELD_STRING, "PoseParameterName" ), + DEFINE_FIELD( m_iPoseParameterIndex, FIELD_INTEGER ), + // Inputs DEFINE_INPUTFUNC( FIELD_VOID, "GetNumSkins", InputGetNumSkins ), DEFINE_INPUTFUNC( FIELD_STRING, "LookupSequence", InputLookupSequence ), DEFINE_INPUTFUNC( FIELD_STRING, "LookupActivity", InputLookupActivity ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetPoseParameterName", InputSetPoseParameterName ), + DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPoseParameterValue", InputSetPoseParameterValue ), + DEFINE_INPUTFUNC( FIELD_VOID, "GetPoseParameter", InputGetPoseParameter ), // Outputs DEFINE_OUTPUT(m_OutNumSkins, "OutNumSkins"), DEFINE_OUTPUT(m_OnHasSequence, "OnHasSequence"), DEFINE_OUTPUT(m_OnLacksSequence, "OnLacksSequence"), + DEFINE_OUTPUT(m_OutPoseParameterValue, "OutPoseParameterValue"), END_DATADESC() @@ -5464,6 +5637,15 @@ inline CBaseAnimating *CLogicModelInfo::GetTarget(inputdata_t &inputdata) return pEntity->GetBaseAnimating(); } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +inline int CLogicModelInfo::GetPoseParameterIndex(CBaseAnimating *pTarget) +{ + if (m_iPoseParameterIndex == -1) + m_iPoseParameterIndex = pTarget->LookupPoseParameter(STRING(m_iszPoseParameterName)); + return m_iPoseParameterIndex; +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void CLogicModelInfo::InputGetNumSkins( inputdata_t &inputdata ) @@ -5519,6 +5701,55 @@ void CLogicModelInfo::InputLookupActivity( inputdata_t &inputdata ) } } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CLogicModelInfo::InputSetPoseParameterName( inputdata_t &inputdata ) +{ + m_iszPoseParameterName = inputdata.value.StringID(); + m_iPoseParameterIndex = -1; + + CBaseAnimating *pAnimating = GetTarget(inputdata); + if (pAnimating && pAnimating->GetModelPtr()) + { + if (GetPoseParameterIndex(pAnimating) == -1) + Warning("%s: Pose parameter \"%s\" does not exist on %s\n", GetDebugName(), inputdata.value.String(), STRING(pAnimating->GetModelName())); + } +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CLogicModelInfo::InputSetPoseParameterValue( inputdata_t &inputdata ) +{ + CBaseAnimating *pAnimating = GetTarget(inputdata); + if (pAnimating && pAnimating->GetModelPtr()) + { + int index = GetPoseParameterIndex(pAnimating); + if (index != -1) + { + pAnimating->SetPoseParameter( index, inputdata.value.Float() ); + } + else + Warning("%s: Pose parameter \"%s\" does not exist on %s\n", GetDebugName(), STRING(m_iszPoseParameterName), STRING(pAnimating->GetModelName())); + } +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CLogicModelInfo::InputGetPoseParameter( inputdata_t &inputdata ) +{ + CBaseAnimating *pAnimating = GetTarget(inputdata); + if (pAnimating && pAnimating->GetModelPtr()) + { + int index = GetPoseParameterIndex(pAnimating); + if (index != -1) + { + m_OutPoseParameterValue.Set( pAnimating->GetPoseParameter( index ), pAnimating, this ); + } + else + Warning("%s: Pose parameter \"%s\" does not exist on %s\n", GetDebugName(), inputdata.value.String(), STRING(pAnimating->GetModelName())); + } +} + //----------------------------------------------------------------------------- // Purpose: Checks and calculates an entity's position. //----------------------------------------------------------------------------- diff --git a/sp/src/game/server/mapbase/ai_grenade.h b/sp/src/game/server/mapbase/ai_grenade.h index 48c75e12..887fef1f 100644 --- a/sp/src/game/server/mapbase/ai_grenade.h +++ b/sp/src/game/server/mapbase/ai_grenade.h @@ -110,6 +110,8 @@ public: // Soldiers use "lefthand", cops use "LHand", and citizens use "anim_attachment_LH" virtual const char* GetGrenadeAttachment() { return "anim_attachment_LH"; } + void ClearAttackConditions( void ); + Vector GetAltFireTarget() { return m_vecAltFireTarget; } virtual bool CanAltFireEnemy( bool bUseFreeKnowledge ); void DelayAltFireAttack( float flDelay ); @@ -493,6 +495,31 @@ bool CAI_GrenadeUser::CheckCanThrowGrenade( const Vector &vecTarget ) } } +//----------------------------------------------------------------------------- +// Purpose: This was copied from soldier code for general AI grenades. +// +// "Soldiers use CAN_RANGE_ATTACK2 to indicate whether they can throw +// a grenade. Because they check only every half-second or so, this +// condition must persist until it is updated again by the code +// that determines whether a grenade can be thrown, so prevent the +// base class from clearing it out. (sjb)" +//----------------------------------------------------------------------------- +template +void CAI_GrenadeUser::ClearAttackConditions() +{ + bool fCanRangeAttack2 = IsGrenadeCapable() && HasCondition( COND_CAN_RANGE_ATTACK2 ); + + // Call the base class. + BaseClass::ClearAttackConditions(); + + if( fCanRangeAttack2 ) + { + // We don't allow the base class to clear this condition because we + // don't sense for it every frame. + SetCondition( COND_CAN_RANGE_ATTACK2 ); + } +} + //----------------------------------------------------------------------------- // Purpose: Task helpers //----------------------------------------------------------------------------- diff --git a/sp/src/game/server/mapbase/matchers.h b/sp/src/game/server/mapbase/matchers.h deleted file mode 100644 index eb0bd6ad..00000000 --- a/sp/src/game/server/mapbase/matchers.h +++ /dev/null @@ -1,160 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ================= -// -// Purpose: General matching functions for things like wildcards and !=. -// -// $NoKeywords: $ -//============================================================================= - -#define MAPBASE_MATCHERS 1 - -extern bool ResponseSystemCompare(const char *criterion, const char *value); -//extern const char *ResponseSystemCompare(const char *criterion, const char *value, bool bReturnToken); - -//============================================================================= -// These are the "matchers" that compare with wildcards (any*) and operators (<3). -// -// Matcher_Match - Supports operators and wildcards. -// Matcher_NamesMatch - Only supports wildcards. -// Matcher_Compare - Long story short, Matcher_Match didn't support wildcards before. -// This was used to support both matchers and wildcards. -// Now it just redirects to Matcher_Match. -// -// AppearsToBeANumber - Checks if the string might be a number. -// Stolen from the Response System, just like the other matchers. -//============================================================================= - -// Compares with != and the like. Basically hijacks the response system matching. -// Now supports trailing wildcards (query* == querything) -// pszQuery = The value that should have the operator(s) at the beginning -// szValue = The value tested against the criterion -inline bool Matcher_Match(const char *pszQuery, const char *szValue) -{ - // I wasn't kidding when I said all this did was hijack response system matching. - return ResponseSystemCompare(pszQuery, szValue); - // (pszQuery && szValue) ? ResponseSystemCompare(pszQuery, szValue, pass) : FStrEq(pszQuery, szValue); -} - -inline bool Matcher_Match(const char *pszQuery, int iValue) -{ - return Matcher_Match(pszQuery, UTIL_VarArgs("%i", iValue)); -} - -// Compares two strings with trailing wildcards. Nothing more. Use Matcher_Match if you want <, !=, etc. -// pszQuery = The value that should have the wildcard. -// szValue = The value tested against the query. -// It's basically just baseentity.cpp's NamesMatch(). -FORCEINLINE bool Matcher_NamesMatch(const char *pszQuery, const char *szValue) -{ - if ( szValue == NULL ) - return (!pszQuery || *pszQuery == 0 || *pszQuery == '*'); - - // If the pointers are identical, we're identical - if ( szValue == pszQuery ) - return true; - - while ( *szValue && *pszQuery ) - { - unsigned char cName = *szValue; - unsigned char cQuery = *pszQuery; - // simple ascii case conversion - if ( cName == cQuery ) - ; - else if ( cName - 'A' <= (unsigned char)'Z' - 'A' && cName - 'A' + 'a' == cQuery ) - ; - else if ( cName - 'a' <= (unsigned char)'z' - 'a' && cName - 'a' + 'A' == cQuery ) - ; - else - break; - ++szValue; - ++pszQuery; - } - - if ( *pszQuery == 0 && *szValue == 0 ) - return true; - - // @TODO (toml 03-18-03): Perhaps support real wildcards. Right now, only thing supported is trailing * - if ( *pszQuery == '*' ) - return true; - - return false; -} - -// Identical to Matcher_NamesMatch(), but either value could use a wildcard. -// pszQuery = The value that serves as the query. This value can use wildcards. -// szValue = The value tested against the query. This value can use wildcards as well. -FORCEINLINE bool Matcher_NamesMatch_MutualWildcard(const char *pszQuery, const char *szValue) -{ - if ( szValue == NULL ) - return (!pszQuery || *pszQuery == 0 || *pszQuery == '*'); - - if ( pszQuery == NULL ) - return (!szValue || *szValue == 0 || *szValue == '*'); - - // If the pointers are identical, we're identical - if ( szValue == pszQuery ) - return true; - - while ( *szValue && *pszQuery ) - { - unsigned char cName = *szValue; - unsigned char cQuery = *pszQuery; - // simple ascii case conversion - if ( cName == cQuery ) - ; - else if ( cName - 'A' <= (unsigned char)'Z' - 'A' && cName - 'A' + 'a' == cQuery ) - ; - else if ( cName - 'a' <= (unsigned char)'z' - 'a' && cName - 'a' + 'A' == cQuery ) - ; - else - break; - ++szValue; - ++pszQuery; - } - - if ( *pszQuery == 0 && *szValue == 0 ) - return true; - - // @TODO (toml 03-18-03): Perhaps support real wildcards. Right now, only thing supported is trailing * - if ( *pszQuery == '*' || *szValue == '*' ) - return true; - - return false; -} - -// While Matcher_Match didn't support wildcards, -// this was used to match with both matchers and wildcards. -// Now that Matcher_Match supports wildcards, it just redirects to that, -// but I use this anyway for consistency purposes and force-of-habit. -// pszQuery = The value that should have the operator or wildcard -// szValue = The value tested against the criterion -inline bool Matcher_Compare(const char *pszQuery, const char *szValue) -{ - return Matcher_Match(pszQuery, szValue); -#if 0 - // I have to do this so wildcards could test *before* the response system comparison. - // I know it removes the operators twice, but I won't worry about it. - bool match = Matcher_NamesMatch(Matcher_RemoveOperators(pszQuery), szValue); - if (match) - return Matcher_Match(pszQuery, szValue); - return false; -#endif -} - -// Yeeted right out of the Response System. -// Checks if the specified string appears to be a number of some sort. -static bool AppearsToBeANumber( char const *token ) -{ - if ( atof( token ) != 0.0f ) - return true; - - char const *p = token; - while ( *p ) - { - if ( *p != '0' ) - return false; - - p++; - } - - return true; -} diff --git a/sp/src/game/server/player.cpp b/sp/src/game/server/player.cpp index fccb4816..9f78a595 100644 --- a/sp/src/game/server/player.cpp +++ b/sp/src/game/server/player.cpp @@ -8352,6 +8352,17 @@ void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const voi pOut->m_Int = ( data & mask ); } + +#ifdef MAPBASE +// Needs to shift bits since network table only sends the player ones +void SendProxy_ShiftPlayerSpawnflags( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) +{ + int *pInt = (int *)pVarData; + + pOut->m_Int = (*pInt) >> 16; +} +#endif + // -------------------------------------------------------------------------------- // // SendTable for CPlayerState. // -------------------------------------------------------------------------------- // @@ -8411,7 +8422,7 @@ void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const voi #ifdef MAPBASE // Transmitted from the server for internal player spawnflags. // See baseplayer_shared.h for more details. - SendPropInt ( SENDINFO( m_spawnflags ), 3, SPROP_UNSIGNED ), + SendPropInt ( SENDINFO( m_spawnflags ), 3, SPROP_UNSIGNED, SendProxy_ShiftPlayerSpawnflags ), SendPropBool ( SENDINFO( m_bDrawPlayerModelExternally ) ), #endif diff --git a/sp/src/game/server/props.cpp b/sp/src/game/server/props.cpp index 82226fac..f8180da8 100644 --- a/sp/src/game/server/props.cpp +++ b/sp/src/game/server/props.cpp @@ -2575,20 +2575,41 @@ void COrnamentProp::InputDetach( inputdata_t &inputdata ) } #ifdef MAPBASE +#define SF_INTERACTABLE_USE_INTERACTS 512 // Allows +USE interaction. +#define SF_INTERACTABLE_TOUCH_INTERACTS 1024 // Allows touch interaction. +#define SF_INTERACTABLE_IGNORE_COMMANDS_WHEN_LOCKED 2048 // Completely ignores player commands when locked. +#define SF_INTERACTABLE_RADIUS_USE 4096 // Uses radius +USE + //----------------------------------------------------------------------------- // Purpose: Button prop for +USEable dynamic props //----------------------------------------------------------------------------- -class CButtonProp : public CDynamicProp +class CInteractableProp : public CDynamicProp { - DECLARE_CLASS( CButtonProp, CDynamicProp ); + DECLARE_CLASS( CInteractableProp, CDynamicProp ); public: DECLARE_DATADESC(); - // Remember to precache - //void Spawn(); + void Spawn(); + void Precache(); //void Activate(); + int ObjectCaps() + { + int caps = BaseClass::ObjectCaps(); + + if (HasSpawnFlags(SF_INTERACTABLE_USE_INTERACTS) && (!HasSpawnFlags( SF_INTERACTABLE_IGNORE_COMMANDS_WHEN_LOCKED ) || !m_bLocked)) + { + caps |= FCAP_IMPULSE_USE; + + if (HasSpawnFlags(SF_INTERACTABLE_RADIUS_USE)) + caps |= FCAP_USE_IN_RADIUS; + } + + return caps; + }; + void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); + void InteractablePropTouch( CBaseEntity *pOther ); void SetPushSequence(int iSequence); void PushThink(); @@ -2596,6 +2617,16 @@ public: // Input handlers void InputLock( inputdata_t &inputdata ); void InputUnlock( inputdata_t &inputdata ); + void InputPress( inputdata_t &inputdata ); + + void InputEnableUseInteraction( inputdata_t &inputdata ) { AddSpawnFlags(SF_INTERACTABLE_USE_INTERACTS); } + void InputDisableUseInteraction( inputdata_t &inputdata ) { RemoveSpawnFlags(SF_INTERACTABLE_USE_INTERACTS); } + void InputEnableTouchInteraction( inputdata_t &inputdata ) { AddSpawnFlags( SF_INTERACTABLE_TOUCH_INTERACTS ); } + void InputDisableTouchInteraction( inputdata_t &inputdata ) { RemoveSpawnFlags( SF_INTERACTABLE_TOUCH_INTERACTS ); } + void InputStartIgnoringCommandsWhenLocked( inputdata_t &inputdata ) { AddSpawnFlags( SF_INTERACTABLE_IGNORE_COMMANDS_WHEN_LOCKED ); } + void InputStopIgnoringCommandsWhenLocked( inputdata_t &inputdata ) { RemoveSpawnFlags( SF_INTERACTABLE_IGNORE_COMMANDS_WHEN_LOCKED ); } + void InputEnableRadiusInteract( inputdata_t &inputdata ) { AddSpawnFlags( SF_INTERACTABLE_RADIUS_USE ); } + void InputDisableRadiusInteract( inputdata_t &inputdata ) { RemoveSpawnFlags( SF_INTERACTABLE_RADIUS_USE ); } COutputEvent m_OnPressed; COutputEvent m_OnLockedUse; @@ -2608,42 +2639,87 @@ public: private: float m_flCooldownTime; - bool m_bOutting; // Currently in out sequence + + int m_iCurSequence = INTERACTSEQ_NONE; // Currently in a sequence + enum + { + INTERACTSEQ_NONE = -1, + INTERACTSEQ_IN, + INTERACTSEQ_OUT, + INTERACTSEQ_LOCKED, + }; string_t m_iszPressedSound; string_t m_iszLockedSound; string_t m_iszInSequence; string_t m_iszOutSequence; + string_t m_iszLockedSequence; }; -LINK_ENTITY_TO_CLASS( prop_button, CButtonProp ); +LINK_ENTITY_TO_CLASS( prop_interactable, CInteractableProp ); -BEGIN_DATADESC( CButtonProp ) +BEGIN_DATADESC( CInteractableProp ) DEFINE_KEYFIELD( m_bLocked, FIELD_BOOLEAN, "Locked" ), DEFINE_INPUT( m_flCooldown, FIELD_FLOAT, "SetCooldown" ), DEFINE_FIELD( m_flCooldownTime, FIELD_TIME ), - DEFINE_FIELD( m_bOutting, FIELD_BOOLEAN ), + DEFINE_FIELD( m_iCurSequence, FIELD_INTEGER ), DEFINE_KEYFIELD( m_iszPressedSound, FIELD_STRING, "PressedSound" ), DEFINE_KEYFIELD( m_iszLockedSound, FIELD_STRING, "LockedSound" ), DEFINE_KEYFIELD( m_iszInSequence, FIELD_STRING, "InSequence" ), DEFINE_KEYFIELD( m_iszOutSequence, FIELD_STRING, "OutSequence" ), + DEFINE_KEYFIELD( m_iszLockedSequence, FIELD_STRING, "LockedSequence" ), // Inputs DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ), DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ), + DEFINE_INPUTFUNC( FIELD_VOID, "Press", InputPress ), + DEFINE_INPUTFUNC( FIELD_VOID, "EnableUseInteraction", InputEnableUseInteraction ), + DEFINE_INPUTFUNC( FIELD_VOID, "DisableUseInteraction", InputDisableUseInteraction ), + DEFINE_INPUTFUNC( FIELD_VOID, "EnableTouchInteraction", InputEnableTouchInteraction ), + DEFINE_INPUTFUNC( FIELD_VOID, "DisableTouchInteraction", InputDisableTouchInteraction ), + DEFINE_INPUTFUNC( FIELD_VOID, "StartIgnoringCommandsWhenLocked", InputStartIgnoringCommandsWhenLocked ), + DEFINE_INPUTFUNC( FIELD_VOID, "StopIgnoringCommandsWhenLocked", InputStopIgnoringCommandsWhenLocked ), + DEFINE_INPUTFUNC( FIELD_VOID, "EnableRadiusInteract", InputEnableRadiusInteract ), + DEFINE_INPUTFUNC( FIELD_VOID, "DisableRadiusInteract", InputDisableRadiusInteract ), + + // Outputs DEFINE_OUTPUT( m_OnPressed, "OnPressed" ), DEFINE_OUTPUT( m_OnLockedUse, "OnLockedUse" ), DEFINE_OUTPUT( m_OnIn, "OnIn" ), DEFINE_OUTPUT( m_OnOut, "OnOut" ), DEFINE_THINKFUNC( PushThink ), + DEFINE_ENTITYFUNC( InteractablePropTouch ), END_DATADESC() +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CInteractableProp::Spawn( void ) +{ + BaseClass::Spawn(); + + SetTouch( &CInteractableProp::InteractablePropTouch ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CInteractableProp::Precache( void ) +{ + BaseClass::Precache(); + + if (m_iszPressedSound != NULL_STRING) + PrecacheScriptSound( STRING(m_iszPressedSound) ); + if (m_iszLockedSound != NULL_STRING) + PrecacheScriptSound( STRING(m_iszLockedSound) ); +} + //----------------------------------------------------------------------------- // Purpose: // Input : *pActivator - @@ -2651,22 +2727,27 @@ END_DATADESC() // useType - // value - //----------------------------------------------------------------------------- -void CButtonProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) +void CInteractableProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if (m_flCooldownTime > gpGlobals->curtime) return; + int nSequence = -1; + if (m_bLocked) { m_OnLockedUse.FireOutput( pActivator, this ); EmitSound(STRING(m_iszLockedSound)); - return; + nSequence = LookupSequence( STRING( m_iszLockedSequence ) ); + m_iCurSequence = INTERACTSEQ_LOCKED; + } + else + { + m_OnPressed.FireOutput( pActivator, this ); + EmitSound(STRING(m_iszPressedSound)); + nSequence = LookupSequence( STRING( m_iszInSequence ) ); + m_iCurSequence = INTERACTSEQ_IN; } - - m_OnPressed.FireOutput( pActivator, this ); - EmitSound(STRING(m_iszPressedSound)); - - int nSequence = LookupSequence( STRING(m_iszInSequence) ); if ( nSequence > ACTIVITY_NOT_AVAILABLE ) { @@ -2681,8 +2762,23 @@ void CButtonProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE u //----------------------------------------------------------------------------- // Purpose: +// Input : *pOther - //----------------------------------------------------------------------------- -void CButtonProp::InputLock( inputdata_t &inputdata ) +void CInteractableProp::InteractablePropTouch( CBaseEntity *pOther ) +{ + // Do base touch function first + BreakablePropTouch( pOther ); + + if ( HasSpawnFlags(SF_INTERACTABLE_TOUCH_INTERACTS) && (!HasSpawnFlags(SF_INTERACTABLE_IGNORE_COMMANDS_WHEN_LOCKED) || !m_bLocked) && pOther->IsPlayer() ) + { + Use( pOther, pOther, USE_ON, 0 ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CInteractableProp::InputLock( inputdata_t &inputdata ) { m_bLocked = true; } @@ -2690,7 +2786,7 @@ void CButtonProp::InputLock( inputdata_t &inputdata ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CButtonProp::InputUnlock( inputdata_t &inputdata ) +void CInteractableProp::InputUnlock( inputdata_t &inputdata ) { m_bLocked = false; } @@ -2698,7 +2794,15 @@ void CButtonProp::InputUnlock( inputdata_t &inputdata ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CButtonProp::SetPushSequence(int iSequence) +void CInteractableProp::InputPress( inputdata_t &inputdata ) +{ + Use( inputdata.pActivator, inputdata.pCaller, USE_ON, 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CInteractableProp::SetPushSequence( int iSequence ) { m_iGoalSequence = iSequence; @@ -2711,7 +2815,7 @@ void CButtonProp::SetPushSequence(int iSequence) FinishSetSequence( nNextSequence ); } - SetThink( &CButtonProp::PushThink ); + SetThink( &CInteractableProp::PushThink ); if ( GetNextThink() <= gpGlobals->curtime ) SetNextThink( gpGlobals->curtime + flInterval ); } @@ -2719,7 +2823,7 @@ void CButtonProp::SetPushSequence(int iSequence) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CButtonProp::PushThink() +void CInteractableProp::PushThink() { if ( m_nPendingSequence != -1 ) { @@ -2727,6 +2831,8 @@ void CButtonProp::PushThink() m_nPendingSequence = -1; } + SetNextThink( gpGlobals->curtime + 0.1f ); + if ( ((m_iTransitionDirection > 0 && GetCycle() >= 0.999f) || (m_iTransitionDirection < 0 && GetCycle() <= 0.0f)) && !SequenceLoops() ) { if (!SequenceLoops()) @@ -2735,33 +2841,49 @@ void CButtonProp::PushThink() m_pOutputAnimOver.FireOutput(NULL, this); } - if (m_bOutting) + if (m_iCurSequence == INTERACTSEQ_OUT) { m_OnOut.FireOutput( NULL, this ); + + m_iCurSequence = INTERACTSEQ_NONE; } else { m_OnIn.FireOutput( NULL, this ); } } - else - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } StudioFrameAdvance(); DispatchAnimEvents(this); m_BoneFollowerManager.UpdateBoneFollowers(this); - if (m_flCooldownTime < gpGlobals->curtime && !m_bOutting) + if (m_flCooldownTime < gpGlobals->curtime) { - int nSequence = LookupSequence( STRING(m_iszOutSequence) ); - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) + if (m_iCurSequence == INTERACTSEQ_IN) { - SetPushSequence(nSequence); + int nSequence = LookupSequence( STRING(m_iszOutSequence) ); + if ( m_iszOutSequence != NULL_STRING && nSequence > ACTIVITY_NOT_AVAILABLE ) + { + m_iCurSequence = INTERACTSEQ_OUT; + SetPushSequence(nSequence); - // We still fire our inherited animation outputs - m_pOutputAnimBegun.FireOutput( NULL, this ); + // We still fire our inherited animation outputs + m_pOutputAnimBegun.FireOutput( NULL, this ); + } + else + { + m_iCurSequence = INTERACTSEQ_NONE; + } + } + + if (m_iCurSequence == INTERACTSEQ_NONE) + { + if (m_iszDefaultAnim != NULL_STRING) + { + PropSetAnim( STRING( m_iszDefaultAnim ) ); + } + + SetNextThink( TICK_NEVER_THINK ); } } } diff --git a/sp/src/game/server/rope.cpp b/sp/src/game/server/rope.cpp index dd8c3bbe..516015fe 100644 --- a/sp/src/game/server/rope.cpp +++ b/sp/src/game/server/rope.cpp @@ -842,9 +842,9 @@ bool CRopeKeyframe::KeyValue( const char *szKeyName, const char *szValue ) { #ifdef MAPBASE if ( atoi( szValue ) != 1 ) - { m_RopeFlags |= ROPE_USE_WIND; - } + else + m_RopeFlags &= ~ROPE_USE_WIND; #else if ( atoi( szValue ) == 1 ) { diff --git a/sp/src/game/server/sceneentity.cpp b/sp/src/game/server/sceneentity.cpp index 14936198..e43cdf33 100644 --- a/sp/src/game/server/sceneentity.cpp +++ b/sp/src/game/server/sceneentity.cpp @@ -139,6 +139,12 @@ public: bool IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes ); bool IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes ); +#ifdef MAPBASE + bool IsRunningScriptedSceneWithFlexAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes, const char *pszNotThisScene = NULL ); + + CUtlVector< CHandle< CSceneEntity > > *GetActiveSceneList(); +#endif + private: @@ -1575,7 +1581,11 @@ void CSceneEntity::DispatchEndGesture( CChoreoScene *scene, CBaseFlex *actor, CC void CSceneEntity::DispatchStartGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) { CBaseEntity *pTarget = FindNamedEntity( event->GetParameters2( ) ); +#ifdef MAPBASE + actor->AddSceneEvent( scene, event, pTarget, this ); +#else actor->AddSceneEvent( scene, event, pTarget ); +#endif } @@ -5668,6 +5678,40 @@ bool CSceneManager::IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pAc } +#ifdef MAPBASE +bool CSceneManager::IsRunningScriptedSceneWithFlexAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes, const char *pszNotThisScene ) +{ + int c = m_ActiveScenes.Count(); + for ( int i = 0; i < c; i++ ) + { + CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); + if ( !pScene || + !pScene->IsPlayingBack() || + pScene->IsPaused() || + ( bIgnoreInstancedScenes && dynamic_cast(pScene) != NULL ) || + ( pszNotThisScene == NULL || Q_strcmp( pszNotThisScene, STRING(pScene->m_iszSceneFile) ) == 0 ) + ) + { + continue; + } + + if ( pScene->InvolvesActor( pActor ) ) + { + if ( pScene->HasFlexAnimation() ) + return true; + } + } + return false; +} + + +CUtlVector< CHandle< CSceneEntity > > *CSceneManager::GetActiveSceneList() +{ + return &m_ActiveScenes; +} +#endif + + //----------------------------------------------------------------------------- // Purpose: // Input : *actor - @@ -5753,6 +5797,18 @@ bool IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgno return GetSceneManager()->IsRunningScriptedSceneWithSpeechAndNotPaused( pActor, bIgnoreInstancedScenes ); } +#ifdef MAPBASE +bool IsRunningScriptedSceneWithFlexAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes, const char *pszNotThisScene ) +{ + return GetSceneManager()->IsRunningScriptedSceneWithFlexAndNotPaused( pActor, bIgnoreInstancedScenes, pszNotThisScene ); +} + +CUtlVector< CHandle< CSceneEntity > > *GetActiveSceneList() +{ + return GetSceneManager()->GetActiveSceneList(); +} +#endif + //=========================================================================================================== // SCENE LIST MANAGER diff --git a/sp/src/game/server/sceneentity.h b/sp/src/game/server/sceneentity.h index 78a499a2..9bc5b4b0 100644 --- a/sp/src/game/server/sceneentity.h +++ b/sp/src/game/server/sceneentity.h @@ -39,6 +39,10 @@ bool IsRunningScriptedScene( CBaseFlex *pActor, bool bIgnoreInstancedScenes = tr bool IsRunningScriptedSceneAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes = true ); bool IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes = false ); bool IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes = false ); +#ifdef MAPBASE +bool IsRunningScriptedSceneWithFlexAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes = false, const char *pszNotThisScene = NULL ); +CUtlVector< CHandle< CSceneEntity > > *GetActiveSceneList(); +#endif float GetSceneDuration( char const *pszScene ); int GetSceneSpeechCount( char const *pszScene ); bool IsInInterruptableScenes( CBaseFlex *pActor ); diff --git a/sp/src/game/server/server_mapbase.vpc b/sp/src/game/server/server_mapbase.vpc index 0df92c87..0a138607 100644 --- a/sp/src/game/server/server_mapbase.vpc +++ b/sp/src/game/server/server_mapbase.vpc @@ -29,6 +29,8 @@ $Project $File "$SRCDIR\game\shared\mapbase\mapbase_game_log.cpp" $File "$SRCDIR\game\shared\mapbase\MapEdit.cpp" $File "$SRCDIR\game\shared\mapbase\MapEdit.h" + $File "$SRCDIR\game\shared\mapbase\matchers.cpp" + $File "$SRCDIR\game\shared\mapbase\matchers.h" $File "mapbase\ai_grenade.cpp" $File "mapbase\ai_grenade.h" @@ -43,7 +45,6 @@ $Project $File "mapbase\GlobalStrings.h" $File "mapbase\logic_externaldata.cpp" $File "mapbase\logic_skill.cpp" - $File "mapbase\matchers.h" $File "mapbase\point_advanced_finder.cpp" $File "mapbase\point_copy_size.cpp" $File "mapbase\point_damageinfo.cpp" diff --git a/sp/src/game/server/world.cpp b/sp/src/game/server/world.cpp index af1fea2b..460809cd 100644 --- a/sp/src/game/server/world.cpp +++ b/sp/src/game/server/world.cpp @@ -395,6 +395,10 @@ BEGIN_DATADESC( CWorld ) DEFINE_KEYFIELD( m_iszDetailSpriteMaterial, FIELD_STRING, "detailmaterial" ), DEFINE_KEYFIELD( m_bColdWorld, FIELD_BOOLEAN, "coldworld" ), +#ifdef MAPBASE + DEFINE_INPUTFUNC( FIELD_STRING, "SetChapterTitle", InputSetChapterTitle ), +#endif + END_DATADESC() @@ -755,3 +759,10 @@ bool CWorld::IsColdWorld( void ) { return m_bColdWorld; } + +#ifdef MAPBASE +void CWorld::InputSetChapterTitle( inputdata_t &inputdata ) +{ + m_iszChapterTitle.Set( inputdata.value.StringID() ); +} +#endif diff --git a/sp/src/game/server/world.h b/sp/src/game/server/world.h index 9c63432f..3737eb49 100644 --- a/sp/src/game/server/world.h +++ b/sp/src/game/server/world.h @@ -57,6 +57,8 @@ public: { return STRING(m_iszChapterTitle.Get()); } + + void InputSetChapterTitle( inputdata_t &inputdata ); #endif private: diff --git a/sp/src/game/shared/activitylist.cpp b/sp/src/game/shared/activitylist.cpp index 6a6b08b6..68805571 100644 --- a/sp/src/game/shared/activitylist.cpp +++ b/sp/src/game/shared/activitylist.cpp @@ -264,10 +264,6 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_RELOAD_LOW ); REGISTER_SHARED_ACTIVITY( ACT_ARM ); REGISTER_SHARED_ACTIVITY( ACT_DISARM ); -#ifdef COMPANION_HOLSTER_WORKAROUND - REGISTER_SHARED_ACTIVITY( ACT_ARM_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_DISARM_RIFLE ); -#endif REGISTER_SHARED_ACTIVITY( ACT_DROP_WEAPON ); REGISTER_SHARED_ACTIVITY( ACT_DROP_WEAPON_SHOTGUN ); @@ -511,11 +507,6 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_SMG2_TOAUTO ); REGISTER_SHARED_ACTIVITY( ACT_SMG2_TOBURST ); -#ifdef SHARED_COMBINE_ACTIVITIES - REGISTER_SHARED_ACTIVITY( ACT_COMBINE_THROW_GRENADE ); - REGISTER_SHARED_ACTIVITY( ACT_COMBINE_AR2_ALTFIRE ); -#endif - // Physcannon special activities REGISTER_SHARED_ACTIVITY( ACT_PHYSCANNON_UPGRADE ); @@ -569,10 +560,6 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_IDLE_RIFLE ); REGISTER_SHARED_ACTIVITY( ACT_IDLE_SMG1 ); REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_SMG1 ); -#if AR2_ACTIVITY_FIX == 1 - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AR2 ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_AR2 ); -#endif REGISTER_SHARED_ACTIVITY( ACT_IDLE_PISTOL ); REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_PISTOL ); REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_SHOTGUN ); @@ -591,25 +578,10 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_WALK_RIFLE_STIMULATED ); REGISTER_SHARED_ACTIVITY( ACT_RUN_RIFLE_STIMULATED ); -#if AR2_ACTIVITY_FIX == 1 - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AR2_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AR2_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AR2_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AR2_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AR2_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AR2_STIMULATED ); -#endif - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_RIFLE_STIMULATED ); REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_RIFLE_STIMULATED ); REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_RIFLE_STIMULATED ); -#if AR2_ACTIVITY_FIX == 1 - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_AR2_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_AR2_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_AR2_STIMULATED ); -#endif - REGISTER_SHARED_ACTIVITY( ACT_IDLE_SHOTGUN_RELAXED ); REGISTER_SHARED_ACTIVITY( ACT_IDLE_SHOTGUN_STIMULATED ); REGISTER_SHARED_ACTIVITY( ACT_IDLE_SHOTGUN_AGITATED ); @@ -648,13 +620,6 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_RUN_CROUCH_AIM_RIFLE ); REGISTER_SHARED_ACTIVITY( ACT_RUN_STEALTH_PISTOL ); -#if AR2_ACTIVITY_FIX == 1 - REGISTER_SHARED_ACTIVITY( ACT_WALK_AR2 ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_AR2 ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AR2 ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_AR2 ); -#endif - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_SHOTGUN ); REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_SHOTGUN ); @@ -673,18 +638,11 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_RELOAD_SMG1_LOW ); REGISTER_SHARED_ACTIVITY( ACT_RELOAD_SHOTGUN ); REGISTER_SHARED_ACTIVITY( ACT_RELOAD_SHOTGUN_LOW ); -#if AR2_ACTIVITY_FIX == 1 - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_AR2 ); - //REGISTER_SHARED_ACTIVITY( ACT_RELOAD_AR2_LOW ); -#endif REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD ); REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_PISTOL ); REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_SMG1 ); REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_SHOTGUN ); -#if AR2_ACTIVITY_FIX == 1 - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_AR2 ); -#endif // Busy animations REGISTER_SHARED_ACTIVITY( ACT_BUSY_LEAN_LEFT ); @@ -2317,6 +2275,42 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_SPELL_VM_ARM ); REGISTER_SHARED_ACTIVITY( ACT_SPELL_VM_FIRE ); +#if AR2_ACTIVITY_FIX == 1 + REGISTER_SHARED_ACTIVITY( ACT_IDLE_AR2 ); + REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_AR2 ); + + REGISTER_SHARED_ACTIVITY( ACT_IDLE_AR2_RELAXED ); + REGISTER_SHARED_ACTIVITY( ACT_IDLE_AR2_STIMULATED ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_AR2_RELAXED ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_AR2_RELAXED ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_AR2_STIMULATED ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_AR2_STIMULATED ); + + REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_AR2_STIMULATED ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_AR2_STIMULATED ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_AR2_STIMULATED ); + + REGISTER_SHARED_ACTIVITY( ACT_WALK_AR2 ); + REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_AR2 ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_AR2 ); + REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_AR2 ); + + REGISTER_SHARED_ACTIVITY( ACT_RELOAD_AR2 ); + //REGISTER_SHARED_ACTIVITY( ACT_RELOAD_AR2_LOW ); + + REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_AR2 ); +#endif + +#ifdef SHARED_COMBINE_ACTIVITIES + REGISTER_SHARED_ACTIVITY( ACT_COMBINE_THROW_GRENADE ); + REGISTER_SHARED_ACTIVITY( ACT_COMBINE_AR2_ALTFIRE ); +#endif + +#ifdef COMPANION_HOLSTER_WORKAROUND + REGISTER_SHARED_ACTIVITY( ACT_ARM_RIFLE ); + REGISTER_SHARED_ACTIVITY( ACT_DISARM_RIFLE ); +#endif + AssertMsg( g_HighestActivity == LAST_SHARED_ACTIVITY - 1, "Not all activities from ai_activity.h registered in activitylist.cpp" ); } diff --git a/sp/src/game/shared/baseplayer_shared.h b/sp/src/game/shared/baseplayer_shared.h index 609d82fb..fc5fdf0f 100644 --- a/sp/src/game/shared/baseplayer_shared.h +++ b/sp/src/game/shared/baseplayer_shared.h @@ -58,10 +58,13 @@ void CopySoundNameWithModifierToken( char *pchDest, const char *pchSource, int n // These are only meant to be used internally or accessed via logic_playerproxy. // I'm sure this isn't a bad idea whatsoever... // +// They start at 16 because some NPC spawnflags (e.g. Wait Till Seen) +// used in places with both NPCs and players don't check whether the target is a NPC or a player. +// Spawnflags are also transmitted to the client and use a special network proxy to get around this without having to transmit unused bits. // Be sure to update the SendPropInt() entry for m_spawnflags in player.cpp when you add any new spawnflags! -#define SF_PLAYER_NO_GEIGER (1 << 0) -#define SF_PLAYER_HIDE_SQUAD_HUD (1 << 1) -#define SF_PLAYER_SUPPRESS_FIRING (1 << 2) +#define SF_PLAYER_NO_GEIGER (1 << 16) +#define SF_PLAYER_HIDE_SQUAD_HUD (1 << 17) +#define SF_PLAYER_SUPPRESS_FIRING (1 << 18) #endif // Shared header file for players diff --git a/sp/src/game/shared/mapbase/mapbase_rpc.cpp b/sp/src/game/shared/mapbase/mapbase_rpc.cpp index 2c7d34b7..592060ef 100644 --- a/sp/src/game/shared/mapbase/mapbase_rpc.cpp +++ b/sp/src/game/shared/mapbase/mapbase_rpc.cpp @@ -301,6 +301,10 @@ static void HandleDiscordJoinRequest(const DiscordUser* request) void MapbaseRPC_Init() { + // Only init if RPC is enabled + if (mapbase_rpc_enabled.GetInt() <= 0) + return; + // First, load the config // (we need its values immediately) KeyValues *pKV = new KeyValues( "MapbaseRPC" ); @@ -463,15 +467,20 @@ void MapbaseRPC_GetDiscordMapInfo( char *pDetails, size_t iSize, const char *pMa } else { + // Show the chapter title first + const char *szChapterTitle = NULL; + C_World *pWorld = GetClientWorldEntity(); if ( pWorld && pWorld->m_iszChapterTitle[0] != '\0' ) { - // Show the chapter title first - const char *pChapterTitle = g_pVGuiLocalize->FindAsUTF8( pWorld->m_iszChapterTitle ); - if (!pChapterTitle || pChapterTitle[0] == '\0') - pChapterTitle = pWorld->m_iszChapterTitle; + szChapterTitle = g_pVGuiLocalize->FindAsUTF8( pWorld->m_iszChapterTitle ); + if (!szChapterTitle || szChapterTitle[0] == '\0') + szChapterTitle = pWorld->m_iszChapterTitle; + } - Q_snprintf( pDetails, iSize, "%s (%s)", pChapterTitle, pMapName ); + if (szChapterTitle) + { + Q_snprintf( pDetails, iSize, "%s (%s)", szChapterTitle, pMapName ); } else { diff --git a/sp/src/game/shared/mapbase/mapbase_shared.cpp b/sp/src/game/shared/mapbase/mapbase_shared.cpp index 188f6dd2..31523c1b 100644 --- a/sp/src/game/shared/mapbase/mapbase_shared.cpp +++ b/sp/src/game/shared/mapbase/mapbase_shared.cpp @@ -24,6 +24,7 @@ #include "soundscape_system.h" #include "AI_ResponseSystem.h" #include "mapbase/SystemConvarMod.h" +#include "gameinterface.h" #endif // memdbgon must be the last include file in a .cpp file!!! @@ -170,7 +171,11 @@ public: if (!gameinfo->GetBool("hide_mod_name", false)) { // Store the game's name - Q_strncpy(g_iszGameName, gameinfo->GetString("game"), sizeof(g_iszGameName)); + const char *pszGameName = gameinfo->GetString("game_rpc", NULL); + if (pszGameName == NULL) + pszGameName = gameinfo->GetString("game"); + + Q_strncpy(g_iszGameName, pszGameName, sizeof(g_iszGameName)); } } gameinfo->deleteThis(); @@ -370,6 +375,51 @@ BEGIN_DATADESC_NO_BASE( CMapbaseSystem ) END_DATADESC() #ifdef GAME_DLL +static CUtlVector g_MapbaseChapterMaps; +static CUtlVector g_MapbaseChapterList; +CUtlVector *Mapbase_GetChapterMaps() +{ + if (g_MapbaseChapterMaps.Count() == 0) + { + // Check the chapter list + KeyValues *chapterlist = new KeyValues("ChapterList"); + if (chapterlist->LoadFromFile(filesystem, "scripts/chapters.txt", "MOD")) + { + KeyValues *pKey = chapterlist->GetFirstSubKey(); + if (pKey) + { + if (Q_stricmp( pKey->GetName(), "Chapters" ) == 0) + { + for (KeyValues *pChapters = pKey->GetFirstSubKey(); pChapters; pChapters = pChapters->GetNextKey()) + { + int index = g_MapbaseChapterList.AddToTail(); + g_MapbaseChapterList[index].iChapter = atoi(pChapters->GetName()); + Q_strncpy(g_MapbaseChapterList[index].pChapterName, pChapters->GetString(), sizeof(g_MapbaseChapterList[index])); + } + } + + for (pKey = pKey->GetNextKey(); pKey; pKey = pKey->GetNextKey()) + { + int index = g_MapbaseChapterMaps.AddToTail(); + Q_strncpy(g_MapbaseChapterMaps[index].pBSPName, pKey->GetName(), sizeof(g_MapbaseChapterMaps[index].pBSPName)); + Q_strncpy(g_MapbaseChapterMaps[index].pTitleName, pKey->GetString(), sizeof(g_MapbaseChapterMaps[index].pTitleName)); + + //comment.pBSPName = pKey->GetName(); + //comment.pTitleName = pKey->GetString(); + } + } + } + chapterlist->deleteThis(); + } + + return &g_MapbaseChapterMaps; +} + +CUtlVector *Mapbase_GetChapterList() +{ + return &g_MapbaseChapterList; +} + ThreeState_t Flashlight_GetLegacyVersionKey() { KeyValues *gameinfo = new KeyValues( "GameInfo" ); diff --git a/sp/src/game/shared/mapbase/matchers.cpp b/sp/src/game/shared/mapbase/matchers.cpp new file mode 100644 index 00000000..b66cf40f --- /dev/null +++ b/sp/src/game/shared/mapbase/matchers.cpp @@ -0,0 +1,234 @@ +//========= Copyright Valve Corporation, All rights reserved. ================= +// +// Purpose: General matching functions for things like wildcards and !=. +// +// $NoKeywords: $ +//============================================================================= + +#include "cbase.h" + +#include "matchers.h" +#include "fmtstr.h" +#include + +ConVar mapbase_wildcards_enabled("mapbase_wildcards_enabled", "1", FCVAR_NONE, "Toggles Mapbase's '?' wildcard and true '*' features. Useful for maps that have '?' in their targetnames."); +ConVar mapbase_regex_enabled("mapbase_regex_enabled", "1", FCVAR_NONE, "Toggles Mapbase's regex matching handover."); + +#ifdef CLIENT_DLL +// FIXME: There is no clientside equivalent to the RS code +bool ResponseSystemCompare(const char *criterion, const char *value) { return Matcher_NamesMatch(criterion, value); } +#else +extern bool ResponseSystemCompare(const char *criterion, const char *value); +#endif + +//============================================================================= +// These are the "matchers" that compare with wildcards ("any*" for text starting with "any") +// and operators (<3 for numbers less than 3). +// +// Matcher_Match - Matching function using RS operators and NamesMatch wildcards/regex. +// Matcher_Regex - Uses regex functions from the std library. +// Matcher_NamesMatch - Based on Valve's original NamesMatch function, using wildcards and regex. +// +// AppearsToBeANumber - Response System-based function which checks if the string might be a number. +//============================================================================= + +inline bool Matcher_Match(const char *pszQuery, const char *szValue) +{ + // I wasn't kidding when I said all this did was hijack response system matching. + return ResponseSystemCompare(pszQuery, szValue); +} + +inline bool Matcher_Match(const char *pszQuery, int iValue) { return Matcher_Match(pszQuery, CNumStr(iValue)); } +inline bool Matcher_Match(const char *pszQuery, float flValue) { return Matcher_Match(pszQuery, CNumStr(flValue)); } + +// ------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------- + +// The recursive part of Mapbase's modified version of Valve's NamesMatch(). +// This part is no longer inlined since it's recursive. +/*FORCEINLINE*/ bool Matcher_RunCharCompare(const char *pszQuery, const char *szValue) +{ + // This matching model is based off of the ASW SDK + while ( *szValue && *pszQuery ) + { + char cName = *szValue; + char cQuery = *pszQuery; + if ( cName != cQuery && tolower(cName) != tolower(cQuery) ) // people almost always use lowercase, so assume that first + { + // Now we'll try the new and improved Mapbase wildcards! + switch (*pszQuery) + { + case '*': + { + // Return true at classic trailing * + if ( *(pszQuery+1) == 0 ) + return true; + + if (mapbase_wildcards_enabled.GetBool()) + { + // There's text after this * which we need to test. + // This recursion allows for multiple wildcards + int vlen = Q_strlen(szValue); + ++pszQuery; + for (int i = 0; i < vlen; i++) + { + if (Matcher_RunCharCompare(pszQuery, szValue + i)) + return true; + } + } + return false; + } break; + case '?': + // Just skip if we're capable of lazy wildcards + if (mapbase_wildcards_enabled.GetBool()) + break; + default: + return false; + } + } + ++szValue; + ++pszQuery; + } + + // Include a classic trailing * check for when szValue is something like "value" and pszQuery is "value*" + return ( ( *pszQuery == 0 && *szValue == 0 ) || *pszQuery == '*' ); +} + +// Regular expressions based off of the std library. +// The C++ is strong in this one. +bool Matcher_Regex(const char *pszQuery, const char *szValue) +{ + std::regex regex; + + // Since I can't find any other way to check for valid regex, + // use a try-catch here to see if it throws an exception. + try { regex = std::regex(pszQuery); } + catch (std::regex_error &e) + { + Msg("Invalid regex \"%s\" (%s)\n", pszQuery, e.what()); + return false; + } + + std::match_results results; + bool bMatch = std::regex_match( szValue, results, regex ); + if (!bMatch) + return false; + + // Only match the *whole* string + return Q_strlen(results.str(0).c_str()) == Q_strlen(szValue); +} + +// The entry point for Mapbase's modified version of Valve's NamesMatch(). +FORCEINLINE bool Matcher_NamesMatch(const char *pszQuery, const char *szValue) +{ + if ( szValue == NULL ) + return (*pszQuery == 0 || *pszQuery == '*'); + + // If the pointers are identical, we're identical + if ( szValue == pszQuery ) + return true; + + // Check for regex + if ( *pszQuery == '@' && mapbase_regex_enabled.GetBool() ) + { + // Make sure it has a forward slash + // (prevents confusion with instance fixup escape) + if (*(pszQuery+1) == '/') + { + return Matcher_Regex( pszQuery+2, szValue ); + } + } + + return Matcher_RunCharCompare( pszQuery, szValue ); +} + +FORCEINLINE bool Matcher_NamesMatch_Classic(const char *pszQuery, const char *szValue) +{ + if ( szValue == NULL ) + return (!pszQuery || *pszQuery == 0 || *pszQuery == '*'); + + // If the pointers are identical, we're identical + if ( szValue == pszQuery ) + return true; + + while ( *szValue && *pszQuery ) + { + unsigned char cName = *szValue; + unsigned char cQuery = *pszQuery; + // simple ascii case conversion + if ( cName == cQuery ) + ; + else if ( cName - 'A' <= (unsigned char)'Z' - 'A' && cName - 'A' + 'a' == cQuery ) + ; + else if ( cName - 'a' <= (unsigned char)'z' - 'a' && cName - 'a' + 'A' == cQuery ) + ; + else + break; + ++szValue; + ++pszQuery; + } + + if ( *pszQuery == 0 && *szValue == 0 ) + return true; + + // @TODO (toml 03-18-03): Perhaps support real wildcards. Right now, only thing supported is trailing * + if ( *pszQuery == '*' ) + return true; + + return false; +} + +FORCEINLINE bool Matcher_NamesMatch_MutualWildcard(const char *pszQuery, const char *szValue) +{ + if ( szValue == NULL ) + return (!pszQuery || *pszQuery == 0 || *pszQuery == '*'); + + if ( pszQuery == NULL ) + return (!szValue || *szValue == 0 || *szValue == '*'); + + // If the pointers are identical, we're identical + if ( szValue == pszQuery ) + return true; + + while ( *szValue && *pszQuery ) + { + unsigned char cName = *szValue; + unsigned char cQuery = *pszQuery; + // simple ascii case conversion + if ( cName == cQuery ) + ; + else if ( cName - 'A' <= (unsigned char)'Z' - 'A' && cName - 'A' + 'a' == cQuery ) + ; + else if ( cName - 'a' <= (unsigned char)'z' - 'a' && cName - 'a' + 'A' == cQuery ) + ; + else + break; + ++szValue; + ++pszQuery; + } + + if ( *pszQuery == 0 && *szValue == 0 ) + return true; + + // @TODO (toml 03-18-03): Perhaps support real wildcards. Right now, only thing supported is trailing * + if ( *pszQuery == '*' || *szValue == '*' ) + return true; + + return false; +} + +// Matcher_Compare is a deprecated alias originally used when Matcher_Match didn't support wildcards. +/* +inline bool Matcher_Compare(const char *pszQuery, const char *szValue) +{ + return Matcher_Match(pszQuery, szValue); +#if 0 + // I have to do this so wildcards could test *before* the response system comparison. + // I know it removes the operators twice, but I won't worry about it. + bool match = Matcher_NamesMatch(Matcher_RemoveOperators(pszQuery), szValue); + if (match) + return Matcher_Match(pszQuery, szValue); + return false; +#endif +} +*/ diff --git a/sp/src/game/shared/mapbase/matchers.h b/sp/src/game/shared/mapbase/matchers.h new file mode 100644 index 00000000..dc2528ae --- /dev/null +++ b/sp/src/game/shared/mapbase/matchers.h @@ -0,0 +1,59 @@ +//========= Copyright Valve Corporation, All rights reserved. ================= +// +// Purpose: General matching functions for things like wildcards and !=. +// +// $NoKeywords: $ +//============================================================================= + +#define MAPBASE_MATCHERS 1 + +// Compares with != and the like. Basically hijacks the response system matching. +// This also loops back around to Matcher_NamesMatch. +// pszQuery = The value that should have the operator(s) at the beginning. +// szValue = The value tested against the criterion. +extern bool Matcher_Match( const char *pszQuery, const char *szValue ); +extern bool Matcher_Match( const char *pszQuery, int iValue ); +extern bool Matcher_Match( const char *pszQuery, float flValue ); + +// Regular expressions based off of the std library. +// pszQuery = The regex text. +// szValue = The value that should be matched. +extern bool Matcher_Regex( const char *pszQuery, const char *szValue ); + +// Compares two strings with support for wildcards or regex. This code is an expanded version of baseentity.cpp's NamesMatch(). +// pszQuery = The value that should have the wildcard. +// szValue = The value tested against the query. +// Use Matcher_Match if you want <, !=, etc. as well. +extern bool Matcher_NamesMatch( const char *pszQuery, const char *szValue ); + +// Identical to baseentity.cpp's original NamesMatch(). +// pszQuery = The value that should have the wildcard. +// szValue = The value tested against the query. +extern bool Matcher_NamesMatch_Classic( const char *pszQuery, const char *szValue ); + +// Identical to Matcher_NamesMatch_Classic(), but either value could use a wildcard. +// pszQuery = The value that serves as the query. This value can use wildcards. +// szValue = The value tested against the query. This value can use wildcards as well. +extern bool Matcher_NamesMatch_MutualWildcard( const char *pszQuery, const char *szValue ); + +// Deprecated; do not use +inline bool Matcher_Compare( const char *pszQuery, const char *szValue ) { return Matcher_Match( pszQuery, szValue ); } + +// Taken from the Response System. +// Checks if the specified string appears to be a number of some sort. +static bool AppearsToBeANumber( char const *token ) +{ + if ( atof( token ) != 0.0f ) + return true; + + char const *p = token; + while ( *p ) + { + if ( *p != '0' ) + return false; + + p++; + } + + return true; +} diff --git a/sp/src/game/shared/point_posecontroller.cpp b/sp/src/game/shared/point_posecontroller.cpp index 660d6248..43404fc8 100644 --- a/sp/src/game/shared/point_posecontroller.cpp +++ b/sp/src/game/shared/point_posecontroller.cpp @@ -326,6 +326,13 @@ void CPoseController::InputGetFMod( inputdata_t &inputdata ) m_fFModAmplitude.Get() ); } +#ifdef MAPBASE +void CPoseController::InputSetTarget( inputdata_t &inputdata ) +{ + SetPropName( inputdata.value.String() ); +} +#endif + #else //#ifndef CLIENT_DLL //----------------------------------------------------------------------------- diff --git a/sp/src/game/shared/point_posecontroller.h b/sp/src/game/shared/point_posecontroller.h index 2e11bc5e..ab8e2e83 100644 --- a/sp/src/game/shared/point_posecontroller.h +++ b/sp/src/game/shared/point_posecontroller.h @@ -73,6 +73,10 @@ public: void InputRandomizeFMod( inputdata_t &inputdata ); void InputGetFMod( inputdata_t &inputdata ); +#ifdef MAPBASE + void InputSetTarget( inputdata_t &inputdata ); +#endif + private: CNetworkArray( EHANDLE, m_hProps, MAX_POSE_CONTROLLED_PROPS ); // Handles to controlled models diff --git a/sp/src/materialsystem/stdshaders/BaseVSShader.cpp b/sp/src/materialsystem/stdshaders/BaseVSShader.cpp index a44cf766..440ceb32 100644 --- a/sp/src/materialsystem/stdshaders/BaseVSShader.cpp +++ b/sp/src/materialsystem/stdshaders/BaseVSShader.cpp @@ -54,6 +54,10 @@ static ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT ); // NOTE: This is externed in BaseVSShader.h so it needs to be here ConVar r_flashlightbrightness( "r_flashlightbrightness", "0.25", FCVAR_CHEAT ); +#ifdef MAPBASE +ConVar mat_specular_disable_on_missing( "mat_specular_disable_on_missing", "1", FCVAR_ARCHIVE, "Disables specular reflections on a material when the envmap cannot be found." ); +#endif + // These functions are to be called from the shaders. //----------------------------------------------------------------------------- diff --git a/sp/src/materialsystem/stdshaders/BaseVSShader.h b/sp/src/materialsystem/stdshaders/BaseVSShader.h index 69c06f4e..ef6b8660 100644 --- a/sp/src/materialsystem/stdshaders/BaseVSShader.h +++ b/sp/src/materialsystem/stdshaders/BaseVSShader.h @@ -25,6 +25,11 @@ #define SUPPORT_DX8 1 #define SUPPORT_DX7 1 #endif + +#ifdef MAPBASE +extern ConVar mat_specular_disable_on_missing; +#endif + //----------------------------------------------------------------------------- // Helper macro for vertex shaders //----------------------------------------------------------------------------- diff --git a/sp/src/materialsystem/stdshaders/SDK_skin_ps20b.fxc b/sp/src/materialsystem/stdshaders/SDK_skin_ps20b.fxc index 8b54473d..852002c9 100644 --- a/sp/src/materialsystem/stdshaders/SDK_skin_ps20b.fxc +++ b/sp/src/materialsystem/stdshaders/SDK_skin_ps20b.fxc @@ -185,7 +185,12 @@ float4 main( PS_INPUT i ) : COLOR float3 worldSpaceNormal, tangentSpaceNormal; float fSpecMask = 1.0f; +#if !DETAILTEXTURE + // Blixibon - $bumpmap transform support + float4 normalTexel = tex2D( NormalMapSampler, i.baseTexCoordDetailTexCoord.zw ); +#else float4 normalTexel = tex2D( NormalMapSampler, i.baseTexCoordDetailTexCoord.xy ); +#endif #if WRINKLEMAP float4 wrinkleNormal = tex2D( NormalWrinkleSampler, i.baseTexCoordDetailTexCoord.xy ); diff --git a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps20b.fxc b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps20b.fxc index 1bc6cdad..7b1cfc68 100644 --- a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps20b.fxc +++ b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps20b.fxc @@ -203,7 +203,12 @@ float4 main( PS_INPUT i ) : COLOR #endif float specularFactor = 1.0f; +#if !DETAILTEXTURE + // Blixibon - $bumpmap transform support + float4 normalTexel = tex2D( BumpmapSampler, i.detailTexCoord_atten3.xy ); +#else float4 normalTexel = tex2D( BumpmapSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); +#endif float3 tangentSpaceNormal = normalTexel * 2.0f - 1.0f; if ( bNormalMapAlphaEnvmapMask ) diff --git a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps2x.fxc b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps2x.fxc index c4ba4bdc..ad37fd5d 100644 --- a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps2x.fxc +++ b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_bump_ps2x.fxc @@ -200,7 +200,12 @@ float4 main( PS_INPUT i ) : COLOR #endif float specularFactor = 1.0f; +#if !DETAILTEXTURE + // Blixibon - $bumpmap transform support + float4 normalTexel = tex2D( BumpmapSampler, i.detailTexCoord_atten3.xy ); +#else float4 normalTexel = tex2D( BumpmapSampler, i.baseTexCoord2_tangentSpaceVertToEyeVectorXY.xy ); +#endif float3 tangentSpaceNormal = normalTexel * 2.0f - 1.0f; if ( bNormalMapAlphaEnvmapMask ) diff --git a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_ps20b.fxc b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_ps20b.fxc index d4650f52..e78ed5d8 100644 --- a/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_ps20b.fxc +++ b/sp/src/materialsystem/stdshaders/SDK_vertexlit_and_unlit_generic_ps20b.fxc @@ -328,7 +328,12 @@ float4 main( PS_INPUT i ) : COLOR float4 envmapMaskTexel; if( bEnvmapMask ) { +#if !DETAILTEXTURE + // Blixibon - $envmapmask transform support + envmapMaskTexel = tex2D( EnvmapMaskSampler, i.detailTexCoord.xy ); +#else envmapMaskTexel = tex2D( EnvmapMaskSampler, i.baseTexCoord.xy ); +#endif specularFactor *= envmapMaskTexel.xyz; } diff --git a/sp/src/materialsystem/stdshaders/game_shader_dx9_mapbase.vpc b/sp/src/materialsystem/stdshaders/game_shader_dx9_mapbase.vpc index d0ab9d1c..fc9b4378 100644 --- a/sp/src/materialsystem/stdshaders/game_shader_dx9_mapbase.vpc +++ b/sp/src/materialsystem/stdshaders/game_shader_dx9_mapbase.vpc @@ -4,6 +4,15 @@ // Project Script for Mapbase shader changes //----------------------------------------------------------------------------- +$Configuration +{ + $Compiler + { + // https://developer.valvesoftware.com/wiki/Parallax_Corrected_Cubemaps + $PreprocessorDefinitions "$BASE;PARALLAX_CORRECTED_CUBEMAPS" + } +} + $Project { $Folder "Source Files" diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp index 49cfe8ae..d04b7e2e 100644 --- a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.cpp @@ -241,6 +241,21 @@ void InitParamsLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** pa } } +#ifdef MAPBASE +// Created for the missing cubemap solution below +void LoadLightmappedGenericEnvmap( CBaseVSShader *pShader, IMaterialVar** params, LightmappedGeneric_DX9_Vars_t &info ) +{ + if ( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) + { + pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); + } + else + { + pShader->LoadTexture( info.m_nEnvmap ); + } +} +#endif + void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, LightmappedGeneric_DX9_Vars_t &info ) { if ( g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined() ) @@ -303,6 +318,20 @@ void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, if (params[info.m_nEnvmap]->IsDefined()) { +#ifdef MAPBASE + LoadLightmappedGenericEnvmap( pShader, params, info ); + + if (mat_specular_disable_on_missing.GetBool()) + { + // Revert to defaultcubemap when the envmap texture is missing + // (should be equivalent to toolsblack in Mapbase) + if (params[info.m_nEnvmap]->GetTextureValue()->IsError()) + { + params[info.m_nEnvmap]->SetStringValue( "engine/defaultcubemap" ); + LoadLightmappedGenericEnvmap( pShader, params, info ); + } + } +#else if ( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) ) { pShader->LoadCubeMap( info.m_nEnvmap, g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ); @@ -311,6 +340,7 @@ void InitLightmappedGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, { pShader->LoadTexture( info.m_nEnvmap ); } +#endif if ( !g_pHardwareConfig->SupportsCubeMaps() ) { diff --git a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h index 87722348..9f5d26f6 100644 --- a/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h +++ b/sp/src/materialsystem/stdshaders/lightmappedgeneric_dx9_helper.h @@ -11,11 +11,6 @@ #include #include "BaseVSShader.h" -#ifdef MAPBASE -// This requires custom compilers, but anyone ahead of us on that should be able to use this anyway -#define PARALLAX_CORRECTED_CUBEMAPS 1 -#endif - //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- diff --git a/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp index 1f27201d..7a59c9d8 100644 --- a/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp +++ b/sp/src/materialsystem/stdshaders/skin_dx9_helper.cpp @@ -734,10 +734,21 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform ); +#ifdef MAPBASE + // The original code makes it seem like we have the opportunity to support both $bumptransform and $detail at the same time, + // and that may or may not have been Valve's intention, but we'd need to add another texcoord for this and it's already + // a limitation with the non-skin shader anyway. + if ( bHasBump ) + { + pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform ); + } + else +#else if( bHasBump ) { pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform ); } +#endif if ( hasDetailTexture ) { diff --git a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp index 7b6e2598..fec69122 100644 --- a/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp +++ b/sp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp @@ -969,6 +969,18 @@ static void DrawVertexLitGeneric_DX9_Internal( CBaseVSShader *pShader, IMaterial pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant4( 10, 1, 1, 1, 1 ); } } +#ifdef MAPBASE + else if ( bHasEnvmapMask && info.m_nEnvmapMaskTransform != -1 ) + { + // Use $envmapmasktransform when there is no detail texture taking up this space + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nEnvmapMaskTransform ); + } + else if ( bHasBump && info.m_nBumpTransform != -1 ) + { + // Use $bumptransform when there is no detail texture taking up this space + pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform ); + } +#endif if ( bDistanceAlpha ) { float flSoftStart = GetFloatParam( info.m_nEdgeSoftnessStart, params ); diff --git a/sp/src/utils/vbsp/matrixinvert.h b/sp/src/utils/vbsp/matrixinvert.h new file mode 100644 index 00000000..6e676ad3 --- /dev/null +++ b/sp/src/utils/vbsp/matrixinvert.h @@ -0,0 +1,117 @@ +// By Jason Yu-Tseh Chi +// From http://chi3x10.wordpress.com/2008/05/28/calculate-matrix-inversion-in-c/ +// Modified to work with valve's matrix_3x4_t + +#include "mathlib\mathlib.h" + +// Calculate the cofactor of element (row,col) +int GetMatrixMinor(float **src, float **dest, int row, int col, int order) +{ + // Indicate which col and row is being copied to dest + int colCount = 0, rowCount = 0; + + for (int i = 0; i < order; i++) + { + if (i != row) + { + colCount = 0; + for (int j = 0; j < order; j++) + { + // When j is not the element + if (j != col) + { + dest[rowCount][colCount] = src[i][j]; + colCount++; + } + } + rowCount++; + } + } + + return 1; +} + +// Calculate the determinant recursively. +double CalcMatrixDeterminant(float **mat, int order) +{ + // Order must be >= 0 + // Stop the recursion when matrix is a single element + if (order == 1) + return mat[0][0]; + + // The determinant value + float det = 0; + + // Allocate the cofactor matrix + float **minor; + minor = new float*[order - 1]; + for (int i = 0; inodes[s] ); } } + +#ifdef MAPBASE + if (!noleaktest) + { + Warning( ("--- AREAPORTAL LEAK ---\n") ); + exit(0); + } +#endif } diff --git a/sp/src/utils/vbsp/vbsp.cpp b/sp/src/utils/vbsp/vbsp.cpp index c1fae6e6..083bc576 100644 --- a/sp/src/utils/vbsp/vbsp.cpp +++ b/sp/src/utils/vbsp/vbsp.cpp @@ -61,7 +61,7 @@ bool g_DisableWaterLighting = false; bool g_bAllowDetailCracks = false; bool g_bNoVirtualMesh = false; #ifdef MAPBASE -bool g_bNoDefaultCubemaps = false; +bool g_bNoDefaultCubemaps = true; #endif float g_defaultLuxelSize = DEFAULT_LUXEL_SIZE; @@ -1156,9 +1156,12 @@ int RunVBSP( int argc, char **argv ) EnableFullMinidumps( true ); } #ifdef MAPBASE - else if ( !Q_stricmp( argv[i], "-nodefaultcubemap" ) ) + // Thanks to Mapbase's shader changes, default cubemaps are no longer needed. + // The command has been switched from "-nodefaultcubemap" to "-defaultcubemap", + // meaning maps are compiled without them by default. + else if ( !Q_stricmp( argv[i], "-defaultcubemap" ) ) { - g_bNoDefaultCubemaps = true; + g_bNoDefaultCubemaps = false; } #endif else if (argv[i][0] == '-')