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
This commit is contained in:
Blixibon 2020-02-05 19:08:49 +00:00
parent b8611071c5
commit c5f3fa0778
63 changed files with 1909 additions and 335 deletions

View File

@ -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 );

View File

@ -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

View File

@ -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;

View File

@ -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"
}

View File

@ -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<C_BasePlayer> 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

View File

@ -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
}

View File

@ -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)
{

View File

@ -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 );

View File

@ -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

View File

@ -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 \"<pose parameter name> <value>\"\n", inputdata.value.String());
}
}
#endif
//-----------------------------------------------------------------------------

View File

@ -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

View File

@ -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.
//-----------------------------------------------------------------------------

View File

@ -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 );

View File

@ -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() )
{

View File

@ -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 );

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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)

View File

@ -1727,9 +1727,41 @@ static TITLECOMMENT gTitleComments[] =
#endif
};
#ifdef MAPBASE
extern CUtlVector<MODTITLECOMMENT> *Mapbase_GetChapterMaps();
extern CUtlVector<MODCHAPTER> *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<MODTITLECOMMENT> *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<MODTITLECOMMENT> *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<MODTITLECOMMENT> *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<MODCHAPTER> *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() )
{

View File

@ -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

View File

@ -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;

View File

@ -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();
}

View File

@ -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

View File

@ -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");

View File

@ -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 )
{

View File

@ -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;

View File

@ -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<CBasePlayer>, m_hPlayer );
#else
CHandle<CBasePlayer> 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

View File

@ -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 );

View File

@ -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.
//-----------------------------------------------------------------------------

View File

@ -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<BASE_NPC>::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 <class BASE_NPC>
void CAI_GrenadeUser<BASE_NPC>::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
//-----------------------------------------------------------------------------

View File

@ -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;
}

View File

@ -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

View File

@ -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 );
}
}
}

View File

@ -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 )
{

View File

@ -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<CInstancedSceneEntity *>(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

View File

@ -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 );

View File

@ -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"

View File

@ -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

View File

@ -57,6 +57,8 @@ public:
{
return STRING(m_iszChapterTitle.Get());
}
void InputSetChapterTitle( inputdata_t &inputdata );
#endif
private:

View File

@ -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" );
}

View File

@ -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

View File

@ -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
{

View File

@ -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<MODTITLECOMMENT> g_MapbaseChapterMaps;
static CUtlVector<MODCHAPTER> g_MapbaseChapterList;
CUtlVector<MODTITLECOMMENT> *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<MODCHAPTER> *Mapbase_GetChapterList()
{
return &g_MapbaseChapterList;
}
ThreeState_t Flashlight_GetLegacyVersionKey()
{
KeyValues *gameinfo = new KeyValues( "GameInfo" );

View File

@ -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 <regex>
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<const char*> 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
}
*/

View File

@ -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;
}

View File

@ -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
//-----------------------------------------------------------------------------

View File

@ -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

View File

@ -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.
//-----------------------------------------------------------------------------

View File

@ -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
//-----------------------------------------------------------------------------

View File

@ -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 );

View File

@ -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 )

View File

@ -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 )

View File

@ -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;
}

View File

@ -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"

View File

@ -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() )
{

View File

@ -11,11 +11,6 @@
#include <string.h>
#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
//-----------------------------------------------------------------------------

View File

@ -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 )
{

View File

@ -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 );

View File

@ -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; i<order - 1; i++)
minor[i] = new float[order - 1];
for (int i = 0; i < order; i++)
{
// Get minor of element (0,i)
GetMatrixMinor(mat, minor, 0, i, order);
// The recusion is here!
det += (i % 2 == 1 ? -1.0 : 1.0) * mat[0][i] * CalcMatrixDeterminant(minor, order - 1);
//det += pow( -1.0, i ) * mat[0][i] * CalcMatrixDeterminant( minor,order-1 );
}
// Release memory
for (int i = 0; i<order - 1; i++)
delete[] minor[i];
delete[] minor;
return det;
}
// Matrix inversion
void MatrixInversion(matrix3x4_t &in, matrix3x4_t &out)
{
float **A;
A = new float*[4];
for (int i = 0; i < 4; i++)
A[i] = new float[4];
int order = 4;
// Load in into A
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
A[i][j] = in[i][j];
}
}
A[3][0] = A[3][1] = A[3][2] = 0;
A[3][3] = 1;
// Get the determinant of a
double det = 1.0 / CalcMatrixDeterminant((float**)A, order);
// Memory allocation
float *temp = new float[(order - 1)*(order - 1)];
float **minor = new float*[order - 1];
for (int i = 0; i<order - 1; i++)
minor[i] = temp + (i*(order - 1));
for (int j = 0; j<order; j++)
{
for (int i = 0; i<order; i++)
{
// Get the co-factor (matrix) of A(j,i)
GetMatrixMinor((float**)A, minor, j, i, order);
out[i][j] = det*CalcMatrixDeterminant(minor, order - 1);
if ((i + j) % 2 == 1)
out[i][j] = -out[i][j];
}
}
// Release memory
for (int i = 0; i < 4; i++)
delete A[i];
delete A;
//delete [] minor[0];
delete[] temp;
delete[] minor;
}

View File

@ -920,6 +920,9 @@ void FindAreas_r (node_t *node)
FloodAreas_r (node, NULL);
}
#ifdef MAPBASE
extern qboolean noleaktest;
#endif
void ReportAreaportalLeak( tree_t *tree, node_t *node )
{
@ -968,6 +971,14 @@ void ReportAreaportalLeak( tree_t *tree, node_t *node )
AreaportalLeakFile( tree, pStart, pBest, pBest->nodes[s] );
}
}
#ifdef MAPBASE
if (!noleaktest)
{
Warning( ("--- AREAPORTAL LEAK ---\n") );
exit(0);
}
#endif
}

View File

@ -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] == '-')