mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2024-12-26 06:45:31 +03:00
commit
7f0aec4371
2
.github/workflows/mapbase_build-base.yml
vendored
2
.github/workflows/mapbase_build-base.yml
vendored
@ -51,7 +51,7 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Add MSBuild to PATH
|
- name: Add MSBuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
1
.github/workflows/mapbase_build-sp-games.yml
vendored
1
.github/workflows/mapbase_build-sp-games.yml
vendored
@ -13,6 +13,7 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- develop
|
- develop
|
||||||
paths:
|
paths:
|
||||||
|
- '.github/workflows/mapbase_build-base.yml'
|
||||||
- '.github/workflows/mapbase_build-sp-rel-games.yml'
|
- '.github/workflows/mapbase_build-sp-rel-games.yml'
|
||||||
- 'sp/src/vpc_scripts/**'
|
- 'sp/src/vpc_scripts/**'
|
||||||
- 'sp/src/game/**'
|
- 'sp/src/game/**'
|
||||||
|
4
.github/workflows/mapbase_pr.yml
vendored
4
.github/workflows/mapbase_pr.yml
vendored
@ -6,12 +6,12 @@
|
|||||||
# https://github.com/actions/labeler
|
# https://github.com/actions/labeler
|
||||||
|
|
||||||
name: Pull Request Automation
|
name: Pull Request Automation
|
||||||
on: [pull_request]
|
on: [pull_request] # pull_request_target
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
label:
|
label:
|
||||||
|
|
||||||
if: github.repository_owner == 'mapbase-source'
|
if: github.repository_owner == 'mapbase-source' # ${{ vars.MAPBASE_LABELS == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
14
README
14
README
@ -1,6 +1,6 @@
|
|||||||
//=========================================================================================================================
|
//=========================================================================================================================
|
||||||
|
|
||||||
Mapbase v7.1 - Source 2013
|
Mapbase v7.2 - Source 2013
|
||||||
https://github.com/mapbase-source/source-sdk-2013
|
https://github.com/mapbase-source/source-sdk-2013
|
||||||
https://www.moddb.com/mods/mapbase
|
https://www.moddb.com/mods/mapbase
|
||||||
|
|
||||||
@ -112,6 +112,12 @@ Direct contributions:
|
|||||||
- https://github.com/mapbase-source/source-sdk-2013/issues/201 (env_projectedtexture shadow filter keyvalue from celisej567)
|
- https://github.com/mapbase-source/source-sdk-2013/issues/201 (env_projectedtexture shadow filter keyvalue from celisej567)
|
||||||
- https://github.com/mapbase-source/source-sdk-2013/pull/193 (RTB:R info_particle_system_coordinate by arbabf and Iridium77)
|
- https://github.com/mapbase-source/source-sdk-2013/pull/193 (RTB:R info_particle_system_coordinate by arbabf and Iridium77)
|
||||||
- https://github.com/mapbase-source/source-sdk-2013/pull/193 (Infinite prop_interactable cooldown by arbabf)
|
- https://github.com/mapbase-source/source-sdk-2013/pull/193 (Infinite prop_interactable cooldown by arbabf)
|
||||||
|
- https://github.com/mapbase-source/source-sdk-2013/pull/229 (Extended point_bugbait functionality by arbabf)
|
||||||
|
- https://github.com/mapbase-source/source-sdk-2013/pull/236 (Toggleable prop sprinting by Crimson-X1)
|
||||||
|
- https://github.com/mapbase-source/source-sdk-2013/pull/237 (Commander goal trace fix by Agrimar)
|
||||||
|
- https://github.com/mapbase-source/source-sdk-2013/pull/245 (ViewPunch random fix by Mr0maks)
|
||||||
|
- https://github.com/mapbase-source/source-sdk-2013/pull/248 (soundlevel_t conversation warning fix by Mechami)
|
||||||
|
- https://github.com/mapbase-source/mapbase-game-src/pull/1 (Advanced video options duplicate field name fix by arbabf; This is asset-based and not reflected in the code)
|
||||||
- Demo autorecord code provided by Klems
|
- Demo autorecord code provided by Klems
|
||||||
- cc_emit crash fix provided by 1upD
|
- cc_emit crash fix provided by 1upD
|
||||||
- Custom HL2 ammo crate models created by Rykah (Textures created by Blixibon; This is asset-based and, aside from the SLAM crate, not reflected in the code)
|
- Custom HL2 ammo crate models created by Rykah (Textures created by Blixibon; This is asset-based and, aside from the SLAM crate, not reflected in the code)
|
||||||
@ -137,6 +143,9 @@ Direct contributions:
|
|||||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/192 (VScript hook manager and fixes)
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/192 (VScript hook manager and fixes)
|
||||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/206 (Fix CScriptNetMsgHelper::WriteEntity())
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/206 (Fix CScriptNetMsgHelper::WriteEntity())
|
||||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/213 (VScript HUD visibility control, optimizations for 3D skybox angles/fake worldportals)
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/213 (VScript HUD visibility control, optimizations for 3D skybox angles/fake worldportals)
|
||||||
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/229 (VScript VGUI HUD viewport parenting, game_text and vgui_text_display VScript font fallback)
|
||||||
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/261 (Misc VScript additions)
|
||||||
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/279 (weapon_custom_scripted fixes)
|
||||||
|
|
||||||
== Contributions from z33ky:
|
== Contributions from z33ky:
|
||||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux compilation fixes)
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux compilation fixes)
|
||||||
@ -156,6 +165,9 @@ Direct contributions:
|
|||||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/184 (Projected texture horizontal FOV shadow fix)
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/184 (Projected texture horizontal FOV shadow fix)
|
||||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/185 (Fix enemyfinders becoming visible when they wake)
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/185 (Fix enemyfinders becoming visible when they wake)
|
||||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/186 (Fix for brightly glowing teeth)
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/186 (Fix for brightly glowing teeth)
|
||||||
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/183 (Enhanced custom weapons support)
|
||||||
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/230 (Caption fixes)
|
||||||
|
=-- https://github.com/mapbase-source/source-sdk-2013/pull/231 (Sentence source bug fix)
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ void CWeaponAR2::DelayedAttack( void )
|
|||||||
|
|
||||||
// pOwner->SnapEyeAngles( angles );
|
// pOwner->SnapEyeAngles( angles );
|
||||||
|
|
||||||
pOwner->ViewPunch( QAngle( SharedRandomInt( "ar2pax", -8, -12 ), SharedRandomInt( "ar2pay", 1, 2 ), 0 ) );
|
pOwner->ViewPunch( QAngle( SharedRandomInt( "ar2pax", -12, -8 ), SharedRandomInt( "ar2pay", 1, 2 ), 0 ) );
|
||||||
|
|
||||||
// Decrease ammo
|
// Decrease ammo
|
||||||
pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
|
pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
|
||||||
|
@ -4042,6 +4042,92 @@ void C_BaseAnimating::FireEvent( const Vector& origin, const QAngle& angles, int
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef MAPBASE // From Alien Swarm SDK
|
||||||
|
case AE_CL_STOP_PARTICLE_EFFECT:
|
||||||
|
{
|
||||||
|
char token[256];
|
||||||
|
char szParticleEffect[256];
|
||||||
|
|
||||||
|
// Get the particle effect name
|
||||||
|
const char *p = options;
|
||||||
|
p = nexttoken(token, p, ' ', sizeof(token));
|
||||||
|
if ( token )
|
||||||
|
{
|
||||||
|
Q_strncpy( szParticleEffect, token, sizeof(szParticleEffect) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the attachment point index
|
||||||
|
p = nexttoken(token, p, ' ', sizeof(token));
|
||||||
|
bool bStopInstantly = ( token && !Q_stricmp( token, "instantly" ) );
|
||||||
|
|
||||||
|
ParticleProp()->StopParticlesNamed( szParticleEffect, bStopInstantly );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AE_CL_ADD_PARTICLE_EFFECT_CP:
|
||||||
|
{
|
||||||
|
int iControlPoint = 1;
|
||||||
|
int iAttachment = -1;
|
||||||
|
int iAttachType = PATTACH_ABSORIGIN_FOLLOW;
|
||||||
|
int iEffectIndex = -1;
|
||||||
|
char token[256];
|
||||||
|
char szParticleEffect[256];
|
||||||
|
|
||||||
|
// Get the particle effect name
|
||||||
|
const char *p = options;
|
||||||
|
p = nexttoken(token, p, ' ', sizeof(token));
|
||||||
|
if ( token )
|
||||||
|
{
|
||||||
|
Q_strncpy( szParticleEffect, token, sizeof(szParticleEffect) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the control point number
|
||||||
|
p = nexttoken(token, p, ' ', sizeof(token));
|
||||||
|
if ( token )
|
||||||
|
{
|
||||||
|
iControlPoint = atoi( token );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the attachment type
|
||||||
|
p = nexttoken(token, p, ' ', sizeof(token));
|
||||||
|
if ( token )
|
||||||
|
{
|
||||||
|
iAttachType = GetAttachTypeFromString( token );
|
||||||
|
if ( iAttachType == -1 )
|
||||||
|
{
|
||||||
|
Warning("Invalid attach type specified for particle effect anim event. Trying to spawn effect '%s' with attach type of '%s'\n", szParticleEffect, token );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the attachment point index
|
||||||
|
p = nexttoken(token, p, ' ', sizeof(token));
|
||||||
|
if ( token )
|
||||||
|
{
|
||||||
|
iAttachment = atoi(token);
|
||||||
|
|
||||||
|
// See if we can find any attachment points matching the name
|
||||||
|
if ( token[0] != '0' && iAttachment == 0 )
|
||||||
|
{
|
||||||
|
iAttachment = LookupAttachment( token );
|
||||||
|
if ( iAttachment == -1 )
|
||||||
|
{
|
||||||
|
Warning("Failed to find attachment point specified for particle effect anim event. Trying to spawn effect '%s' on attachment named '%s'\n", szParticleEffect, token );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iEffectIndex = ParticleProp()->FindEffect( szParticleEffect );
|
||||||
|
if ( iEffectIndex == -1 )
|
||||||
|
{
|
||||||
|
Warning("Failed to find specified particle effect. Trying to add CP to '%s' on attachment named '%s'\n", szParticleEffect, token );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ParticleProp()->AddControlPoint( iEffectIndex, iControlPoint, this, (ParticleAttachment_t)iAttachType, iAttachment );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case AE_CL_PLAYSOUND:
|
case AE_CL_PLAYSOUND:
|
||||||
{
|
{
|
||||||
CLocalPlayerFilter filter;
|
CLocalPlayerFilter filter;
|
||||||
@ -4291,6 +4377,22 @@ void C_BaseAnimating::FireEvent( const Vector& origin, const QAngle& angles, int
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
case AE_VSCRIPT_RUN:
|
||||||
|
{
|
||||||
|
if (!RunScript( options ))
|
||||||
|
Warning( "%s failed to run AE_VSCRIPT_RUN on client with \"%s\"\n", GetDebugName(), options );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AE_VSCRIPT_RUN_FILE:
|
||||||
|
{
|
||||||
|
if (!RunScriptFile( options ))
|
||||||
|
Warning( "%s failed to run AE_VSCRIPT_RUN_FILE on client with \"%s\"\n", GetDebugName(), options );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ END_PREDICTION_DATA()
|
|||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
|
||||||
BEGIN_ENT_SCRIPTDESC( C_BaseCombatCharacter, CBaseEntity, "" )
|
BEGIN_ENT_SCRIPTDESC( C_BaseCombatCharacter, C_BaseAnimating, "" )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAmmoCount, "GetAmmoCount", "" )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAmmoCount, "GetAmmoCount", "" )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetActiveWeapon, "GetActiveWeapon", "" )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetActiveWeapon, "GetActiveWeapon", "" )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetWeapon, "GetWeapon", "" )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetWeapon, "GetWeapon", "" )
|
||||||
|
@ -502,6 +502,9 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
|
|||||||
DEFINE_SCRIPTFUNC_NAMED( GetScriptOwnerEntity, "GetOwner", "Gets this entity's owner" )
|
DEFINE_SCRIPTFUNC_NAMED( GetScriptOwnerEntity, "GetOwner", "Gets this entity's owner" )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( SetScriptOwnerEntity, "SetOwner", "Sets this entity's owner" )
|
DEFINE_SCRIPTFUNC_NAMED( SetScriptOwnerEntity, "SetOwner", "Sets this entity's owner" )
|
||||||
|
|
||||||
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetGroundEntity, "GetGroundEntity", "Get the entity we're standing on." )
|
||||||
|
DEFINE_SCRIPTFUNC_NAMED( ScriptSetGroundEntity, "SetGroundEntity", "Set the entity we're standing on." )
|
||||||
|
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorVector, "GetRenderColorVector", "Get the render color as a vector" )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorVector, "GetRenderColorVector", "Get the render color as a vector" )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorR, "GetRenderColorR", "Get the render color's R value" )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorR, "GetRenderColorR", "Get the render color's R value" )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorG, "GetRenderColorG", "Get the render color's G value" )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorG, "GetRenderColorG", "Get the render color's G value" )
|
||||||
|
@ -288,6 +288,11 @@ public:
|
|||||||
HSCRIPT GetScriptOwnerEntity();
|
HSCRIPT GetScriptOwnerEntity();
|
||||||
virtual void SetScriptOwnerEntity(HSCRIPT pOwner);
|
virtual void SetScriptOwnerEntity(HSCRIPT pOwner);
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
HSCRIPT ScriptGetGroundEntity();
|
||||||
|
void ScriptSetGroundEntity( HSCRIPT hGroundEnt );
|
||||||
|
#endif
|
||||||
|
|
||||||
HSCRIPT GetScriptInstance();
|
HSCRIPT GetScriptInstance();
|
||||||
|
|
||||||
HSCRIPT m_hScriptInstance;
|
HSCRIPT m_hScriptInstance;
|
||||||
|
@ -69,6 +69,7 @@ $Project
|
|||||||
$File "mapbase\c_func_fake_worldportal.h"
|
$File "mapbase\c_func_fake_worldportal.h"
|
||||||
$File "mapbase\c_point_glow.cpp"
|
$File "mapbase\c_point_glow.cpp"
|
||||||
$File "mapbase\c_vgui_text_display.cpp"
|
$File "mapbase\c_vgui_text_display.cpp"
|
||||||
|
$File "mapbase\c_weapon_custom_hl2.cpp"
|
||||||
$File "mapbase\mapbase_autocubemap.cpp"
|
$File "mapbase\mapbase_autocubemap.cpp"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1496,9 +1496,23 @@ void CHudCloseCaption::Process( const wchar_t *stream, float duration, const cha
|
|||||||
|
|
||||||
if ( m_Items.Count() > 0 )
|
if ( m_Items.Count() > 0 )
|
||||||
{
|
{
|
||||||
|
#ifndef MAPBASE
|
||||||
// Get the remaining life span of the last item
|
// Get the remaining life span of the last item
|
||||||
CCloseCaptionItem* final = m_Items[m_Items.Count() - 1];
|
CCloseCaptionItem* final = m_Items[m_Items.Count() - 1];
|
||||||
float prevlife = final->GetTimeToLive();
|
float prevlife = final->GetTimeToLive();
|
||||||
|
#else
|
||||||
|
float prevlife = 0.f;
|
||||||
|
// Get the remaining life span of the last displayed item
|
||||||
|
for (int i = m_Items.Count() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (m_Items[i]->GetPreDisplayTime() > cc_predisplay_time.GetFloat())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
prevlife = m_Items[i]->GetTimeToLive();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // !MAPBASE
|
||||||
|
|
||||||
|
|
||||||
if ( prevlife > lifespan )
|
if ( prevlife > lifespan )
|
||||||
{
|
{
|
||||||
@ -1532,7 +1546,31 @@ void CHudCloseCaption::Process( const wchar_t *stream, float duration, const cha
|
|||||||
if ( wcslen( phrase ) > 0 )
|
if ( wcslen( phrase ) > 0 )
|
||||||
{
|
{
|
||||||
CCloseCaptionItem *item = new CCloseCaptionItem( phrase, lifespan, addedlife, delay, valid, fromplayer );
|
CCloseCaptionItem *item = new CCloseCaptionItem( phrase, lifespan, addedlife, delay, valid, fromplayer );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_Items.Count())
|
||||||
|
{
|
||||||
|
// Add it where it will appear
|
||||||
|
for (int i = m_Items.Count() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (m_Items[i]->GetPreDisplayTime() > delay + cc_predisplay_time.GetFloat())
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
m_Items.AddToHead(item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Items.InsertAfter(i, item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // MAPBASE
|
||||||
m_Items.AddToTail(item);
|
m_Items.AddToTail(item);
|
||||||
|
|
||||||
if ( StreamHasCommand( phrase, L"sfx" ) )
|
if ( StreamHasCommand( phrase, L"sfx" ) )
|
||||||
{
|
{
|
||||||
// SFX show up instantly.
|
// SFX show up instantly.
|
||||||
@ -1541,6 +1579,9 @@ void CHudCloseCaption::Process( const wchar_t *stream, float duration, const cha
|
|||||||
|
|
||||||
if ( GetFloatCommandValue( phrase, L"len", override_duration ) )
|
if ( GetFloatCommandValue( phrase, L"len", override_duration ) )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
override_duration += cc_linger_time.GetFloat();
|
||||||
|
#endif // MAPBASE
|
||||||
item->SetTimeToLive( override_duration );
|
item->SetTimeToLive( override_duration );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1569,6 +1610,29 @@ void CHudCloseCaption::Process( const wchar_t *stream, float duration, const cha
|
|||||||
if ( wcslen( phrase ) > 0 )
|
if ( wcslen( phrase ) > 0 )
|
||||||
{
|
{
|
||||||
CCloseCaptionItem *item = new CCloseCaptionItem( phrase, lifespan, addedlife, delay, valid, fromplayer );
|
CCloseCaptionItem *item = new CCloseCaptionItem( phrase, lifespan, addedlife, delay, valid, fromplayer );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_Items.Count())
|
||||||
|
{
|
||||||
|
// Add it where it will appear
|
||||||
|
for (int i = m_Items.Count() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (m_Items[i]->GetPreDisplayTime() > delay + cc_predisplay_time.GetFloat())
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
m_Items.AddToHead(item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Items.InsertAfter(i, item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // MAPBASE
|
||||||
m_Items.AddToTail(item);
|
m_Items.AddToTail(item);
|
||||||
|
|
||||||
if ( StreamHasCommand( phrase, L"sfx" ) )
|
if ( StreamHasCommand( phrase, L"sfx" ) )
|
||||||
@ -1579,6 +1643,10 @@ void CHudCloseCaption::Process( const wchar_t *stream, float duration, const cha
|
|||||||
|
|
||||||
if ( GetFloatCommandValue( phrase, L"len", override_duration ) )
|
if ( GetFloatCommandValue( phrase, L"len", override_duration ) )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
override_duration += cc_linger_time.GetFloat();
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
item->SetTimeToLive( override_duration );
|
item->SetTimeToLive( override_duration );
|
||||||
item->SetInitialLifeSpan( override_duration );
|
item->SetInitialLifeSpan( override_duration );
|
||||||
}
|
}
|
||||||
@ -2614,8 +2682,14 @@ void CHudCloseCaption::InitCaptionDictionary( const char *dbfile )
|
|||||||
|
|
||||||
g_AsyncCaptionResourceManager.Clear();
|
g_AsyncCaptionResourceManager.Clear();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int iBufferSize = filesystem->GetSearchPath("GAME", true, nullptr, 0);
|
||||||
|
char* searchPaths = (char*)stackalloc(iBufferSize);
|
||||||
|
filesystem->GetSearchPath("GAME", true, searchPaths, iBufferSize);
|
||||||
|
#else
|
||||||
char searchPaths[4096];
|
char searchPaths[4096];
|
||||||
filesystem->GetSearchPath( "GAME", true, searchPaths, sizeof( searchPaths ) );
|
filesystem->GetSearchPath( "GAME", true, searchPaths, sizeof( searchPaths ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
for ( char *path = strtok( searchPaths, ";" ); path; path = strtok( NULL, ";" ) )
|
for ( char *path = strtok( searchPaths, ";" ); path; path = strtok( NULL, ";" ) )
|
||||||
{
|
{
|
||||||
@ -2626,8 +2700,13 @@ void CHudCloseCaption::InitCaptionDictionary( const char *dbfile )
|
|||||||
}
|
}
|
||||||
|
|
||||||
char fullpath[MAX_PATH];
|
char fullpath[MAX_PATH];
|
||||||
|
#ifndef MAPBASE
|
||||||
Q_snprintf(fullpath, sizeof(fullpath), "%s%s", path, dbfile);
|
Q_snprintf(fullpath, sizeof(fullpath), "%s%s", path, dbfile);
|
||||||
Q_FixSlashes(fullpath);
|
Q_FixSlashes(fullpath);
|
||||||
|
#else
|
||||||
|
V_ComposeFileName(path, dbfile, fullpath, sizeof(fullpath));
|
||||||
|
#endif // !MAPBASE
|
||||||
|
|
||||||
|
|
||||||
if ( IsX360() )
|
if ( IsX360() )
|
||||||
{
|
{
|
||||||
@ -2692,8 +2771,7 @@ void CHudCloseCaption::AddAdditionalCaptionDictionary( const char *dbfile, CUtlV
|
|||||||
}
|
}
|
||||||
|
|
||||||
char fullpath[MAX_PATH];
|
char fullpath[MAX_PATH];
|
||||||
Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", path, dbfile );
|
V_ComposeFileName(path, dbfile, fullpath, sizeof(fullpath));
|
||||||
Q_FixSlashes( fullpath );
|
|
||||||
|
|
||||||
if ( IsX360() )
|
if ( IsX360() )
|
||||||
{
|
{
|
||||||
|
@ -215,6 +215,13 @@ void C_TextDisplayPanel::UpdateText()
|
|||||||
if (pszFontName && pszFontName[0] != '\0')
|
if (pszFontName && pszFontName[0] != '\0')
|
||||||
{
|
{
|
||||||
HFont font = scheme()->GetIScheme( GetScheme() )->GetFont( pszFontName );
|
HFont font = scheme()->GetIScheme( GetScheme() )->GetFont( pszFontName );
|
||||||
|
|
||||||
|
if ( !font )
|
||||||
|
{
|
||||||
|
extern HFont GetScriptFont( const char *, bool );
|
||||||
|
font = GetScriptFont( pszFontName, false );
|
||||||
|
}
|
||||||
|
|
||||||
m_pDisplayTextLabel->SetFont( font );
|
m_pDisplayTextLabel->SetFont( font );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
91
sp/src/game/client/mapbase/c_weapon_custom_hl2.cpp
Normal file
91
sp/src/game/client/mapbase/c_weapon_custom_hl2.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||||
|
//
|
||||||
|
// Purpose: Client classes for Half-Life 2 based custom weapons.
|
||||||
|
//
|
||||||
|
// Author: Peter Covington (petercov@outlook.com)
|
||||||
|
//
|
||||||
|
//==================================================================================//
|
||||||
|
|
||||||
|
#include "cbase.h"
|
||||||
|
#include "c_weapon__stubs.h"
|
||||||
|
#include "basehlcombatweapon_shared.h"
|
||||||
|
#include "c_basehlcombatweapon.h"
|
||||||
|
|
||||||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
|
#include "tier0/memdbgon.h"
|
||||||
|
|
||||||
|
class C_HLCustomWeaponMelee : public C_BaseHLBludgeonWeapon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(C_HLCustomWeaponMelee, C_BaseHLBludgeonWeapon);
|
||||||
|
DECLARE_CLIENTCLASS();
|
||||||
|
DECLARE_PREDICTABLE();
|
||||||
|
|
||||||
|
C_HLCustomWeaponMelee();
|
||||||
|
|
||||||
|
void OnDataChanged( DataUpdateType_t updateType );
|
||||||
|
|
||||||
|
virtual const char* GetWeaponScriptName() { return m_iszWeaponScriptName; }
|
||||||
|
private:
|
||||||
|
char m_iszWeaponScriptName[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
STUB_WEAPON_CLASS_IMPLEMENT(weapon_hlcustommelee, C_HLCustomWeaponMelee);
|
||||||
|
|
||||||
|
IMPLEMENT_CLIENTCLASS_DT(C_HLCustomWeaponMelee, DT_HLCustomWeaponMelee, CHLCustomWeaponMelee)
|
||||||
|
RecvPropString(RECVINFO(m_iszWeaponScriptName)),
|
||||||
|
END_RECV_TABLE();
|
||||||
|
|
||||||
|
C_HLCustomWeaponMelee::C_HLCustomWeaponMelee()
|
||||||
|
{
|
||||||
|
m_iszWeaponScriptName[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void C_HLCustomWeaponMelee::OnDataChanged( DataUpdateType_t updateType )
|
||||||
|
{
|
||||||
|
if (updateType == DATA_UPDATE_CREATED)
|
||||||
|
{
|
||||||
|
Precache();
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseClass::OnDataChanged( updateType );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class C_HLCustomWeaponGun : public C_BaseHLCombatWeapon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS(C_HLCustomWeaponGun, C_BaseHLCombatWeapon);
|
||||||
|
DECLARE_CLIENTCLASS();
|
||||||
|
DECLARE_PREDICTABLE();
|
||||||
|
|
||||||
|
C_HLCustomWeaponGun();
|
||||||
|
|
||||||
|
void OnDataChanged( DataUpdateType_t updateType );
|
||||||
|
|
||||||
|
virtual const char* GetWeaponScriptName() { return m_iszWeaponScriptName; }
|
||||||
|
private:
|
||||||
|
char m_iszWeaponScriptName[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
STUB_WEAPON_CLASS_IMPLEMENT(weapon_hlcustomgun, C_HLCustomWeaponGun);
|
||||||
|
|
||||||
|
IMPLEMENT_CLIENTCLASS_DT(C_HLCustomWeaponGun, DT_HLCustomWeaponGun, CHLCustomWeaponGun)
|
||||||
|
RecvPropString(RECVINFO(m_iszWeaponScriptName)),
|
||||||
|
END_RECV_TABLE();
|
||||||
|
|
||||||
|
C_HLCustomWeaponGun::C_HLCustomWeaponGun()
|
||||||
|
{
|
||||||
|
m_iszWeaponScriptName[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void C_HLCustomWeaponGun::OnDataChanged( DataUpdateType_t updateType )
|
||||||
|
{
|
||||||
|
if (updateType == DATA_UPDATE_CREATED)
|
||||||
|
{
|
||||||
|
Precache();
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseClass::OnDataChanged( updateType );
|
||||||
|
}
|
@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "hudelement.h"
|
#include "hudelement.h"
|
||||||
//#include "iclientmode.h" // g_pClientMode->GetViewport()
|
#include "iclientmode.h" // g_pClientMode->GetViewport()
|
||||||
|
|
||||||
#include "vscript_vgui.h"
|
#include "vscript_vgui.h"
|
||||||
#include "vscript_vgui.nut"
|
#include "vscript_vgui.nut"
|
||||||
@ -92,10 +92,18 @@
|
|||||||
// Changing this is not backwards compatible, as existing top level script panel depth would then change relative to non-script panels.
|
// Changing this is not backwards compatible, as existing top level script panel depth would then change relative to non-script panels.
|
||||||
#define SCRIPT_ENGINE_ROOT_PANELS 1
|
#define SCRIPT_ENGINE_ROOT_PANELS 1
|
||||||
|
|
||||||
// NOTE: causes rendering issues
|
//
|
||||||
#define ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL 0
|
// Options to restrict where script panels can be parented to.
|
||||||
|
// The safest options any game can have are HUD viewport and clientdll.
|
||||||
|
//
|
||||||
|
|
||||||
#define ALLOW_SCRIPT_GAMEUI_ROOT_PANEL 0
|
#define ALLOW_ROOT_PANEL_PARENT 1
|
||||||
|
|
||||||
|
#define ALLOW_HUD_VIEWPORT_ROOT_PARENT 1
|
||||||
|
|
||||||
|
#define ALLOW_CLIENTDLL_ROOT_PARENT 1
|
||||||
|
|
||||||
|
#define ALLOW_GAMEUI_ROOT_PARENT 0
|
||||||
|
|
||||||
// On level transitions Restore is called up to 4 times in a row (due to .hl? client state files), each time
|
// On level transitions Restore is called up to 4 times in a row (due to .hl? client state files), each time
|
||||||
// trying to restore script panels from pre and post transitions, failing every time because script panels are
|
// trying to restore script panels from pre and post transitions, failing every time because script panels are
|
||||||
@ -353,8 +361,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ALLOW_CLIENTDLL_ROOT_PARENT
|
||||||
CScriptRootDLLPanel *g_pScriptClientDLLPanel = NULL;
|
CScriptRootDLLPanel *g_pScriptClientDLLPanel = NULL;
|
||||||
#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL
|
#endif
|
||||||
|
#if ALLOW_GAMEUI_ROOT_PARENT
|
||||||
CScriptRootDLLPanel *g_pScriptGameUIDLLPanel = NULL;
|
CScriptRootDLLPanel *g_pScriptGameUIDLLPanel = NULL;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -367,12 +377,14 @@ void VGUI_DestroyScriptRootPanels()
|
|||||||
g_pScriptRootPanel = NULL;
|
g_pScriptRootPanel = NULL;
|
||||||
}
|
}
|
||||||
#if SCRIPT_ENGINE_ROOT_PANELS
|
#if SCRIPT_ENGINE_ROOT_PANELS
|
||||||
|
#if ALLOW_CLIENTDLL_ROOT_PARENT
|
||||||
if ( g_pScriptClientDLLPanel )
|
if ( g_pScriptClientDLLPanel )
|
||||||
{
|
{
|
||||||
delete g_pScriptClientDLLPanel;
|
delete g_pScriptClientDLLPanel;
|
||||||
g_pScriptClientDLLPanel = NULL;
|
g_pScriptClientDLLPanel = NULL;
|
||||||
}
|
}
|
||||||
#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL
|
#endif
|
||||||
|
#if ALLOW_GAMEUI_ROOT_PARENT
|
||||||
if ( g_pScriptGameUIDLLPanel )
|
if ( g_pScriptGameUIDLLPanel )
|
||||||
{
|
{
|
||||||
delete g_pScriptGameUIDLLPanel;
|
delete g_pScriptGameUIDLLPanel;
|
||||||
@ -384,30 +396,29 @@ void VGUI_DestroyScriptRootPanels()
|
|||||||
|
|
||||||
VPANEL VGUI_GetScriptRootPanel( VGuiPanel_t type )
|
VPANEL VGUI_GetScriptRootPanel( VGuiPanel_t type )
|
||||||
{
|
{
|
||||||
#if !SCRIPT_ENGINE_ROOT_PANELS
|
#if SCRIPT_ENGINE_ROOT_PANELS
|
||||||
if ( !g_pScriptRootPanel )
|
|
||||||
g_pScriptRootPanel = new CScriptRootPanel();
|
|
||||||
|
|
||||||
return enginevgui->GetPanel( type );
|
|
||||||
#else
|
|
||||||
switch ( type )
|
switch ( type )
|
||||||
{
|
{
|
||||||
case PANEL_ROOT:
|
case PANEL_ROOT:
|
||||||
|
#if ALLOW_ROOT_PANEL_PARENT
|
||||||
{
|
{
|
||||||
if ( !g_pScriptRootPanel )
|
if ( !g_pScriptRootPanel )
|
||||||
g_pScriptRootPanel = new CScriptRootPanel();
|
g_pScriptRootPanel = new CScriptRootPanel();
|
||||||
|
|
||||||
return g_pScriptRootPanel->GetVPanel();
|
return g_pScriptRootPanel->GetVPanel();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
case PANEL_CLIENTDLL:
|
case PANEL_CLIENTDLL:
|
||||||
|
#if ALLOW_CLIENTDLL_ROOT_PARENT
|
||||||
{
|
{
|
||||||
if ( !g_pScriptClientDLLPanel )
|
if ( !g_pScriptClientDLLPanel )
|
||||||
g_pScriptClientDLLPanel = new CScriptRootDLLPanel( PANEL_CLIENTDLL, "VScriptClient" );
|
g_pScriptClientDLLPanel = new CScriptRootDLLPanel( PANEL_CLIENTDLL, "VScriptClient" );
|
||||||
|
|
||||||
return g_pScriptClientDLLPanel->GetVPanel();
|
return g_pScriptClientDLLPanel->GetVPanel();
|
||||||
}
|
}
|
||||||
#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL
|
#endif
|
||||||
case PANEL_GAMEUIDLL:
|
case PANEL_GAMEUIDLL:
|
||||||
|
#if ALLOW_GAMEUI_ROOT_PARENT
|
||||||
{
|
{
|
||||||
if ( !g_pScriptGameUIDLLPanel )
|
if ( !g_pScriptGameUIDLLPanel )
|
||||||
g_pScriptGameUIDLLPanel = new CScriptRootDLLPanel( PANEL_GAMEUIDLL, "VScriptGameUI" );
|
g_pScriptGameUIDLLPanel = new CScriptRootDLLPanel( PANEL_GAMEUIDLL, "VScriptGameUI" );
|
||||||
@ -415,8 +426,10 @@ VPANEL VGUI_GetScriptRootPanel( VGuiPanel_t type )
|
|||||||
return g_pScriptGameUIDLLPanel->GetVPanel();
|
return g_pScriptGameUIDLLPanel->GetVPanel();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
default: return NULL;
|
||||||
}
|
}
|
||||||
return NULL;
|
#else
|
||||||
|
return enginevgui->GetPanel(type);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,6 +676,11 @@ int CScriptSurface::GetCharacterWidth( int font, int ch )
|
|||||||
|
|
||||||
void CScriptSurface::CreateFont( const char *customName, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int yresMin, int yresMax, bool proportional )
|
void CScriptSurface::CreateFont( const char *customName, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int yresMin, int yresMax, bool proportional )
|
||||||
{
|
{
|
||||||
|
// Make sure font invalidation callback is established.
|
||||||
|
// Not necessary if script fonts are reloaded in engine.
|
||||||
|
if ( !g_pScriptRootPanel )
|
||||||
|
g_pScriptRootPanel = new CScriptRootPanel();
|
||||||
|
|
||||||
if ( flags & ISurface::FONTFLAG_BITMAP )
|
if ( flags & ISurface::FONTFLAG_BITMAP )
|
||||||
{
|
{
|
||||||
AssertMsg( 0, "Bitmap fonts are not supported!" );
|
AssertMsg( 0, "Bitmap fonts are not supported!" );
|
||||||
@ -681,16 +699,41 @@ void CScriptSurface::CreateFont( const char *customName, const char *windowsFont
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
bool bProportionalFallbackFont = false;
|
||||||
|
if ( proportional )
|
||||||
|
{
|
||||||
|
// Find if this is a resolution filtered font alias
|
||||||
|
const char *fontAlias = GetFixedFontName( customName, false );
|
||||||
|
int idx = g_ScriptFonts.Find( fontAlias );
|
||||||
|
if ( idx != g_ScriptFonts.InvalidIndex() )
|
||||||
|
{
|
||||||
|
fontalias_t &alias = g_ScriptFonts[idx];
|
||||||
|
for ( int i = 0; i < alias.Count(); ++i )
|
||||||
|
{
|
||||||
|
FontData_t &data = alias.Element(i);
|
||||||
|
if ( data.yres_min && data.yres_max )
|
||||||
|
{
|
||||||
|
bProportionalFallbackFont = true;
|
||||||
|
|
||||||
|
// Save this proportional font in non-proportional alias
|
||||||
|
proportional = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *fontAlias = GetFixedFontName( customName, proportional );
|
const char *fontAlias = GetFixedFontName( customName, proportional );
|
||||||
|
|
||||||
int idx = g_ScriptFonts.Find( fontAlias );
|
int idx = g_ScriptFonts.Find( fontAlias );
|
||||||
if ( idx != g_ScriptFonts.InvalidIndex() )
|
if ( idx != g_ScriptFonts.InvalidIndex() )
|
||||||
{
|
{
|
||||||
fontalias_t &alias = g_ScriptFonts[idx];
|
fontalias_t &alias = g_ScriptFonts[idx];
|
||||||
// TODO: One proportional font to fall back to amongst resolution filtered fonts.
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
if ( !yresMin && !yresMax )
|
if ( !yresMin && !yresMax /*&& !bProportionalFallbackFont*/ )
|
||||||
{
|
{
|
||||||
// There must be only one font registered.
|
// There must be only one font registered.
|
||||||
Assert( alias.Count() == 1 );
|
Assert( alias.Count() == 1 );
|
||||||
@ -703,7 +746,7 @@ void CScriptSurface::CreateFont( const char *customName, const char *windowsFont
|
|||||||
// Font changes will not be applied.
|
// Font changes will not be applied.
|
||||||
Assert( oldTall == newTall );
|
Assert( oldTall == newTall );
|
||||||
if ( oldName ) // can be null
|
if ( oldName ) // can be null
|
||||||
Assert( !V_stricmp( oldName, windowsFontName ) );
|
AssertMsg( !V_stricmp( oldName, windowsFontName ), "'%s' != '%s'", oldName, windowsFontName );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -716,7 +759,10 @@ void CScriptSurface::CreateFont( const char *customName, const char *windowsFont
|
|||||||
if ( yresMin == data.yres_min && yresMax == data.yres_max )
|
if ( yresMin == data.yres_min && yresMax == data.yres_max )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ( bProportionalFallbackFont )
|
||||||
|
proportional = true;
|
||||||
|
#endif
|
||||||
DebugMsg( "Create font add '%s' [%d %d]\n", fontAlias, yresMin, yresMax );
|
DebugMsg( "Create font add '%s' [%d %d]\n", fontAlias, yresMin, yresMax );
|
||||||
|
|
||||||
FontData_t &newFont = alias.Element( alias.AddToTail() );
|
FontData_t &newFont = alias.Element( alias.AddToTail() );
|
||||||
@ -731,6 +777,22 @@ void CScriptSurface::CreateFont( const char *customName, const char *windowsFont
|
|||||||
newFont.yres_max = yresMax;
|
newFont.yres_max = yresMax;
|
||||||
newFont.proportional = proportional;
|
newFont.proportional = proportional;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Put the proportional font in the very end so that it is loaded only when no resolution is matched
|
||||||
|
struct L
|
||||||
|
{
|
||||||
|
static int __cdecl F( const FontData_t* a, const FontData_t* b )
|
||||||
|
{
|
||||||
|
if ( !a->proportional && b->proportional )
|
||||||
|
return -1;
|
||||||
|
if ( a->proportional && !b->proportional )
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
alias.Sort( L::F );
|
||||||
|
#endif
|
||||||
|
|
||||||
LoadFont( newFont DBG_PARAM(, fontAlias) );
|
LoadFont( newFont DBG_PARAM(, fontAlias) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1067,7 +1129,7 @@ public:\
|
|||||||
class CScript_##panelClass : public panelClass\
|
class CScript_##panelClass : public panelClass\
|
||||||
{\
|
{\
|
||||||
DECLARE_SCRIPTVGUI_CLASS( panelClass )\
|
DECLARE_SCRIPTVGUI_CLASS( panelClass )\
|
||||||
void Shutdown() {}\
|
void ScriptShutdown() {}\
|
||||||
\
|
\
|
||||||
public:\
|
public:\
|
||||||
CScript_##panelClass( Panel *parent, const char *name )\
|
CScript_##panelClass( Panel *parent, const char *name )\
|
||||||
@ -1085,7 +1147,7 @@ public:\
|
|||||||
class CScript_##panelClass : public panelClass\
|
class CScript_##panelClass : public panelClass\
|
||||||
{\
|
{\
|
||||||
DECLARE_SCRIPTVGUI_CLASS( panelClass )\
|
DECLARE_SCRIPTVGUI_CLASS( panelClass )\
|
||||||
void Shutdown() {}\
|
void ScriptShutdown() {}\
|
||||||
\
|
\
|
||||||
public:\
|
public:\
|
||||||
CScript_##panelClass( Panel *parent, const char *name, const char *text )\
|
CScript_##panelClass( Panel *parent, const char *name, const char *text )\
|
||||||
@ -1292,7 +1354,7 @@ public:
|
|||||||
if ( GetVPanel() )
|
if ( GetVPanel() )
|
||||||
{
|
{
|
||||||
DebugMsg( " Destroy panel '%s' %s\n", _base->GetName(), GetDebugName() );
|
DebugMsg( " Destroy panel '%s' %s\n", _base->GetName(), GetDebugName() );
|
||||||
_base->Shutdown();
|
_base->ScriptShutdown();
|
||||||
ResolveChildren_r( _vpanel );
|
ResolveChildren_r( _vpanel );
|
||||||
_base->MarkForDeletion();
|
_base->MarkForDeletion();
|
||||||
}
|
}
|
||||||
@ -1339,6 +1401,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
AssertMsg( 0, "invalid parent" );
|
AssertMsg( 0, "invalid parent" );
|
||||||
|
|
||||||
|
g_ScriptPanels.AddToTail( this );
|
||||||
|
|
||||||
|
// leave me parentless
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_ScriptPanels.AddToTail( this );
|
g_ScriptPanels.AddToTail( this );
|
||||||
@ -1348,27 +1415,37 @@ public:
|
|||||||
//
|
//
|
||||||
// This parameter is hidden in script, and is defined by the return value of dummy functions.
|
// This parameter is hidden in script, and is defined by the return value of dummy functions.
|
||||||
VPANEL vparent = 0;
|
VPANEL vparent = 0;
|
||||||
|
|
||||||
switch ( root )
|
switch ( root )
|
||||||
{
|
{
|
||||||
|
#if ALLOW_ROOT_PANEL_PARENT
|
||||||
case 0:
|
case 0:
|
||||||
vparent = VGUI_GetScriptRootPanel( PANEL_ROOT );
|
vparent = VGUI_GetScriptRootPanel( PANEL_ROOT );
|
||||||
break;
|
break;
|
||||||
#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL
|
#endif
|
||||||
|
#if ALLOW_GAMEUI_ROOT_PARENT
|
||||||
case 1:
|
case 1:
|
||||||
vparent = VGUI_GetScriptRootPanel( PANEL_GAMEUIDLL );
|
vparent = VGUI_GetScriptRootPanel( PANEL_GAMEUIDLL );
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if ALLOW_CLIENTDLL_ROOT_PARENT
|
||||||
case 2:
|
case 2:
|
||||||
vparent = VGUI_GetScriptRootPanel( PANEL_CLIENTDLL );
|
vparent = VGUI_GetScriptRootPanel( PANEL_CLIENTDLL );
|
||||||
break;
|
break;
|
||||||
#if ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL
|
#endif
|
||||||
// Hud viewport
|
#if ALLOW_HUD_VIEWPORT_ROOT_PARENT
|
||||||
case 10:
|
case 10: // Hud viewport
|
||||||
Assert( g_pClientMode && g_pClientMode->GetViewport() );
|
Assert( g_pClientMode && g_pClientMode->GetViewport() );
|
||||||
vparent = g_pClientMode->GetViewport()->GetVPanel();
|
vparent = g_pClientMode->GetViewport()->GetVPanel();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default: UNREACHABLE(); // Invalid parent panel
|
default:
|
||||||
|
#if SCRIPT_ENGINE_ROOT_PANELS
|
||||||
|
UNREACHABLE(); // Invalid parent panel
|
||||||
|
#else
|
||||||
|
// Allow everything defined in vscript_vgui.nut
|
||||||
|
vparent = VGUI_GetScriptRootPanel( (VGuiPanel_t)root );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
_base->SetParent( vparent );
|
_base->SetParent( vparent );
|
||||||
@ -1400,6 +1477,11 @@ public:
|
|||||||
{
|
{
|
||||||
ivgui()->AddTickSignal( this->GetVPanel(), i );
|
ivgui()->AddTickSignal( this->GetVPanel(), i );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoveTickSignal()
|
||||||
|
{
|
||||||
|
ivgui()->RemoveTickSignal( this->GetVPanel() );
|
||||||
|
}
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
void AddActionSignalTarget( HSCRIPT messageTarget )
|
void AddActionSignalTarget( HSCRIPT messageTarget )
|
||||||
{
|
{
|
||||||
@ -1434,10 +1516,12 @@ public:
|
|||||||
bool bRootParent = false;
|
bool bRootParent = false;
|
||||||
#if SCRIPT_ENGINE_ROOT_PANELS
|
#if SCRIPT_ENGINE_ROOT_PANELS
|
||||||
if ( ( parent == g_pScriptRootPanel->GetVPanel() )
|
if ( ( parent == g_pScriptRootPanel->GetVPanel() )
|
||||||
#if ALLOW_SCRIPT_GAMEUI_ROOT_PANEL
|
#if ALLOW_GAMEUI_ROOT_PARENT
|
||||||
|| ( g_pScriptGameUIDLLPanel && parent == g_pScriptGameUIDLLPanel->GetVPanel() )
|
|| ( g_pScriptGameUIDLLPanel && parent == g_pScriptGameUIDLLPanel->GetVPanel() )
|
||||||
#endif
|
#endif
|
||||||
|
#if ALLOW_CLIENTDLL_ROOT_PARENT
|
||||||
|| ( g_pScriptClientDLLPanel && parent == g_pScriptClientDLLPanel->GetVPanel() )
|
|| ( g_pScriptClientDLLPanel && parent == g_pScriptClientDLLPanel->GetVPanel() )
|
||||||
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bRootParent = true;
|
bRootParent = true;
|
||||||
@ -1452,7 +1536,7 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if ALLOW_SCRIPT_HUD_VIEWPORT_ROOT_PANEL
|
#if ALLOW_HUD_VIEWPORT_ROOT_PARENT
|
||||||
if ( g_pClientMode && g_pClientMode->GetViewport() && ( parent == g_pClientMode->GetViewport()->GetVPanel() ) )
|
if ( g_pClientMode && g_pClientMode->GetViewport() && ( parent == g_pClientMode->GetViewport()->GetVPanel() ) )
|
||||||
bRootParent = true;
|
bRootParent = true;
|
||||||
#endif
|
#endif
|
||||||
@ -1788,6 +1872,7 @@ public:
|
|||||||
DEFINE_SCRIPTFUNC( MakeReadyForUse, "" )\
|
DEFINE_SCRIPTFUNC( MakeReadyForUse, "" )\
|
||||||
DEFINE_SCRIPTFUNC( GetName, "" )\
|
DEFINE_SCRIPTFUNC( GetName, "" )\
|
||||||
DEFINE_SCRIPTFUNC( AddTickSignal, "" )\
|
DEFINE_SCRIPTFUNC( AddTickSignal, "" )\
|
||||||
|
DEFINE_SCRIPTFUNC( RemoveTickSignal, "" )\
|
||||||
\
|
\
|
||||||
DEFINE_SCRIPTFUNC( GetParent, "" )\
|
DEFINE_SCRIPTFUNC( GetParent, "" )\
|
||||||
DEFINE_SCRIPTFUNC( SetParent, "" )\
|
DEFINE_SCRIPTFUNC( SetParent, "" )\
|
||||||
@ -1829,10 +1914,12 @@ public:
|
|||||||
\
|
\
|
||||||
DEFINE_SCRIPTFUNC( SetCursor, "" )\
|
DEFINE_SCRIPTFUNC( SetCursor, "" )\
|
||||||
DEFINE_SCRIPTFUNC( IsCursorOver, "" )\
|
DEFINE_SCRIPTFUNC( IsCursorOver, "" )\
|
||||||
|
\
|
||||||
DEFINE_SCRIPTFUNC( HasFocus, "" )\
|
DEFINE_SCRIPTFUNC( HasFocus, "" )\
|
||||||
DEFINE_SCRIPTFUNC( RequestFocus, "" )\
|
DEFINE_SCRIPTFUNC( RequestFocus, "" )\
|
||||||
DEFINE_SCRIPTFUNC( MakePopup, "" )\
|
DEFINE_SCRIPTFUNC( MakePopup, "" )\
|
||||||
DEFINE_SCRIPTFUNC( MoveToFront, "" )\
|
DEFINE_SCRIPTFUNC( MoveToFront, "" )\
|
||||||
|
\
|
||||||
DEFINE_SCRIPTFUNC( SetMouseInputEnabled, "" )\
|
DEFINE_SCRIPTFUNC( SetMouseInputEnabled, "" )\
|
||||||
DEFINE_SCRIPTFUNC( SetKeyBoardInputEnabled, "" )\
|
DEFINE_SCRIPTFUNC( SetKeyBoardInputEnabled, "" )\
|
||||||
\
|
\
|
||||||
@ -1842,10 +1929,7 @@ public:
|
|||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
// These need more testing.
|
// These need more testing.
|
||||||
// TODO: IScript_Panel::FindChildByName()
|
|
||||||
// TODO: DECLARE_BUILD_FACTORY_SCRIPT() to create overridable script panels from controls file
|
// TODO: DECLARE_BUILD_FACTORY_SCRIPT() to create overridable script panels from controls file
|
||||||
// TODO: CScript_EditablePanel::ApplySchemeSettings() callback
|
|
||||||
// (IScheme parameter can be passed as null until schemes are also tested)
|
|
||||||
#if BUILD_GROUPS_ENABLED
|
#if BUILD_GROUPS_ENABLED
|
||||||
CLASS_HELPER_INTERFACE( EditablePanel, Panel )
|
CLASS_HELPER_INTERFACE( EditablePanel, Panel )
|
||||||
{
|
{
|
||||||
@ -1855,11 +1939,27 @@ public:
|
|||||||
{
|
{
|
||||||
__base()->LoadControlSettings( resName );
|
__base()->LoadControlSettings( resName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HSCRIPT FindChildByName( const char *childName )
|
||||||
|
{
|
||||||
|
Panel *pPanel = __base()->FindChildByName( childName, false );
|
||||||
|
if ( pPanel )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
IScriptVGUIObject* obj = FindInScriptPanels( child, i );
|
||||||
|
if ( obj )
|
||||||
|
{
|
||||||
|
return obj->GetScriptInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_VGUI_SCRIPTFUNC_EditablePanel()\
|
#define DEFINE_VGUI_SCRIPTFUNC_EditablePanel()\
|
||||||
DEFINE_VGUI_SCRIPTFUNC_Panel()\
|
DEFINE_VGUI_SCRIPTFUNC_Panel()\
|
||||||
DEFINE_SCRIPTFUNC( LoadControlSettings, "" )
|
DEFINE_SCRIPTFUNC( LoadControlSettings, "" )\
|
||||||
|
DEFINE_SCRIPTFUNC( FindChildByName, "" )
|
||||||
#endif
|
#endif
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
@ -2106,6 +2206,16 @@ public:
|
|||||||
{
|
{
|
||||||
__base()->SetShouldScaleImage( state );
|
__base()->SetShouldScaleImage( state );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetRotation( int rotation )
|
||||||
|
{
|
||||||
|
Assert( rotation == ROTATED_UNROTATED ||
|
||||||
|
rotation == ROTATED_CLOCKWISE_90 ||
|
||||||
|
rotation == ROTATED_ANTICLOCKWISE_90 ||
|
||||||
|
rotation == ROTATED_FLIPPED );
|
||||||
|
|
||||||
|
__base()->SetRotation( rotation );
|
||||||
|
}
|
||||||
#if 0
|
#if 0
|
||||||
void SetFrame( int nFrame )
|
void SetFrame( int nFrame )
|
||||||
{
|
{
|
||||||
@ -2120,6 +2230,7 @@ public:
|
|||||||
DEFINE_SCRIPTFUNC( SetDrawColor, "" )\
|
DEFINE_SCRIPTFUNC( SetDrawColor, "" )\
|
||||||
DEFINE_SCRIPTFUNC( SetTileImage, "" )\
|
DEFINE_SCRIPTFUNC( SetTileImage, "" )\
|
||||||
DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" )\
|
DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" )\
|
||||||
|
DEFINE_SCRIPTFUNC( SetRotation, "" )\
|
||||||
|
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
@ -2435,10 +2546,10 @@ public:
|
|||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
#if VGUI_TGA_IMAGE_PANEL
|
#if VGUI_TGA_IMAGE_PANEL
|
||||||
CLASS_HELPER_INTERFACE( TGAImagePanel, Panel )
|
CLASS_HELPER_INTERFACE( TGAImage, Panel )
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void SetTGAImage( const char *p )
|
void SetImage( const char *p )
|
||||||
{
|
{
|
||||||
__base()->SetTGAImage( p );
|
__base()->SetTGAImage( p );
|
||||||
}
|
}
|
||||||
@ -2454,9 +2565,37 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_VGUI_SCRIPTFUNC_TGAImagePanel()\
|
#define DEFINE_VGUI_SCRIPTFUNC_TGAImage()\
|
||||||
DEFINE_VGUI_SCRIPTFUNC_Panel()\
|
DEFINE_VGUI_SCRIPTFUNC_Panel()\
|
||||||
DEFINE_SCRIPTFUNC( SetTGAImage, "" )\
|
DEFINE_SCRIPTFUNC( SetImage, "" )\
|
||||||
|
DEFINE_SCRIPTFUNC( SetDrawColor, "" )\
|
||||||
|
DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" )
|
||||||
|
#endif
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
#if 0
|
||||||
|
CLASS_HELPER_INTERFACE( PNGImage, Panel )
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void SetImage( const char *p )
|
||||||
|
{
|
||||||
|
__base()->SetPNGImage( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDrawColor( int r, int g, int b, int a )
|
||||||
|
{
|
||||||
|
__base()->SetDrawColor( r, g, b, a );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetShouldScaleImage( bool i )
|
||||||
|
{
|
||||||
|
__base()->SetShouldScaleImage( i );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFINE_VGUI_SCRIPTFUNC_PNGImage()\
|
||||||
|
DEFINE_VGUI_SCRIPTFUNC_Panel()\
|
||||||
|
DEFINE_SCRIPTFUNC( SetImage, "" )\
|
||||||
DEFINE_SCRIPTFUNC( SetDrawColor, "" )\
|
DEFINE_SCRIPTFUNC( SetDrawColor, "" )\
|
||||||
DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" )
|
DEFINE_SCRIPTFUNC( SetShouldScaleImage, "" )
|
||||||
#endif
|
#endif
|
||||||
@ -2479,7 +2618,7 @@ static inline void SetHScript( HSCRIPT &var, HSCRIPT val )
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CheckCallback(s)\
|
#define CheckCallback(s)\
|
||||||
if ( FStrEq( cb, #s ) )\
|
if ( !V_strcmp( cb, #s ) )\
|
||||||
{\
|
{\
|
||||||
SetHScript( m_hfn##s, fn );\
|
SetHScript( m_hfn##s, fn );\
|
||||||
return;\
|
return;\
|
||||||
@ -2515,6 +2654,7 @@ private:
|
|||||||
HSCRIPT m_hfnOnKeyCodePressed;
|
HSCRIPT m_hfnOnKeyCodePressed;
|
||||||
HSCRIPT m_hfnOnKeyCodeReleased;
|
HSCRIPT m_hfnOnKeyCodeReleased;
|
||||||
HSCRIPT m_hfnOnKeyCodeTyped;
|
HSCRIPT m_hfnOnKeyCodeTyped;
|
||||||
|
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
HSCRIPT m_hfnOnCommand;
|
HSCRIPT m_hfnOnCommand;
|
||||||
#endif
|
#endif
|
||||||
@ -2530,7 +2670,9 @@ public:
|
|||||||
m_hfnPerformLayout(NULL),
|
m_hfnPerformLayout(NULL),
|
||||||
m_hfnOnTick(NULL),
|
m_hfnOnTick(NULL),
|
||||||
m_hfnOnScreenSizeChanged(NULL),
|
m_hfnOnScreenSizeChanged(NULL),
|
||||||
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
|
m_hfnOnCommand(NULL),
|
||||||
|
#endif
|
||||||
m_hfnOnCursorEntered(NULL),
|
m_hfnOnCursorEntered(NULL),
|
||||||
m_hfnOnCursorExited(NULL),
|
m_hfnOnCursorExited(NULL),
|
||||||
m_hfnOnCursorMoved(NULL),
|
m_hfnOnCursorMoved(NULL),
|
||||||
@ -2543,13 +2685,9 @@ public:
|
|||||||
m_hfnOnKeyCodePressed(NULL),
|
m_hfnOnKeyCodePressed(NULL),
|
||||||
m_hfnOnKeyCodeReleased(NULL),
|
m_hfnOnKeyCodeReleased(NULL),
|
||||||
m_hfnOnKeyCodeTyped(NULL)
|
m_hfnOnKeyCodeTyped(NULL)
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
|
||||||
,
|
|
||||||
m_hfnOnCommand(NULL)
|
|
||||||
#endif
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Shutdown()
|
void ScriptShutdown()
|
||||||
{
|
{
|
||||||
ivgui()->RemoveTickSignal( GetVPanel() );
|
ivgui()->RemoveTickSignal( GetVPanel() );
|
||||||
|
|
||||||
@ -2573,6 +2711,7 @@ public:
|
|||||||
SetHScript( m_hfnOnKeyCodePressed, NULL );
|
SetHScript( m_hfnOnKeyCodePressed, NULL );
|
||||||
SetHScript( m_hfnOnKeyCodeReleased, NULL );
|
SetHScript( m_hfnOnKeyCodeReleased, NULL );
|
||||||
SetHScript( m_hfnOnKeyCodeTyped, NULL );
|
SetHScript( m_hfnOnKeyCodeTyped, NULL );
|
||||||
|
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
SetHScript( m_hfnOnCommand, NULL );
|
SetHScript( m_hfnOnCommand, NULL );
|
||||||
#endif
|
#endif
|
||||||
@ -2775,6 +2914,7 @@ public:
|
|||||||
CheckCallback( OnKeyCodePressed );
|
CheckCallback( OnKeyCodePressed );
|
||||||
CheckCallback( OnKeyCodeReleased );
|
CheckCallback( OnKeyCodeReleased );
|
||||||
CheckCallback( OnKeyCodeTyped );
|
CheckCallback( OnKeyCodeTyped );
|
||||||
|
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
CheckCallback( OnCommand );
|
CheckCallback( OnCommand );
|
||||||
#endif
|
#endif
|
||||||
@ -2810,6 +2950,7 @@ private:
|
|||||||
HSCRIPT m_hfnOnKeyCodePressed;
|
HSCRIPT m_hfnOnKeyCodePressed;
|
||||||
HSCRIPT m_hfnOnKeyCodeReleased;
|
HSCRIPT m_hfnOnKeyCodeReleased;
|
||||||
HSCRIPT m_hfnOnKeyCodeTyped;
|
HSCRIPT m_hfnOnKeyCodeTyped;
|
||||||
|
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
HSCRIPT m_hfnOnCommand;
|
HSCRIPT m_hfnOnCommand;
|
||||||
#endif
|
#endif
|
||||||
@ -2826,6 +2967,9 @@ public:
|
|||||||
m_hfnPerformLayout(NULL),
|
m_hfnPerformLayout(NULL),
|
||||||
m_hfnOnTick(NULL),
|
m_hfnOnTick(NULL),
|
||||||
m_hfnOnScreenSizeChanged(NULL),
|
m_hfnOnScreenSizeChanged(NULL),
|
||||||
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
|
m_hfnOnCommand(NULL),
|
||||||
|
#endif
|
||||||
|
|
||||||
m_hfnOnCursorEntered(NULL),
|
m_hfnOnCursorEntered(NULL),
|
||||||
m_hfnOnCursorExited(NULL),
|
m_hfnOnCursorExited(NULL),
|
||||||
@ -2839,15 +2983,11 @@ public:
|
|||||||
m_hfnOnKeyCodePressed(NULL),
|
m_hfnOnKeyCodePressed(NULL),
|
||||||
m_hfnOnKeyCodeReleased(NULL),
|
m_hfnOnKeyCodeReleased(NULL),
|
||||||
m_hfnOnKeyCodeTyped(NULL)
|
m_hfnOnKeyCodeTyped(NULL)
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
|
||||||
,
|
|
||||||
m_hfnOnCommand(NULL)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
SetFadeEffectDisableOverride( true );
|
SetFadeEffectDisableOverride( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void ScriptShutdown()
|
||||||
{
|
{
|
||||||
ivgui()->RemoveTickSignal( GetVPanel() );
|
ivgui()->RemoveTickSignal( GetVPanel() );
|
||||||
|
|
||||||
@ -2866,6 +3006,7 @@ public:
|
|||||||
SetHScript( m_hfnOnKeyCodePressed, NULL );
|
SetHScript( m_hfnOnKeyCodePressed, NULL );
|
||||||
SetHScript( m_hfnOnKeyCodeReleased, NULL );
|
SetHScript( m_hfnOnKeyCodeReleased, NULL );
|
||||||
SetHScript( m_hfnOnKeyCodeTyped, NULL );
|
SetHScript( m_hfnOnKeyCodeTyped, NULL );
|
||||||
|
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
SetHScript( m_hfnOnCommand, NULL );
|
SetHScript( m_hfnOnCommand, NULL );
|
||||||
#endif
|
#endif
|
||||||
@ -2898,7 +3039,18 @@ public:
|
|||||||
g_pScriptVM->ExecuteFunction( m_hfnPerformLayout, NULL, 0, NULL, NULL, true );
|
g_pScriptVM->ExecuteFunction( m_hfnPerformLayout, NULL, 0, NULL, NULL, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
void ApplySchemeSettings( IScheme *pScheme )
|
||||||
|
{
|
||||||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||||||
|
|
||||||
|
if ( m_hfnApplySchemeSettings )
|
||||||
|
{
|
||||||
|
ScriptVariant_t arg;
|
||||||
|
g_pScriptVM->ExecuteFunction( m_hfnApplySchemeSettings, &arg, 1, NULL, NULL, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
void OnTick()
|
void OnTick()
|
||||||
{
|
{
|
||||||
g_pScriptVM->ExecuteFunction( m_hfnOnTick, NULL, 0, NULL, NULL, true );
|
g_pScriptVM->ExecuteFunction( m_hfnOnTick, NULL, 0, NULL, NULL, true );
|
||||||
@ -3072,6 +3224,7 @@ public:
|
|||||||
CheckCallback( OnKeyCodePressed );
|
CheckCallback( OnKeyCodePressed );
|
||||||
CheckCallback( OnKeyCodeReleased );
|
CheckCallback( OnKeyCodeReleased );
|
||||||
CheckCallback( OnKeyCodeTyped );
|
CheckCallback( OnKeyCodeTyped );
|
||||||
|
|
||||||
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
#if SCRIPT_VGUI_SIGNAL_INTERFACE
|
||||||
CheckCallback( OnCommand );
|
CheckCallback( OnCommand );
|
||||||
#endif
|
#endif
|
||||||
@ -3102,7 +3255,7 @@ public:
|
|||||||
m_hfnDoClick(NULL)
|
m_hfnDoClick(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Shutdown()
|
void ScriptShutdown()
|
||||||
{
|
{
|
||||||
SetHScript( m_hfnPaint, NULL );
|
SetHScript( m_hfnPaint, NULL );
|
||||||
SetHScript( m_hfnPaintBackground, NULL );
|
SetHScript( m_hfnPaintBackground, NULL );
|
||||||
@ -3173,7 +3326,7 @@ public:
|
|||||||
m_hfnTextChanged(NULL)
|
m_hfnTextChanged(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Shutdown()
|
void ScriptShutdown()
|
||||||
{
|
{
|
||||||
SetHScript( m_hfnTextChanged, NULL );
|
SetHScript( m_hfnTextChanged, NULL );
|
||||||
}
|
}
|
||||||
@ -3216,9 +3369,12 @@ public:
|
|||||||
SetShouldDrawFriendIcon( false );
|
SetShouldDrawFriendIcon( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_DESTRUCTOR( ~CScript_AvatarImage, CAvatarImagePanel )
|
~CScript_AvatarImage()
|
||||||
|
{
|
||||||
|
DebugDestructor( CAvatarImagePanel );
|
||||||
|
}
|
||||||
|
|
||||||
void Shutdown() {}
|
void ScriptShutdown() {}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
@ -3229,7 +3385,7 @@ class CTGAImagePanel : public Panel
|
|||||||
DECLARE_SCRIPTVGUI_CLASS_EX( CTGAImagePanel, Panel );
|
DECLARE_SCRIPTVGUI_CLASS_EX( CTGAImagePanel, Panel );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_iTextureID;
|
int m_iTexture;
|
||||||
int m_nWidth;
|
int m_nWidth;
|
||||||
int m_nHeight;
|
int m_nHeight;
|
||||||
Color m_ImageColor;
|
Color m_ImageColor;
|
||||||
@ -3238,7 +3394,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
CTGAImagePanel( Panel *parent, const char *name ) :
|
CTGAImagePanel( Panel *parent, const char *name ) :
|
||||||
BaseClass( parent, name ),
|
BaseClass( parent, name ),
|
||||||
m_iTextureID(-1),
|
m_iTexture(-1),
|
||||||
m_bScaleImage(0),
|
m_bScaleImage(0),
|
||||||
m_ImageColor( 255, 255, 255, 255 )
|
m_ImageColor( 255, 255, 255, 255 )
|
||||||
{
|
{
|
||||||
@ -3249,21 +3405,21 @@ public:
|
|||||||
{
|
{
|
||||||
DebugDestructor( CTGAImagePanel );
|
DebugDestructor( CTGAImagePanel );
|
||||||
|
|
||||||
if ( m_iTextureID != -1 )
|
if ( m_iTexture != -1 )
|
||||||
{
|
{
|
||||||
surface()->DestroyTextureID( m_iTextureID );
|
surface()->DestroyTextureID( m_iTexture );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown() {}
|
void ScriptShutdown() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Paint()
|
void Paint()
|
||||||
{
|
{
|
||||||
if ( m_iTextureID != -1 )
|
if ( m_iTexture != -1 )
|
||||||
{
|
{
|
||||||
surface()->DrawSetColor( m_ImageColor );
|
surface()->DrawSetColor( m_ImageColor );
|
||||||
surface()->DrawSetTexture( m_iTextureID );
|
surface()->DrawSetTexture( m_iTexture );
|
||||||
|
|
||||||
if ( m_bScaleImage )
|
if ( m_bScaleImage )
|
||||||
{
|
{
|
||||||
@ -3288,19 +3444,21 @@ public:
|
|||||||
public:
|
public:
|
||||||
void SetTGAImage( const char *fileName )
|
void SetTGAImage( const char *fileName )
|
||||||
{
|
{
|
||||||
if ( V_stricmp( V_GetFileExtension( fileName ), "tga" ) != 0 )
|
const char *ext = V_GetFileExtension( fileName );
|
||||||
|
|
||||||
|
if ( ext && V_stricmp( ext, "tga" ) != 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CUtlMemory< unsigned char > tga;
|
CUtlMemory< unsigned char > tga;
|
||||||
|
|
||||||
if ( TGALoader::LoadRGBA8888( fileName, tga, m_nWidth, m_nHeight ) )
|
if ( TGALoader::LoadRGBA8888( fileName, tga, m_nWidth, m_nHeight ) )
|
||||||
{
|
{
|
||||||
if ( m_iTextureID == -1 )
|
if ( m_iTexture == -1 )
|
||||||
{
|
{
|
||||||
m_iTextureID = surface()->CreateNewTextureID( true );
|
m_iTexture = surface()->CreateNewTextureID( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
surface()->DrawSetTextureRGBA( m_iTextureID, tga.Base(), m_nWidth, m_nHeight, false, false );
|
surface()->DrawSetTextureRGBA( m_iTexture, tga.Base(), m_nWidth, m_nHeight, false, false );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3393,10 +3551,19 @@ END_SCRIPTDESC()
|
|||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
#if VGUI_TGA_IMAGE_PANEL
|
#if VGUI_TGA_IMAGE_PANEL
|
||||||
BEGIN_VGUI_HELPER_EX( TGAImagePanel, CTGAImagePanel )
|
BEGIN_VGUI_HELPER_EX( TGAImage, CTGAImagePanel )
|
||||||
END_VGUI_HELPER()
|
END_VGUI_HELPER()
|
||||||
|
|
||||||
BEGIN_SCRIPTDESC_VGUI( TGAImagePanel )
|
BEGIN_SCRIPTDESC_VGUI( TGAImage )
|
||||||
|
END_SCRIPTDESC()
|
||||||
|
#endif
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
//--------------------------------------------------------------
|
||||||
|
#if 0
|
||||||
|
BEGIN_VGUI_HELPER_EX( PNGImage, CPNGImagePanel )
|
||||||
|
END_VGUI_HELPER()
|
||||||
|
|
||||||
|
BEGIN_SCRIPTDESC_VGUI( PNGImage )
|
||||||
END_SCRIPTDESC()
|
END_SCRIPTDESC()
|
||||||
#endif
|
#endif
|
||||||
//--------------------------------------------------------------
|
//--------------------------------------------------------------
|
||||||
@ -3448,7 +3615,7 @@ HSCRIPT CScriptVGUI::CreatePanel( const char* panelClass, HSCRIPT parent, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define Check( _name )\
|
#define Check( _name )\
|
||||||
if ( FStrEq( panelClass, #_name ) )\
|
if ( !V_strcmp( panelClass, #_name ) )\
|
||||||
{\
|
{\
|
||||||
CScript_##_name##_Helper *helper = AllocScriptPanel< CScript_##_name##_Helper >();\
|
CScript_##_name##_Helper *helper = AllocScriptPanel< CScript_##_name##_Helper >();\
|
||||||
helper->CreateFromScript< CScript_##_name##_Helper >( (HSCRIPT)parent, panelName, root );\
|
helper->CreateFromScript< CScript_##_name##_Helper >( (HSCRIPT)parent, panelName, root );\
|
||||||
@ -3467,7 +3634,7 @@ HSCRIPT CScriptVGUI::CreatePanel( const char* panelClass, HSCRIPT parent, const
|
|||||||
Check( AvatarImage );
|
Check( AvatarImage );
|
||||||
#endif
|
#endif
|
||||||
#if VGUI_TGA_IMAGE_PANEL
|
#if VGUI_TGA_IMAGE_PANEL
|
||||||
Check( TGAImagePanel );
|
Check( TGAImage );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_pScriptVM->RaiseException("invalid vgui class");
|
g_pScriptVM->RaiseException("invalid vgui class");
|
||||||
@ -3480,6 +3647,8 @@ void CScriptVGUI::LevelShutdownPostEntity()
|
|||||||
{
|
{
|
||||||
DebugMsg( "LevelShutdownPostEntity()\n" );
|
DebugMsg( "LevelShutdownPostEntity()\n" );
|
||||||
|
|
||||||
|
if ( g_ScriptPanels.Count() )
|
||||||
|
{
|
||||||
while ( g_ScriptPanels.Count() )
|
while ( g_ScriptPanels.Count() )
|
||||||
{
|
{
|
||||||
Assert( g_ScriptPanels.Head() != g_ScriptPanels.InvalidIndex() );
|
Assert( g_ScriptPanels.Head() != g_ScriptPanels.InvalidIndex() );
|
||||||
@ -3487,9 +3656,13 @@ void CScriptVGUI::LevelShutdownPostEntity()
|
|||||||
int head = g_ScriptPanels.Head();
|
int head = g_ScriptPanels.Head();
|
||||||
g_ScriptPanels[ head ]->Destroy( head );
|
g_ScriptPanels[ head ]->Destroy( head );
|
||||||
}
|
}
|
||||||
g_ScriptPanels.Purge();
|
|
||||||
|
|
||||||
FOR_EACH_VEC( g_ScriptTextureIDs, i )
|
g_ScriptPanels.Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( int i = g_ScriptTextureIDs.Count() )
|
||||||
|
{
|
||||||
|
while ( i-- )
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
char tex[MAX_PATH];
|
char tex[MAX_PATH];
|
||||||
@ -3498,7 +3671,9 @@ void CScriptVGUI::LevelShutdownPostEntity()
|
|||||||
#endif
|
#endif
|
||||||
surface()->DestroyTextureID( g_ScriptTextureIDs[i] );
|
surface()->DestroyTextureID( g_ScriptTextureIDs[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
g_ScriptTextureIDs.Purge();
|
g_ScriptTextureIDs.Purge();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reset hud element visibility
|
// Reset hud element visibility
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
static const char* g_Script_vgui_init = R"script(
|
static const char* g_Script_vgui_init = R"script(
|
||||||
local DoCreateFont = ISurface.CreateFont;
|
local DoCreateFont = ISurface.CreateFont;
|
||||||
ISurface.CreateFont <- function( name, props )
|
function ISurface::CreateFont( name, props )
|
||||||
{
|
{
|
||||||
if ( !("name" in props) || typeof props.name != "string" )
|
if ( !("name" in props) || typeof props.name != "string" )
|
||||||
throw "invalid parameter 'name'";
|
throw "invalid parameter 'name'";
|
||||||
@ -86,12 +86,12 @@ ISurface.CreateFont <- function( name, props )
|
|||||||
return DoCreateFont( name, props.name, props.tall, props.weight, blur, scanlines, flags, yres_min, yres_max, proportional );
|
return DoCreateFont( name, props.name, props.tall, props.weight, blur, scanlines, flags, yres_min, yres_max, proportional );
|
||||||
}
|
}
|
||||||
|
|
||||||
local _Schemes = {}
|
|
||||||
local _FontTall = {}
|
local _FontTall = {}
|
||||||
|
local _Schemes = {}
|
||||||
local DoGetFont = ISurface.DoGetFont <- ISurface.GetFont;
|
local DoGetFont = ISurface.DoGetFont <- ISurface.GetFont;
|
||||||
local DoGetFontTall = ISurface.GetFontTall;
|
local DoGetFontTall = ISurface.GetFontTall;
|
||||||
|
|
||||||
ISurface.GetFont <- function( name, proportional, sch = "" )
|
function ISurface::GetFont( name, proportional, sch = "" )
|
||||||
{
|
{
|
||||||
if ( sch in _Schemes )
|
if ( sch in _Schemes )
|
||||||
{
|
{
|
||||||
@ -151,33 +151,28 @@ ISurface.GetTextureID <- function( name )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Forward compatibility
|
// Forward compatibility
|
||||||
IVGui.GetRootPanel <- function() { return 1000 }
|
IVGui.GetRootPanel <- function() { return 0x8888 }
|
||||||
//IVGui.GetGameUIRootPanel <- function() { return 1001 }
|
//IVGui.GetGameUIRootPanel <- function() { return 0x8888+1 }
|
||||||
IVGui.GetClientDLLRootPanel <- function() { return 1002 }
|
IVGui.GetClientDLLRootPanel <- function() { return 0x8888+2 }
|
||||||
//IVGui.GetHudViewportPanel <- function() { return 1010 }
|
IVGui.GetHudViewport <- function() { return 0x8888+10 }
|
||||||
|
|
||||||
local CreatePanel = IVGui.CreatePanel;
|
local CreatePanel = IVGui.CreatePanel;
|
||||||
IVGui.CreatePanel <- function( type, parent, name )
|
function IVGui::CreatePanel( type, parent, name )
|
||||||
{
|
{
|
||||||
if ( !parent )
|
if ( !parent )
|
||||||
throw "invalid parent";
|
throw "invalid parent";
|
||||||
|
|
||||||
local root = 0;
|
local root = -1;
|
||||||
|
|
||||||
if ( typeof parent == "integer" )
|
if ( typeof parent == "integer" )
|
||||||
{
|
{
|
||||||
switch ( parent )
|
root = parent-0x8888;
|
||||||
|
switch ( root )
|
||||||
{
|
{
|
||||||
case 1000:
|
case 0:
|
||||||
root = 0;
|
case 2:
|
||||||
|
case 10:
|
||||||
break;
|
break;
|
||||||
|
default: throw "invalid parent";
|
||||||
case 1002:
|
|
||||||
root = 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw "invalid parent";
|
|
||||||
}
|
}
|
||||||
parent = null;
|
parent = null;
|
||||||
}
|
}
|
||||||
@ -390,5 +385,6 @@ if ( __Documentation.RegisterHelp != dummy )
|
|||||||
__Documentation.RegisterHelp( "IVGui::CreatePanel", "handle IVGui::CreatePanel(string, handle, string)", "" );
|
__Documentation.RegisterHelp( "IVGui::CreatePanel", "handle IVGui::CreatePanel(string, handle, string)", "" );
|
||||||
__Documentation.RegisterHelp( "IVGui::GetRootPanel", "handle IVGui::GetRootPanel()", "" );
|
__Documentation.RegisterHelp( "IVGui::GetRootPanel", "handle IVGui::GetRootPanel()", "" );
|
||||||
__Documentation.RegisterHelp( "IVGui::GetClientDLLRootPanel", "handle IVGui::GetClientDLLRootPanel()", "" );
|
__Documentation.RegisterHelp( "IVGui::GetClientDLLRootPanel", "handle IVGui::GetClientDLLRootPanel()", "" );
|
||||||
|
__Documentation.RegisterHelp( "IVGui::GetHudViewport", "handle IVGui::GetHudViewport()", "" );
|
||||||
}
|
}
|
||||||
)script";
|
)script";
|
||||||
|
@ -447,6 +447,8 @@ void CHudMessage::MessageScanStart( void )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Font was just set in MessageDrawScan()
|
||||||
|
#ifndef MAPBASE
|
||||||
m_parms.font = g_hFontTrebuchet24;
|
m_parms.font = g_hFontTrebuchet24;
|
||||||
|
|
||||||
if ( m_parms.vguiFontName != NULL &&
|
if ( m_parms.vguiFontName != NULL &&
|
||||||
@ -455,6 +457,7 @@ void CHudMessage::MessageScanStart( void )
|
|||||||
|
|
||||||
SetFont( vgui::scheme()->GetDefaultScheme(), m_parms.vguiFontName );
|
SetFont( vgui::scheme()->GetDefaultScheme(), m_parms.vguiFontName );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -497,7 +500,30 @@ void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time )
|
|||||||
m_parms.totalWidth = 0;
|
m_parms.totalWidth = 0;
|
||||||
m_parms.vguiFontName = pMessage->pVGuiSchemeFontName;
|
m_parms.vguiFontName = pMessage->pVGuiSchemeFontName;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_parms.vguiFontName != NULL &&
|
||||||
|
m_parms.vguiFontName[ 0 ] )
|
||||||
|
{
|
||||||
|
SetFont( vgui::scheme()->GetDefaultScheme(), m_parms.vguiFontName );
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
if ( m_parms.font == vgui::INVALID_FONT )
|
||||||
|
{
|
||||||
|
extern vgui::HFont GetScriptFont( const char *, bool );
|
||||||
|
|
||||||
|
vgui::HFont font = GetScriptFont( m_parms.vguiFontName, IsProportional() );
|
||||||
|
textmessage->SetFont( font );
|
||||||
|
m_parms.font = font;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
m_parms.font = g_hFontTrebuchet24;
|
m_parms.font = g_hFontTrebuchet24;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
m_parms.font = g_hFontTrebuchet24;
|
||||||
|
#endif
|
||||||
|
|
||||||
while ( *pText )
|
while ( *pText )
|
||||||
{
|
{
|
||||||
|
@ -855,7 +855,7 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||||||
C_BaseCombatWeapon *weapon = dynamic_cast< C_BaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
|
C_BaseCombatWeapon *weapon = dynamic_cast< C_BaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
|
||||||
if ( weapon )
|
if ( weapon )
|
||||||
{
|
{
|
||||||
player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
|
player->SelectItem( weapon->GetClassname(), ucmd->weaponsubtype );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +431,6 @@ const Vector& CScriptMaterialProxy::GetVarVector( int i )
|
|||||||
if (m_MaterialVars[i]->GetType() != MATERIAL_VAR_TYPE_VECTOR)
|
if (m_MaterialVars[i]->GetType() != MATERIAL_VAR_TYPE_VECTOR)
|
||||||
return vec3_origin;
|
return vec3_origin;
|
||||||
|
|
||||||
// This is really bad. Too bad!
|
|
||||||
return *(reinterpret_cast<const Vector*>(m_MaterialVars[i]->GetVecValue()));
|
return *(reinterpret_cast<const Vector*>(m_MaterialVars[i]->GetVecValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,6 +760,8 @@ public:
|
|||||||
virtual void LevelShutdownPostEntity( void )
|
virtual void LevelShutdownPostEntity( void )
|
||||||
{
|
{
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
g_ScriptEntityIterator.DisableEntityListening();
|
||||||
|
|
||||||
g_ScriptNetMsg->LevelShutdownPreVM();
|
g_ScriptNetMsg->LevelShutdownPreVM();
|
||||||
|
|
||||||
GetScriptHookManager().OnShutdown();
|
GetScriptHookManager().OnShutdown();
|
||||||
|
@ -76,6 +76,23 @@ int CAI_BaseNPC::GetActivityID(const char* actName)
|
|||||||
return m_pActivitySR->GetStringID(actName);
|
return m_pActivitySR->GetStringID(actName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Gets an activity ID or registers a new private one if it doesn't exist
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int CAI_BaseNPC::GetOrRegisterActivity( const char *actName )
|
||||||
|
{
|
||||||
|
int actID = GetActivityID( actName );
|
||||||
|
if (actID == ACT_INVALID)
|
||||||
|
{
|
||||||
|
actID = ActivityList_RegisterPrivateActivity( actName );
|
||||||
|
AddActivityToSR( actName, actID );
|
||||||
|
}
|
||||||
|
|
||||||
|
return actID;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ADD_ACTIVITY_TO_SR(activityname) AddActivityToSR(#activityname,activityname)
|
#define ADD_ACTIVITY_TO_SR(activityname) AddActivityToSR(#activityname,activityname)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -671,13 +671,27 @@ void CAI_BaseNPC::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bo
|
|||||||
{
|
{
|
||||||
BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner );
|
BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Alyx's enemy ignited code from below can now be run on any NPC as long as
|
||||||
|
// it's our current enemy.
|
||||||
|
if ( GetEnemy() && GetEnemy()->IsNPC() )
|
||||||
|
{
|
||||||
|
GetEnemy()->MyNPCPointer()->EnemyIgnited( this );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HL2_EPISODIC
|
#ifdef HL2_EPISODIC
|
||||||
CBasePlayer *pPlayer = AI_GetSinglePlayer();
|
CBasePlayer *pPlayer = AI_GetSinglePlayer();
|
||||||
if ( pPlayer && pPlayer->IRelationType( this ) != D_LI )
|
if ( pPlayer && pPlayer->IRelationType( this ) != D_LI )
|
||||||
{
|
{
|
||||||
CNPC_Alyx *alyx = CNPC_Alyx::GetAlyx();
|
CNPC_Alyx *alyx = CNPC_Alyx::GetAlyx();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Alyx's code continues to run if Alyx was not this NPC's enemy.
|
||||||
|
if ( alyx && alyx != GetEnemy() )
|
||||||
|
#else
|
||||||
if ( alyx )
|
if ( alyx )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
alyx->EnemyIgnited( this );
|
alyx->EnemyIgnited( this );
|
||||||
}
|
}
|
||||||
@ -3026,6 +3040,10 @@ void CAI_BaseNPC::PopulatePoseParameters( void )
|
|||||||
m_poseAim_Yaw = LookupPoseParameter( "aim_yaw" );
|
m_poseAim_Yaw = LookupPoseParameter( "aim_yaw" );
|
||||||
m_poseMove_Yaw = LookupPoseParameter( "move_yaw" );
|
m_poseMove_Yaw = LookupPoseParameter( "move_yaw" );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_poseInteractionRelativeYaw = LookupPoseParameter( "interaction_relative_yaw" );
|
||||||
|
#endif
|
||||||
|
|
||||||
BaseClass::PopulatePoseParameters();
|
BaseClass::PopulatePoseParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9526,6 +9544,12 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
{
|
{
|
||||||
m_hCine->FireScriptEvent( atoi( pEvent->options ) );
|
m_hCine->FireScriptEvent( atoi( pEvent->options ) );
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else if ( GetHintNode() )
|
||||||
|
{
|
||||||
|
GetHintNode()->FireScriptEvent( atoi( pEvent->options ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIXME: look so see if it's playing a vcd and fire those instead
|
// FIXME: look so see if it's playing a vcd and fire those instead
|
||||||
@ -12333,6 +12357,7 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
|||||||
|
|
||||||
DEFINE_SCRIPTFUNC( IsCommandable, "Check if the NPC is commandable." )
|
DEFINE_SCRIPTFUNC( IsCommandable, "Check if the NPC is commandable." )
|
||||||
DEFINE_SCRIPTFUNC( IsInPlayerSquad, "Check if the NPC is in the player's squad." )
|
DEFINE_SCRIPTFUNC( IsInPlayerSquad, "Check if the NPC is in the player's squad." )
|
||||||
|
DEFINE_SCRIPTFUNC( IsMedic, "Returns true if this NPC is a medic." )
|
||||||
|
|
||||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetCine, "GetCine", "Get the NPC's currently running scripted sequence if it has one." )
|
DEFINE_SCRIPTFUNC_NAMED( VScriptGetCine, "GetCine", "Get the NPC's currently running scripted sequence if it has one." )
|
||||||
DEFINE_SCRIPTFUNC( GetScriptState, "Get the NPC's current scripted sequence state." )
|
DEFINE_SCRIPTFUNC( GetScriptState, "Get the NPC's current scripted sequence state." )
|
||||||
@ -12443,7 +12468,11 @@ BEGIN_SIMPLE_DATADESC( ScriptedNPCInteraction_t )
|
|||||||
DEFINE_FIELD( bValidOnCurrentEnemy, FIELD_BOOLEAN ),
|
DEFINE_FIELD( bValidOnCurrentEnemy, FIELD_BOOLEAN ),
|
||||||
DEFINE_FIELD( flNextAttemptTime, FIELD_TIME ),
|
DEFINE_FIELD( flNextAttemptTime, FIELD_TIME ),
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
DEFINE_FIELD( MiscCriteria, FIELD_STRING ),//DEFINE_UTLVECTOR( MiscCriteria, FIELD_EMBEDDED ),
|
DEFINE_EMBEDDED_ARRAY( sTheirPhases, SNPCINT_NUM_PHASES ),
|
||||||
|
DEFINE_FIELD( bHasSeparateSequenceNames, FIELD_BOOLEAN ),
|
||||||
|
DEFINE_FIELD( flMaxAngleDiff, FIELD_FLOAT ),
|
||||||
|
DEFINE_FIELD( iszRelatedInteractions, FIELD_STRING ),
|
||||||
|
DEFINE_FIELD( MiscCriteria, FIELD_STRING ),
|
||||||
#endif
|
#endif
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
|
|
||||||
@ -13200,17 +13229,14 @@ void CAI_BaseNPC::InputSetEnemyFilter( inputdata_t &inputdata )
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CAI_BaseNPC::InputSetHealthFraction( inputdata_t &inputdata )
|
void CAI_BaseNPC::InputSetHealthFraction( inputdata_t &inputdata )
|
||||||
{
|
{
|
||||||
// npc_helicopter uses SetHealth() instead of the regular NPC practice of TakeHealth() and TakeDamage().
|
// npc_helicopter uses an identically named input and scales down whole numbers instead of using fractions directly.
|
||||||
// It also also uses 50, 75, etc. and scales it by 0.01 for some reason.
|
// This function is overridden by npc_helicopter for other reasons, but support for its differing behavior is also available through this input.
|
||||||
// We're using the same model as InputSetHealth() and just letting npc_helicopter override it. No big deal.
|
|
||||||
// We're also adding support for its "whole number * 0.01" thing too.
|
|
||||||
float flFactor = inputdata.value.Float();
|
float flFactor = inputdata.value.Float();
|
||||||
if ( flFactor > 1.0f )
|
if ( flFactor > 1.0f )
|
||||||
{
|
{
|
||||||
flFactor *= 0.01f;
|
flFactor *= 0.01f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Excuse the complication...
|
|
||||||
float flNewHealth = (GetMaxHealth() * flFactor);
|
float flNewHealth = (GetMaxHealth() * flFactor);
|
||||||
int iNewHealth = (int)flNewHealth;
|
int iNewHealth = (int)flNewHealth;
|
||||||
if (flNewHealth < (GetMaxHealth() / 2))
|
if (flNewHealth < (GetMaxHealth() / 2))
|
||||||
@ -13510,6 +13536,10 @@ bool CAI_BaseNPC::CineCleanup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear interaction partner, because we're not running a scripted sequence anymore
|
// Clear interaction partner, because we're not running a scripted sequence anymore
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// We need the interaction partner for server ragdoll death cleanup, so don't clear if we're not alive
|
||||||
|
if (IsAlive())
|
||||||
|
#endif
|
||||||
m_hInteractionPartner = NULL;
|
m_hInteractionPartner = NULL;
|
||||||
CleanupForcedInteraction();
|
CleanupForcedInteraction();
|
||||||
}
|
}
|
||||||
@ -14850,32 +14880,66 @@ void CAI_BaseNPC::ParseScriptedNPCInteractions(void)
|
|||||||
else if (!Q_strncmp(szName, "entry_sequence", 14))
|
else if (!Q_strncmp(szName, "entry_sequence", 14))
|
||||||
sInteraction.sPhases[SNPCINT_ENTRY].iszSequence = AllocPooledString(szValue);
|
sInteraction.sPhases[SNPCINT_ENTRY].iszSequence = AllocPooledString(szValue);
|
||||||
else if (!Q_strncmp(szName, "entry_activity", 14))
|
else if (!Q_strncmp(szName, "entry_activity", 14))
|
||||||
sInteraction.sPhases[SNPCINT_ENTRY].iActivity = GetActivityID(szValue);
|
sInteraction.sPhases[SNPCINT_ENTRY].iActivity = GetOrRegisterActivity(szValue);
|
||||||
|
|
||||||
else if (!Q_strncmp(szName, "sequence", 8))
|
else if (!Q_strncmp(szName, "sequence", 8))
|
||||||
sInteraction.sPhases[SNPCINT_SEQUENCE].iszSequence = AllocPooledString(szValue);
|
sInteraction.sPhases[SNPCINT_SEQUENCE].iszSequence = AllocPooledString(szValue);
|
||||||
else if (!Q_strncmp(szName, "activity", 8))
|
else if (!Q_strncmp(szName, "activity", 8))
|
||||||
sInteraction.sPhases[SNPCINT_SEQUENCE].iActivity = GetActivityID(szValue);
|
sInteraction.sPhases[SNPCINT_SEQUENCE].iActivity = GetOrRegisterActivity(szValue);
|
||||||
|
|
||||||
else if (!Q_strncmp(szName, "exit_sequence", 13))
|
else if (!Q_strncmp(szName, "exit_sequence", 13))
|
||||||
sInteraction.sPhases[SNPCINT_EXIT].iszSequence = AllocPooledString(szValue);
|
sInteraction.sPhases[SNPCINT_EXIT].iszSequence = AllocPooledString(szValue);
|
||||||
else if (!Q_strncmp(szName, "exit_activity", 13))
|
else if (!Q_strncmp(szName, "exit_activity", 13))
|
||||||
sInteraction.sPhases[SNPCINT_EXIT].iActivity = GetActivityID(szValue);
|
sInteraction.sPhases[SNPCINT_EXIT].iActivity = GetOrRegisterActivity(szValue);
|
||||||
|
|
||||||
|
else if (!Q_strncmp(szName, "their_", 6))
|
||||||
|
{
|
||||||
|
const char *szTheirName = szName + 6;
|
||||||
|
sInteraction.bHasSeparateSequenceNames = true;
|
||||||
|
|
||||||
|
if (!Q_strncmp(szTheirName, "entry_sequence", 14))
|
||||||
|
sInteraction.sTheirPhases[SNPCINT_ENTRY].iszSequence = AllocPooledString(szValue);
|
||||||
|
else if (!Q_strncmp(szTheirName, "entry_activity", 14))
|
||||||
|
sInteraction.sTheirPhases[SNPCINT_ENTRY].iActivity = GetOrRegisterActivity(szValue);
|
||||||
|
|
||||||
|
else if (!Q_strncmp(szTheirName, "sequence", 8))
|
||||||
|
sInteraction.sTheirPhases[SNPCINT_SEQUENCE].iszSequence = AllocPooledString(szValue);
|
||||||
|
else if (!Q_strncmp(szTheirName, "activity", 8))
|
||||||
|
sInteraction.sTheirPhases[SNPCINT_SEQUENCE].iActivity = GetOrRegisterActivity(szValue);
|
||||||
|
|
||||||
|
else if (!Q_strncmp(szTheirName, "exit_sequence", 13))
|
||||||
|
sInteraction.sTheirPhases[SNPCINT_EXIT].iszSequence = AllocPooledString(szValue);
|
||||||
|
else if (!Q_strncmp(szTheirName, "exit_activity", 13))
|
||||||
|
sInteraction.sTheirPhases[SNPCINT_EXIT].iActivity = GetOrRegisterActivity(szValue);
|
||||||
|
|
||||||
|
// Add anything else to our miscellaneous criteria
|
||||||
|
else
|
||||||
|
{
|
||||||
|
szCriteria = UTIL_VarArgs("%s,%s:%s", szCriteria, szName, szValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if (!Q_strncmp(szName, "delay", 5))
|
else if (!Q_strncmp(szName, "delay", 5))
|
||||||
sInteraction.flDelay = atof(szValue);
|
sInteraction.flDelay = atof(szValue);
|
||||||
else if (!Q_strncmp(szName, "origin_max_delta", 16))
|
else if (!Q_strncmp(szName, "origin_max_delta", 16))
|
||||||
sInteraction.flDistSqr = atof(szValue);
|
sInteraction.flDistSqr = atof(szValue);
|
||||||
|
else if (!Q_strncmp(szName, "angles_max_diff", 15))
|
||||||
|
sInteraction.flMaxAngleDiff = atof(szValue);
|
||||||
|
|
||||||
else if (!Q_strncmp(szName, "loop_in_action", 14) && !FStrEq(szValue, "0"))
|
else if (!Q_strncmp(szName, "loop_in_action", 14) && !FStrEq(szValue, "0"))
|
||||||
sInteraction.iFlags |= SCNPC_FLAG_LOOP_IN_ACTION;
|
sInteraction.iFlags |= SCNPC_FLAG_LOOP_IN_ACTION;
|
||||||
|
|
||||||
else if (!Q_strncmp(szName, "dont_teleport_at_end", 20))
|
else if (!Q_strncmp(szName, "dont_teleport_at_end", 20))
|
||||||
{
|
{
|
||||||
if (!Q_stricmp(szValue, "me") || !Q_stricmp(szValue, "both"))
|
if (!Q_stricmp(szValue, "me"))
|
||||||
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_ME;
|
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_ME;
|
||||||
else if (!Q_stricmp(szValue, "them") || !Q_stricmp(szValue, "both"))
|
else if (!Q_stricmp(szValue, "them"))
|
||||||
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM;
|
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM;
|
||||||
|
else if (!Q_stricmp( szValue, "both" ))
|
||||||
|
{
|
||||||
|
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_ME;
|
||||||
|
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!Q_strncmp(szName, "needs_weapon", 12))
|
else if (!Q_strncmp(szName, "needs_weapon", 12))
|
||||||
@ -14902,6 +14966,11 @@ void CAI_BaseNPC::ParseScriptedNPCInteractions(void)
|
|||||||
sInteraction.iszTheirWeapon = AllocPooledString(szValue);
|
sInteraction.iszTheirWeapon = AllocPooledString(szValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (!Q_strncmp(szName, "related_interactions", 20))
|
||||||
|
{
|
||||||
|
sInteraction.iszRelatedInteractions = AllocPooledString(szValue);
|
||||||
|
}
|
||||||
|
|
||||||
// Add anything else to our miscellaneous criteria
|
// Add anything else to our miscellaneous criteria
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -15133,8 +15202,23 @@ void CAI_BaseNPC::AddScriptedNPCInteraction( ScriptedNPCInteraction_t *pInteract
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
const char *CAI_BaseNPC::GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase )
|
const char *CAI_BaseNPC::GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase, bool bOtherNPC )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (bOtherNPC && pInteraction->bHasSeparateSequenceNames)
|
||||||
|
{
|
||||||
|
// Check unique phases
|
||||||
|
if ( pInteraction->sTheirPhases[iPhase].iActivity != ACT_INVALID )
|
||||||
|
{
|
||||||
|
int iSequence = SelectWeightedSequence( (Activity)pInteraction->sTheirPhases[iPhase].iActivity );
|
||||||
|
return GetSequenceName( iSequence );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pInteraction->sTheirPhases[iPhase].iszSequence != NULL_STRING )
|
||||||
|
return STRING(pInteraction->sTheirPhases[iPhase].iszSequence);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( pInteraction->sPhases[iPhase].iActivity != ACT_INVALID )
|
if ( pInteraction->sPhases[iPhase].iActivity != ACT_INVALID )
|
||||||
{
|
{
|
||||||
int iSequence = SelectWeightedSequence( (Activity)pInteraction->sPhases[iPhase].iActivity );
|
int iSequence = SelectWeightedSequence( (Activity)pInteraction->sPhases[iPhase].iActivity );
|
||||||
@ -15228,6 +15312,37 @@ void CAI_BaseNPC::StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedN
|
|||||||
|
|
||||||
// Setup next attempt
|
// Setup next attempt
|
||||||
pInteraction->flNextAttemptTime = gpGlobals->curtime + pInteraction->flDelay + RandomFloat(-2,2);
|
pInteraction->flNextAttemptTime = gpGlobals->curtime + pInteraction->flDelay + RandomFloat(-2,2);
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (pInteraction->iszRelatedInteractions != NULL_STRING)
|
||||||
|
{
|
||||||
|
// Delay related interactions as well
|
||||||
|
char szRelatedInteractions[256];
|
||||||
|
Q_strncpy( szRelatedInteractions, STRING( pInteraction->iszRelatedInteractions ), sizeof( szRelatedInteractions ) );
|
||||||
|
|
||||||
|
char *pszInteraction = strtok( szRelatedInteractions, "," );
|
||||||
|
while (pszInteraction)
|
||||||
|
{
|
||||||
|
bool bWildCard = Matcher_ContainsWildcard( pszInteraction );
|
||||||
|
|
||||||
|
for ( int i = 0; i < m_ScriptedInteractions.Count(); i++ )
|
||||||
|
{
|
||||||
|
ScriptedNPCInteraction_t *pOtherInteraction = &m_ScriptedInteractions[i];
|
||||||
|
|
||||||
|
if ( Matcher_NamesMatch( pszInteraction, STRING( pOtherInteraction->iszInteractionName ) ) && pOtherInteraction != pInteraction )
|
||||||
|
{
|
||||||
|
if (pOtherInteraction->flNextAttemptTime < pInteraction->flNextAttemptTime)
|
||||||
|
pOtherInteraction->flNextAttemptTime = pInteraction->flNextAttemptTime;
|
||||||
|
|
||||||
|
// Not looking for multiple
|
||||||
|
if (!bWildCard)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pszInteraction = strtok( NULL, "," );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Spawn a scripted sequence for this NPC to play the interaction anim
|
// Spawn a scripted sequence for this NPC to play the interaction anim
|
||||||
CAI_ScriptedSequence *pMySequence = (CAI_ScriptedSequence*)CreateEntityByName( "scripted_sequence" );
|
CAI_ScriptedSequence *pMySequence = (CAI_ScriptedSequence*)CreateEntityByName( "scripted_sequence" );
|
||||||
@ -15259,6 +15374,15 @@ void CAI_BaseNPC::StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedN
|
|||||||
CAI_ScriptedSequence *pTheirSequence = NULL;
|
CAI_ScriptedSequence *pTheirSequence = NULL;
|
||||||
if ( pOtherNPC )
|
if ( pOtherNPC )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (pInteraction->bHasSeparateSequenceNames)
|
||||||
|
{
|
||||||
|
pszEntrySequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_ENTRY, true );
|
||||||
|
pszSequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_SEQUENCE, true );
|
||||||
|
pszExitSequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_EXIT, true );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
pTheirSequence = (CAI_ScriptedSequence*)CreateEntityByName( "scripted_sequence" );
|
pTheirSequence = (CAI_ScriptedSequence*)CreateEntityByName( "scripted_sequence" );
|
||||||
pTheirSequence->KeyValue( "m_iszEntry", pszEntrySequence );
|
pTheirSequence->KeyValue( "m_iszEntry", pszEntrySequence );
|
||||||
pTheirSequence->KeyValue( "m_iszPlay", pszSequence );
|
pTheirSequence->KeyValue( "m_iszPlay", pszSequence );
|
||||||
@ -15282,6 +15406,26 @@ void CAI_BaseNPC::StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedN
|
|||||||
|
|
||||||
// Tell their sequence to keep their position relative to me
|
// Tell their sequence to keep their position relative to me
|
||||||
pTheirSequence->SetupInteractionPosition( this, pInteraction->matDesiredLocalToWorld );
|
pTheirSequence->SetupInteractionPosition( this, pInteraction->matDesiredLocalToWorld );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( !(pInteraction->iFlags & SCNPC_FLAG_TEST_OTHER_ANGLES) )
|
||||||
|
{
|
||||||
|
// Set up interaction yaw pose if it exists
|
||||||
|
float flYaw = AngleDistance( angDesired.y, angOtherAngles.y );
|
||||||
|
|
||||||
|
int nInteractionPose = LookupPoseInteractionRelativeYaw();
|
||||||
|
if (nInteractionPose > -1)
|
||||||
|
{
|
||||||
|
SetPoseParameter( nInteractionPose, flYaw );
|
||||||
|
}
|
||||||
|
|
||||||
|
nInteractionPose = pOtherNPC->LookupPoseInteractionRelativeYaw();
|
||||||
|
if (nInteractionPose > -1)
|
||||||
|
{
|
||||||
|
pOtherNPC->SetPoseParameter( nInteractionPose, flYaw );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn both sequences at once
|
// Spawn both sequences at once
|
||||||
@ -15370,7 +15514,7 @@ bool CAI_BaseNPC::CanRunAScriptedNPCInteraction( bool bForced )
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Default AI prevents interactions while melee attacking, but not ranged attacking
|
// Default AI prevents interactions while melee attacking, but not ranged attacking
|
||||||
if ( IsCurSchedule( SCHED_MELEE_ATTACK1 ) || IsCurSchedule( SCHED_MELEE_ATTACK2 ) )
|
if ( ( IsCurSchedule( SCHED_MELEE_ATTACK1 ) || IsCurSchedule( SCHED_MELEE_ATTACK2 ) ) && !CanStartDynamicInteractionDuringMelee() )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15559,8 +15703,14 @@ void CAI_BaseNPC::CalculateValidEnemyInteractions( void )
|
|||||||
|
|
||||||
if (bSame)
|
if (bSame)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// Resolve the activity or sequence, and make sure our enemy has it
|
||||||
|
const char *pszSequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_SEQUENCE, true );
|
||||||
|
if ( !pszSequence )
|
||||||
|
continue;
|
||||||
|
if ( pNPC->LookupSequence( pszSequence ) == -1 )
|
||||||
|
continue;
|
||||||
|
#else
|
||||||
// Use sequence? or activity?
|
// Use sequence? or activity?
|
||||||
if ( pInteraction->sPhases[SNPCINT_SEQUENCE].iActivity != ACT_INVALID )
|
if ( pInteraction->sPhases[SNPCINT_SEQUENCE].iActivity != ACT_INVALID )
|
||||||
{
|
{
|
||||||
@ -15576,53 +15726,6 @@ void CAI_BaseNPC::CalculateValidEnemyInteractions( void )
|
|||||||
if ( pNPC->LookupSequence( STRING(pInteraction->sPhases[SNPCINT_SEQUENCE].iszSequence) ) == -1 )
|
if ( pNPC->LookupSequence( STRING(pInteraction->sPhases[SNPCINT_SEQUENCE].iszSequence) ) == -1 )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAPBASE
|
|
||||||
if (pInteraction->MiscCriteria != NULL_STRING)
|
|
||||||
{
|
|
||||||
// Test against response system criteria
|
|
||||||
AI_CriteriaSet set;
|
|
||||||
ModifyOrAppendCriteria( set );
|
|
||||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
|
||||||
if( pPlayer )
|
|
||||||
pPlayer->ModifyOrAppendPlayerCriteria( set );
|
|
||||||
ReAppendContextCriteria( set );
|
|
||||||
|
|
||||||
DevMsg("Testing %s misc criteria\n", STRING(pInteraction->MiscCriteria));
|
|
||||||
|
|
||||||
int index;
|
|
||||||
const char *criteriavalue;
|
|
||||||
char key[128];
|
|
||||||
char value[128];
|
|
||||||
const char *p = STRING(pInteraction->MiscCriteria);
|
|
||||||
while ( p )
|
|
||||||
{
|
|
||||||
#ifdef NEW_RESPONSE_SYSTEM
|
|
||||||
p = SplitContext( p, key, sizeof( key ), value, sizeof( value ), NULL, STRING(pInteraction->MiscCriteria) );
|
|
||||||
#else
|
|
||||||
p = SplitContext( p, key, sizeof( key ), value, sizeof( value ), NULL );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
index = set.FindCriterionIndex(key);
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
criteriavalue = set.GetValue(index);
|
|
||||||
if (!Matcher_Match(value, criteriavalue))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Test with empty string in case our criteria is != or something
|
|
||||||
criteriavalue = "";
|
|
||||||
if (!Matcher_Match(value, criteriavalue))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pInteraction->bValidOnCurrentEnemy = true;
|
pInteraction->bValidOnCurrentEnemy = true;
|
||||||
@ -15792,7 +15895,95 @@ bool CAI_BaseNPC::InteractionIsAllowed( CAI_BaseNPC *pOtherNPC, ScriptedNPCInter
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// m_iDynamicInteractionsAllowed == TRS_FALSE case is already handled in CanRunAScriptedNPCInteraction().
|
// m_iDynamicInteractionsAllowed == TRS_FALSE case is already handled in CanRunAScriptedNPCInteraction().
|
||||||
return !(pInteraction->iFlags & SCNPC_FLAG_MAPBASE_ADDITION && m_iDynamicInteractionsAllowed == TRS_NONE);
|
if (pInteraction->iFlags & SCNPC_FLAG_MAPBASE_ADDITION && m_iDynamicInteractionsAllowed == TRS_NONE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Test misc. criteria here since some of it may not have been valid on initial calculation, but could be now
|
||||||
|
if (pInteraction->MiscCriteria != NULL_STRING)
|
||||||
|
{
|
||||||
|
// Test against response system criteria
|
||||||
|
AI_CriteriaSet set;
|
||||||
|
ModifyOrAppendCriteria( set );
|
||||||
|
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||||
|
if (pPlayer)
|
||||||
|
pPlayer->ModifyOrAppendPlayerCriteria( set );
|
||||||
|
|
||||||
|
// Get criteria from target if we want it
|
||||||
|
if ( V_strstr( STRING( pInteraction->MiscCriteria ), "their_" ) )
|
||||||
|
{
|
||||||
|
// Currently, in order to get everything which might be desired, we call the other NPC's ModifyOrAppendCriteria.
|
||||||
|
// We put it in a separate criteria set, then assign a prefix and append it to the main set, similar to how contexts are appended.
|
||||||
|
// This includes a few global criterions which we might not need, so we throw them out before they're merged.
|
||||||
|
// This isn't a very efficient solution, but there are no better options available without rewriting parts of the response criteria system.
|
||||||
|
AI_CriteriaSet theirSet;
|
||||||
|
pOtherNPC->ModifyOrAppendCriteria( theirSet );
|
||||||
|
|
||||||
|
set.EnsureCapacity( (theirSet.GetCount()-2) + set.GetCount() ); // We know we'll be throwing out 2 global criterions
|
||||||
|
|
||||||
|
char sz[ 128 ];
|
||||||
|
for ( int i = 0; i < theirSet.GetCount(); i++ )
|
||||||
|
{
|
||||||
|
const char *name = theirSet.GetName( i );
|
||||||
|
const char *value = theirSet.GetValue( i );
|
||||||
|
|
||||||
|
if (FStrEq( name, "map" ) || FStrEq( name, "episodic" ) || FStrEq( name, "is_console" )
|
||||||
|
|| FStrEq( name, "month" ) || FStrEq( name, "day" )
|
||||||
|
|| FStrEq( name, "is_console" ) || FStrEq( name, "is_pc" )
|
||||||
|
|| V_strnicmp( name, "world", 5 ) == 0)
|
||||||
|
{
|
||||||
|
// Global criterion, ignore
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_snprintf( sz, sizeof( sz ), "their_%s", name );
|
||||||
|
|
||||||
|
if (ai_debug_dyninteractions.GetInt() == 3)
|
||||||
|
Msg( "%i: %s -> %s:%s\n", i, name, sz, value );
|
||||||
|
|
||||||
|
set.AppendCriteria( sz, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append this afterwards because it has its own prefix system
|
||||||
|
pOtherNPC->AppendContextToCriteria( set, "their_" );
|
||||||
|
}
|
||||||
|
|
||||||
|
ReAppendContextCriteria( set );
|
||||||
|
|
||||||
|
int index;
|
||||||
|
const char *criteriavalue;
|
||||||
|
char key[128];
|
||||||
|
char value[128];
|
||||||
|
const char *p = STRING( pInteraction->MiscCriteria );
|
||||||
|
while ( p )
|
||||||
|
{
|
||||||
|
#ifdef NEW_RESPONSE_SYSTEM
|
||||||
|
p = SplitContext( p, key, sizeof( key ), value, sizeof( value ), NULL, STRING( pInteraction->MiscCriteria ) );
|
||||||
|
#else
|
||||||
|
p = SplitContext( p, key, sizeof( key ), value, sizeof( value ), NULL );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
index = set.FindCriterionIndex( key );
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
criteriavalue = set.GetValue( index );
|
||||||
|
if (!Matcher_Match( value, criteriavalue ))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Test with empty string in case our criteria is != or something
|
||||||
|
criteriavalue = "";
|
||||||
|
if (!Matcher_Match( value, criteriavalue ))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -15830,6 +16021,11 @@ bool CAI_BaseNPC::InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInte
|
|||||||
{
|
{
|
||||||
Msg(" %s distsqr: %0.2f (%0.2f %0.2f %0.2f), desired: <%0.2f (%0.2f %0.2f %0.2f)\n", GetDebugName(), flDistSqr,
|
Msg(" %s distsqr: %0.2f (%0.2f %0.2f %0.2f), desired: <%0.2f (%0.2f %0.2f %0.2f)\n", GetDebugName(), flDistSqr,
|
||||||
pOtherNPC->GetAbsOrigin().x, pOtherNPC->GetAbsOrigin().y, pOtherNPC->GetAbsOrigin().z, pInteraction->flDistSqr, vecOrigin.x, vecOrigin.y, vecOrigin.z );
|
pOtherNPC->GetAbsOrigin().x, pOtherNPC->GetAbsOrigin().y, pOtherNPC->GetAbsOrigin().z, pInteraction->flDistSqr, vecOrigin.x, vecOrigin.y, vecOrigin.z );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector vecForward, vecRight;
|
||||||
|
GetVectors( &vecForward, &vecRight, NULL );
|
||||||
|
NDebugOverlay::Circle( vecOrigin + Vector(0,0,2), vecForward, vecRight, FastSqrt(pInteraction->flDistSqr), 255, 0, 0, 255, true, 0.1f );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -15842,6 +16038,11 @@ bool CAI_BaseNPC::InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInte
|
|||||||
Msg(" %s is at: %0.2f %0.2f %0.2f\n", GetDebugName(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z );
|
Msg(" %s is at: %0.2f %0.2f %0.2f\n", GetDebugName(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z );
|
||||||
Msg(" %s distsqr: %0.2f (%0.2f %0.2f %0.2f), desired: (%0.2f %0.2f %0.2f)\n", GetDebugName(), flDistSqr,
|
Msg(" %s distsqr: %0.2f (%0.2f %0.2f %0.2f), desired: (%0.2f %0.2f %0.2f)\n", GetDebugName(), flDistSqr,
|
||||||
pOtherNPC->GetAbsOrigin().x, pOtherNPC->GetAbsOrigin().y, pOtherNPC->GetAbsOrigin().z, vecOrigin.x, vecOrigin.y, vecOrigin.z );
|
pOtherNPC->GetAbsOrigin().x, pOtherNPC->GetAbsOrigin().y, pOtherNPC->GetAbsOrigin().z, vecOrigin.x, vecOrigin.y, vecOrigin.z );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector vecForward, vecRight;
|
||||||
|
GetVectors( &vecForward, &vecRight, NULL );
|
||||||
|
NDebugOverlay::Circle( vecOrigin + Vector( 0, 0, 2 ), vecForward, vecRight, FastSqrt( pInteraction->flDistSqr ), 255, 0, 0, 255, true, 0.1f );
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( pOtherNPC )
|
if ( pOtherNPC )
|
||||||
{
|
{
|
||||||
@ -15858,14 +16059,28 @@ bool CAI_BaseNPC::InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInte
|
|||||||
for ( int ang = 0; ang < 3; ang++ )
|
for ( int ang = 0; ang < 3; ang++ )
|
||||||
{
|
{
|
||||||
float flAngDiff = AngleDiff( angEnemyAngles[ang], angAngles[ang] );
|
float flAngDiff = AngleDiff( angEnemyAngles[ang], angAngles[ang] );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( fabs(flAngDiff) > pInteraction->flMaxAngleDiff )
|
||||||
|
#else
|
||||||
if ( fabs(flAngDiff) > DSS_MAX_ANGLE_DIFF )
|
if ( fabs(flAngDiff) > DSS_MAX_ANGLE_DIFF )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
bMatches = false;
|
bMatches = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( !bMatches )
|
if ( !bMatches )
|
||||||
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( bDebug )
|
||||||
|
{
|
||||||
|
Msg(" %s angle not matched: (%0.2f %0.2f %0.2f), desired (%0.2f, %0.2f, %0.2f)\n", GetDebugName(),
|
||||||
|
anglemod(angEnemyAngles.x), anglemod(angEnemyAngles.y), anglemod(angEnemyAngles.z), anglemod(angAngles.x), anglemod(angAngles.y), anglemod(angAngles.z) );
|
||||||
|
Msg(" diff: (%0.2f, %0.2f, %0.2f)\n", AngleDiff( angEnemyAngles.x, angAngles.x ), AngleDiff( angEnemyAngles.y, angAngles.y ), AngleDiff( angEnemyAngles.z, angAngles.z ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ( bDebug )
|
if ( bDebug )
|
||||||
{
|
{
|
||||||
@ -15873,6 +16088,13 @@ bool CAI_BaseNPC::InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInte
|
|||||||
anglemod(angEnemyAngles.x), anglemod(angEnemyAngles.y), anglemod(angEnemyAngles.z), anglemod(angAngles.x), anglemod(angAngles.y), anglemod(angAngles.z) );
|
anglemod(angEnemyAngles.x), anglemod(angEnemyAngles.y), anglemod(angEnemyAngles.z), anglemod(angAngles.x), anglemod(angAngles.y), anglemod(angAngles.z) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we're not using angles, then use the NPC's current angles
|
||||||
|
angAngles = pOtherNPC->GetAbsAngles();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO: Velocity check, if we're supposed to
|
// TODO: Velocity check, if we're supposed to
|
||||||
if ( pInteraction->iFlags & SCNPC_FLAG_TEST_OTHER_VELOCITY )
|
if ( pInteraction->iFlags & SCNPC_FLAG_TEST_OTHER_VELOCITY )
|
||||||
@ -15952,6 +16174,7 @@ bool CAI_BaseNPC::InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInte
|
|||||||
if ( bDebug )
|
if ( bDebug )
|
||||||
{
|
{
|
||||||
NDebugOverlay::Box( vecPos, GetHullMins(), GetHullMaxs(), 255,0,0, 100, 1.0 );
|
NDebugOverlay::Box( vecPos, GetHullMins(), GetHullMaxs(), 255,0,0, 100, 1.0 );
|
||||||
|
NDebugOverlay::HorzArrow( GetAbsOrigin(), vecPos, 16.0f, 255, 0, 0, 255, true, 1.0f );
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -15959,7 +16182,39 @@ bool CAI_BaseNPC::InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInte
|
|||||||
{
|
{
|
||||||
//NDebugOverlay::Box( vecPos, GetHullMins(), GetHullMaxs(), 0,255,0, 100, 1.0 );
|
//NDebugOverlay::Box( vecPos, GetHullMins(), GetHullMaxs(), 0,255,0, 100, 1.0 );
|
||||||
|
|
||||||
NDebugOverlay::Axis( vecPos, angAngles, 20, true, 10.0 );
|
NDebugOverlay::Axis( vecPos, angAngles, 20, true, 1.0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Instead, make sure we fit into where the sequence movement ends at
|
||||||
|
const char *pszSequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_SEQUENCE );
|
||||||
|
int nSeq = LookupSequence( pszSequence );
|
||||||
|
if ( pszSequence && nSeq != -1 )
|
||||||
|
{
|
||||||
|
Vector vecDeltaPos;
|
||||||
|
QAngle angDeltaAngles;
|
||||||
|
GetSequenceMovement( nSeq, 0.0f, 1.0f, vecDeltaPos, angDeltaAngles );
|
||||||
|
if (!vecDeltaPos.IsZero())
|
||||||
|
{
|
||||||
|
QAngle angInteraction = GetAbsAngles();
|
||||||
|
angInteraction[YAW] = m_flInteractionYaw;
|
||||||
|
|
||||||
|
Vector vecPos;
|
||||||
|
VectorRotate( vecDeltaPos, angInteraction, vecPos );
|
||||||
|
vecPos += GetAbsOrigin();
|
||||||
|
|
||||||
|
AI_TraceHull( vecPos, vecPos, GetHullMins(), GetHullMaxs(), MASK_SOLID, &traceFilter, &tr);
|
||||||
|
if ( tr.fraction != 1.0 )
|
||||||
|
{
|
||||||
|
if ( bDebug )
|
||||||
|
{
|
||||||
|
NDebugOverlay::Box( vecPos, GetHullMins(), GetHullMaxs(), 255,0,0, 100, 1.0 );
|
||||||
|
NDebugOverlay::HorzArrow( GetAbsOrigin(), vecPos, 16.0f, 255, 0, 0, 255, true, 1.0f );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -15983,6 +16238,25 @@ bool CAI_BaseNPC::HasInteractionCantDie( void )
|
|||||||
return ( m_bCannotDieDuringInteraction && IsRunningDynamicInteraction() );
|
return ( m_bCannotDieDuringInteraction && IsRunningDynamicInteraction() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Return true if this NPC has valid interactions on the current enemy.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CAI_BaseNPC::HasValidInteractionsOnCurrentEnemy( void )
|
||||||
|
{
|
||||||
|
if ( !GetEnemy() || !GetEnemy()->IsNPC() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for ( int i = 0; i < m_ScriptedInteractions.Count(); i++ )
|
||||||
|
{
|
||||||
|
ScriptedNPCInteraction_t *pInteraction = &m_ScriptedInteractions[i];
|
||||||
|
|
||||||
|
if ( pInteraction->bValidOnCurrentEnemy )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
// Input : &inputdata -
|
// Input : &inputdata -
|
||||||
@ -16216,6 +16490,21 @@ void CAI_BaseNPC::ModifyOrAppendEnemyCriteria( AI_CriteriaSet& set, CBaseEntity
|
|||||||
set.AppendCriteria( "enemyclass", g_pGameRules->AIClassText( pEnemy->Classify() ) ); // UTIL_VarArgs("%i", pEnemy->Classify())
|
set.AppendCriteria( "enemyclass", g_pGameRules->AIClassText( pEnemy->Classify() ) ); // UTIL_VarArgs("%i", pEnemy->Classify())
|
||||||
set.AppendCriteria( "distancetoenemy", UTIL_VarArgs( "%f", EnemyDistance(pEnemy) ) );
|
set.AppendCriteria( "distancetoenemy", UTIL_VarArgs( "%f", EnemyDistance(pEnemy) ) );
|
||||||
set.AppendCriteria( "timesincecombat", "-1" );
|
set.AppendCriteria( "timesincecombat", "-1" );
|
||||||
|
|
||||||
|
CAI_BaseNPC *pNPC = pEnemy->MyNPCPointer();
|
||||||
|
if (pNPC)
|
||||||
|
{
|
||||||
|
set.AppendCriteria("enemy_is_npc", "1");
|
||||||
|
|
||||||
|
set.AppendCriteria( "enemy_activity", CAI_BaseNPC::GetActivityName( pNPC->GetActivity() ) );
|
||||||
|
set.AppendCriteria( "enemy_weapon", pNPC->GetActiveWeapon() ? pNPC->GetActiveWeapon()->GetClassname() : "0" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set.AppendCriteria("enemy_is_npc", "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
pEnemy->AppendContextToCriteria( set, "enemy_" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -425,6 +425,9 @@ struct ScriptedNPCInteraction_t
|
|||||||
iszTheirWeapon = NULL_STRING;
|
iszTheirWeapon = NULL_STRING;
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
vecRelativeEndPos = vec3_origin;
|
vecRelativeEndPos = vec3_origin;
|
||||||
|
bHasSeparateSequenceNames = false;
|
||||||
|
flMaxAngleDiff = DSS_MAX_ANGLE_DIFF;
|
||||||
|
iszRelatedInteractions = NULL_STRING;
|
||||||
MiscCriteria = NULL_STRING;
|
MiscCriteria = NULL_STRING;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -432,6 +435,10 @@ struct ScriptedNPCInteraction_t
|
|||||||
{
|
{
|
||||||
sPhases[i].iszSequence = NULL_STRING;
|
sPhases[i].iszSequence = NULL_STRING;
|
||||||
sPhases[i].iActivity = ACT_INVALID;
|
sPhases[i].iActivity = ACT_INVALID;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
sTheirPhases[i].iszSequence = NULL_STRING;
|
||||||
|
sTheirPhases[i].iActivity = ACT_INVALID;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,10 +466,14 @@ struct ScriptedNPCInteraction_t
|
|||||||
float flNextAttemptTime;
|
float flNextAttemptTime;
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
// Unrecognized keyvalues are tested against response criteria later.
|
ScriptedNPCInteraction_Phases_t sTheirPhases[SNPCINT_NUM_PHASES]; // The animations played by the target NPC, if they are different
|
||||||
// This was originally a CUtlVector that carries response contexts, but I couldn't get it working due to some CUtlVector-struct shenanigans.
|
bool bHasSeparateSequenceNames;
|
||||||
// It works when we use a single string_t that's split and read each time the code runs, but feel free to improve on this.
|
|
||||||
string_t MiscCriteria; // CUtlVector<ResponseContext_t>
|
float flMaxAngleDiff;
|
||||||
|
string_t iszRelatedInteractions; // These interactions will be delayed as well when this interaction is used.
|
||||||
|
|
||||||
|
// Unrecognized keyvalues which are tested against response criteria later.
|
||||||
|
string_t MiscCriteria;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DECLARE_SIMPLE_DATADESC();
|
DECLARE_SIMPLE_DATADESC();
|
||||||
@ -838,6 +849,9 @@ protected: // pose parameters
|
|||||||
int m_poseAim_Pitch;
|
int m_poseAim_Pitch;
|
||||||
int m_poseAim_Yaw;
|
int m_poseAim_Yaw;
|
||||||
int m_poseMove_Yaw;
|
int m_poseMove_Yaw;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int m_poseInteractionRelativeYaw;
|
||||||
|
#endif
|
||||||
virtual void PopulatePoseParameters( void );
|
virtual void PopulatePoseParameters( void );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -846,6 +860,10 @@ public:
|
|||||||
// Return the stored pose parameter for "move_yaw"
|
// Return the stored pose parameter for "move_yaw"
|
||||||
inline int LookupPoseMoveYaw() { return m_poseMove_Yaw; }
|
inline int LookupPoseMoveYaw() { return m_poseMove_Yaw; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
inline int LookupPoseInteractionRelativeYaw() { return m_poseInteractionRelativeYaw; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
//
|
//
|
||||||
@ -1304,10 +1322,14 @@ private:
|
|||||||
public:
|
public:
|
||||||
float GetInteractionYaw( void ) const { return m_flInteractionYaw; }
|
float GetInteractionYaw( void ) const { return m_flInteractionYaw; }
|
||||||
|
|
||||||
|
bool IsRunningDynamicInteraction( void ) { return (m_iInteractionState != NPCINT_NOT_RUNNING && (m_hCine != NULL)); }
|
||||||
|
bool IsActiveDynamicInteraction( void ) { return (m_iInteractionState == NPCINT_RUNNING_ACTIVE && (m_hCine != NULL)); }
|
||||||
|
CAI_BaseNPC *GetInteractionPartner( void );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ParseScriptedNPCInteractions( void );
|
void ParseScriptedNPCInteractions( void );
|
||||||
void AddScriptedNPCInteraction( ScriptedNPCInteraction_t *pInteraction );
|
void AddScriptedNPCInteraction( ScriptedNPCInteraction_t *pInteraction );
|
||||||
const char *GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase );
|
const char *GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase, bool bOtherNPC = false );
|
||||||
void StartRunningInteraction( CAI_BaseNPC *pOtherNPC, bool bActive );
|
void StartRunningInteraction( CAI_BaseNPC *pOtherNPC, bool bActive );
|
||||||
void StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector vecOtherOrigin, QAngle angOtherAngles );
|
void StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector vecOtherOrigin, QAngle angOtherAngles );
|
||||||
void CheckForScriptedNPCInteractions( void );
|
void CheckForScriptedNPCInteractions( void );
|
||||||
@ -1320,17 +1342,16 @@ protected:
|
|||||||
#endif
|
#endif
|
||||||
bool InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles );
|
bool InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles );
|
||||||
virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
|
virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
|
||||||
bool IsRunningDynamicInteraction( void ) { return (m_iInteractionState != NPCINT_NOT_RUNNING && (m_hCine != NULL)); }
|
|
||||||
bool IsActiveDynamicInteraction( void ) { return (m_iInteractionState == NPCINT_RUNNING_ACTIVE && (m_hCine != NULL)); }
|
|
||||||
ScriptedNPCInteraction_t *GetRunningDynamicInteraction( void ) { return &(m_ScriptedInteractions[m_iInteractionPlaying]); }
|
ScriptedNPCInteraction_t *GetRunningDynamicInteraction( void ) { return &(m_ScriptedInteractions[m_iInteractionPlaying]); }
|
||||||
void SetInteractionCantDie( bool bCantDie ) { m_bCannotDieDuringInteraction = bCantDie; }
|
void SetInteractionCantDie( bool bCantDie ) { m_bCannotDieDuringInteraction = bCantDie; }
|
||||||
bool HasInteractionCantDie( void );
|
bool HasInteractionCantDie( void );
|
||||||
|
bool HasValidInteractionsOnCurrentEnemy( void );
|
||||||
|
virtual bool CanStartDynamicInteractionDuringMelee() { return false; }
|
||||||
|
|
||||||
void InputForceInteractionWithNPC( inputdata_t &inputdata );
|
void InputForceInteractionWithNPC( inputdata_t &inputdata );
|
||||||
void StartForcedInteraction( CAI_BaseNPC *pNPC, int iInteraction );
|
void StartForcedInteraction( CAI_BaseNPC *pNPC, int iInteraction );
|
||||||
void CleanupForcedInteraction( void );
|
void CleanupForcedInteraction( void );
|
||||||
void CalculateForcedInteractionPosition( void );
|
void CalculateForcedInteractionPosition( void );
|
||||||
CAI_BaseNPC *GetInteractionPartner( void );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Forced interactions
|
// Forced interactions
|
||||||
@ -1974,6 +1995,9 @@ public:
|
|||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
|
||||||
virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false );
|
virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void EnemyIgnited( CAI_BaseNPC *pVictim ) {}
|
||||||
|
#endif
|
||||||
virtual bool PassesDamageFilter( const CTakeDamageInfo &info );
|
virtual bool PassesDamageFilter( const CTakeDamageInfo &info );
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
@ -2228,6 +2252,9 @@ public:
|
|||||||
static const char* GetActivityName (int actID);
|
static const char* GetActivityName (int actID);
|
||||||
|
|
||||||
static void AddActivityToSR(const char *actName, int conID);
|
static void AddActivityToSR(const char *actName, int conID);
|
||||||
|
#ifdef MAPBASE
|
||||||
|
static int GetOrRegisterActivity( const char *actName );
|
||||||
|
#endif
|
||||||
|
|
||||||
static void AddEventToSR(const char *eventName, int conID);
|
static void AddEventToSR(const char *eventName, int conID);
|
||||||
static const char* GetEventName (int actID);
|
static const char* GetEventName (int actID);
|
||||||
|
@ -1610,6 +1610,12 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
|||||||
// as this should only run with the NPC "receiving" the interaction
|
// as this should only run with the NPC "receiving" the interaction
|
||||||
ScriptedNPCInteraction_t *pInteraction = m_hForcedInteractionPartner->GetRunningDynamicInteraction();
|
ScriptedNPCInteraction_t *pInteraction = m_hForcedInteractionPartner->GetRunningDynamicInteraction();
|
||||||
|
|
||||||
|
if ( !(pInteraction->iFlags & SCNPC_FLAG_TEST_OTHER_ANGLES) )
|
||||||
|
{
|
||||||
|
TaskComplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get our target's origin
|
// Get our target's origin
|
||||||
Vector vecTarget = m_hForcedInteractionPartner->GetAbsOrigin();
|
Vector vecTarget = m_hForcedInteractionPartner->GetAbsOrigin();
|
||||||
|
|
||||||
@ -1617,7 +1623,7 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
|||||||
float angInteractionAngle = pInteraction->angRelativeAngles.y;
|
float angInteractionAngle = pInteraction->angRelativeAngles.y;
|
||||||
angInteractionAngle += 180.0f;
|
angInteractionAngle += 180.0f;
|
||||||
|
|
||||||
GetMotor()->SetIdealYaw( CalcIdealYaw( vecTarget ) + angInteractionAngle );
|
GetMotor()->SetIdealYaw( AngleNormalize( CalcIdealYaw( vecTarget ) + angInteractionAngle ) );
|
||||||
|
|
||||||
if (FacingIdeal())
|
if (FacingIdeal())
|
||||||
TaskComplete();
|
TaskComplete();
|
||||||
@ -4113,6 +4119,15 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
|||||||
m_hCine->SynchronizeSequence( this );
|
m_hCine->SynchronizeSequence( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( IsRunningDynamicInteraction() && m_poseInteractionRelativeYaw > -1 )
|
||||||
|
{
|
||||||
|
// Animations in progress require pose parameters to be set every frame, so keep setting the interaction relative yaw pose.
|
||||||
|
// The random value is added to help it pass server transmit checks.
|
||||||
|
SetPoseParameter( m_poseInteractionRelativeYaw, GetPoseParameter( m_poseInteractionRelativeYaw ) + RandomFloat( -0.1f, 0.1f ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,6 +477,20 @@ public:
|
|||||||
|
|
||||||
AI_TraceHull( baseNPC->GetAbsOrigin(), vUpBit, baseNPC->GetHullMins(), baseNPC->GetHullMaxs(),
|
AI_TraceHull( baseNPC->GetAbsOrigin(), vUpBit, baseNPC->GetHullMins(), baseNPC->GetHullMaxs(),
|
||||||
MASK_NPCSOLID, baseNPC, COLLISION_GROUP_NONE, &tr );
|
MASK_NPCSOLID, baseNPC, COLLISION_GROUP_NONE, &tr );
|
||||||
|
|
||||||
|
// NEW: For vphysics/flying entities, do a second attempt which teleports based on bounding box
|
||||||
|
if ( (baseNPC->GetMoveType() == MOVETYPE_VPHYSICS || baseNPC->CapabilitiesGet() & bits_CAP_MOVE_FLY) && (tr.startsolid || tr.fraction < 1.0) )
|
||||||
|
{
|
||||||
|
vUpBit.z += baseNPC->BoundingRadius();
|
||||||
|
baseNPC->Teleport( &vUpBit, NULL, NULL );
|
||||||
|
UTIL_DropToFloor( baseNPC, MASK_NPCSOLID );
|
||||||
|
|
||||||
|
Vector vUpBit2 = vUpBit;
|
||||||
|
vUpBit2.z += 1;
|
||||||
|
AI_TraceHull( vUpBit, vUpBit2, baseNPC->CollisionProp()->OBBMins(), baseNPC->CollisionProp()->OBBMaxs(),
|
||||||
|
MASK_NPCSOLID, baseNPC, COLLISION_GROUP_NONE, &tr );
|
||||||
|
}
|
||||||
|
|
||||||
if ( tr.startsolid || (tr.fraction < 1.0) )
|
if ( tr.startsolid || (tr.fraction < 1.0) )
|
||||||
{
|
{
|
||||||
baseNPC->SUB_Remove();
|
baseNPC->SUB_Remove();
|
||||||
|
@ -88,6 +88,15 @@ static void DispatchComeback( CAI_ExpresserWithFollowup *pExpress, CBaseEntity *
|
|||||||
// add in any provided contexts from the parameters onto the ones stored in the followup
|
// add in any provided contexts from the parameters onto the ones stored in the followup
|
||||||
criteria.Merge( followup.followup_contexts );
|
criteria.Merge( followup.followup_contexts );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (CAI_ExpresserSink *pSink = dynamic_cast<CAI_ExpresserSink *>(pRespondent))
|
||||||
|
{
|
||||||
|
criteria.AppendCriteria( "dist_from_issuer", UTIL_VarArgs( "%f", (pRespondent->GetAbsOrigin() - pSpeaker->GetAbsOrigin()).Length() ) );
|
||||||
|
g_ResponseQueueManager.GetQueue()->AppendFollowupCriteria( followup.followup_concept, criteria, pSink->GetSinkExpresser(), pSink, pRespondent, pSpeaker, kDRT_SPECIFIC );
|
||||||
|
|
||||||
|
pSink->Speak( followup.followup_concept, &criteria );
|
||||||
|
}
|
||||||
|
#else
|
||||||
// This is kludgy and needs to be fixed in class hierarchy, but for now, try to guess at the most likely
|
// This is kludgy and needs to be fixed in class hierarchy, but for now, try to guess at the most likely
|
||||||
// kinds of targets and dispatch to them.
|
// kinds of targets and dispatch to them.
|
||||||
if (CBaseMultiplayerPlayer *pPlayer = dynamic_cast<CBaseMultiplayerPlayer *>(pRespondent))
|
if (CBaseMultiplayerPlayer *pPlayer = dynamic_cast<CBaseMultiplayerPlayer *>(pRespondent))
|
||||||
@ -99,6 +108,7 @@ static void DispatchComeback( CAI_ExpresserWithFollowup *pExpress, CBaseEntity *
|
|||||||
{
|
{
|
||||||
pActor->Speak( followup.followup_concept, &criteria );
|
pActor->Speak( followup.followup_concept, &criteria );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -902,6 +902,17 @@ BEGIN_DATADESC( CAI_Hint )
|
|||||||
DEFINE_OUTPUT( m_OnNPCStartedUsing, "OnNPCStartedUsing" ),
|
DEFINE_OUTPUT( m_OnNPCStartedUsing, "OnNPCStartedUsing" ),
|
||||||
DEFINE_OUTPUT( m_OnNPCStoppedUsing, "OnNPCStoppedUsing" ),
|
DEFINE_OUTPUT( m_OnNPCStoppedUsing, "OnNPCStoppedUsing" ),
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_OUTPUT( m_OnScriptEvent[0], "OnScriptEvent01" ),
|
||||||
|
DEFINE_OUTPUT( m_OnScriptEvent[1], "OnScriptEvent02" ),
|
||||||
|
DEFINE_OUTPUT( m_OnScriptEvent[2], "OnScriptEvent03" ),
|
||||||
|
DEFINE_OUTPUT( m_OnScriptEvent[3], "OnScriptEvent04" ),
|
||||||
|
DEFINE_OUTPUT( m_OnScriptEvent[4], "OnScriptEvent05" ),
|
||||||
|
DEFINE_OUTPUT( m_OnScriptEvent[5], "OnScriptEvent06" ),
|
||||||
|
DEFINE_OUTPUT( m_OnScriptEvent[6], "OnScriptEvent07" ),
|
||||||
|
DEFINE_OUTPUT( m_OnScriptEvent[7], "OnScriptEvent08" ),
|
||||||
|
#endif
|
||||||
|
|
||||||
END_DATADESC( );
|
END_DATADESC( );
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
@ -1325,7 +1336,7 @@ bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hint
|
|||||||
|
|
||||||
if ( distance > nRadius * nRadius )
|
if ( distance > nRadius * nRadius )
|
||||||
{
|
{
|
||||||
REPORTFAILURE( "NPC is not within the node's radius." );
|
REPORTFAILURE( "Not within the node's radius." );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1705,6 +1716,19 @@ void CAI_Hint::NPCStoppedUsing( CAI_BaseNPC *pNPC )
|
|||||||
m_OnNPCStoppedUsing.Set( pNPC, pNPC, this );
|
m_OnNPCStoppedUsing.Set( pNPC, pNPC, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_Hint::FireScriptEvent( int nEvent )
|
||||||
|
{
|
||||||
|
if ( ( nEvent >= 1 ) && ( nEvent <= 8 ) )
|
||||||
|
{
|
||||||
|
m_OnScriptEvent[nEvent - 1].FireOutput( m_hHintOwner, this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
CON_COMMAND(ai_dump_hints, "")
|
CON_COMMAND(ai_dump_hints, "")
|
||||||
{
|
{
|
||||||
@ -1794,6 +1818,11 @@ hinttypedescs_t g_pszHintDescriptions[] =
|
|||||||
{ HINT_HL1_WORLD_ALIEN_BLOOD, "HL1: World: Alien Blood" },
|
{ HINT_HL1_WORLD_ALIEN_BLOOD, "HL1: World: Alien Blood" },
|
||||||
|
|
||||||
{ HINT_CSTRIKE_HOSTAGE_ESCAPE, "CS Port: Hostage Escape" },
|
{ HINT_CSTRIKE_HOSTAGE_ESCAPE, "CS Port: Hostage Escape" },
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
{ HINT_TACTICAL_COVER_CUSTOM, "Mapbase: Custom Cover" },
|
||||||
|
{ HINT_TACTICAL_GRENADE_THROW, "Mapbase: Grenade Throw Hint" },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -118,6 +118,7 @@ enum Hint_e
|
|||||||
// (these start at a high number to avoid potential conflicts with mod hints)
|
// (these start at a high number to avoid potential conflicts with mod hints)
|
||||||
|
|
||||||
HINT_TACTICAL_COVER_CUSTOM = 10000, // Cover node with a custom hint activity (NPCs can take cover and reload here while playing said activity)
|
HINT_TACTICAL_COVER_CUSTOM = 10000, // Cover node with a custom hint activity (NPCs can take cover and reload here while playing said activity)
|
||||||
|
HINT_TACTICAL_GRENADE_THROW, // Pre-determined position for NPCs to throw grenades at when their target in combat is near it
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
const char *GetHintTypeDescription( Hint_e iHintType );
|
const char *GetHintTypeDescription( Hint_e iHintType );
|
||||||
@ -322,6 +323,9 @@ public:
|
|||||||
void FixupTargetNode();
|
void FixupTargetNode();
|
||||||
void NPCStartedUsing( CAI_BaseNPC *pNPC );
|
void NPCStartedUsing( CAI_BaseNPC *pNPC );
|
||||||
void NPCStoppedUsing( CAI_BaseNPC *pNPC );
|
void NPCStoppedUsing( CAI_BaseNPC *pNPC );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void FireScriptEvent( int nEvent );
|
||||||
|
#endif
|
||||||
|
|
||||||
HintIgnoreFacing_t GetIgnoreFacing() const { return m_NodeData.fIgnoreFacing; }
|
HintIgnoreFacing_t GetIgnoreFacing() const { return m_NodeData.fIgnoreFacing; }
|
||||||
|
|
||||||
@ -384,6 +388,10 @@ private:
|
|||||||
float m_nodeFOV;
|
float m_nodeFOV;
|
||||||
Vector m_vecForward;
|
Vector m_vecForward;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
COutputEvent m_OnScriptEvent[8];
|
||||||
|
#endif
|
||||||
|
|
||||||
// The next hint in list of all hints
|
// The next hint in list of all hints
|
||||||
friend class CAI_HintManager;
|
friend class CAI_HintManager;
|
||||||
|
|
||||||
|
@ -128,6 +128,12 @@ ConceptInfo_t g_ConceptInfos[] =
|
|||||||
|
|
||||||
// Passenger behaviour
|
// Passenger behaviour
|
||||||
{ TLK_PASSENGER_NEW_RADAR_CONTACT, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, },
|
{ TLK_PASSENGER_NEW_RADAR_CONTACT, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, },
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
{ TLK_TAKING_FIRE, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, },
|
||||||
|
{ TLK_NEW_ENEMY, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, },
|
||||||
|
{ TLK_COMBAT_IDLE, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1259,6 +1265,38 @@ void CAI_PlayerAlly::OnKilledNPC( CBaseCombatCharacter *pKilled )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_PlayerAlly::OnEnemyRangeAttackedMe( CBaseEntity *pEnemy, const Vector &vecDir, const Vector &vecEnd )
|
||||||
|
{
|
||||||
|
BaseClass::OnEnemyRangeAttackedMe( pEnemy, vecDir, vecEnd );
|
||||||
|
|
||||||
|
if ( IRelationType( pEnemy ) <= D_FR )
|
||||||
|
{
|
||||||
|
AI_CriteriaSet modifiers;
|
||||||
|
ModifyOrAppendEnemyCriteria( modifiers, pEnemy );
|
||||||
|
|
||||||
|
Vector vecEntDir = (pEnemy->EyePosition() - EyePosition());
|
||||||
|
float flDot = DotProduct( vecEntDir.Normalized(), vecDir );
|
||||||
|
modifiers.AppendCriteria( "shot_dot", CNumStr( flDot ) );
|
||||||
|
|
||||||
|
if (GetLastDamageTime() == gpGlobals->curtime)
|
||||||
|
modifiers.AppendCriteria( "missed", "0" );
|
||||||
|
else
|
||||||
|
modifiers.AppendCriteria( "missed", "1" );
|
||||||
|
|
||||||
|
// Check if they're out of ammo
|
||||||
|
if ( pEnemy->IsCombatCharacter() && pEnemy->MyCombatCharacterPointer()->GetActiveWeapon() && pEnemy->MyCombatCharacterPointer()->GetActiveWeapon()->Clip1() <= 0 )
|
||||||
|
modifiers.AppendCriteria( "last_attack", "1" );
|
||||||
|
else
|
||||||
|
modifiers.AppendCriteria( "last_attack", "0" );
|
||||||
|
|
||||||
|
SpeakIfAllowed( TLK_TAKING_FIRE, modifiers );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CAI_PlayerAlly::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
|
void CAI_PlayerAlly::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator )
|
||||||
{
|
{
|
||||||
@ -1762,6 +1800,54 @@ bool CAI_PlayerAlly::IsAllowedToSpeak( AIConcept_t concept, bool bRespondingToPl
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Specifically for player allies handling followup responses.
|
||||||
|
// Better-accounts for unknown concepts so that users are free in what they use.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CAI_PlayerAlly::IsAllowedToSpeakFollowup( AIConcept_t concept, CBaseEntity *pIssuer, bool bSpecific )
|
||||||
|
{
|
||||||
|
CAI_AllySpeechManager * pSpeechManager = GetAllySpeechManager();
|
||||||
|
ConceptInfo_t * pInfo = pSpeechManager->GetConceptInfo( concept );
|
||||||
|
ConceptCategory_t category = SPEECH_PRIORITY; // Must be SPEECH_PRIORITY to get around semaphore
|
||||||
|
|
||||||
|
if ( !IsOkToSpeak( category, true ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If this followup is specifically targeted towards us, speak if we're not already speaking
|
||||||
|
// If it's meant to be spoken by anyone, respect speech delay and semaphore
|
||||||
|
if ( bSpecific )
|
||||||
|
{
|
||||||
|
if ( !GetExpresser()->CanSpeakAfterMyself() )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( !GetExpresser()->CanSpeak() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CAI_TimedSemaphore *pSemaphore = GetExpresser()->GetMySpeechSemaphore( this );
|
||||||
|
if ( pSemaphore && !pSemaphore->IsAvailable( this ) )
|
||||||
|
{
|
||||||
|
// Only if the semaphore holder isn't the one dispatching the followup
|
||||||
|
if ( pSemaphore->GetOwner() != pIssuer )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !pSpeechManager->ConceptDelayExpired( concept ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( ( pInfo && pInfo->flags & AICF_SPEAK_ONCE ) && GetExpresser()->SpokeConcept( concept ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( !GetExpresser()->CanSpeakConcept( concept ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CAI_PlayerAlly::SpeakIfAllowed( AIConcept_t concept, const char *modifiers, bool bRespondingToPlayer, char *pszOutResponseChosen, size_t bufsize )
|
bool CAI_PlayerAlly::SpeakIfAllowed( AIConcept_t concept, const char *modifiers, bool bRespondingToPlayer, char *pszOutResponseChosen, size_t bufsize )
|
||||||
|
@ -132,6 +132,13 @@
|
|||||||
#define TLK_TGCATCHUP "TLK_TGCATCHUP"
|
#define TLK_TGCATCHUP "TLK_TGCATCHUP"
|
||||||
#define TLK_TGENDTOUR "TLK_TGENDTOUR"
|
#define TLK_TGENDTOUR "TLK_TGENDTOUR"
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Additional concepts for companions in mods
|
||||||
|
#define TLK_TAKING_FIRE "TLK_TAKING_FIRE" // Someone fired at me (regardless of whether I was hit)
|
||||||
|
#define TLK_NEW_ENEMY "TLK_NEW_ENEMY" // A new enemy appeared while combat was already in progress
|
||||||
|
#define TLK_COMBAT_IDLE "TLK_COMBAT_IDLE" // Similar to TLK_ATTACKING, but specifically for when *not* currently attacking (e.g. when in cover or reloading)
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define TALKRANGE_MIN 500.0 // don't talk to anyone farther away than this
|
#define TALKRANGE_MIN 500.0 // don't talk to anyone farther away than this
|
||||||
@ -315,6 +322,10 @@ public:
|
|||||||
//---------------------------------
|
//---------------------------------
|
||||||
void OnKilledNPC( CBaseCombatCharacter *pKilled );
|
void OnKilledNPC( CBaseCombatCharacter *pKilled );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void OnEnemyRangeAttackedMe( CBaseEntity *pEnemy, const Vector &vecDir, const Vector &vecEnd );
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
// Damage handling
|
// Damage handling
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
@ -392,6 +403,9 @@ public:
|
|||||||
|
|
||||||
bool ShouldSpeakRandom( AIConcept_t concept, int iChance );
|
bool ShouldSpeakRandom( AIConcept_t concept, int iChance );
|
||||||
bool IsAllowedToSpeak( AIConcept_t concept, bool bRespondingToPlayer = false );
|
bool IsAllowedToSpeak( AIConcept_t concept, bool bRespondingToPlayer = false );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool IsAllowedToSpeakFollowup( AIConcept_t concept, CBaseEntity *pIssuer, bool bSpecific );
|
||||||
|
#endif
|
||||||
virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
|
virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
virtual bool SpeakIfAllowed( AIConcept_t concept, AI_CriteriaSet& modifiers, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
|
virtual bool SpeakIfAllowed( AIConcept_t concept, AI_CriteriaSet& modifiers, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
|
||||||
|
@ -532,6 +532,7 @@ public:
|
|||||||
|
|
||||||
// Must override CAI_Relationship
|
// Must override CAI_Relationship
|
||||||
void Spawn() { m_bIsActive = false; }
|
void Spawn() { m_bIsActive = false; }
|
||||||
|
void Activate();
|
||||||
|
|
||||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||||
|
|
||||||
@ -557,6 +558,19 @@ BEGIN_DATADESC( CAI_ClassRelationship )
|
|||||||
|
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
//---------------------------------------------------------
|
||||||
|
void CAI_ClassRelationship::Activate()
|
||||||
|
{
|
||||||
|
BaseClass::Activate();
|
||||||
|
|
||||||
|
// Must re-apply every time a save is loaded
|
||||||
|
if ( m_bIsActive )
|
||||||
|
{
|
||||||
|
ApplyRelationship();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Caches entity key values until spawn is called.
|
// Purpose: Caches entity key values until spawn is called.
|
||||||
// Input : szKeyName -
|
// Input : szKeyName -
|
||||||
@ -615,6 +629,9 @@ void CAI_ClassRelationship::ChangeRelationships( int disposition, int iReverting
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !CBaseCombatCharacter::DefaultRelationshipsLoaded() )
|
||||||
|
return;
|
||||||
|
|
||||||
if ( m_iPreviousDisposition == -1 && iReverting == NOT_REVERTING )
|
if ( m_iPreviousDisposition == -1 && iReverting == NOT_REVERTING )
|
||||||
{
|
{
|
||||||
// Set previous disposition.
|
// Set previous disposition.
|
||||||
|
@ -126,6 +126,13 @@ public:
|
|||||||
virtual void OnSpokeConcept( AIConcept_t concept, AI_Response *response ) {};
|
virtual void OnSpokeConcept( AIConcept_t concept, AI_Response *response ) {};
|
||||||
virtual void OnStartSpeaking() {}
|
virtual void OnStartSpeaking() {}
|
||||||
virtual bool UseSemaphore() { return true; }
|
virtual bool UseSemaphore() { return true; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Works around issues with CAI_ExpresserHost<> class hierarchy
|
||||||
|
virtual CAI_Expresser *GetSinkExpresser() { return NULL; }
|
||||||
|
virtual bool IsAllowedToSpeakFollowup( AIConcept_t concept, CBaseEntity *pIssuer, bool bSpecific ) { return true; }
|
||||||
|
virtual bool Speak( AIConcept_t concept, AI_CriteriaSet *pCriteria, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ) { return false; }
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConceptHistory_t
|
struct ConceptHistory_t
|
||||||
@ -244,9 +251,15 @@ public:
|
|||||||
static bool RunScriptResponse( CBaseEntity *pTarget, const char *response, AI_CriteriaSet *criteria, bool file );
|
static bool RunScriptResponse( CBaseEntity *pTarget, const char *response, AI_CriteriaSet *criteria, bool file );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
public:
|
||||||
|
#else
|
||||||
protected:
|
protected:
|
||||||
|
#endif
|
||||||
CAI_TimedSemaphore *GetMySpeechSemaphore( CBaseEntity *pNpc );
|
CAI_TimedSemaphore *GetMySpeechSemaphore( CBaseEntity *pNpc );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
bool SpeakRawScene( const char *pszScene, float delay, AI_Response *response, IRecipientFilter *filter = NULL );
|
bool SpeakRawScene( const char *pszScene, float delay, AI_Response *response, IRecipientFilter *filter = NULL );
|
||||||
// This will create a fake .vcd/CChoreoScene to wrap the sound to be played
|
// This will create a fake .vcd/CChoreoScene to wrap the sound to be played
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
@ -311,11 +324,15 @@ private:
|
|||||||
//
|
//
|
||||||
|
|
||||||
template <class BASE_NPC>
|
template <class BASE_NPC>
|
||||||
class CAI_ExpresserHost : public BASE_NPC, protected CAI_ExpresserSink
|
class CAI_ExpresserHost : public BASE_NPC, public CAI_ExpresserSink
|
||||||
{
|
{
|
||||||
DECLARE_CLASS_NOFRIEND( CAI_ExpresserHost, BASE_NPC );
|
DECLARE_CLASS_NOFRIEND( CAI_ExpresserHost, BASE_NPC );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CAI_Expresser *GetSinkExpresser() { return this->GetExpresser(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void NoteSpeaking( float duration, float delay );
|
virtual void NoteSpeaking( float duration, float delay );
|
||||||
|
|
||||||
virtual bool Speak( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
virtual bool Speak( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL );
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
#include "ai_baseactor.h"
|
#include "ai_baseactor.h"
|
||||||
#include "ai_speech.h"
|
#include "ai_speech.h"
|
||||||
//#include "flex_expresser.h"
|
//#include "flex_expresser.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "sceneentity.h"
|
||||||
|
#endif
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include <tier0/memdbgon.h>
|
#include <tier0/memdbgon.h>
|
||||||
|
|
||||||
@ -170,15 +173,25 @@ void CResponseQueue::RemoveExpresserHost(CBaseEntity *host)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
/// Get the expresser for a base entity.
|
||||||
|
static CAI_Expresser *InferExpresserFromBaseEntity(CBaseEntity * RESTRICT pEnt, CAI_ExpresserSink **ppSink = NULL)
|
||||||
|
{
|
||||||
|
if ( CAI_ExpresserSink *pSink = dynamic_cast<CAI_ExpresserSink *>(pEnt) )
|
||||||
|
{
|
||||||
|
if (ppSink)
|
||||||
|
*ppSink = pSink;
|
||||||
|
return pSink->GetSinkExpresser();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
/// Get the expresser for a base entity.
|
/// Get the expresser for a base entity.
|
||||||
/// TODO: Kind of an ugly hack until I get the class hierarchy straightened out.
|
/// TODO: Kind of an ugly hack until I get the class hierarchy straightened out.
|
||||||
static CAI_Expresser *InferExpresserFromBaseEntity(CBaseEntity * RESTRICT pEnt)
|
static CAI_Expresser *InferExpresserFromBaseEntity(CBaseEntity * RESTRICT pEnt)
|
||||||
{
|
{
|
||||||
#ifdef MAPBASE
|
|
||||||
if ( CBasePlayer *pPlayer = ToBasePlayer(pEnt) )
|
|
||||||
#else
|
|
||||||
if ( CBaseMultiplayerPlayer *pPlayer = dynamic_cast<CBaseMultiplayerPlayer *>(pEnt) )
|
if ( CBaseMultiplayerPlayer *pPlayer = dynamic_cast<CBaseMultiplayerPlayer *>(pEnt) )
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
return pPlayer->GetExpresser();
|
return pPlayer->GetExpresser();
|
||||||
}
|
}
|
||||||
@ -197,6 +210,7 @@ static CAI_Expresser *InferExpresserFromBaseEntity(CBaseEntity * RESTRICT pEnt)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void CResponseQueue::CDeferredResponse::Quash()
|
void CResponseQueue::CDeferredResponse::Quash()
|
||||||
@ -205,6 +219,23 @@ void CResponseQueue::CDeferredResponse::Quash()
|
|||||||
m_fDispatchTime = 0;
|
m_fDispatchTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void CResponseQueue::AppendFollowupCriteria( AIConcept_t concept, AI_CriteriaSet &set, CAI_Expresser *pEx,
|
||||||
|
CAI_ExpresserSink *pSink, CBaseEntity *pTarget, CBaseEntity *pIssuer, DeferredResponseTarget_t nTargetType )
|
||||||
|
{
|
||||||
|
// Allows control over which followups interrupt speech routines
|
||||||
|
set.AppendCriteria( "followup_allowed_to_speak", (pSink->IsAllowedToSpeakFollowup( concept, pIssuer, nTargetType == kDRT_SPECIFIC )) ? "1" : "0" );
|
||||||
|
|
||||||
|
set.AppendCriteria( "followup_target_type", UTIL_VarArgs( "%i", (int)nTargetType ) );
|
||||||
|
|
||||||
|
// NOTE: This assumes any expresser entity derived from CBaseFlex is also derived from CBaseCombatCharacter
|
||||||
|
if (pTarget->IsCombatCharacter())
|
||||||
|
set.AppendCriteria( "is_speaking", (pEx->IsSpeaking() || IsRunningScriptedSceneWithSpeechAndNotPaused( assert_cast<CBaseFlex*>(pTarget) )) ? "1" : "0" );
|
||||||
|
else
|
||||||
|
set.AppendCriteria( "is_speaking", "0" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool CResponseQueue::DispatchOneResponse(CDeferredResponse &response)
|
bool CResponseQueue::DispatchOneResponse(CDeferredResponse &response)
|
||||||
{
|
{
|
||||||
// find the target.
|
// find the target.
|
||||||
@ -272,9 +303,15 @@ bool CResponseQueue::DispatchOneResponse(CDeferredResponse &response)
|
|||||||
continue; // too far
|
continue; // too far
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CAI_ExpresserSink *pSink = NULL;
|
||||||
|
pEx = InferExpresserFromBaseEntity( pTarget, &pSink );
|
||||||
|
#else
|
||||||
pEx = InferExpresserFromBaseEntity(pTarget);
|
pEx = InferExpresserFromBaseEntity(pTarget);
|
||||||
|
#endif
|
||||||
if ( !pEx || pTarget == pIssuer )
|
if ( !pEx || pTarget == pIssuer )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AI_CriteriaSet characterCriteria;
|
AI_CriteriaSet characterCriteria;
|
||||||
pEx->GatherCriteria(&characterCriteria, response.m_concept, NULL);
|
pEx->GatherCriteria(&characterCriteria, response.m_concept, NULL);
|
||||||
characterCriteria.Merge(&deferredCriteria);
|
characterCriteria.Merge(&deferredCriteria);
|
||||||
@ -282,6 +319,11 @@ bool CResponseQueue::DispatchOneResponse(CDeferredResponse &response)
|
|||||||
{
|
{
|
||||||
characterCriteria.AppendCriteria( "dist_from_issuer", UTIL_VarArgs( "%f", sqrt(distIssuerToTargetSq) ) );
|
characterCriteria.AppendCriteria( "dist_from_issuer", UTIL_VarArgs( "%f", sqrt(distIssuerToTargetSq) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
AppendFollowupCriteria( response.m_concept, characterCriteria, pEx, pSink, pTarget, pIssuer, kDRT_ALL );
|
||||||
|
#endif
|
||||||
|
|
||||||
AI_Response prospectiveResponse;
|
AI_Response prospectiveResponse;
|
||||||
if ( pEx->FindResponse( prospectiveResponse, response.m_concept, &characterCriteria ) )
|
if ( pEx->FindResponse( prospectiveResponse, response.m_concept, &characterCriteria ) )
|
||||||
{
|
{
|
||||||
@ -304,14 +346,26 @@ bool CResponseQueue::DispatchOneResponse(CDeferredResponse &response)
|
|||||||
return false; // we're done right here.
|
return false; // we're done right here.
|
||||||
|
|
||||||
// Get the expresser for the target.
|
// Get the expresser for the target.
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CAI_ExpresserSink *pSink = NULL;
|
||||||
|
pEx = InferExpresserFromBaseEntity( pTarget, &pSink );
|
||||||
|
#else
|
||||||
pEx = InferExpresserFromBaseEntity(pTarget);
|
pEx = InferExpresserFromBaseEntity(pTarget);
|
||||||
|
#endif
|
||||||
if (!pEx)
|
if (!pEx)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
AI_CriteriaSet characterCriteria;
|
AI_CriteriaSet characterCriteria;
|
||||||
pEx->GatherCriteria(&characterCriteria, response.m_concept, NULL);
|
pEx->GatherCriteria(&characterCriteria, response.m_concept, NULL);
|
||||||
characterCriteria.Merge(&deferredCriteria);
|
characterCriteria.Merge(&deferredCriteria);
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( pIssuer )
|
||||||
|
{
|
||||||
|
characterCriteria.AppendCriteria( "dist_from_issuer", UTIL_VarArgs( "%f", (pTarget->GetAbsOrigin() - pIssuer->GetAbsOrigin()).Length() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendFollowupCriteria( response.m_concept, characterCriteria, pEx, pSink, pTarget, pIssuer, kDRT_SPECIFIC );
|
||||||
|
#endif
|
||||||
pEx->Speak( response.m_concept, &characterCriteria );
|
pEx->Speak( response.m_concept, &characterCriteria );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -364,7 +418,12 @@ bool CResponseQueue::DispatchOneResponse_ThenANY( CDeferredResponse &response, A
|
|||||||
continue; // too far
|
continue; // too far
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CAI_ExpresserSink *pSink = NULL;
|
||||||
|
pEx = InferExpresserFromBaseEntity( pTarget, &pSink );
|
||||||
|
#else
|
||||||
pEx = InferExpresserFromBaseEntity(pTarget);
|
pEx = InferExpresserFromBaseEntity(pTarget);
|
||||||
|
#endif
|
||||||
if ( !pEx )
|
if ( !pEx )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -376,6 +435,11 @@ bool CResponseQueue::DispatchOneResponse_ThenANY( CDeferredResponse &response, A
|
|||||||
{
|
{
|
||||||
characterCriteria.AppendCriteria( "dist_from_issuer", UTIL_VarArgs( "%f", sqrt(distIssuerToTargetSq) ) );
|
characterCriteria.AppendCriteria( "dist_from_issuer", UTIL_VarArgs( "%f", sqrt(distIssuerToTargetSq) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
AppendFollowupCriteria( response.m_concept, characterCriteria, pEx, pSink, pTarget, pIssuer, kDRT_ANY );
|
||||||
|
#endif
|
||||||
|
|
||||||
AI_Response prospectiveResponse;
|
AI_Response prospectiveResponse;
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
|
@ -116,6 +116,11 @@ public:
|
|||||||
inline int GetNumExpresserTargets() const;
|
inline int GetNumExpresserTargets() const;
|
||||||
inline CBaseEntity *GetExpresserHost(int which) const;
|
inline CBaseEntity *GetExpresserHost(int which) const;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void AppendFollowupCriteria( AIConcept_t concept, AI_CriteriaSet &set, CAI_Expresser *pEx,
|
||||||
|
CAI_ExpresserSink *pSink, CBaseEntity *pTarget, CBaseEntity *pIssuer, DeferredResponseTarget_t nTargetType );
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Actually send off one response to a consumer
|
/// Actually send off one response to a consumer
|
||||||
/// Return true if dispatch succeeded
|
/// Return true if dispatch succeeded
|
||||||
|
@ -335,6 +335,8 @@ BEGIN_ENT_SCRIPTDESC( CBaseAnimating, CBaseEntity, "Animating models" )
|
|||||||
DEFINE_SCRIPTFUNC( FindBodygroupByName, "Finds a bodygroup by name" )
|
DEFINE_SCRIPTFUNC( FindBodygroupByName, "Finds a bodygroup by name" )
|
||||||
DEFINE_SCRIPTFUNC( GetBodygroupCount, "Gets the number of models in a bodygroup" )
|
DEFINE_SCRIPTFUNC( GetBodygroupCount, "Gets the number of models in a bodygroup" )
|
||||||
DEFINE_SCRIPTFUNC( GetNumBodyGroups, "Gets the number of bodygroups" )
|
DEFINE_SCRIPTFUNC( GetNumBodyGroups, "Gets the number of bodygroups" )
|
||||||
|
DEFINE_SCRIPTFUNC( GetModelScale, "Gets the model's scale" )
|
||||||
|
DEFINE_SCRIPTFUNC( SetModelScale, "Sets the model's scale with the specified change duration" )
|
||||||
|
|
||||||
DEFINE_SCRIPTFUNC( Dissolve, "Use 'sprites/blueglow1.vmt' for the default material, Time() for the default start time, false for npcOnly if you don't want it to check if the entity is a NPC first, 0 for the default dissolve type, Vector(0,0,0) for the default dissolver origin, and 0 for the default magnitude." )
|
DEFINE_SCRIPTFUNC( Dissolve, "Use 'sprites/blueglow1.vmt' for the default material, Time() for the default start time, false for npcOnly if you don't want it to check if the entity is a NPC first, 0 for the default dissolve type, Vector(0,0,0) for the default dissolver origin, and 0 for the default magnitude." )
|
||||||
DEFINE_SCRIPTFUNC( Ignite, "'NPCOnly' only lets this fall through if the entity is a NPC and 'CalledByLevelDesigner' determines whether to treat this like the Ignite input or just an internal ignition call." )
|
DEFINE_SCRIPTFUNC( Ignite, "'NPCOnly' only lets this fall through if the entity is a NPC and 'CalledByLevelDesigner' determines whether to treat this like the Ignite input or just an internal ignition call." )
|
||||||
@ -1331,7 +1333,7 @@ void CBaseAnimating::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
else if ( pEvent->event == AE_NPC_RESPONSE )
|
else if ( pEvent->event == AE_NPC_RESPONSE )
|
||||||
{
|
{
|
||||||
if (!MyNPCPointer()->GetExpresser()->IsSpeaking())
|
if (MyNPCPointer() && MyNPCPointer()->GetExpresser() && !MyNPCPointer()->GetExpresser()->IsSpeaking())
|
||||||
{
|
{
|
||||||
DispatchResponse( pEvent->options );
|
DispatchResponse( pEvent->options );
|
||||||
}
|
}
|
||||||
@ -1342,6 +1344,18 @@ void CBaseAnimating::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
DispatchResponse( pEvent->options );
|
DispatchResponse( pEvent->options );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if ( pEvent->event == AE_VSCRIPT_RUN )
|
||||||
|
{
|
||||||
|
if (!RunScript( pEvent->options ))
|
||||||
|
Warning( "%s failed to run AE_VSCRIPT_RUN on server with \"%s\"\n", GetDebugName(), pEvent->options );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ( pEvent->event == AE_VSCRIPT_RUN_FILE )
|
||||||
|
{
|
||||||
|
if (!RunScriptFile( pEvent->options ))
|
||||||
|
Warning( "%s failed to run AE_VSCRIPT_RUN_FILE on server with \"%s\"\n", GetDebugName(), pEvent->options );
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if ( pEvent->event == AE_RAGDOLL )
|
else if ( pEvent->event == AE_RAGDOLL )
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,15 @@
|
|||||||
IMPLEMENT_SERVERCLASS_ST( CBaseHLBludgeonWeapon, DT_BaseHLBludgeonWeapon )
|
IMPLEMENT_SERVERCLASS_ST( CBaseHLBludgeonWeapon, DT_BaseHLBludgeonWeapon )
|
||||||
END_SEND_TABLE()
|
END_SEND_TABLE()
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
BEGIN_DATADESC(CBaseHLBludgeonWeapon)
|
||||||
|
|
||||||
|
DEFINE_FIELD(m_flDelayedFire, FIELD_TIME),
|
||||||
|
DEFINE_FIELD(m_bShotDelayed, FIELD_BOOLEAN),
|
||||||
|
|
||||||
|
END_DATADESC()
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
#define BLUDGEON_HULL_DIM 16
|
#define BLUDGEON_HULL_DIM 16
|
||||||
|
|
||||||
static const Vector g_bludgeonMins(-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM);
|
static const Vector g_bludgeonMins(-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM);
|
||||||
@ -39,6 +48,9 @@ static const Vector g_bludgeonMaxs(BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM,BLUDGEON_
|
|||||||
CBaseHLBludgeonWeapon::CBaseHLBludgeonWeapon()
|
CBaseHLBludgeonWeapon::CBaseHLBludgeonWeapon()
|
||||||
{
|
{
|
||||||
m_bFiresUnderwater = true;
|
m_bFiresUnderwater = true;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_bShotDelayed = false;
|
||||||
|
#endif // MAPBASE
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -96,11 +108,19 @@ void CBaseHLBludgeonWeapon::ItemPostFrame( void )
|
|||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
if (pOwner->HasSpawnFlags( SF_PLAYER_SUPPRESS_FIRING ))
|
if (pOwner->HasSpawnFlags( SF_PLAYER_SUPPRESS_FIRING ))
|
||||||
{
|
{
|
||||||
|
m_bShotDelayed = false;
|
||||||
WeaponIdle();
|
WeaponIdle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// See if we need to fire off our secondary round
|
||||||
|
if (m_bShotDelayed)
|
||||||
|
{
|
||||||
|
if (gpGlobals->curtime > m_flDelayedFire)
|
||||||
|
DelayedAttack();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
|
if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
|
||||||
{
|
{
|
||||||
PrimaryAttack();
|
PrimaryAttack();
|
||||||
@ -162,7 +182,12 @@ void CBaseHLBludgeonWeapon::Hit( trace_t &traceHit, Activity nHitActivity, bool
|
|||||||
pPlayer->EyeVectors( &hitDirection, NULL, NULL );
|
pPlayer->EyeVectors( &hitDirection, NULL, NULL );
|
||||||
VectorNormalize( hitDirection );
|
VectorNormalize( hitDirection );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CTakeDamageInfo info(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), GetDamageType());
|
||||||
|
#else
|
||||||
CTakeDamageInfo info(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
|
CTakeDamageInfo info(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
|
|
||||||
if( pPlayer && pHitEntity->IsNPC() )
|
if( pPlayer && pHitEntity->IsNPC() )
|
||||||
{
|
{
|
||||||
@ -234,7 +259,7 @@ Activity CBaseHLBludgeonWeapon::ChooseIntersectionPointAndActivity( trace_t &hit
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return ACT_VM_HITCENTER;
|
return GetPrimaryAttackActivity();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -292,7 +317,6 @@ void CBaseHLBludgeonWeapon::ImpactEffect( trace_t &traceHit )
|
|||||||
UTIL_ImpactTrace( &traceHit, DMG_CLUB );
|
UTIL_ImpactTrace( &traceHit, DMG_CLUB );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Purpose : Starts the swing of the weapon and determines the animation
|
// Purpose : Starts the swing of the weapon and determines the animation
|
||||||
// Input : bIsSecondary - is this a secondary attack?
|
// Input : bIsSecondary - is this a secondary attack?
|
||||||
@ -315,10 +339,14 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
|
|||||||
|
|
||||||
Vector swingEnd = swingStart + forward * GetRange();
|
Vector swingEnd = swingStart + forward * GetRange();
|
||||||
UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
|
UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
|
||||||
Activity nHitActivity = ACT_VM_HITCENTER;
|
Activity nHitActivity = GetPrimaryAttackActivity();
|
||||||
|
|
||||||
// Like bullets, bludgeon traces have to trace against triggers.
|
// Like bullets, bludgeon traces have to trace against triggers.
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), GetDamageType());
|
||||||
|
#else
|
||||||
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
|
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
|
||||||
|
#endif // MAPBASE
|
||||||
triggerInfo.SetDamagePosition( traceHit.startpos );
|
triggerInfo.SetDamagePosition( traceHit.startpos );
|
||||||
triggerInfo.SetDamageForce( forward );
|
triggerInfo.SetDamageForce( forward );
|
||||||
TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, forward );
|
TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, forward );
|
||||||
@ -369,31 +397,20 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
|
|||||||
{
|
{
|
||||||
nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER;
|
nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER;
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
// We want to test the first swing again
|
// We want to test the first swing again
|
||||||
Vector testEnd = swingStart + forward * GetRange();
|
Vector testEnd = swingStart + forward * GetRange();
|
||||||
|
|
||||||
#ifdef MAPBASE
|
|
||||||
// Sound has been moved here since we're using the other melee sounds now
|
|
||||||
WeaponSound( SINGLE );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// See if we happened to hit water
|
// See if we happened to hit water
|
||||||
ImpactWater(swingStart, testEnd);
|
ImpactWater(swingStart, testEnd);
|
||||||
|
#endif // !MAPBASE
|
||||||
}
|
}
|
||||||
|
#ifndef MAPBASE
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef MAPBASE
|
|
||||||
// Other melee sounds
|
|
||||||
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
|
|
||||||
WeaponSound(MELEE_HIT_WORLD);
|
|
||||||
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
|
|
||||||
WeaponSound(MELEE_MISS);
|
|
||||||
else
|
|
||||||
WeaponSound(MELEE_HIT);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Hit( traceHit, nHitActivity, bIsSecondary ? true : false );
|
Hit( traceHit, nHitActivity, bIsSecondary ? true : false );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Send the anim
|
// Send the anim
|
||||||
SendWeaponAnim( nHitActivity );
|
SendWeaponAnim( nHitActivity );
|
||||||
@ -409,5 +426,125 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
|
|||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
pOwner->SetAnimation( PLAYER_ATTACK1 );
|
pOwner->SetAnimation( PLAYER_ATTACK1 );
|
||||||
|
|
||||||
|
if (GetHitDelay() > 0.f)
|
||||||
|
{
|
||||||
|
//Play swing sound
|
||||||
|
WeaponSound(SINGLE);
|
||||||
|
|
||||||
|
m_flDelayedFire = gpGlobals->curtime + GetHitDelay();
|
||||||
|
m_bShotDelayed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (traceHit.fraction == 1.0f)
|
||||||
|
{
|
||||||
|
// We want to test the first swing again
|
||||||
|
Vector testEnd = swingStart + forward * GetRange();
|
||||||
|
|
||||||
|
//Play swing sound
|
||||||
|
WeaponSound(SINGLE);
|
||||||
|
|
||||||
|
// See if we happened to hit water
|
||||||
|
ImpactWater(swingStart, testEnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Other melee sounds
|
||||||
|
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
|
||||||
|
WeaponSound(MELEE_HIT_WORLD);
|
||||||
|
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
|
||||||
|
WeaponSound(MELEE_MISS);
|
||||||
|
else
|
||||||
|
WeaponSound(MELEE_HIT);
|
||||||
|
|
||||||
|
Hit(traceHit, nHitActivity, bIsSecondary ? true : false);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void CBaseHLBludgeonWeapon::DelayedAttack(void)
|
||||||
|
{
|
||||||
|
m_bShotDelayed = false;
|
||||||
|
|
||||||
|
trace_t traceHit;
|
||||||
|
|
||||||
|
// Try a ray
|
||||||
|
CBasePlayer* pOwner = ToBasePlayer(GetOwner());
|
||||||
|
if (!pOwner)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pOwner->RumbleEffect(RUMBLE_CROWBAR_SWING, 0, RUMBLE_FLAG_RESTART);
|
||||||
|
|
||||||
|
Vector swingStart = pOwner->Weapon_ShootPosition();
|
||||||
|
Vector forward;
|
||||||
|
|
||||||
|
forward = pOwner->GetAutoaimVector(AUTOAIM_SCALE_DEFAULT, GetRange());
|
||||||
|
|
||||||
|
Vector swingEnd = swingStart + forward * GetRange();
|
||||||
|
UTIL_TraceLine(swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit);
|
||||||
|
|
||||||
|
if (traceHit.fraction == 1.0)
|
||||||
|
{
|
||||||
|
float bludgeonHullRadius = 1.732f * BLUDGEON_HULL_DIM; // hull is +/- 16, so use cuberoot of 2 to determine how big the hull is from center to the corner point
|
||||||
|
|
||||||
|
// Back off by hull "radius"
|
||||||
|
swingEnd -= forward * bludgeonHullRadius;
|
||||||
|
|
||||||
|
UTIL_TraceHull(swingStart, swingEnd, g_bludgeonMins, g_bludgeonMaxs, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit);
|
||||||
|
if (traceHit.fraction < 1.0 && traceHit.m_pEnt)
|
||||||
|
{
|
||||||
|
Vector vecToTarget = traceHit.m_pEnt->GetAbsOrigin() - swingStart;
|
||||||
|
VectorNormalize(vecToTarget);
|
||||||
|
|
||||||
|
float dot = vecToTarget.Dot(forward);
|
||||||
|
|
||||||
|
// YWB: Make sure they are sort of facing the guy at least...
|
||||||
|
if (dot < 0.70721f)
|
||||||
|
{
|
||||||
|
// Force amiss
|
||||||
|
traceHit.fraction = 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ChooseIntersectionPointAndActivity(traceHit, g_bludgeonMins, g_bludgeonMaxs, pOwner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (traceHit.fraction == 1.0f)
|
||||||
|
{
|
||||||
|
// We want to test the first swing again
|
||||||
|
Vector testEnd = swingStart + forward * GetRange();
|
||||||
|
|
||||||
|
// See if we happened to hit water
|
||||||
|
ImpactWater(swingStart, testEnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(GetActivity()), GetDamageType());
|
||||||
|
triggerInfo.SetDamagePosition(traceHit.startpos);
|
||||||
|
triggerInfo.SetDamageForce(forward);
|
||||||
|
|
||||||
|
// Other melee sounds
|
||||||
|
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
|
||||||
|
WeaponSound(MELEE_HIT_WORLD);
|
||||||
|
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
|
||||||
|
WeaponSound(MELEE_MISS);
|
||||||
|
else
|
||||||
|
WeaponSound(MELEE_HIT);
|
||||||
|
|
||||||
|
Hit(traceHit, GetActivity(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBaseHLBludgeonWeapon::CanHolster(void)
|
||||||
|
{
|
||||||
|
if (m_bShotDelayed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return BaseClass::CanHolster();
|
||||||
|
}
|
||||||
|
#endif // MAPBASE
|
||||||
|
@ -23,6 +23,9 @@ public:
|
|||||||
CBaseHLBludgeonWeapon();
|
CBaseHLBludgeonWeapon();
|
||||||
|
|
||||||
DECLARE_SERVERCLASS();
|
DECLARE_SERVERCLASS();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DECLARE_DATADESC();
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
virtual void Spawn( void );
|
virtual void Spawn( void );
|
||||||
virtual void Precache( void );
|
virtual void Precache( void );
|
||||||
@ -30,6 +33,9 @@ public:
|
|||||||
//Attack functions
|
//Attack functions
|
||||||
virtual void PrimaryAttack( void );
|
virtual void PrimaryAttack( void );
|
||||||
virtual void SecondaryAttack( void );
|
virtual void SecondaryAttack( void );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void DelayedAttack(void);
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
virtual void ItemPostFrame( void );
|
virtual void ItemPostFrame( void );
|
||||||
|
|
||||||
@ -44,6 +50,12 @@ public:
|
|||||||
virtual int CapabilitiesGet( void );
|
virtual int CapabilitiesGet( void );
|
||||||
virtual int WeaponMeleeAttack1Condition( float flDot, float flDist );
|
virtual int WeaponMeleeAttack1Condition( float flDot, float flDist );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual int GetDamageType() { return DMG_CLUB; }
|
||||||
|
virtual float GetHitDelay() { return 0.f; }
|
||||||
|
virtual bool CanHolster(void);
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void ImpactEffect( trace_t &trace );
|
virtual void ImpactEffect( trace_t &trace );
|
||||||
|
|
||||||
@ -52,6 +64,11 @@ private:
|
|||||||
void Swing( int bIsSecondary );
|
void Swing( int bIsSecondary );
|
||||||
void Hit( trace_t &traceHit, Activity nHitActivity, bool bIsSecondary );
|
void Hit( trace_t &traceHit, Activity nHitActivity, bool bIsSecondary );
|
||||||
Activity ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner );
|
Activity ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float m_flDelayedFire;
|
||||||
|
bool m_bShotDelayed;
|
||||||
|
#endif // MAPBASE
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -175,6 +175,7 @@ BEGIN_ENT_SCRIPTDESC( CBaseCombatCharacter, CBaseFlex, "The base class shared by
|
|||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptRelationType, "GetRelationship", "Get a character's relationship to a specific entity." )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptRelationType, "GetRelationship", "Get a character's relationship to a specific entity." )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptRelationPriority, "GetRelationPriority", "Get a character's relationship priority for a specific entity." )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptRelationPriority, "GetRelationPriority", "Get a character's relationship priority for a specific entity." )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetRelationship, "SetRelationship", "Set a character's relationship with a specific entity." )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptSetRelationship, "SetRelationship", "Set a character's relationship with a specific entity." )
|
||||||
|
DEFINE_SCRIPTFUNC_NAMED( ScriptSetClassRelationship, "SetClassRelationship", "Set a character's relationship with a specific Classify() class." )
|
||||||
|
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetVehicleEntity, "GetVehicleEntity", "Get the entity for a character's current vehicle if they're in one." )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetVehicleEntity, "GetVehicleEntity", "Get the entity for a character's current vehicle if they're in one." )
|
||||||
|
|
||||||
@ -1264,6 +1265,11 @@ bool CTraceFilterMelee::ShouldHitEntity( IHandleEntity *pHandleEntity, int conte
|
|||||||
if ( pEntity->m_takedamage == DAMAGE_NO )
|
if ( pEntity->m_takedamage == DAMAGE_NO )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
#ifdef MAPBASE // Moved from CheckTraceHullAttack()
|
||||||
|
if( m_pPassEnt && !pEntity->CanBeHitByMeleeAttack( const_cast<CBaseEntity*>(EntityFromEntityHandle( m_pPassEnt ) ) ) )
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
// FIXME: Do not translate this to the driver because the driver only accepts damage from the vehicle
|
// FIXME: Do not translate this to the driver because the driver only accepts damage from the vehicle
|
||||||
// Translate the vehicle into its driver for damage
|
// Translate the vehicle into its driver for damage
|
||||||
/*
|
/*
|
||||||
@ -1311,6 +1317,10 @@ bool CTraceFilterMelee::ShouldHitEntity( IHandleEntity *pHandleEntity, int conte
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Do not override an existing hit entity
|
||||||
|
if (!m_pHit)
|
||||||
|
#endif
|
||||||
m_pHit = pEntity;
|
m_pHit = pEntity;
|
||||||
|
|
||||||
// Make sure if the player is holding this, he drops it
|
// Make sure if the player is holding this, he drops it
|
||||||
@ -1386,11 +1396,13 @@ CBaseEntity *CBaseCombatCharacter::CheckTraceHullAttack( const Vector &vStart, c
|
|||||||
pEntity = traceFilter.m_pHit;
|
pEntity = traceFilter.m_pHit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef MAPBASE // Moved to CTraceFilterMelee
|
||||||
if( pEntity && !pEntity->CanBeHitByMeleeAttack(this) )
|
if( pEntity && !pEntity->CanBeHitByMeleeAttack(this) )
|
||||||
{
|
{
|
||||||
// If we touched something, but it shouldn't be hit, return nothing.
|
// If we touched something, but it shouldn't be hit, return nothing.
|
||||||
pEntity = NULL;
|
pEntity = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return pEntity;
|
return pEntity;
|
||||||
|
|
||||||
@ -3239,6 +3251,16 @@ void CBaseCombatCharacter::SetDefaultRelationship(Class_T nClass, Class_T nClass
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Determine whether or not default relationships are loaded
|
||||||
|
// Input :
|
||||||
|
// Output :
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CBaseCombatCharacter::DefaultRelationshipsLoaded()
|
||||||
|
{
|
||||||
|
return m_DefaultRelationship != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Fetch the default (ignore ai_relationship changes) relationship
|
// Purpose: Fetch the default (ignore ai_relationship changes) relationship
|
||||||
// Input :
|
// Input :
|
||||||
@ -3466,7 +3488,7 @@ void CBaseCombatCharacter::AddRelationship( const char *pszRelationship, CBaseEn
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef MAPBASE // I know the extra #ifdef is pointless, but it's there so you know this is new
|
// NEW: Classify class relationships
|
||||||
if (!Q_strnicmp(entityString, "CLASS_", 5))
|
if (!Q_strnicmp(entityString, "CLASS_", 5))
|
||||||
{
|
{
|
||||||
// Go through all of the classes and find which one this is
|
// Go through all of the classes and find which one this is
|
||||||
@ -3487,7 +3509,6 @@ void CBaseCombatCharacter::AddRelationship( const char *pszRelationship, CBaseEn
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!bFoundEntity)
|
if (!bFoundEntity)
|
||||||
#endif
|
|
||||||
DevWarning( "Couldn't set relationship to unknown entity or class (%s)!\n", entityString );
|
DevWarning( "Couldn't set relationship to unknown entity or class (%s)!\n", entityString );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3594,7 +3615,7 @@ CBaseEntity *CBaseCombatCharacter::Weapon_FindUsable( const Vector &range )
|
|||||||
else if (hl2_episodic.GetBool() && !GetActiveWeapon())
|
else if (hl2_episodic.GetBool() && !GetActiveWeapon())
|
||||||
{
|
{
|
||||||
// Unarmed citizens are conservative in their weapon finding...in Episode One
|
// Unarmed citizens are conservative in their weapon finding...in Episode One
|
||||||
if (Classify() != CLASS_PLAYER_ALLY_VITAL && Q_strncmp(STRING(gpGlobals->mapname), "ep1_", 4))
|
if (Classify() != CLASS_PLAYER_ALLY_VITAL && Q_strncmp(STRING(gpGlobals->mapname), "ep1_", 4) == 0)
|
||||||
bConservative = true;
|
bConservative = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -4643,6 +4664,13 @@ void CBaseCombatCharacter::ScriptSetRelationship( HSCRIPT pTarget, int dispositi
|
|||||||
AddEntityRelationship( ToEnt( pTarget ), (Disposition_t)disposition, priority );
|
AddEntityRelationship( ToEnt( pTarget ), (Disposition_t)disposition, priority );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CBaseCombatCharacter::ScriptSetClassRelationship( int classify, int disposition, int priority )
|
||||||
|
{
|
||||||
|
AddClassRelationship( (Class_T)classify, (Disposition_t)disposition, priority);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
HSCRIPT CBaseCombatCharacter::ScriptGetVehicleEntity()
|
HSCRIPT CBaseCombatCharacter::ScriptGetVehicleEntity()
|
||||||
|
@ -263,6 +263,10 @@ public:
|
|||||||
|
|
||||||
virtual bool CanBecomeServerRagdoll( void ) { return true; }
|
virtual bool CanBecomeServerRagdoll( void ) { return true; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void OnEnemyRangeAttackedMe( CBaseEntity *pEnemy, const Vector &vecDir, const Vector &vecEnd ) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// Damage
|
// Damage
|
||||||
// -----------------------
|
// -----------------------
|
||||||
@ -440,6 +444,7 @@ public:
|
|||||||
int ScriptRelationType( HSCRIPT pTarget );
|
int ScriptRelationType( HSCRIPT pTarget );
|
||||||
int ScriptRelationPriority( HSCRIPT pTarget );
|
int ScriptRelationPriority( HSCRIPT pTarget );
|
||||||
void ScriptSetRelationship( HSCRIPT pTarget, int disposition, int priority );
|
void ScriptSetRelationship( HSCRIPT pTarget, int disposition, int priority );
|
||||||
|
void ScriptSetClassRelationship( int classify, int disposition, int priority );
|
||||||
|
|
||||||
HSCRIPT ScriptGetVehicleEntity();
|
HSCRIPT ScriptGetVehicleEntity();
|
||||||
|
|
||||||
@ -462,6 +467,7 @@ public:
|
|||||||
static void AllocateDefaultRelationships( );
|
static void AllocateDefaultRelationships( );
|
||||||
static void SetDefaultRelationship( Class_T nClass, Class_T nClassTarget, Disposition_t nDisposition, int nPriority );
|
static void SetDefaultRelationship( Class_T nClass, Class_T nClassTarget, Disposition_t nDisposition, int nPriority );
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
|
static bool DefaultRelationshipsLoaded();
|
||||||
static Disposition_t GetDefaultRelationshipDisposition( Class_T nClassSource, Class_T nClassTarget );
|
static Disposition_t GetDefaultRelationshipDisposition( Class_T nClassSource, Class_T nClassTarget );
|
||||||
static int GetDefaultRelationshipPriority( Class_T nClassSource, Class_T nClassTarget );
|
static int GetDefaultRelationshipPriority( Class_T nClassSource, Class_T nClassTarget );
|
||||||
int GetDefaultRelationshipPriority( Class_T nClassTarget );
|
int GetDefaultRelationshipPriority( Class_T nClassTarget );
|
||||||
|
@ -2379,6 +2379,9 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
|||||||
DEFINE_SCRIPTFUNC( GetContextCount, "Get the number of response contexts" )
|
DEFINE_SCRIPTFUNC( GetContextCount, "Get the number of response contexts" )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetContextIndex, "GetContextIndex", "Get a response context at a specific index in the form of a table" )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetContextIndex, "GetContextIndex", "Get a response context at a specific index in the form of a table" )
|
||||||
|
|
||||||
|
DEFINE_SCRIPTFUNC_NAMED( ScriptGetGroundEntity, "GetGroundEntity", "Get the entity we're standing on." )
|
||||||
|
DEFINE_SCRIPTFUNC_NAMED( ScriptSetGroundEntity, "SetGroundEntity", "Set the entity we're standing on." )
|
||||||
|
|
||||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFollowEntity, "FollowEntity", "Begin following the specified entity. This makes this entity non-solid, parents it to the target entity, and teleports it to the specified entity's origin. The second parameter is whether or not to use bonemerging while following." )
|
DEFINE_SCRIPTFUNC_NAMED( ScriptFollowEntity, "FollowEntity", "Begin following the specified entity. This makes this entity non-solid, parents it to the target entity, and teleports it to the specified entity's origin. The second parameter is whether or not to use bonemerging while following." )
|
||||||
DEFINE_SCRIPTFUNC( StopFollowingEntity, "Stops following an entity if we're following one." )
|
DEFINE_SCRIPTFUNC( StopFollowingEntity, "Stops following an entity if we're following one." )
|
||||||
DEFINE_SCRIPTFUNC( IsFollowingEntity, "Returns true if this entity is following another entity." )
|
DEFINE_SCRIPTFUNC( IsFollowingEntity, "Returns true if this entity is following another entity." )
|
||||||
@ -10297,8 +10300,9 @@ bool CBaseEntity::ScriptAddOutput( const char *pszOutputName, const char *pszTar
|
|||||||
const char *CBaseEntity::ScriptGetKeyValue( const char *pszKeyName )
|
const char *CBaseEntity::ScriptGetKeyValue( const char *pszKeyName )
|
||||||
{
|
{
|
||||||
static char szValue[128];
|
static char szValue[128];
|
||||||
GetKeyValue( pszKeyName, szValue, sizeof(szValue) );
|
if ( GetKeyValue( pszKeyName, szValue, sizeof(szValue) ) )
|
||||||
return szValue;
|
return szValue;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1446,6 +1446,11 @@ public:
|
|||||||
CBaseEntity *GetGroundEntity( void );
|
CBaseEntity *GetGroundEntity( void );
|
||||||
CBaseEntity *GetGroundEntity( void ) const { return const_cast<CBaseEntity *>(this)->GetGroundEntity(); }
|
CBaseEntity *GetGroundEntity( void ) const { return const_cast<CBaseEntity *>(this)->GetGroundEntity(); }
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
HSCRIPT ScriptGetGroundEntity();
|
||||||
|
void ScriptSetGroundEntity( HSCRIPT hGroundEnt );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Gets the velocity we impart to a player standing on us
|
// Gets the velocity we impart to a player standing on us
|
||||||
virtual void GetGroundVelocityToApply( Vector &vecGroundVel ) { vecGroundVel = vec3_origin; }
|
virtual void GetGroundVelocityToApply( Vector &vecGroundVel ) { vecGroundVel = vec3_origin; }
|
||||||
|
|
||||||
@ -1575,7 +1580,7 @@ public:
|
|||||||
float flVolume, soundlevel_t iSoundlevel, int iFlags = 0, int iPitch = PITCH_NORM,
|
float flVolume, soundlevel_t iSoundlevel, int iFlags = 0, int iPitch = PITCH_NORM,
|
||||||
const Vector *pOrigin = NULL, const Vector *pDirection = NULL, bool bUpdatePositions = true, float soundtime = 0.0f
|
const Vector *pOrigin = NULL, const Vector *pDirection = NULL, bool bUpdatePositions = true, float soundtime = 0.0f
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
, int iSpecialDSP = 0, int iSpeakerIndex = 0 // Needed for env_microphone
|
, int iSpecialDSP = 0, int iSpeakerIndex = -1 // Needed for env_microphone
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -736,6 +736,12 @@ CBaseEntity *CGlobalEntityList::FindEntityCustomProcedural( CBaseEntity *pStartE
|
|||||||
|
|
||||||
g_pScriptVM->ExecuteFunction( g_CustomProcedurals[i].hFunc, args, 5, &functionReturn, NULL, true );
|
g_pScriptVM->ExecuteFunction( g_CustomProcedurals[i].hFunc, args, 5, &functionReturn, NULL, true );
|
||||||
|
|
||||||
|
if (pStartEntity && ToEnt( functionReturn.m_hScript ) == pStartEntity)
|
||||||
|
{
|
||||||
|
Warning( "WARNING: Custom procedural %s returned entity identical to start entity (%s), returning null\n", g_CustomProcedurals[i].szName, pStartEntity->GetDebugName() );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return ToEnt( functionReturn.m_hScript );
|
return ToEnt( functionReturn.m_hScript );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,10 +162,10 @@ void CBaseFilter::InputSetField( inputdata_t& inputdata )
|
|||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
bool CBaseFilter::ScriptPassesFilter( HSCRIPT pCaller, HSCRIPT pEntity ) { return PassesFilter( ToEnt(pCaller), ToEnt(pEntity) ); }
|
bool CBaseFilter::ScriptPassesFilter( HSCRIPT pCaller, HSCRIPT pEntity ) { return PassesFilter( ToEnt(pCaller), ToEnt(pEntity) ); }
|
||||||
bool CBaseFilter::ScriptPassesDamageFilter( HSCRIPT pCaller, HSCRIPT pInfo ) { return (pInfo) ? PassesDamageFilter( ToEnt( pCaller ), *const_cast<const CTakeDamageInfo*>(HScriptToClass<CTakeDamageInfo>( pInfo )) ) : NULL; }
|
bool CBaseFilter::ScriptPassesDamageFilter( HSCRIPT pCaller, HSCRIPT pInfo ) { return (pInfo) ? PassesDamageFilter( ToEnt( pCaller ), *const_cast<const CTakeDamageInfo*>(HScriptToClass<CTakeDamageInfo>( pInfo )) ) : false; }
|
||||||
bool CBaseFilter::ScriptPassesFinalDamageFilter( HSCRIPT pCaller, HSCRIPT pInfo ) { return (pInfo) ? PassesFinalDamageFilter( ToEnt( pCaller ), *const_cast<const CTakeDamageInfo*>(HScriptToClass<CTakeDamageInfo>( pInfo )) ) : NULL; }
|
bool CBaseFilter::ScriptPassesFinalDamageFilter( HSCRIPT pCaller, HSCRIPT pInfo ) { return (pInfo) ? PassesFinalDamageFilter( ToEnt( pCaller ), *const_cast<const CTakeDamageInfo*>(HScriptToClass<CTakeDamageInfo>( pInfo )) ) : false; }
|
||||||
bool CBaseFilter::ScriptBloodAllowed( HSCRIPT pCaller, HSCRIPT pInfo ) { return (pInfo) ? BloodAllowed( ToEnt( pCaller ), *const_cast<const CTakeDamageInfo*>(HScriptToClass<CTakeDamageInfo>( pInfo )) ) : NULL; }
|
bool CBaseFilter::ScriptBloodAllowed( HSCRIPT pCaller, HSCRIPT pInfo ) { return (pInfo) ? BloodAllowed( ToEnt( pCaller ), *const_cast<const CTakeDamageInfo*>(HScriptToClass<CTakeDamageInfo>( pInfo )) ) : false; }
|
||||||
bool CBaseFilter::ScriptDamageMod( HSCRIPT pCaller, HSCRIPT pInfo ) { return (pInfo) ? DamageMod( ToEnt( pCaller ), *HScriptToClass<CTakeDamageInfo>( pInfo ) ) : NULL; }
|
bool CBaseFilter::ScriptDamageMod( HSCRIPT pCaller, HSCRIPT pInfo ) { return (pInfo) ? DamageMod( ToEnt( pCaller ), *HScriptToClass<CTakeDamageInfo>( pInfo ) ) : false; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,6 +190,24 @@ int CAI_FuncTankBehavior::SelectSchedule()
|
|||||||
return SCHED_IDLE_STAND;
|
return SCHED_IDLE_STAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_FuncTankBehavior::ModifyOrAppendCriteria( AI_CriteriaSet &set )
|
||||||
|
{
|
||||||
|
BaseClass::ModifyOrAppendCriteria( set );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
set.AppendCriteria( "ft_mounted", m_bMounted ? "1" : "0" );
|
||||||
|
|
||||||
|
if (m_hFuncTank)
|
||||||
|
{
|
||||||
|
set.AppendCriteria( "ft_classname", m_hFuncTank->GetClassname() );
|
||||||
|
m_hFuncTank->AppendContextToCriteria( set, "ft_" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
// Input : activity -
|
// Input : activity -
|
||||||
|
@ -55,6 +55,8 @@ public:
|
|||||||
bool CanManTank( CFuncTank *pTank, bool bForced );
|
bool CanManTank( CFuncTank *pTank, bool bForced );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void ModifyOrAppendCriteria( AI_CriteriaSet &set );
|
||||||
|
|
||||||
Activity NPC_TranslateActivity( Activity activity );
|
Activity NPC_TranslateActivity( Activity activity );
|
||||||
|
|
||||||
// Conditions:
|
// Conditions:
|
||||||
|
@ -35,6 +35,9 @@ CBugBaitSensor* GetBugBaitSensorList()
|
|||||||
CBugBaitSensor::CBugBaitSensor( void )
|
CBugBaitSensor::CBugBaitSensor( void )
|
||||||
{
|
{
|
||||||
g_BugBaitSensorList.Insert( this );
|
g_BugBaitSensorList.Insert( this );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_bUseRadius = true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CBugBaitSensor::~CBugBaitSensor( void )
|
CBugBaitSensor::~CBugBaitSensor( void )
|
||||||
@ -50,10 +53,24 @@ BEGIN_DATADESC( CBugBaitSensor )
|
|||||||
DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "Enabled" ),
|
DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "Enabled" ),
|
||||||
DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ),
|
DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ),
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_KEYFIELD( m_bUseRadius, FIELD_BOOLEAN, "useradius" ),
|
||||||
|
DEFINE_KEYFIELD( m_vecMins, FIELD_VECTOR, "bmins" ),
|
||||||
|
DEFINE_KEYFIELD( m_vecMaxs, FIELD_VECTOR, "bmaxs" ),
|
||||||
|
#endif
|
||||||
|
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "EnableRadius", InputEnableRadius ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "DisableRadius", InputDisableRadius ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetRadius", InputSetRadius ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetMins", InputSetMins ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VECTOR, "SetMaxs", InputSetMaxs ),
|
||||||
|
#endif
|
||||||
|
|
||||||
// Function Pointers
|
// Function Pointers
|
||||||
DEFINE_OUTPUT( m_OnBaited, "OnBaited" ),
|
DEFINE_OUTPUT( m_OnBaited, "OnBaited" ),
|
||||||
|
|
||||||
@ -267,6 +284,9 @@ bool CGrenadeBugBait::ActivateBugbaitTargets( CBaseEntity *pOwner, Vector vecOri
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
//Make sure we're within range of the sensor
|
//Make sure we're within range of the sensor
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( pSensor->UsesRadius() ){
|
||||||
|
#endif
|
||||||
if ( pSensor->GetRadius() > (pSensor->GetAbsOrigin() - vecOrigin).Length() )
|
if ( pSensor->GetRadius() > (pSensor->GetAbsOrigin() - vecOrigin).Length() )
|
||||||
{
|
{
|
||||||
//Tell the sensor it's been hit
|
//Tell the sensor it's been hit
|
||||||
@ -279,6 +299,27 @@ bool CGrenadeBugBait::ActivateBugbaitTargets( CBaseEntity *pOwner, Vector vecOri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Vector vMins = pSensor->GetAbsMins();
|
||||||
|
Vector vMaxs = pSensor->GetAbsMaxs();
|
||||||
|
bool inBox = ((vecOrigin.x >= vMins.x && vecOrigin.x <= vMaxs.x) &&
|
||||||
|
(vecOrigin.y >= vMins.y && vecOrigin.y <= vMaxs.y) &&
|
||||||
|
(vecOrigin.z >= vMins.z && vecOrigin.z <= vMaxs.z));
|
||||||
|
if ( inBox ){
|
||||||
|
//Tell the sensor it's been hit
|
||||||
|
if ( pSensor->Baited( pOwner ) )
|
||||||
|
{
|
||||||
|
//If we're suppressing the call to antlions, then don't make a bugbait sound
|
||||||
|
if ( pSensor->SuppressCall() )
|
||||||
|
{
|
||||||
|
suppressCall = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return suppressCall;
|
return suppressCall;
|
||||||
|
@ -63,6 +63,28 @@ public:
|
|||||||
m_bEnabled = !m_bEnabled;
|
m_bEnabled = !m_bEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputEnableRadius( inputdata_t &data ){
|
||||||
|
m_bUseRadius = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputDisableRadius( inputdata_t &data ){
|
||||||
|
m_bUseRadius = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSetRadius( inputdata_t &data ){
|
||||||
|
m_flRadius = data.value.Int();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSetMins( inputdata_t &data ){
|
||||||
|
data.value.Vector3D( m_vecMins );
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputSetMaxs( inputdata_t &data ){
|
||||||
|
data.value.Vector3D( m_vecMaxs );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool SuppressCall( void )
|
bool SuppressCall( void )
|
||||||
{
|
{
|
||||||
return ( HasSpawnFlags( SF_BUGBAIT_SUPPRESS_CALL ) );
|
return ( HasSpawnFlags( SF_BUGBAIT_SUPPRESS_CALL ) );
|
||||||
@ -91,10 +113,28 @@ public:
|
|||||||
return !m_bEnabled;
|
return !m_bEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool UsesRadius( void ) const {
|
||||||
|
return m_bUseRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector GetAbsMins( void ) const {
|
||||||
|
return GetAbsOrigin() + m_vecMins;
|
||||||
|
}
|
||||||
|
Vector GetAbsMaxs( void ) const {
|
||||||
|
return GetAbsOrigin() + m_vecMaxs;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
float m_flRadius;
|
float m_flRadius;
|
||||||
bool m_bEnabled;
|
bool m_bEnabled;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bUseRadius;
|
||||||
|
Vector m_vecMins;
|
||||||
|
Vector m_vecMaxs;
|
||||||
|
#endif
|
||||||
COutputEvent m_OnBaited;
|
COutputEvent m_OnBaited;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1814,7 +1814,7 @@ bool CHL2_Player::CommanderFindGoal( commandgoal_t *pGoal )
|
|||||||
// Get either our +USE entity or the gravity gun entity
|
// Get either our +USE entity or the gravity gun entity
|
||||||
CBaseEntity *pHeldEntity = GetPlayerHeldEntity(this);
|
CBaseEntity *pHeldEntity = GetPlayerHeldEntity(this);
|
||||||
if ( !pHeldEntity )
|
if ( !pHeldEntity )
|
||||||
PhysCannonGetHeldEntity( GetActiveWeapon() );
|
pHeldEntity = PhysCannonGetHeldEntity( GetActiveWeapon() );
|
||||||
|
|
||||||
CTraceFilterSkipTwoEntities filter( this, pHeldEntity, COLLISION_GROUP_INTERACTIVE_DEBRIS );
|
CTraceFilterSkipTwoEntities filter( this, pHeldEntity, COLLISION_GROUP_INTERACTIVE_DEBRIS );
|
||||||
#else
|
#else
|
||||||
|
@ -159,6 +159,10 @@ ConVar zombie_decaymax( "zombie_decaymax", "0.4" );
|
|||||||
|
|
||||||
ConVar zombie_ambushdist( "zombie_ambushdist", "16000" );
|
ConVar zombie_ambushdist( "zombie_ambushdist", "16000" );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVar zombie_no_flinch_during_unique_anim( "zombie_no_flinch_during_unique_anim", "1", FCVAR_NONE, "Prevents zombies from flinching during actbusies and scripted sequences." );
|
||||||
|
#endif
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// For a couple of reasons, we keep a running count of how
|
// For a couple of reasons, we keep a running count of how
|
||||||
// many zombies in the world are angry at any given time.
|
// many zombies in the world are angry at any given time.
|
||||||
@ -1745,7 +1749,11 @@ void CNPC_BaseZombie::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
|
|
||||||
dmgInfo.SetDamagePosition( vecHeadCrabPosition );
|
dmgInfo.SetDamagePosition( vecHeadCrabPosition );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ReleaseHeadcrab( vecHeadCrabPosition, vVelocity *iSpeed, true, false, true );
|
||||||
|
#else
|
||||||
ReleaseHeadcrab( EyePosition(), vVelocity * iSpeed, true, false, true );
|
ReleaseHeadcrab( EyePosition(), vVelocity * iSpeed, true, false, true );
|
||||||
|
#endif
|
||||||
|
|
||||||
GuessDamageForce( &dmgInfo, vVelocity, vecHeadCrabPosition, 0.5f );
|
GuessDamageForce( &dmgInfo, vVelocity, vecHeadCrabPosition, 0.5f );
|
||||||
TakeDamage( dmgInfo );
|
TakeDamage( dmgInfo );
|
||||||
@ -1927,6 +1935,31 @@ void CNPC_BaseZombie::OnScheduleChange( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
//---------------------------------------------------------
|
||||||
|
|
||||||
|
bool CNPC_BaseZombie::CanFlinch( void )
|
||||||
|
{
|
||||||
|
if (!BaseClass::CanFlinch())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (zombie_no_flinch_during_unique_anim.GetBool())
|
||||||
|
{
|
||||||
|
// Don't flinch if currently playing actbusy animation (navigating to or from one is fine)
|
||||||
|
if (m_ActBusyBehavior.IsInsideActBusy())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't flinch if currently playing scripted sequence (navigating to or from one is fine)
|
||||||
|
if (m_NPCState == NPC_STATE_SCRIPT && (IsCurSchedule( SCHED_SCRIPTED_WAIT, false ) || IsCurSchedule( SCHED_SCRIPTED_FACE, false )))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
int CNPC_BaseZombie::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode )
|
int CNPC_BaseZombie::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode )
|
||||||
@ -2435,6 +2468,20 @@ void CNPC_BaseZombie::RemoveHead( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
//---------------------------------------------------------
|
||||||
|
void CNPC_BaseZombie::SetModel( const char *szModelName )
|
||||||
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Zombies setting the same model again is a problem when they should maintain their current sequence (e.g. during dynamic interactions)
|
||||||
|
if ( IsRunningDynamicInteraction() && GetModelIndex() != 0 && FStrEq( szModelName, STRING(GetModelName()) ) )
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BaseClass::SetModel( szModelName );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CNPC_BaseZombie::ShouldPlayFootstepMoan( void )
|
bool CNPC_BaseZombie::ShouldPlayFootstepMoan( void )
|
||||||
{
|
{
|
||||||
if( random->RandomInt( 1, zombie_stepfreq.GetInt() * s_iAngryZombies ) == 1 )
|
if( random->RandomInt( 1, zombie_stepfreq.GetInt() * s_iAngryZombies ) == 1 )
|
||||||
@ -2450,9 +2497,15 @@ bool CNPC_BaseZombie::ShouldPlayFootstepMoan( void )
|
|||||||
#define CRAB_HULL_EXPAND 1.1f
|
#define CRAB_HULL_EXPAND 1.1f
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CNPC_BaseZombie::HeadcrabFits( CBaseAnimating *pCrab )
|
bool CNPC_BaseZombie::HeadcrabFits( CBaseAnimating *pCrab, const Vector *vecOrigin )
|
||||||
{
|
{
|
||||||
Vector vecSpawnLoc = pCrab->GetAbsOrigin();
|
Vector vecSpawnLoc;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (vecOrigin)
|
||||||
|
vecSpawnLoc = *vecOrigin;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
vecSpawnLoc = pCrab->GetAbsOrigin();
|
||||||
|
|
||||||
CTraceFilterSimpleList traceFilter( COLLISION_GROUP_NONE );
|
CTraceFilterSimpleList traceFilter( COLLISION_GROUP_NONE );
|
||||||
traceFilter.AddEntityToIgnore( pCrab );
|
traceFilter.AddEntityToIgnore( pCrab );
|
||||||
@ -2535,7 +2588,12 @@ void CNPC_BaseZombie::ReleaseHeadcrab( const Vector &vecOrigin, const Vector &ve
|
|||||||
SetHeadcrabSpawnLocation( iCrabAttachment, pAnimatingGib );
|
SetHeadcrabSpawnLocation( iCrabAttachment, pAnimatingGib );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Server ragdolls don't have a valid origin on spawn, so we have to use the origin originally passed
|
||||||
|
if( !HeadcrabFits( pAnimatingGib, m_bForceServerRagdoll ? &vecOrigin : NULL ) )
|
||||||
|
#else
|
||||||
if( !HeadcrabFits(pAnimatingGib) )
|
if( !HeadcrabFits(pAnimatingGib) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
UTIL_Remove(pGib);
|
UTIL_Remove(pGib);
|
||||||
return;
|
return;
|
||||||
@ -2552,11 +2610,20 @@ void CNPC_BaseZombie::ReleaseHeadcrab( const Vector &vecOrigin, const Vector &ve
|
|||||||
|
|
||||||
if( UTIL_ShouldShowBlood(BLOOD_COLOR_YELLOW) )
|
if( UTIL_ShouldShowBlood(BLOOD_COLOR_YELLOW) )
|
||||||
{
|
{
|
||||||
UTIL_BloodImpact( pGib->WorldSpaceCenter(), Vector(0,0,1), BLOOD_COLOR_YELLOW, 1 );
|
Vector vecGibCenter;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Server ragdolls don't have a valid origin on spawn, so we have to use the origin originally passed
|
||||||
|
if (m_bForceServerRagdoll)
|
||||||
|
vecGibCenter = vecOrigin;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
vecGibCenter = pGib->WorldSpaceCenter();
|
||||||
|
|
||||||
|
UTIL_BloodImpact( vecGibCenter, Vector(0,0,1), BLOOD_COLOR_YELLOW, 1 );
|
||||||
|
|
||||||
for ( int i = 0 ; i < 3 ; i++ )
|
for ( int i = 0 ; i < 3 ; i++ )
|
||||||
{
|
{
|
||||||
Vector vecSpot = pGib->WorldSpaceCenter();
|
Vector vecSpot = vecGibCenter;
|
||||||
|
|
||||||
vecSpot.x += random->RandomFloat( -8, 8 );
|
vecSpot.x += random->RandomFloat( -8, 8 );
|
||||||
vecSpot.y += random->RandomFloat( -8, 8 );
|
vecSpot.y += random->RandomFloat( -8, 8 );
|
||||||
@ -2590,6 +2657,9 @@ void CNPC_BaseZombie::ReleaseHeadcrab( const Vector &vecOrigin, const Vector &ve
|
|||||||
// Inherit some misc. properties
|
// Inherit some misc. properties
|
||||||
pCrab->m_bForceServerRagdoll = m_bForceServerRagdoll;
|
pCrab->m_bForceServerRagdoll = m_bForceServerRagdoll;
|
||||||
pCrab->m_iViewHideFlags = m_iViewHideFlags;
|
pCrab->m_iViewHideFlags = m_iViewHideFlags;
|
||||||
|
|
||||||
|
// Add response context for companion response (more reliable than checking for post-death zombie entity)
|
||||||
|
pCrab->AddContext( "from_zombie", "1", 2.0f );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// make me the crab's owner to avoid collision issues
|
// make me the crab's owner to avoid collision issues
|
||||||
|
@ -151,6 +151,8 @@ public:
|
|||||||
int OnTakeDamage_Alive( const CTakeDamageInfo &info );
|
int OnTakeDamage_Alive( const CTakeDamageInfo &info );
|
||||||
virtual float GetReactionDelay( CBaseEntity *pEnemy ) { return 0.0; }
|
virtual float GetReactionDelay( CBaseEntity *pEnemy ) { return 0.0; }
|
||||||
|
|
||||||
|
bool CanFlinch( void );
|
||||||
|
|
||||||
virtual int SelectSchedule ( void );
|
virtual int SelectSchedule ( void );
|
||||||
virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
|
virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
|
||||||
virtual void BuildScheduleTestBits( void );
|
virtual void BuildScheduleTestBits( void );
|
||||||
@ -186,9 +188,10 @@ public:
|
|||||||
// Headcrab releasing/breaking apart
|
// Headcrab releasing/breaking apart
|
||||||
void RemoveHead( void );
|
void RemoveHead( void );
|
||||||
virtual void SetZombieModel( void ) { };
|
virtual void SetZombieModel( void ) { };
|
||||||
|
virtual void SetModel( const char *szModelName );
|
||||||
virtual void BecomeTorso( const Vector &vecTorsoForce, const Vector &vecLegsForce );
|
virtual void BecomeTorso( const Vector &vecTorsoForce, const Vector &vecLegsForce );
|
||||||
virtual bool CanBecomeLiveTorso() { return false; }
|
virtual bool CanBecomeLiveTorso() { return false; }
|
||||||
virtual bool HeadcrabFits( CBaseAnimating *pCrab );
|
virtual bool HeadcrabFits( CBaseAnimating *pCrab, const Vector *vecOrigin = NULL );
|
||||||
void ReleaseHeadcrab( const Vector &vecOrigin, const Vector &vecVelocity, bool fRemoveHead, bool fRagdollBody, bool fRagdollCrab = false );
|
void ReleaseHeadcrab( const Vector &vecOrigin, const Vector &vecVelocity, bool fRemoveHead, bool fRagdollBody, bool fRagdollCrab = false );
|
||||||
void SetHeadcrabSpawnLocation( int iCrabAttachment, CBaseAnimating *pCrab );
|
void SetHeadcrabSpawnLocation( int iCrabAttachment, CBaseAnimating *pCrab );
|
||||||
|
|
||||||
|
@ -1092,10 +1092,14 @@ void CNPC_Alyx::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CNPC_Alyx::EnemyIgnited( CAI_BaseNPC *pVictim )
|
void CNPC_Alyx::EnemyIgnited( CAI_BaseNPC *pVictim )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
BaseClass::EnemyIgnited( pVictim );
|
||||||
|
#else
|
||||||
if ( FVisible( pVictim ) )
|
if ( FVisible( pVictim ) )
|
||||||
{
|
{
|
||||||
SpeakIfAllowed( TLK_ENEMY_BURNING );
|
SpeakIfAllowed( TLK_ENEMY_BURNING );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1252,6 +1256,7 @@ void CNPC_Alyx::DoCustomSpeechAI( void )
|
|||||||
|
|
||||||
CBasePlayer *pPlayer = AI_GetSinglePlayer();
|
CBasePlayer *pPlayer = AI_GetSinglePlayer();
|
||||||
|
|
||||||
|
#ifndef MAPBASE // Ported to CNPC_PlayerCompanion
|
||||||
if ( HasCondition(COND_NEW_ENEMY) && GetEnemy() )
|
if ( HasCondition(COND_NEW_ENEMY) && GetEnemy() )
|
||||||
{
|
{
|
||||||
if ( GetEnemy()->Classify() == CLASS_HEADCRAB )
|
if ( GetEnemy()->Classify() == CLASS_HEADCRAB )
|
||||||
@ -1278,6 +1283,7 @@ void CNPC_Alyx::DoCustomSpeechAI( void )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Darkness mode speech
|
// Darkness mode speech
|
||||||
ClearCondition( COND_ALYX_IN_DARK );
|
ClearCondition( COND_ALYX_IN_DARK );
|
||||||
@ -1917,6 +1923,7 @@ int CNPC_Alyx::SelectSchedule( void )
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int CNPC_Alyx::SelectScheduleDanger( void )
|
int CNPC_Alyx::SelectScheduleDanger( void )
|
||||||
{
|
{
|
||||||
|
#ifndef MAPBASE
|
||||||
if( HasCondition( COND_HEAR_DANGER ) )
|
if( HasCondition( COND_HEAR_DANGER ) )
|
||||||
{
|
{
|
||||||
CSound *pSound;
|
CSound *pSound;
|
||||||
@ -1929,6 +1936,7 @@ int CNPC_Alyx::SelectScheduleDanger( void )
|
|||||||
SpeakIfAllowed( TLK_DANGER_ZOMBINE_GRENADE );
|
SpeakIfAllowed( TLK_DANGER_ZOMBINE_GRENADE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return BaseClass::SelectScheduleDanger();
|
return BaseClass::SelectScheduleDanger();
|
||||||
}
|
}
|
||||||
|
@ -412,7 +412,6 @@ ScriptHook_t CNPC_Citizen::g_Hook_SelectModel;
|
|||||||
|
|
||||||
BEGIN_ENT_SCRIPTDESC( CNPC_Citizen, CAI_BaseActor, "npc_citizen from Half-Life 2" )
|
BEGIN_ENT_SCRIPTDESC( CNPC_Citizen, CAI_BaseActor, "npc_citizen from Half-Life 2" )
|
||||||
|
|
||||||
DEFINE_SCRIPTFUNC( IsMedic, "Returns true if this citizen is a medic." )
|
|
||||||
DEFINE_SCRIPTFUNC( IsAmmoResupplier, "Returns true if this citizen is an ammo resupplier." )
|
DEFINE_SCRIPTFUNC( IsAmmoResupplier, "Returns true if this citizen is an ammo resupplier." )
|
||||||
DEFINE_SCRIPTFUNC( CanHeal, "Returns true if this citizen is a medic or ammo resupplier currently able to heal/give ammo." )
|
DEFINE_SCRIPTFUNC( CanHeal, "Returns true if this citizen is a medic or ammo resupplier currently able to heal/give ammo." )
|
||||||
|
|
||||||
|
@ -47,6 +47,8 @@ ConVar npc_combine_protected_run( "npc_combine_protected_run", "0", FCVAR_NONE,
|
|||||||
ConVar npc_combine_altfire_not_allies_only( "npc_combine_altfire_not_allies_only", "1", FCVAR_NONE, "Mapbase: Elites are normally only allowed to fire their alt-fire attack at the player and the player's allies; This allows elites to alt-fire at other enemies too." );
|
ConVar npc_combine_altfire_not_allies_only( "npc_combine_altfire_not_allies_only", "1", FCVAR_NONE, "Mapbase: Elites are normally only allowed to fire their alt-fire attack at the player and the player's allies; This allows elites to alt-fire at other enemies too." );
|
||||||
|
|
||||||
ConVar npc_combine_new_cover_behavior( "npc_combine_new_cover_behavior", "1", FCVAR_NONE, "Mapbase: Toggles small patches for parts of npc_combine AI related to soldiers failing to take cover. These patches are minimal and only change cases where npc_combine would otherwise look at an enemy without shooting or run up to the player to melee attack when they don't have to. Consult the Mapbase wiki for more information." );
|
ConVar npc_combine_new_cover_behavior( "npc_combine_new_cover_behavior", "1", FCVAR_NONE, "Mapbase: Toggles small patches for parts of npc_combine AI related to soldiers failing to take cover. These patches are minimal and only change cases where npc_combine would otherwise look at an enemy without shooting or run up to the player to melee attack when they don't have to. Consult the Mapbase wiki for more information." );
|
||||||
|
|
||||||
|
ConVar npc_combine_fixed_shootpos( "npc_combine_fixed_shootpos", "0", FCVAR_NONE, "Mapbase: Toggles fixed Combine soldier shoot position." );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COMBINE_SKIN_DEFAULT 0
|
#define COMBINE_SKIN_DEFAULT 0
|
||||||
@ -2959,6 +2961,28 @@ Vector CNPC_Combine::Weapon_ShootPosition( )
|
|||||||
// FIXME: rename this "estimated" since it's not based on animation
|
// FIXME: rename this "estimated" since it's not based on animation
|
||||||
// FIXME: the orientation won't be correct when testing from arbitary positions for arbitary angles
|
// FIXME: the orientation won't be correct when testing from arbitary positions for arbitary angles
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// HACKHACK: This weapon shoot position code does not work properly when in close range, causing the aim
|
||||||
|
// to drift to the left as the enemy gets closer to it.
|
||||||
|
// This problem is usually bearable for regular combat, but it causes dynamic interaction yaw to be offset
|
||||||
|
// as well, preventing most from ever being triggered.
|
||||||
|
// Ideally, this should be fixed from the root cause, but due to the sensitivity of such a change, this is
|
||||||
|
// currently being tied to a cvar which is off by default.
|
||||||
|
//
|
||||||
|
// If the cvar is disabled but the soldier has valid interactions on its current enemy, then a separate hack
|
||||||
|
// will still attempt to correct the drift as the enemy gets closer.
|
||||||
|
if ( npc_combine_fixed_shootpos.GetBool() )
|
||||||
|
{
|
||||||
|
right *= 0.0f;
|
||||||
|
}
|
||||||
|
else if ( HasValidInteractionsOnCurrentEnemy() )
|
||||||
|
{
|
||||||
|
float flDistSqr = GetEnemy()->WorldSpaceCenter().DistToSqr( WorldSpaceCenter() );
|
||||||
|
if (flDistSqr < Square( 128.0f ))
|
||||||
|
right *= (flDistSqr / Square( 128.0f ));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( bStanding )
|
if ( bStanding )
|
||||||
{
|
{
|
||||||
if( HasShotgun() )
|
if( HasShotgun() )
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include "mapbase/GlobalStrings.h"
|
#include "mapbase/GlobalStrings.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "vehicle_base.h"
|
#include "vehicle_base.h"
|
||||||
|
#include "npc_headcrab.h"
|
||||||
|
#include "npc_BaseZombie.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConVar ai_debug_readiness("ai_debug_readiness", "0" );
|
ConVar ai_debug_readiness("ai_debug_readiness", "0" );
|
||||||
@ -640,6 +642,55 @@ void CNPC_PlayerCompanion::DoCustomSpeechAI( void )
|
|||||||
{
|
{
|
||||||
SpeakIfAllowed( TLK_PLDEAD );
|
SpeakIfAllowed( TLK_PLDEAD );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Unique new enemy concepts ported from Alyx
|
||||||
|
// The casts have been changed to dynamic_cast due to the risk of non-CBaseHeadcrab/CNPC_BaseZombie enemies using those classes
|
||||||
|
if ( HasCondition(COND_NEW_ENEMY) && GetEnemy() )
|
||||||
|
{
|
||||||
|
int nClass = GetEnemy()->Classify();
|
||||||
|
if ( nClass == CLASS_HEADCRAB )
|
||||||
|
{
|
||||||
|
CBaseHeadcrab *pHC = dynamic_cast<CBaseHeadcrab*>(GetEnemy());
|
||||||
|
if ( pHC )
|
||||||
|
{
|
||||||
|
// If we see a headcrab for the first time as he's jumping at me, freak out!
|
||||||
|
if ( ( GetEnemy()->GetEnemy() == this ) && pHC->IsJumping() && gpGlobals->curtime - GetEnemies()->FirstTimeSeen(GetEnemy()) < 0.5 )
|
||||||
|
{
|
||||||
|
SpeakIfAllowed( "TLK_SPOTTED_INCOMING_HEADCRAB" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we see a headcrab leaving a zombie that just died, mention it
|
||||||
|
// (Note that this is now a response context since some death types remove the zombie instantly)
|
||||||
|
int nContext = pHC->FindContextByName( "from_zombie" );
|
||||||
|
if ( nContext > -1 && !ContextExpired( nContext ) ) // pHC->GetOwnerEntity() && ( pHC->GetOwnerEntity()->Classify() == CLASS_ZOMBIE ) && !pHC->GetOwnerEntity()->IsAlive()
|
||||||
|
{
|
||||||
|
SpeakIfAllowed( "TLK_SPOTTED_HEADCRAB_LEAVING_ZOMBIE" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( nClass == CLASS_ZOMBIE )
|
||||||
|
{
|
||||||
|
CNPC_BaseZombie *pZombie = dynamic_cast<CNPC_BaseZombie*>(GetEnemy());
|
||||||
|
// If we see a zombie getting up, mention it
|
||||||
|
if ( pZombie && pZombie->IsGettingUp() )
|
||||||
|
{
|
||||||
|
SpeakIfAllowed( "TLK_SPOTTED_ZOMBIE_WAKEUP" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( gpGlobals->curtime - GetEnemies()->TimeAtFirstHand( GetEnemy() ) <= 1.0f && nClass != CLASS_BULLSEYE )
|
||||||
|
{
|
||||||
|
// New concept which did not originate from Alyx, but is in the same category as the above concepts.
|
||||||
|
// This is meant to be used when a new enemy enters the arena while combat is already in progress.
|
||||||
|
// (Note that this can still trigger when combat begins, but unlike TLK_STARTCOMBAT, it has no delay
|
||||||
|
// between combat engagements.)
|
||||||
|
SpeakIfAllowed( TLK_NEW_ENEMY );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -910,8 +961,21 @@ int CNPC_PlayerCompanion::SelectScheduleDanger()
|
|||||||
|
|
||||||
if ( pSound && (pSound->m_iType & SOUND_DANGER) )
|
if ( pSound && (pSound->m_iType & SOUND_DANGER) )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( pSound->SoundChannel() == SOUNDENT_CHANNEL_ZOMBINE_GRENADE )
|
||||||
|
{
|
||||||
|
SetSpeechTarget( pSound->m_hOwner );
|
||||||
|
SpeakIfAllowed( TLK_DANGER_ZOMBINE_GRENADE );
|
||||||
|
}
|
||||||
|
else if (!(pSound->SoundContext() & (SOUND_CONTEXT_MORTAR | SOUND_CONTEXT_FROM_SNIPER)) || IsOkToCombatSpeak())
|
||||||
|
{
|
||||||
|
SetSpeechTarget( pSound->m_hOwner );
|
||||||
|
SpeakIfAllowed( TLK_DANGER );
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ( !(pSound->SoundContext() & (SOUND_CONTEXT_MORTAR|SOUND_CONTEXT_FROM_SNIPER)) || IsOkToCombatSpeak() )
|
if ( !(pSound->SoundContext() & (SOUND_CONTEXT_MORTAR|SOUND_CONTEXT_FROM_SNIPER)) || IsOkToCombatSpeak() )
|
||||||
SpeakIfAllowed( TLK_DANGER );
|
SpeakIfAllowed( TLK_DANGER );
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( HasCondition( COND_PC_SAFE_FROM_MORTAR ) )
|
if ( HasCondition( COND_PC_SAFE_FROM_MORTAR ) )
|
||||||
{
|
{
|
||||||
@ -4309,6 +4373,20 @@ void CNPC_PlayerCompanion::Event_KilledOther( CBaseEntity *pVictim, const CTakeD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Called by enemy NPC's when they are ignited
|
||||||
|
// Input : pVictim - entity that was ignited
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CNPC_PlayerCompanion::EnemyIgnited( CAI_BaseNPC *pVictim )
|
||||||
|
{
|
||||||
|
BaseClass::EnemyIgnited( pVictim );
|
||||||
|
|
||||||
|
if ( FVisible( pVictim ) )
|
||||||
|
{
|
||||||
|
SpeakIfAllowed( TLK_ENEMY_BURNING );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Handles custom combat speech stuff ported from Alyx.
|
// Purpose: Handles custom combat speech stuff ported from Alyx.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -4376,6 +4454,21 @@ void CNPC_PlayerCompanion::DoCustomCombatAI( void )
|
|||||||
{
|
{
|
||||||
SpeakIfAllowed( TLK_MANY_ENEMIES );
|
SpeakIfAllowed( TLK_MANY_ENEMIES );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're not currently attacking or vulnerable, try speaking
|
||||||
|
else if ( gpGlobals->curtime - GetLastAttackTime() > 1.0f && (!HasCondition( COND_SEE_ENEMY ) || IsCurSchedule( SCHED_RELOAD ) || IsCurSchedule( SCHED_HIDE_AND_RELOAD )) )
|
||||||
|
{
|
||||||
|
int chance = ( IsMoving() ) ? 20 : 3;
|
||||||
|
if ( ShouldSpeakRandom( TLK_COMBAT_IDLE, chance ) )
|
||||||
|
{
|
||||||
|
AI_CriteriaSet modifiers;
|
||||||
|
|
||||||
|
modifiers.AppendCriteria( "in_cover", HasMemory( bits_MEMORY_INCOVER ) ? "1" : "0" );
|
||||||
|
modifiers.AppendCriteria( "lastseenenemy", UTIL_VarArgs( "%f", gpGlobals->curtime - GetEnemyLastTimeSeen() ) );
|
||||||
|
|
||||||
|
SpeakIfAllowed( TLK_COMBAT_IDLE, modifiers );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -242,6 +242,7 @@ public:
|
|||||||
|
|
||||||
virtual void Event_Killed( const CTakeDamageInfo &info );
|
virtual void Event_Killed( const CTakeDamageInfo &info );
|
||||||
virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info );
|
virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info );
|
||||||
|
virtual void EnemyIgnited( CAI_BaseNPC *pVictim );
|
||||||
virtual void DoCustomCombatAI( void );
|
virtual void DoCustomCombatAI( void );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -121,6 +121,33 @@ acttable_t CWeaponAnnabelle::m_acttable[] =
|
|||||||
{ ACT_RELOAD_LOW, ACT_RELOAD_ANNABELLE_LOW, false },
|
{ ACT_RELOAD_LOW, ACT_RELOAD_ANNABELLE_LOW, false },
|
||||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_ANNABELLE, false },
|
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_ANNABELLE, false },
|
||||||
|
|
||||||
|
// Readiness activities (not aiming)
|
||||||
|
{ ACT_IDLE_RELAXED, ACT_IDLE_AR2_RELAXED, false },//never aims
|
||||||
|
{ ACT_IDLE_STIMULATED, ACT_IDLE_AR2_STIMULATED, false },
|
||||||
|
{ ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_AR2, false },//always aims
|
||||||
|
|
||||||
|
{ ACT_WALK_RELAXED, ACT_WALK_AR2_RELAXED, false },//never aims
|
||||||
|
{ ACT_WALK_STIMULATED, ACT_WALK_AR2_STIMULATED, false },
|
||||||
|
{ ACT_WALK_AGITATED, ACT_WALK_AIM_AR2, false },//always aims
|
||||||
|
|
||||||
|
{ ACT_RUN_RELAXED, ACT_RUN_AR2_RELAXED, false },//never aims
|
||||||
|
{ ACT_RUN_STIMULATED, ACT_RUN_AR2_STIMULATED, false },
|
||||||
|
{ ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
|
||||||
|
|
||||||
|
// Readiness activities (aiming)
|
||||||
|
{ ACT_IDLE_AIM_RELAXED, ACT_IDLE_AR2_RELAXED, false },//never aims
|
||||||
|
{ ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_AR2_STIMULATED, false },
|
||||||
|
{ ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_AR2, false },//always aims
|
||||||
|
|
||||||
|
{ ACT_WALK_AIM_RELAXED, ACT_WALK_AR2_RELAXED, false },//never aims
|
||||||
|
{ ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_AR2_STIMULATED, false },
|
||||||
|
{ ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_AR2, false },//always aims
|
||||||
|
|
||||||
|
{ ACT_RUN_AIM_RELAXED, ACT_RUN_AR2_RELAXED, false },//never aims
|
||||||
|
{ ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_AR2_STIMULATED, false },
|
||||||
|
{ ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
|
||||||
|
//End readiness activities
|
||||||
|
|
||||||
{ ACT_ARM, ACT_ARM_RIFLE, true },
|
{ ACT_ARM, ACT_ARM_RIFLE, true },
|
||||||
{ ACT_DISARM, ACT_DISARM_RIFLE, true },
|
{ ACT_DISARM, ACT_DISARM_RIFLE, true },
|
||||||
#else
|
#else
|
||||||
@ -143,6 +170,13 @@ acttable_t CWeaponAnnabelle::m_acttable[] =
|
|||||||
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, false },
|
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, false },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if EXPANDED_HL2_COVER_ACTIVITIES
|
||||||
|
{ ACT_COVER_WALL_R, ACT_COVER_WALL_R_RIFLE, false },
|
||||||
|
{ ACT_COVER_WALL_L, ACT_COVER_WALL_L_RIFLE, false },
|
||||||
|
{ ACT_COVER_WALL_LOW_R, ACT_COVER_WALL_LOW_R_RIFLE, false },
|
||||||
|
{ ACT_COVER_WALL_LOW_L, ACT_COVER_WALL_LOW_L_RIFLE, false },
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
// HL2:DM activities (for third-person animations in SP)
|
// HL2:DM activities (for third-person animations in SP)
|
||||||
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false },
|
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false },
|
||||||
@ -161,6 +195,18 @@ acttable_t CWeaponAnnabelle::m_acttable[] =
|
|||||||
|
|
||||||
IMPLEMENT_ACTTABLE(CWeaponAnnabelle);
|
IMPLEMENT_ACTTABLE(CWeaponAnnabelle);
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
acttable_t* GetAnnabelleActtable()
|
||||||
|
{
|
||||||
|
return CWeaponAnnabelle::m_acttable;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetAnnabelleActtableCount()
|
||||||
|
{
|
||||||
|
return ARRAYSIZE(CWeaponAnnabelle::m_acttable);
|
||||||
|
}
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
void CWeaponAnnabelle::Precache( void )
|
void CWeaponAnnabelle::Precache( void )
|
||||||
{
|
{
|
||||||
CBaseCombatWeapon::Precache();
|
CBaseCombatWeapon::Precache();
|
||||||
|
@ -346,7 +346,7 @@ void CWeaponAR2::DelayedAttack( void )
|
|||||||
|
|
||||||
pOwner->SnapEyeAngles( angles );
|
pOwner->SnapEyeAngles( angles );
|
||||||
|
|
||||||
pOwner->ViewPunch( QAngle( random->RandomInt( -8, -12 ), random->RandomInt( 1, 2 ), 0 ) );
|
pOwner->ViewPunch( QAngle( random->RandomInt( -12, -8 ), random->RandomInt( 1, 2 ), 0 ) );
|
||||||
|
|
||||||
// Decrease ammo
|
// Decrease ammo
|
||||||
pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
|
pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
|
||||||
|
@ -762,6 +762,16 @@ acttable_t CWeaponCrossbow::m_acttable[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
IMPLEMENT_ACTTABLE(CWeaponCrossbow);
|
IMPLEMENT_ACTTABLE(CWeaponCrossbow);
|
||||||
|
|
||||||
|
acttable_t* GetCrossbowActtable()
|
||||||
|
{
|
||||||
|
return CWeaponCrossbow::m_acttable;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetCrossbowActtableCount()
|
||||||
|
{
|
||||||
|
return ARRAYSIZE(CWeaponCrossbow::m_acttable);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -68,6 +68,10 @@ ConVar player_throwforce( "player_throwforce", "1000" );
|
|||||||
ConVar physcannon_dmg_glass( "physcannon_dmg_glass", "15" );
|
ConVar physcannon_dmg_glass( "physcannon_dmg_glass", "15" );
|
||||||
ConVar physcannon_right_turrets( "physcannon_right_turrets", "0" );
|
ConVar physcannon_right_turrets( "physcannon_right_turrets", "0" );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVar sv_player_enable_propsprint("sv_player_enable_propsprint", "0", FCVAR_NONE, "If enabled, allows the player to sprint while holding a physics object" );
|
||||||
|
ConVar sv_player_enable_gravgun_sprint("sv_player_enable_gravgun_sprint", "0", FCVAR_NONE, "Enables the player to sprint while holding a phys. object with the gravity gun" );
|
||||||
|
#endif
|
||||||
extern ConVar hl2_normspeed;
|
extern ConVar hl2_normspeed;
|
||||||
extern ConVar hl2_walkspeed;
|
extern ConVar hl2_walkspeed;
|
||||||
|
|
||||||
@ -1043,10 +1047,20 @@ void CPlayerPickupController::Init( CBasePlayer *pPlayer, CBaseEntity *pObject )
|
|||||||
|
|
||||||
CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( pPlayer );
|
CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( pPlayer );
|
||||||
if ( pOwner )
|
if ( pOwner )
|
||||||
|
{
|
||||||
|
#ifndef MAPBASE
|
||||||
|
pOwner->EnableSprint( false );
|
||||||
|
#else
|
||||||
|
if ( sv_player_enable_propsprint.GetBool() == false )
|
||||||
{
|
{
|
||||||
pOwner->EnableSprint( false );
|
pOwner->EnableSprint( false );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pOwner->EnableSprint( true );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
// If the target is debris, convert it to non-debris
|
// If the target is debris, convert it to non-debris
|
||||||
if ( pObject->GetCollisionGroup() == COLLISION_GROUP_DEBRIS )
|
if ( pObject->GetCollisionGroup() == COLLISION_GROUP_DEBRIS )
|
||||||
{
|
{
|
||||||
@ -1102,10 +1116,17 @@ void CPlayerPickupController::Shutdown( bool bThrown )
|
|||||||
if ( m_pPlayer )
|
if ( m_pPlayer )
|
||||||
{
|
{
|
||||||
CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( m_pPlayer );
|
CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( m_pPlayer );
|
||||||
|
#ifndef MAPBASE
|
||||||
if ( pOwner )
|
if ( pOwner )
|
||||||
{
|
{
|
||||||
pOwner->EnableSprint( true );
|
pOwner->EnableSprint( true );
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if ( pOwner && sv_player_enable_propsprint.GetBool() == false )
|
||||||
|
{
|
||||||
|
pOwner->EnableSprint( true );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_pPlayer->SetUseEntity( NULL );
|
m_pPlayer->SetUseEntity( NULL );
|
||||||
if ( m_pPlayer->GetActiveWeapon() )
|
if ( m_pPlayer->GetActiveWeapon() )
|
||||||
@ -2497,6 +2518,7 @@ bool CWeaponPhysCannon::AttachObject( CBaseEntity *pObject, const Vector &vPosit
|
|||||||
// NVNT set the players constant force to simulate holding mass
|
// NVNT set the players constant force to simulate holding mass
|
||||||
HapticSetConstantForce(pOwner,clamp(m_grabController.GetLoadWeight()*0.05,1,5)*Vector(0,-1,0));
|
HapticSetConstantForce(pOwner,clamp(m_grabController.GetLoadWeight()*0.05,1,5)*Vector(0,-1,0));
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MAPBASE
|
||||||
pOwner->EnableSprint( false );
|
pOwner->EnableSprint( false );
|
||||||
|
|
||||||
float loadWeight = ( 1.0f - GetLoadPercentage() );
|
float loadWeight = ( 1.0f - GetLoadPercentage() );
|
||||||
@ -2504,6 +2526,22 @@ bool CWeaponPhysCannon::AttachObject( CBaseEntity *pObject, const Vector &vPosit
|
|||||||
|
|
||||||
//Msg( "Load perc: %f -- Movement speed: %f/%f\n", loadWeight, maxSpeed, hl2_normspeed.GetFloat() );
|
//Msg( "Load perc: %f -- Movement speed: %f/%f\n", loadWeight, maxSpeed, hl2_normspeed.GetFloat() );
|
||||||
pOwner->SetMaxSpeed( maxSpeed );
|
pOwner->SetMaxSpeed( maxSpeed );
|
||||||
|
#else
|
||||||
|
if ( sv_player_enable_gravgun_sprint.GetBool() == false )
|
||||||
|
{
|
||||||
|
pOwner->EnableSprint( false );
|
||||||
|
|
||||||
|
float loadWeight = ( 1.0f - GetLoadPercentage() );
|
||||||
|
float maxSpeed = hl2_walkspeed.GetFloat() + ( ( hl2_normspeed.GetFloat() - hl2_walkspeed.GetFloat() ) * loadWeight );
|
||||||
|
|
||||||
|
//Msg( "Load perc: %f -- Movement speed: %f/%f\n", loadWeight, maxSpeed, hl2_normspeed.GetFloat() );
|
||||||
|
pOwner->SetMaxSpeed( maxSpeed );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pOwner->EnableSprint( true );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't drop again for a slight delay, in case they were pulling objects near them
|
// Don't drop again for a slight delay, in case they were pulling objects near them
|
||||||
@ -2950,9 +2988,17 @@ void CWeaponPhysCannon::DetachObject( bool playSound, bool wasLaunched )
|
|||||||
CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( GetOwner() );
|
CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( GetOwner() );
|
||||||
if( pOwner != NULL )
|
if( pOwner != NULL )
|
||||||
{
|
{
|
||||||
|
#ifndef MAPBASE
|
||||||
pOwner->EnableSprint( true );
|
pOwner->EnableSprint( true );
|
||||||
pOwner->SetMaxSpeed( hl2_normspeed.GetFloat() );
|
pOwner->SetMaxSpeed( hl2_normspeed.GetFloat() );
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (sv_player_enable_gravgun_sprint.GetBool() == false)
|
||||||
|
{
|
||||||
|
pOwner->EnableSprint( true );
|
||||||
|
pOwner->SetMaxSpeed( hl2_normspeed.GetFloat() );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if( wasLaunched )
|
if( wasLaunched )
|
||||||
{
|
{
|
||||||
pOwner->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAG_RESTART );
|
pOwner->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAG_RESTART );
|
||||||
|
@ -526,6 +526,10 @@ bool CWeaponPistol::Reload( void )
|
|||||||
return fRet;
|
return fRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVar weapon_pistol_upwards_viewkick( "weapon_pistol_upwards_viewkick", "0" );
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -538,7 +542,11 @@ void CWeaponPistol::AddViewKick( void )
|
|||||||
|
|
||||||
QAngle viewPunch;
|
QAngle viewPunch;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
viewPunch.x = weapon_pistol_upwards_viewkick.GetBool() ? random->RandomFloat( -0.5f, -0.25f ) : random->RandomFloat( 0.25f, 0.5f );
|
||||||
|
#else
|
||||||
viewPunch.x = random->RandomFloat( 0.25f, 0.5f );
|
viewPunch.x = random->RandomFloat( 0.25f, 0.5f );
|
||||||
|
#endif
|
||||||
viewPunch.y = random->RandomFloat( -.6f, .6f );
|
viewPunch.y = random->RandomFloat( -.6f, .6f );
|
||||||
viewPunch.z = 0.0f;
|
viewPunch.z = 0.0f;
|
||||||
|
|
||||||
|
@ -3112,7 +3112,7 @@ void CLogicBranch::UpdateOnRemove()
|
|||||||
CBaseEntity *pEntity = m_Listeners.Element( i ).Get();
|
CBaseEntity *pEntity = m_Listeners.Element( i ).Get();
|
||||||
if ( pEntity )
|
if ( pEntity )
|
||||||
{
|
{
|
||||||
g_EventQueue.AddEvent( this, "_OnLogicBranchRemoved", 0, this, this );
|
g_EventQueue.AddEvent( pEntity, "_OnLogicBranchRemoved", 0, this, this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4059,7 +4059,7 @@ void CLogicFormat::FormatString(const char *szStringToFormat, char *szOutput, in
|
|||||||
curparam = atoi(szToken);
|
curparam = atoi(szToken);
|
||||||
if (curparam < MAX_LOGIC_FORMAT_PARAMETERS /*&& szParameters[curparam] != NULL*/) //if (curparam < MAX_FORMAT_PARAMETERS)
|
if (curparam < MAX_LOGIC_FORMAT_PARAMETERS /*&& szParameters[curparam] != NULL*/) //if (curparam < MAX_FORMAT_PARAMETERS)
|
||||||
{
|
{
|
||||||
Q_snprintf(szFormatted, sizeof(szFormatted), "%s%s", szFormatted, szParameters[curparam]);
|
Q_strncat(szFormatted, szParameters[curparam], sizeof(szFormatted));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4068,8 +4068,8 @@ void CLogicFormat::FormatString(const char *szStringToFormat, char *szOutput, in
|
|||||||
// This might not be the best way to do this, but
|
// This might not be the best way to do this, but
|
||||||
// reaching it is supposed to be the result of a mistake anyway.
|
// reaching it is supposed to be the result of a mistake anyway.
|
||||||
m_iszBackupParameter != NULL_STRING ?
|
m_iszBackupParameter != NULL_STRING ?
|
||||||
Q_snprintf(szFormatted, sizeof(szFormatted), "%s%s", szFormatted, STRING(m_iszBackupParameter)) :
|
Q_strncat( szFormatted, STRING(m_iszBackupParameter), sizeof( szFormatted ) ) :
|
||||||
Q_snprintf(szFormatted, sizeof(szFormatted), "%s<null>", szFormatted);
|
Q_strncat( szFormatted, "<null>", sizeof( szFormatted ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
inparam = false;
|
inparam = false;
|
||||||
@ -4077,7 +4077,7 @@ void CLogicFormat::FormatString(const char *szStringToFormat, char *szOutput, in
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Q_snprintf(szFormatted, sizeof(szFormatted), "%s%s", szFormatted, szToken);
|
Q_strncat( szFormatted, szToken, sizeof( szFormatted ) );
|
||||||
|
|
||||||
inparam = true;
|
inparam = true;
|
||||||
szToken = strtok(NULL, "}");
|
szToken = strtok(NULL, "}");
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "hl2_gamerules.h"
|
#include "hl2_gamerules.h"
|
||||||
#include "weapon_physcannon.h"
|
#include "weapon_physcannon.h"
|
||||||
#include "globalstate.h"
|
#include "globalstate.h"
|
||||||
|
#include "ai_hint.h"
|
||||||
|
|
||||||
#define COMBINE_AE_GREN_TOSS ( 7 )
|
#define COMBINE_AE_GREN_TOSS ( 7 )
|
||||||
|
|
||||||
@ -138,6 +139,8 @@ public:
|
|||||||
|
|
||||||
void ClearAttackConditions( void );
|
void ClearAttackConditions( void );
|
||||||
|
|
||||||
|
bool FValidateHintType( CAI_Hint *pHint );
|
||||||
|
|
||||||
Vector GetAltFireTarget() { return m_vecAltFireTarget; }
|
Vector GetAltFireTarget() { return m_vecAltFireTarget; }
|
||||||
virtual bool CanAltFireEnemy( bool bUseFreeKnowledge );
|
virtual bool CanAltFireEnemy( bool bUseFreeKnowledge );
|
||||||
void DelayAltFireAttack( float flDelay );
|
void DelayAltFireAttack( float flDelay );
|
||||||
@ -558,6 +561,29 @@ bool CAI_GrenadeUser<BASE_NPC>::CanThrowGrenade( const Vector &vecTarget )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHintCriteria hintCriteria;
|
||||||
|
hintCriteria.SetHintType( HINT_TACTICAL_GRENADE_THROW );
|
||||||
|
hintCriteria.SetFlag( bits_HINT_NPC_IN_NODE_FOV );
|
||||||
|
hintCriteria.SetGroup( this->GetHintGroup() );
|
||||||
|
hintCriteria.AddIncludePosition( this->GetAbsOrigin(), 1024 );
|
||||||
|
|
||||||
|
if (this->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)
|
||||||
|
hintCriteria.SetFlag( bits_HINT_NODE_REPORT_FAILURES );
|
||||||
|
|
||||||
|
// If there's a grenade throw hint nearby, try using it
|
||||||
|
CAI_Hint *pHint = CAI_HintManager::FindHint( this, vecTarget, hintCriteria );
|
||||||
|
if ( pHint )
|
||||||
|
{
|
||||||
|
if ( CheckCanThrowGrenade( pHint->GetAbsOrigin() ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DevMsg( this, "Unable to throw grenade at hint %s\n", pHint->GetDebugName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CheckCanThrowGrenade( vecTarget );
|
return CheckCanThrowGrenade( vecTarget );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,6 +662,18 @@ void CAI_GrenadeUser<BASE_NPC>::ClearAttackConditions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <class BASE_NPC>
|
||||||
|
bool CAI_GrenadeUser<BASE_NPC>::FValidateHintType( CAI_Hint *pHint )
|
||||||
|
{
|
||||||
|
if ( pHint->HintType() == HINT_TACTICAL_GRENADE_THROW )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return BaseClass::FValidateHintType( pHint );
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Drops grenades and alt-fire items on death. Based on code from npc_combines.cpp and npc_combine.cpp
|
// Purpose: Drops grenades and alt-fire items on death. Based on code from npc_combines.cpp and npc_combine.cpp
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
208
sp/src/game/server/mapbase/custom_weapon_factory.cpp
Normal file
208
sp/src/game/server/mapbase/custom_weapon_factory.cpp
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||||
|
//
|
||||||
|
// Purpose: The central manager of the custom weapons system.
|
||||||
|
//
|
||||||
|
// Author: Peter Covington (petercov@outlook.com)
|
||||||
|
//
|
||||||
|
//==================================================================================//
|
||||||
|
|
||||||
|
#include "cbase.h"
|
||||||
|
#include "custom_weapon_factory.h"
|
||||||
|
|
||||||
|
#define GENERIC_MANIFEST_FILE "scripts/mapbase_default_manifest.txt"
|
||||||
|
#define AUTOLOADED_MANIFEST_FILE UTIL_VarArgs("maps/%s_manifest.txt", STRING(gpGlobals->mapname))
|
||||||
|
#define GLOBAL_WEAPONS_MANIFEST "scripts/custom_weapon_manifest.txt"
|
||||||
|
|
||||||
|
extern ConVar mapbase_load_default_manifest;
|
||||||
|
|
||||||
|
IMPLEMENT_PRIVATE_SYMBOLTYPE(CustomWeaponSymbol);
|
||||||
|
|
||||||
|
CCustomWeaponSystem::CCustomWeaponSystem() : CAutoGameSystem("CustomWeaponFactorySystem")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::LevelInitPreEntity()
|
||||||
|
{
|
||||||
|
LoadCustomWeaponsManifest(GLOBAL_WEAPONS_MANIFEST);
|
||||||
|
|
||||||
|
// Check for a generic "mapname_manifest.txt" file and load it.
|
||||||
|
if (filesystem->FileExists(AUTOLOADED_MANIFEST_FILE, "GAME"))
|
||||||
|
{
|
||||||
|
AddManifestFile(AUTOLOADED_MANIFEST_FILE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load the generic script instead.
|
||||||
|
ParseGenericManifest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a generic, hardcoded manifest with hardcoded names.
|
||||||
|
void CCustomWeaponSystem::ParseGenericManifest()
|
||||||
|
{
|
||||||
|
if (!mapbase_load_default_manifest.GetBool())
|
||||||
|
return;
|
||||||
|
|
||||||
|
KeyValues* pKV = new KeyValues("DefaultManifest");
|
||||||
|
pKV->LoadFromFile(filesystem, GENERIC_MANIFEST_FILE);
|
||||||
|
|
||||||
|
AddManifestFile(pKV/*, true*/);
|
||||||
|
|
||||||
|
pKV->deleteThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::AddManifestFile(const char* file)
|
||||||
|
{
|
||||||
|
KeyValues* pKV = new KeyValues(file);
|
||||||
|
if (!pKV->LoadFromFile(filesystem, file))
|
||||||
|
{
|
||||||
|
Warning("Mapbase Manifest: \"%s\" is unreadable or missing (can't load KV, check for syntax errors)\n", file);
|
||||||
|
pKV->deleteThis();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGMsg(1, CON_GROUP_MAPBASE_MISC, "===== Mapbase Manifest: Loading manifest file %s =====\n", file);
|
||||||
|
|
||||||
|
AddManifestFile(pKV, false);
|
||||||
|
|
||||||
|
CGMsg(1, CON_GROUP_MAPBASE_MISC, "==============================================================================\n");
|
||||||
|
|
||||||
|
pKV->deleteThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::AddManifestFile(KeyValues* pKV, bool bDontWarn)
|
||||||
|
{
|
||||||
|
KeyValues* pKey = pKV->FindKey("weapons");
|
||||||
|
|
||||||
|
if (pKey)
|
||||||
|
{
|
||||||
|
char value[MAX_PATH];
|
||||||
|
value[0] = '\0';
|
||||||
|
|
||||||
|
// Parse %mapname%, etc.
|
||||||
|
bool inparam = false;
|
||||||
|
CUtlStringList outStrings;
|
||||||
|
V_SplitString(pKey->GetString(), "%", outStrings);
|
||||||
|
for (int i = 0; i < outStrings.Count(); i++)
|
||||||
|
{
|
||||||
|
if (inparam)
|
||||||
|
{
|
||||||
|
if (FStrEq(outStrings[i], "mapname"))
|
||||||
|
{
|
||||||
|
Q_strncat(value, STRING(gpGlobals->mapname), sizeof(value));
|
||||||
|
}
|
||||||
|
else if (FStrEq(outStrings[i], "language"))
|
||||||
|
{
|
||||||
|
#ifdef CLIENT_DLL
|
||||||
|
char uilanguage[64];
|
||||||
|
engine->GetUILanguage(uilanguage, sizeof(uilanguage));
|
||||||
|
Q_strncat(value, uilanguage, sizeof(value));
|
||||||
|
#else
|
||||||
|
// Give up, use English
|
||||||
|
Q_strncat(value, "english", sizeof(value));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_strncat(value, outStrings[i], sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
inparam = !inparam;
|
||||||
|
}
|
||||||
|
|
||||||
|
outStrings.PurgeAndDeleteElements();
|
||||||
|
bDontWarn = pKV->GetBool("NoErrors", bDontWarn);
|
||||||
|
|
||||||
|
LoadCustomWeaponsManifest(value, bDontWarn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Factory CustomWeaponsFactoryDictionary()
|
||||||
|
void CCustomWeaponSystem::LoadCustomWeaponsManifest(const char* file, bool bDontWarn)
|
||||||
|
{
|
||||||
|
KeyValuesAD pKV("weapons_manifest");
|
||||||
|
if (pKV->LoadFromFile(filesystem, file, "GAME"))
|
||||||
|
{
|
||||||
|
for (KeyValues *pkvWeapon = pKV->GetFirstValue(); pkvWeapon != nullptr; pkvWeapon = pkvWeapon->GetNextValue())
|
||||||
|
{
|
||||||
|
const char* pszClassname = pkvWeapon->GetName();
|
||||||
|
KeyValuesAD pkvWeaponScript("WeaponData");
|
||||||
|
if (pkvWeaponScript->LoadFromFile(filesystem, pkvWeapon->GetString(), "GAME"))
|
||||||
|
{
|
||||||
|
const char* pszFactory = pkvWeaponScript->GetString("custom_factory", nullptr);
|
||||||
|
unsigned short FactoryIndex = Factory.Find(pszFactory);
|
||||||
|
if (Factory.IsValidIndex(FactoryIndex))
|
||||||
|
{
|
||||||
|
auto* pFactory = Factory.Element(FactoryIndex);
|
||||||
|
const void* pData = pFactory->ParseDataFromWeaponFile(pkvWeaponScript);
|
||||||
|
if (!pData)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unsigned short ClassIndex = m_ClassFactories.Find(pszClassname);
|
||||||
|
if (!m_ClassFactories.IsValidIndex(ClassIndex))
|
||||||
|
{
|
||||||
|
ClassIndex = m_ClassFactories.Insert(pszClassname);
|
||||||
|
m_ClassFactories[ClassIndex].pOldFactory = EntityFactoryDictionary()->FindFactory(pszClassname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert(m_ClassFactories[ClassIndex].pNewFactory);
|
||||||
|
Assert(m_ClassFactories[ClassIndex].pData);
|
||||||
|
|
||||||
|
m_ClassFactories[ClassIndex].pNewFactory->ReleaseData(m_ClassFactories[ClassIndex].pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ClassFactories[ClassIndex].sDataFile = pkvWeapon->GetString();
|
||||||
|
m_ClassFactories[ClassIndex].pNewFactory = pFactory;
|
||||||
|
m_ClassFactories[ClassIndex].pData = pData;
|
||||||
|
EntityFactoryDictionary()->UninstallFactory(pszClassname);
|
||||||
|
EntityFactoryDictionary()->InstallFactory(m_ClassFactories[ClassIndex].pNewFactory, pszClassname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef Factory
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::LevelShutdownPostEntity()
|
||||||
|
{
|
||||||
|
for (unsigned short i = 0; i < m_ClassFactories.Count(); i++)
|
||||||
|
{
|
||||||
|
EntityFactoryDictionary()->UninstallFactory(m_ClassFactories.GetElementName(i));
|
||||||
|
const CustomClassName_t& entry = m_ClassFactories.Element(i);
|
||||||
|
if (entry.pOldFactory)
|
||||||
|
EntityFactoryDictionary()->InstallFactory(entry.pOldFactory, m_ClassFactories.GetElementName(i));
|
||||||
|
|
||||||
|
Assert(entry.pData);
|
||||||
|
entry.pNewFactory->ReleaseData(entry.pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ClassFactories.Purge();
|
||||||
|
g_CustomWeaponSymbolSymbolTable.RemoveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCustomWeaponSystem::ParseWeapon(CBaseCombatWeapon* pWeapon, const char* pClassName)
|
||||||
|
{
|
||||||
|
ICustomWeapon* pCustom = dynamic_cast<ICustomWeapon*> (pWeapon);
|
||||||
|
if (!pCustom)
|
||||||
|
return;
|
||||||
|
|
||||||
|
unsigned short i = m_ClassFactories.Find(pClassName);
|
||||||
|
if (!m_ClassFactories.IsValidIndex(i))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pCustom->InitCustomWeaponFromData(m_ClassFactories[i].pData, m_ClassFactories[i].sDataFile.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlDict<ICustomWeaponDataLoader*, unsigned short>& CustomWeaponsFactoryDictionary()
|
||||||
|
{
|
||||||
|
static CUtlDict<ICustomWeaponDataLoader*, unsigned short> dict;
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CCustomWeaponSystem g_CustomWeaponsSystem;
|
||||||
|
CCustomWeaponSystem* CustomWeaponSystem()
|
||||||
|
{
|
||||||
|
return &g_CustomWeaponsSystem;
|
||||||
|
}
|
117
sp/src/game/server/mapbase/custom_weapon_factory.h
Normal file
117
sp/src/game/server/mapbase/custom_weapon_factory.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||||
|
//
|
||||||
|
// Purpose: See custom_weapon_factory.cpp
|
||||||
|
//
|
||||||
|
// Author: Peter Covington (petercov@outlook.com)
|
||||||
|
//
|
||||||
|
//==================================================================================//
|
||||||
|
|
||||||
|
#ifndef CUSTOM_WEAPON_FACTORY_H
|
||||||
|
#define CUSTOM_WEAPON_FACTORY_H
|
||||||
|
#pragma once
|
||||||
|
#include "utldict.h"
|
||||||
|
#include "utlsymbol.h"
|
||||||
|
|
||||||
|
DECLARE_PRIVATE_SYMBOLTYPE(CustomWeaponSymbol);
|
||||||
|
|
||||||
|
class ICustomWeaponDataLoader : public IEntityFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const void* ParseDataFromWeaponFile(KeyValues* pKV) const = 0;
|
||||||
|
virtual void ReleaseData(const void* pData) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ICustomWeapon
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void InitCustomWeaponFromData(const void* pData, const char *pszWeaponScript) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCustomWeaponSystem : public CAutoGameSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCustomWeaponSystem();
|
||||||
|
|
||||||
|
// Level init, shutdown
|
||||||
|
virtual void LevelInitPreEntity();
|
||||||
|
virtual void LevelShutdownPostEntity();
|
||||||
|
|
||||||
|
void ParseWeapon(CBaseCombatWeapon* pWeapon, const char* pClassName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ParseGenericManifest();
|
||||||
|
void AddManifestFile(const char* file);
|
||||||
|
void AddManifestFile(KeyValues* pKV, bool bDontWarn = false);
|
||||||
|
void LoadCustomWeaponsManifest(const char* file, bool bDontWarn = false);
|
||||||
|
|
||||||
|
typedef struct CustomClassName_s
|
||||||
|
{
|
||||||
|
CustomWeaponSymbol sDataFile;
|
||||||
|
ICustomWeaponDataLoader* pNewFactory;
|
||||||
|
IEntityFactory* pOldFactory;
|
||||||
|
const void* pData;
|
||||||
|
} CustomClassName_t;
|
||||||
|
CUtlDict<CustomClassName_t, unsigned short> m_ClassFactories;
|
||||||
|
};
|
||||||
|
|
||||||
|
CCustomWeaponSystem* CustomWeaponSystem();
|
||||||
|
|
||||||
|
CUtlDict< ICustomWeaponDataLoader*, unsigned short >& CustomWeaponsFactoryDictionary();
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class CCustomWeaponEntityFactoryBase : public ICustomWeaponDataLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCustomWeaponEntityFactoryBase(const char* pFactoryClass)
|
||||||
|
{
|
||||||
|
CustomWeaponsFactoryDictionary().Insert(pFactoryClass, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
IServerNetworkable* Create(const char* pClassName)
|
||||||
|
{
|
||||||
|
T* pEnt = _CreateEntityTemplate((T*)NULL, pClassName);
|
||||||
|
CustomWeaponSystem()->ParseWeapon(pEnt, pClassName);
|
||||||
|
return pEnt->NetworkProp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Destroy(IServerNetworkable* pNetworkable)
|
||||||
|
{
|
||||||
|
if (pNetworkable)
|
||||||
|
{
|
||||||
|
pNetworkable->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t GetEntitySize()
|
||||||
|
{
|
||||||
|
return sizeof(T);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Entity, class Data>
|
||||||
|
class CDefaultCustomWeaponEntityFactory : public CCustomWeaponEntityFactoryBase<Entity>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CDefaultCustomWeaponEntityFactory(const char *pFactoryClass) : CCustomWeaponEntityFactoryBase<Entity>(pFactoryClass)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual const void* ParseDataFromWeaponFile(KeyValues* pKV) const
|
||||||
|
{
|
||||||
|
Data* pData = new Data;
|
||||||
|
if (pData && pData->Parse(pKV))
|
||||||
|
return pData;
|
||||||
|
|
||||||
|
delete pData;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void ReleaseData(const void* pData) const
|
||||||
|
{
|
||||||
|
delete pData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFINE_CUSTOM_WEAPON_FACTORY(factoryName, DLLClassName, DataStruct) \
|
||||||
|
static CDefaultCustomWeaponEntityFactory<DLLClassName, DataStruct> custom_weapon_##factoryName##_factory( #factoryName );
|
||||||
|
|
||||||
|
#endif // !CUSTOM_WEAPON_FACTORY_H
|
1546
sp/src/game/server/mapbase/weapon_custom_hl2.cpp
Normal file
1546
sp/src/game/server/mapbase/weapon_custom_hl2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -447,7 +447,8 @@ void CGameText::SetText( const char* pszStr )
|
|||||||
|
|
||||||
for (int i = 1; i < vecLines.Count(); i++)
|
for (int i = 1; i < vecLines.Count(); i++)
|
||||||
{
|
{
|
||||||
Q_snprintf( szMsg, sizeof( szMsg ), "%s\n%s", szMsg, vecLines[i] );
|
Q_strncat( szMsg, "\n", sizeof( szMsg ) );
|
||||||
|
Q_strncat( szMsg, vecLines[i], sizeof( szMsg ) );
|
||||||
}
|
}
|
||||||
m_iszMessage = AllocPooledString( szMsg );
|
m_iszMessage = AllocPooledString( szMsg );
|
||||||
}
|
}
|
||||||
|
@ -1557,6 +1557,16 @@ CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, con
|
|||||||
pRagdoll->CollisionProp()->SetCollisionBounds( mins, maxs );
|
pRagdoll->CollisionProp()->SetCollisionBounds( mins, maxs );
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
|
// If this was a NPC running a dynamic interaction, disable collisions with the interaction partner
|
||||||
|
if (pAnimating->IsNPC() /*&& pAnimating->MyNPCPointer()->IsRunningDynamicInteraction()*/)
|
||||||
|
{
|
||||||
|
CAI_BaseNPC *pNPC = pAnimating->MyNPCPointer();
|
||||||
|
if (pNPC->GetInteractionPartner() && pNPC->GetInteractionPartner()->VPhysicsGetObject())
|
||||||
|
{
|
||||||
|
PhysDisableEntityCollisions( pRagdoll, pNPC->GetInteractionPartner() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
variant_t variant;
|
variant_t variant;
|
||||||
variant.SetEntity(pRagdoll);
|
variant.SetEntity(pRagdoll);
|
||||||
pAnimating->FireNamedOutput("OnServerRagdoll", variant, pRagdoll, pAnimating);
|
pAnimating->FireNamedOutput("OnServerRagdoll", variant, pRagdoll, pAnimating);
|
||||||
|
@ -7021,7 +7021,7 @@ bool CBasePlayer::BumpWeapon( CBaseCombatWeapon *pWeapon )
|
|||||||
{
|
{
|
||||||
//Weapon_EquipAmmoOnly( pWeapon );
|
//Weapon_EquipAmmoOnly( pWeapon );
|
||||||
|
|
||||||
// I'm too lazy to make my own version of Weapon_EquipAmmoOnly that doesn't check if we already have the weapon first
|
// Weapon_EquipAmmoOnly checks the array again, which isn't necessary here
|
||||||
int primaryGiven = (pWeapon->UsesClipsForAmmo1()) ? pWeapon->m_iClip1 : pWeapon->GetPrimaryAmmoCount();
|
int primaryGiven = (pWeapon->UsesClipsForAmmo1()) ? pWeapon->m_iClip1 : pWeapon->GetPrimaryAmmoCount();
|
||||||
int secondaryGiven = (pWeapon->UsesClipsForAmmo2()) ? pWeapon->m_iClip2 : pWeapon->GetSecondaryAmmoCount();
|
int secondaryGiven = (pWeapon->UsesClipsForAmmo2()) ? pWeapon->m_iClip2 : pWeapon->GetSecondaryAmmoCount();
|
||||||
|
|
||||||
@ -7734,6 +7734,93 @@ void CBasePlayer::ResetAutoaim( void )
|
|||||||
m_fOnTarget = false;
|
m_fOnTarget = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVar player_debug_probable_aim_target( "player_debug_probable_aim_target", "0", FCVAR_CHEAT, "" );
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
CBaseEntity *CBasePlayer::GetProbableAimTarget( const Vector &vecSrc, const Vector &vecDir )
|
||||||
|
{
|
||||||
|
trace_t tr;
|
||||||
|
CBaseEntity *pIgnore = NULL;
|
||||||
|
if (IsInAVehicle())
|
||||||
|
pIgnore = GetVehicleEntity();
|
||||||
|
|
||||||
|
CTraceFilterSkipTwoEntities traceFilter( this, pIgnore, COLLISION_GROUP_NONE );
|
||||||
|
|
||||||
|
// Based on dot product and distance
|
||||||
|
// If we aim directly at something, only return it if there's not a larger entity slightly off-center
|
||||||
|
// Should be weighted based on whether an entity is a NPC, etc.
|
||||||
|
CBaseEntity *pBestEnt = NULL;
|
||||||
|
float flBestWeight = 0.0f;
|
||||||
|
for (CBaseEntity *pEntity = UTIL_EntitiesInPVS( this, NULL ); pEntity; pEntity = UTIL_EntitiesInPVS( this, pEntity ))
|
||||||
|
{
|
||||||
|
// Combat characters can be unviewable if they just died
|
||||||
|
if (!pEntity->IsViewable() && !pEntity->IsCombatCharacter())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pEntity == this || pEntity->GetMoveParent() == this || pEntity == GetVehicleEntity())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector vecEntDir = (pEntity->EyePosition() - vecSrc);
|
||||||
|
float flDot = DotProduct( vecEntDir.Normalized(), vecDir);
|
||||||
|
|
||||||
|
if (flDot < m_flFieldOfView)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Make sure we can see it
|
||||||
|
UTIL_TraceLine( vecSrc, pEntity->EyePosition(), MASK_SHOT, &traceFilter, &tr );
|
||||||
|
if (tr.m_pEnt != pEntity)
|
||||||
|
{
|
||||||
|
if (pEntity->IsCombatCharacter())
|
||||||
|
{
|
||||||
|
// Trace between centers as well just in case our eyes are blocked
|
||||||
|
UTIL_TraceLine( WorldSpaceCenter(), pEntity->WorldSpaceCenter(), MASK_SHOT, &traceFilter, &tr );
|
||||||
|
if (tr.m_pEnt != pEntity)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float flWeight = flDot - (vecEntDir.LengthSqr() / Square( 2048.0f ));
|
||||||
|
|
||||||
|
if (pEntity->IsCombatCharacter())
|
||||||
|
{
|
||||||
|
// Hostile NPCs are more likely targets
|
||||||
|
if (IRelationType( pEntity ) <= D_FR)
|
||||||
|
flWeight += 0.5f;
|
||||||
|
}
|
||||||
|
else if (pEntity->GetFlags() & FL_AIMTARGET)
|
||||||
|
{
|
||||||
|
// FL_AIMTARGET is often used for props like explosive barrels
|
||||||
|
flWeight += 0.25f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player_debug_probable_aim_target.GetBool())
|
||||||
|
{
|
||||||
|
float flWeightClamped = 1.0f - RemapValClamped( flWeight, -2.0f, 2.0f, 0.0f, 1.0f );
|
||||||
|
pEntity->EntityText( 0, UTIL_VarArgs( "%f", flWeight ), 2.0f, flWeightClamped * 255.0f, 255.0f, flWeightClamped * 255.0f, 255 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flWeight > flBestWeight)
|
||||||
|
{
|
||||||
|
pBestEnt = pEntity;
|
||||||
|
flBestWeight = flWeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player_debug_probable_aim_target.GetBool())
|
||||||
|
{
|
||||||
|
Msg( "Best probable aim target is %s\n", pBestEnt->GetDebugName() );
|
||||||
|
NDebugOverlay::EntityBounds( pBestEnt, 255, 100, 0, 0, 2.0f );
|
||||||
|
}
|
||||||
|
|
||||||
|
return pBestEnt;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// > Weapon stuff
|
// > Weapon stuff
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@ -608,6 +608,11 @@ public:
|
|||||||
virtual bool ShouldAutoaim( void );
|
virtual bool ShouldAutoaim( void );
|
||||||
void SetTargetInfo( Vector &vecSrc, float flDist );
|
void SetTargetInfo( Vector &vecSrc, float flDist );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Tries to figure out what the player is trying to aim at
|
||||||
|
CBaseEntity *GetProbableAimTarget( const Vector &vecSrc, const Vector &vecDir );
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetViewEntity( CBaseEntity *pEntity );
|
void SetViewEntity( CBaseEntity *pEntity );
|
||||||
CBaseEntity *GetViewEntity( void ) { return m_hViewEntity; }
|
CBaseEntity *GetViewEntity( void ) { return m_hViewEntity; }
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||||||
if ( weapon )
|
if ( weapon )
|
||||||
{
|
{
|
||||||
VPROF( "player->SelectItem()" );
|
VPROF( "player->SelectItem()" );
|
||||||
player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
|
player->SelectItem( weapon->GetClassname(), ucmd->weaponsubtype );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6308,14 +6308,12 @@ void CPropDoorRotating::Break( CBaseEntity *pBreaker, const CTakeDamageInfo &inf
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MAPBASE
|
|
||||||
void CPropDoorRotating::InputSetSpeed(inputdata_t &inputdata)
|
void CPropDoorRotating::InputSetSpeed(inputdata_t &inputdata)
|
||||||
{
|
{
|
||||||
AssertMsg1(inputdata.value.Float() > 0.0f, "InputSetSpeed on %s called with negative parameter!", GetDebugName() );
|
AssertMsg1(inputdata.value.Float() > 0.0f, "InputSetSpeed on %s called with negative parameter!", GetDebugName() );
|
||||||
m_flSpeed = inputdata.value.Float();
|
m_flSpeed = inputdata.value.Float();
|
||||||
DoorResume();
|
DoorResume();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Debug sphere
|
// Debug sphere
|
||||||
class CPhysSphere : public CPhysicsProp
|
class CPhysSphere : public CPhysicsProp
|
||||||
@ -6362,15 +6360,6 @@ BEGIN_DATADESC( CPhysSphere )
|
|||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MAPBASE // Yes, all I'm doing is moving this up a few lines and I'm still using the preprocessor.
|
|
||||||
void CPropDoorRotating::InputSetSpeed(inputdata_t &inputdata)
|
|
||||||
{
|
|
||||||
AssertMsg1(inputdata.value.Float() > 0.0f, "InputSetSpeed on %s called with negative parameter!", GetDebugName() );
|
|
||||||
m_flSpeed = inputdata.value.Float();
|
|
||||||
DoorResume();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LINK_ENTITY_TO_CLASS( prop_sphere, CPhysSphere );
|
LINK_ENTITY_TO_CLASS( prop_sphere, CPhysSphere );
|
||||||
|
|
||||||
|
|
||||||
|
@ -1396,11 +1396,31 @@ void CAI_ScriptedSequence::ModifyScriptedAutoMovement( Vector *vecNewPos )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VMatrix matInteractionPosition = m_matInteractionPosition;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Account for our own sequence movement
|
||||||
|
pAnimating = m_hTargetEnt->GetBaseAnimating();
|
||||||
|
if (pAnimating)
|
||||||
|
{
|
||||||
|
Vector vecDeltaPos;
|
||||||
|
QAngle angDeltaAngles;
|
||||||
|
|
||||||
|
pAnimating->GetSequenceMovement( pAnimating->GetSequence(), 0.0f, pAnimating->GetCycle(), vecDeltaPos, angDeltaAngles );
|
||||||
|
if (!vecDeltaPos.IsZero())
|
||||||
|
{
|
||||||
|
VMatrix matLocalMovement;
|
||||||
|
matLocalMovement.SetupMatrixOrgAngles( vecDeltaPos, angDeltaAngles );
|
||||||
|
MatrixMultiply( m_matInteractionPosition, matLocalMovement, matInteractionPosition );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// We've been asked to maintain a specific position relative to the other NPC
|
// We've been asked to maintain a specific position relative to the other NPC
|
||||||
// we're interacting with. Lerp towards the relative position.
|
// we're interacting with. Lerp towards the relative position.
|
||||||
VMatrix matMeToWorld, matLocalToWorld;
|
VMatrix matMeToWorld, matLocalToWorld;
|
||||||
matMeToWorld.SetupMatrixOrgAngles( vecRelativeOrigin, angRelativeAngles );
|
matMeToWorld.SetupMatrixOrgAngles( vecRelativeOrigin, angRelativeAngles );
|
||||||
MatrixMultiply( matMeToWorld, m_matInteractionPosition, matLocalToWorld );
|
MatrixMultiply( matMeToWorld, matInteractionPosition, matLocalToWorld );
|
||||||
|
|
||||||
// Get the desired NPC position in worldspace
|
// Get the desired NPC position in worldspace
|
||||||
Vector vecOrigin;
|
Vector vecOrigin;
|
||||||
|
@ -63,6 +63,8 @@ $Project
|
|||||||
$File "mapbase\ai_grenade.h"
|
$File "mapbase\ai_grenade.h"
|
||||||
$File "mapbase\ai_monitor.cpp"
|
$File "mapbase\ai_monitor.cpp"
|
||||||
$File "mapbase\ai_weaponmodifier.cpp"
|
$File "mapbase\ai_weaponmodifier.cpp"
|
||||||
|
$File "mapbase\custom_weapon_factory.cpp"
|
||||||
|
$File "mapbase\custom_weapon_factory.h"
|
||||||
$File "mapbase\closecaption_entity.cpp"
|
$File "mapbase\closecaption_entity.cpp"
|
||||||
$File "mapbase\datadesc_mod.cpp"
|
$File "mapbase\datadesc_mod.cpp"
|
||||||
$File "mapbase\datadesc_mod.h"
|
$File "mapbase\datadesc_mod.h"
|
||||||
@ -86,6 +88,7 @@ $Project
|
|||||||
$File "mapbase\SystemConvarMod.h"
|
$File "mapbase\SystemConvarMod.h"
|
||||||
$File "mapbase\variant_tools.h"
|
$File "mapbase\variant_tools.h"
|
||||||
$File "mapbase\vgui_text_display.cpp"
|
$File "mapbase\vgui_text_display.cpp"
|
||||||
|
$File "mapbase\weapon_custom_hl2.cpp"
|
||||||
|
|
||||||
$File "mapbase\logic_eventlistener.cpp"
|
$File "mapbase\logic_eventlistener.cpp"
|
||||||
$File "mapbase\logic_register_activator.cpp"
|
$File "mapbase\logic_register_activator.cpp"
|
||||||
|
@ -96,7 +96,7 @@ public:
|
|||||||
bool PointIsWithin( const Vector &vecPoint );
|
bool PointIsWithin( const Vector &vecPoint );
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
bool ScriptPassesTriggerFilters( HSCRIPT hOther ) { return ToEnt(hOther) ? PassesTriggerFilters( ToEnt(hOther) ) : NULL; }
|
bool ScriptPassesTriggerFilters( HSCRIPT hOther ) { return ToEnt(hOther) ? PassesTriggerFilters( ToEnt(hOther) ) : false; }
|
||||||
HSCRIPT ScriptGetTouchedEntityOfType( const char *sClassName ) { return ToHScript( GetTouchedEntityOfType(sClassName) ); }
|
HSCRIPT ScriptGetTouchedEntityOfType( const char *sClassName ) { return ToHScript( GetTouchedEntityOfType(sClassName) ); }
|
||||||
|
|
||||||
void ScriptGetTouchingEntities( HSCRIPT hTable );
|
void ScriptGetTouchingEntities( HSCRIPT hTable );
|
||||||
|
@ -76,6 +76,10 @@ public:
|
|||||||
virtual const char *GetCannonicalName( const char *pClassName );
|
virtual const char *GetCannonicalName( const char *pClassName );
|
||||||
void ReportEntitySizes();
|
void ReportEntitySizes();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void UninstallFactory(const char* pClassName);
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IEntityFactory *FindFactory( const char *pClassName );
|
IEntityFactory *FindFactory( const char *pClassName );
|
||||||
public:
|
public:
|
||||||
@ -203,6 +207,11 @@ void CEntityFactoryDictionary::ReportEntitySizes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
|
void CEntityFactoryDictionary::UninstallFactory(const char* pClassName)
|
||||||
|
{
|
||||||
|
m_Factories.Remove(pClassName);
|
||||||
|
}
|
||||||
|
|
||||||
int EntityFactory_AutoComplete( const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0 )
|
int EntityFactory_AutoComplete( const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0 )
|
||||||
{
|
{
|
||||||
CEntityFactoryDictionary *pFactoryDict = (CEntityFactoryDictionary*)EntityFactoryDictionary();
|
CEntityFactoryDictionary *pFactoryDict = (CEntityFactoryDictionary*)EntityFactoryDictionary();
|
||||||
|
@ -100,6 +100,9 @@ public:
|
|||||||
virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) = 0;
|
virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) = 0;
|
||||||
virtual IEntityFactory *FindFactory( const char *pClassName ) = 0;
|
virtual IEntityFactory *FindFactory( const char *pClassName ) = 0;
|
||||||
virtual const char *GetCannonicalName( const char *pClassName ) = 0;
|
virtual const char *GetCannonicalName( const char *pClassName ) = 0;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void UninstallFactory(const char* pClassName) = 0;
|
||||||
|
#endif // MAPBASE
|
||||||
};
|
};
|
||||||
|
|
||||||
IEntityFactoryDictionary *EntityFactoryDictionary();
|
IEntityFactoryDictionary *EntityFactoryDictionary();
|
||||||
@ -188,8 +191,7 @@ extern CGlobalVars *gpGlobals;
|
|||||||
inline bool FStrEq(const char *sz1, const char *sz2)
|
inline bool FStrEq(const char *sz1, const char *sz2)
|
||||||
{
|
{
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
// V_stricmp() already checks if the pointers are equal, so having a pointer comparison here is pointless.
|
// V_stricmp() already checks if the pointers are equal, so having a pointer comparison here is unnecessary.
|
||||||
// I'm not sure if this was already automatically phased out by the compiler, but if it wasn't, then this is a very good change.
|
|
||||||
return ( V_stricmp(sz1, sz2) == 0 );
|
return ( V_stricmp(sz1, sz2) == 0 );
|
||||||
#else
|
#else
|
||||||
return ( sz1 == sz2 || V_stricmp(sz1, sz2) == 0 );
|
return ( sz1 == sz2 || V_stricmp(sz1, sz2) == 0 );
|
||||||
|
@ -606,10 +606,10 @@ bool VScriptServerInit()
|
|||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
// MULTIPLAYER
|
// MULTIPLAYER
|
||||||
|
// NOTE: 'PlayerInstanceFromIndex' and 'GetPlayerFromUserID' are used in L4D2 and Source 2,
|
||||||
|
// but the GetPlayerBy* names are more consistent.
|
||||||
// ScriptRegisterFunctionNamed( g_pScriptVM, UTIL_PlayerByIndex, "GetPlayerByIndex", "PlayerInstanceFromIndex" );
|
// ScriptRegisterFunctionNamed( g_pScriptVM, UTIL_PlayerByIndex, "GetPlayerByIndex", "PlayerInstanceFromIndex" );
|
||||||
// ScriptRegisterFunctionNamed( g_pScriptVM, UTIL_PlayerByUserId, "GetPlayerByUserId", "GetPlayerFromUserID" );
|
// ScriptRegisterFunctionNamed( g_pScriptVM, UTIL_PlayerByUserId, "GetPlayerByUserID", "GetPlayerFromUserID" );
|
||||||
// ScriptRegisterFunctionNamed( g_pScriptVM, UTIL_PlayerByName, "GetPlayerByName", "" );
|
|
||||||
// ScriptRegisterFunctionNamed( g_pScriptVM, ScriptGetPlayerByNetworkID, "GetPlayerByNetworkID", "" );
|
|
||||||
|
|
||||||
ScriptRegisterFunctionNamed( g_pScriptVM, UTIL_ShowMessageAll, "ShowMessage", "Print a hud message on all clients" );
|
ScriptRegisterFunctionNamed( g_pScriptVM, UTIL_ShowMessageAll, "ShowMessage", "Print a hud message on all clients" );
|
||||||
#else
|
#else
|
||||||
@ -841,6 +841,8 @@ public:
|
|||||||
virtual void LevelShutdownPostEntity( void )
|
virtual void LevelShutdownPostEntity( void )
|
||||||
{
|
{
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
g_ScriptEntityIterator.DisableEntityListening();
|
||||||
|
|
||||||
g_ScriptNetMsg->LevelShutdownPreVM();
|
g_ScriptNetMsg->LevelShutdownPreVM();
|
||||||
|
|
||||||
GetScriptHookManager().OnShutdown();
|
GetScriptHookManager().OnShutdown();
|
||||||
|
@ -239,7 +239,7 @@ const unsigned char *CBaseCombatWeapon::GetEncryptionKey( void )
|
|||||||
void CBaseCombatWeapon::Precache( void )
|
void CBaseCombatWeapon::Precache( void )
|
||||||
{
|
{
|
||||||
#if defined( CLIENT_DLL )
|
#if defined( CLIENT_DLL )
|
||||||
Assert( Q_strlen( GetClassname() ) > 0 );
|
Assert( Q_strlen(GetWeaponScriptName() ) > 0 );
|
||||||
// Msg( "Client got %s\n", GetClassname() );
|
// Msg( "Client got %s\n", GetClassname() );
|
||||||
#endif
|
#endif
|
||||||
m_iPrimaryAmmoType = m_iSecondaryAmmoType = -1;
|
m_iPrimaryAmmoType = m_iSecondaryAmmoType = -1;
|
||||||
@ -321,7 +321,7 @@ void CBaseCombatWeapon::Precache( void )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Couldn't read data file, remove myself
|
// Couldn't read data file, remove myself
|
||||||
Warning( "Error reading weapon data file for: %s\n", GetClassname() );
|
Warning( "Error reading weapon data file for: %s\n", GetWeaponScriptName() );
|
||||||
// Remove( ); //don't remove, this gets released soon!
|
// Remove( ); //don't remove, this gets released soon!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2886,6 +2886,15 @@ bool CBaseCombatWeapon::IsLocked( CBaseEntity *pAsker )
|
|||||||
return ( m_flUnlockTime > gpGlobals->curtime && m_hLocker != pAsker );
|
return ( m_flUnlockTime > gpGlobals->curtime && m_hLocker != pAsker );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBaseCombatWeapon::CanBePickedUpByNPCs(void)
|
||||||
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
return GetWpnData().m_nWeaponRestriction != WPNRESTRICT_PLAYER_ONLY;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif // MAPBASE
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
// Input :
|
// Input :
|
||||||
|
@ -390,7 +390,7 @@ public:
|
|||||||
bool IsLocked( CBaseEntity *pAsker );
|
bool IsLocked( CBaseEntity *pAsker );
|
||||||
|
|
||||||
//All weapons can be picked up by NPCs by default
|
//All weapons can be picked up by NPCs by default
|
||||||
virtual bool CanBePickedUpByNPCs( void ) { return true; }
|
virtual bool CanBePickedUpByNPCs(void);
|
||||||
|
|
||||||
virtual int GetSkinOverride() const { return -1; }
|
virtual int GetSkinOverride() const { return -1; }
|
||||||
|
|
||||||
|
@ -83,6 +83,10 @@ ConVar ai_shot_bias_min( "ai_shot_bias_min", "-1.0", FCVAR_REPLICATED );
|
|||||||
ConVar ai_shot_bias_max( "ai_shot_bias_max", "1.0", FCVAR_REPLICATED );
|
ConVar ai_shot_bias_max( "ai_shot_bias_max", "1.0", FCVAR_REPLICATED );
|
||||||
ConVar ai_debug_shoot_positions( "ai_debug_shoot_positions", "0", FCVAR_REPLICATED | FCVAR_CHEAT );
|
ConVar ai_debug_shoot_positions( "ai_debug_shoot_positions", "0", FCVAR_REPLICATED | FCVAR_CHEAT );
|
||||||
|
|
||||||
|
#if defined(MAPBASE) && defined(GAME_DLL)
|
||||||
|
ConVar ai_shot_notify_targets( "ai_shot_notify_targets", "0", FCVAR_NONE, "Allows fired bullets to notify the NPCs and players they are targeting, regardless of whether they hit them or not. Can be used for custom AI and speech." );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Utility func to throttle rate at which the "reasonable position" spew goes out
|
// Utility func to throttle rate at which the "reasonable position" spew goes out
|
||||||
static double s_LastEntityReasonableEmitTime;
|
static double s_LastEntityReasonableEmitTime;
|
||||||
bool CheckEmitReasonablePhysicsSpew()
|
bool CheckEmitReasonablePhysicsSpew()
|
||||||
@ -2081,6 +2085,25 @@ void CBaseEntity::FireBullets( const FireBulletsInfo_t &info )
|
|||||||
CTakeDamageInfo dmgInfo( this, pAttacker, flCumulativeDamage, nDamageType );
|
CTakeDamageInfo dmgInfo( this, pAttacker, flCumulativeDamage, nDamageType );
|
||||||
gamestats->Event_WeaponHit( pPlayer, info.m_bPrimaryAttack, pPlayer->GetActiveWeapon()->GetClassname(), dmgInfo );
|
gamestats->Event_WeaponHit( pPlayer, info.m_bPrimaryAttack, pPlayer->GetActiveWeapon()->GetClassname(), dmgInfo );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( ai_shot_notify_targets.GetBool() )
|
||||||
|
{
|
||||||
|
if ( IsPlayer() )
|
||||||
|
{
|
||||||
|
// Look for probable target to notify of attack
|
||||||
|
CBaseEntity *pAimTarget = static_cast<CBasePlayer*>(this)->GetProbableAimTarget( info.m_vecSrc, info.m_vecDirShooting );
|
||||||
|
if ( pAimTarget && pAimTarget->IsCombatCharacter() )
|
||||||
|
{
|
||||||
|
pAimTarget->MyCombatCharacterPointer()->OnEnemyRangeAttackedMe( this, vecDir, vecEnd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( GetEnemy() && GetEnemy()->IsCombatCharacter() )
|
||||||
|
{
|
||||||
|
GetEnemy()->MyCombatCharacterPointer()->OnEnemyRangeAttackedMe( this, vecDir, vecEnd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2736,6 +2759,18 @@ void CBaseEntity::SetScriptOwnerEntity(HSCRIPT pOwner)
|
|||||||
SetOwnerEntity(ToEnt(pOwner));
|
SetOwnerEntity(ToEnt(pOwner));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
HSCRIPT CBaseEntity::ScriptGetGroundEntity()
|
||||||
|
{
|
||||||
|
return ToHScript( m_hGroundEntity.Get() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBaseEntity::ScriptSetGroundEntity( HSCRIPT hGroundEnt )
|
||||||
|
{
|
||||||
|
SetGroundEntity( ToEnt( hGroundEnt ) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
const Vector& CBaseEntity::ScriptGetColorVector()
|
const Vector& CBaseEntity::ScriptGetColorVector()
|
||||||
|
@ -233,6 +233,11 @@ void EventList_RegisterSharedEvents( void )
|
|||||||
REGISTER_SHARED_ANIMEVENT( AE_SV_DUSTTRAIL, AE_TYPE_SERVER );
|
REGISTER_SHARED_ANIMEVENT( AE_SV_DUSTTRAIL, AE_TYPE_SERVER );
|
||||||
|
|
||||||
REGISTER_SHARED_ANIMEVENT( AE_CL_CREATE_PARTICLE_EFFECT, AE_TYPE_CLIENT );
|
REGISTER_SHARED_ANIMEVENT( AE_CL_CREATE_PARTICLE_EFFECT, AE_TYPE_CLIENT );
|
||||||
|
#ifdef MAPBASE // From Alien Swarm SDK
|
||||||
|
REGISTER_SHARED_ANIMEVENT( AE_CL_STOP_PARTICLE_EFFECT, AE_TYPE_CLIENT );
|
||||||
|
REGISTER_SHARED_ANIMEVENT( AE_CL_ADD_PARTICLE_EFFECT_CP, AE_TYPE_CLIENT );
|
||||||
|
//REGISTER_SHARED_ANIMEVENT( AE_CL_CREATE_PARTICLE_BRASS, AE_TYPE_CLIENT );
|
||||||
|
#endif
|
||||||
|
|
||||||
REGISTER_SHARED_ANIMEVENT( AE_RAGDOLL, AE_TYPE_SERVER );
|
REGISTER_SHARED_ANIMEVENT( AE_RAGDOLL, AE_TYPE_SERVER );
|
||||||
|
|
||||||
@ -252,5 +257,8 @@ void EventList_RegisterSharedEvents( void )
|
|||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
REGISTER_SHARED_ANIMEVENT( AE_NPC_RESPONSE, AE_TYPE_SERVER );
|
REGISTER_SHARED_ANIMEVENT( AE_NPC_RESPONSE, AE_TYPE_SERVER );
|
||||||
REGISTER_SHARED_ANIMEVENT( AE_NPC_RESPONSE_FORCED, AE_TYPE_SERVER );
|
REGISTER_SHARED_ANIMEVENT( AE_NPC_RESPONSE_FORCED, AE_TYPE_SERVER );
|
||||||
|
|
||||||
|
REGISTER_SHARED_ANIMEVENT( AE_VSCRIPT_RUN, AE_TYPE_CLIENT | AE_TYPE_SERVER );
|
||||||
|
REGISTER_SHARED_ANIMEVENT( AE_VSCRIPT_RUN_FILE, AE_TYPE_CLIENT | AE_TYPE_SERVER );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
@ -69,6 +69,11 @@ typedef enum
|
|||||||
AE_SV_DUSTTRAIL,
|
AE_SV_DUSTTRAIL,
|
||||||
|
|
||||||
AE_CL_CREATE_PARTICLE_EFFECT,
|
AE_CL_CREATE_PARTICLE_EFFECT,
|
||||||
|
#ifdef MAPBASE // From Alien Swarm SDK
|
||||||
|
AE_CL_STOP_PARTICLE_EFFECT,
|
||||||
|
AE_CL_ADD_PARTICLE_EFFECT_CP,
|
||||||
|
//AE_CL_CREATE_PARTICLE_BRASS,
|
||||||
|
#endif
|
||||||
|
|
||||||
AE_RAGDOLL,
|
AE_RAGDOLL,
|
||||||
|
|
||||||
@ -88,6 +93,9 @@ typedef enum
|
|||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
AE_NPC_RESPONSE, // Play a response system concept if we're not speaking
|
AE_NPC_RESPONSE, // Play a response system concept if we're not speaking
|
||||||
AE_NPC_RESPONSE_FORCED, // Always play a response system concept
|
AE_NPC_RESPONSE_FORCED, // Always play a response system concept
|
||||||
|
|
||||||
|
AE_VSCRIPT_RUN, // Run vscript code (server + client)
|
||||||
|
AE_VSCRIPT_RUN_FILE, // Run vscript file (server + client)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LAST_SHARED_ANIMEVENT,
|
LAST_SHARED_ANIMEVENT,
|
||||||
|
@ -208,7 +208,7 @@ void CWeaponAR2::DelayedAttack( void )
|
|||||||
|
|
||||||
// pOwner->SnapEyeAngles( angles );
|
// pOwner->SnapEyeAngles( angles );
|
||||||
|
|
||||||
pOwner->ViewPunch( QAngle( SharedRandomInt( "ar2pax", -8, -12 ), SharedRandomInt( "ar2pay", 1, 2 ), 0 ) );
|
pOwner->ViewPunch( QAngle( SharedRandomInt( "ar2pax", -12, -8 ), SharedRandomInt( "ar2pay", 1, 2 ), 0 ) );
|
||||||
|
|
||||||
// Decrease ammo
|
// Decrease ammo
|
||||||
pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
|
pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType );
|
||||||
|
@ -70,7 +70,7 @@ ConVar mapbase_version_client( "mapbase_version_client", MAPBASE_VERSION, FCVAR_
|
|||||||
// This is from the vgui_controls library
|
// This is from the vgui_controls library
|
||||||
extern vgui::HScheme g_iCustomClientSchemeOverride;
|
extern vgui::HScheme g_iCustomClientSchemeOverride;
|
||||||
|
|
||||||
bool g_bUsingCustomHudAnimations = false;
|
extern bool g_bUsingCustomHudAnimations;
|
||||||
bool g_bUsingCustomHudLayout = false;
|
bool g_bUsingCustomHudLayout = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "igameevents.h"
|
#include "igameevents.h"
|
||||||
#include "engine/ivdebugoverlay.h"
|
#include "engine/ivdebugoverlay.h"
|
||||||
|
#include "icommandline.h"
|
||||||
|
|
||||||
#ifdef CLIENT_DLL
|
#ifdef CLIENT_DLL
|
||||||
#include "IEffects.h"
|
#include "IEffects.h"
|
||||||
@ -1094,7 +1095,7 @@ const char *CScriptReadWriteFile::FileRead( const char *szFile )
|
|||||||
char pszFullName[MAX_PATH];
|
char pszFullName[MAX_PATH];
|
||||||
V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile );
|
V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile );
|
||||||
|
|
||||||
if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) )
|
if ( !CommandLine()->FindParm( "-script_dotslash_read" ) && !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) )
|
||||||
{
|
{
|
||||||
DevWarning( 2, "Invalid file location : %s\n", szFile );
|
DevWarning( 2, "Invalid file location : %s\n", szFile );
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1143,7 +1144,7 @@ bool CScriptReadWriteFile::FileExists( const char *szFile )
|
|||||||
char pszFullName[MAX_PATH];
|
char pszFullName[MAX_PATH];
|
||||||
V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile );
|
V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile );
|
||||||
|
|
||||||
if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) )
|
if ( !CommandLine()->FindParm( "-script_dotslash_read" ) && !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) )
|
||||||
{
|
{
|
||||||
DevWarning( 2, "Invalid file location : %s\n", szFile );
|
DevWarning( 2, "Invalid file location : %s\n", szFile );
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1224,7 +1225,7 @@ HSCRIPT CScriptReadWriteFile::KeyValuesRead( const char *szFile )
|
|||||||
char pszFullName[MAX_PATH];
|
char pszFullName[MAX_PATH];
|
||||||
V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile );
|
V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile );
|
||||||
|
|
||||||
if ( !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) )
|
if ( !CommandLine()->FindParm( "-script_dotslash_read" ) && !V_RemoveDotSlashes( pszFullName, CORRECT_PATH_SEPARATOR, true ) )
|
||||||
{
|
{
|
||||||
DevWarning( 2, "Invalid file location : %s\n", szFile );
|
DevWarning( 2, "Invalid file location : %s\n", szFile );
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1338,8 +1339,7 @@ static const char *HasNetMsgCollision( int hash, const char *ignore )
|
|||||||
|
|
||||||
inline int CNetMsgScriptHelper::Hash( const char *key )
|
inline int CNetMsgScriptHelper::Hash( const char *key )
|
||||||
{
|
{
|
||||||
int hash = HashStringCaseless( key );
|
int hash = CaselessStringHashFunctor()( key );
|
||||||
Assert( hash < (1 << SCRIPT_NETMSG_HEADER_BITS) );
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1445,7 +1445,7 @@ void CNetMsgScriptHelper::ReceiveMessage( bf_read &msg )
|
|||||||
while ( count-- )
|
while ( count-- )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int hash = m_MsgIn_()ReadWord();
|
int hash = m_MsgIn_()ReadUBitLong( SCRIPT_NETMSG_HEADER_BITS );
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
const char *msgName = GetNetMsgName( hash );
|
const char *msgName = GetNetMsgName( hash );
|
||||||
@ -1514,7 +1514,7 @@ void CNetMsgScriptHelper::Start( const char *msg )
|
|||||||
Reset();
|
Reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_MsgOut.WriteWord( Hash( msg ) );
|
m_MsgOut.WriteUBitLong( Hash( msg ), SCRIPT_NETMSG_HEADER_BITS );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GAME_DLL
|
#ifdef GAME_DLL
|
||||||
@ -1923,7 +1923,7 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CNetMsgScriptHelper, "CNetMsg", SCRIPT_SINGLETON "N
|
|||||||
DEFINE_SCRIPTFUNC( Receive, "Set custom network message callback" )
|
DEFINE_SCRIPTFUNC( Receive, "Set custom network message callback" )
|
||||||
DEFINE_SCRIPTFUNC_NAMED( Receive, "Recieve", SCRIPT_HIDE ) // This was a typo until v6.3
|
DEFINE_SCRIPTFUNC_NAMED( Receive, "Recieve", SCRIPT_HIDE ) // This was a typo until v6.3
|
||||||
#ifdef GAME_DLL
|
#ifdef GAME_DLL
|
||||||
DEFINE_SCRIPTFUNC( Send, "Send a custom network message from the server to the client (max 252 bytes)" )
|
DEFINE_SCRIPTFUNC( Send, "Send a custom network message from the server to the client (max 251 bytes)" )
|
||||||
#else
|
#else
|
||||||
DEFINE_SCRIPTFUNC( Send, "Send a custom network message from the client to the server (max 2044 bytes)" )
|
DEFINE_SCRIPTFUNC( Send, "Send a custom network message from the client to the server (max 2044 bytes)" )
|
||||||
#endif
|
#endif
|
||||||
@ -2742,6 +2742,11 @@ public:
|
|||||||
|
|
||||||
void CScriptConvarAccessor::RegisterCommand( const char *name, HSCRIPT fn, const char *helpString, int flags )
|
void CScriptConvarAccessor::RegisterCommand( const char *name, HSCRIPT fn, const char *helpString, int flags )
|
||||||
{
|
{
|
||||||
|
#if CLIENT_DLL
|
||||||
|
// FIXME: This crashes in engine when used as a hook (dispatched from CScriptConCommand::CommandCallback())
|
||||||
|
Assert( V_stricmp( name, "load" ) != 0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned int hash = Hash(name);
|
unsigned int hash = Hash(name);
|
||||||
int idx = g_ScriptConCommands.Find(hash);
|
int idx = g_ScriptConCommands.Find(hash);
|
||||||
if ( idx == g_ScriptConCommands.InvalidIndex() )
|
if ( idx == g_ScriptConCommands.InvalidIndex() )
|
||||||
|
@ -24,7 +24,7 @@ void RegisterScriptSingletons();
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SCRIPT_NETMSG_QUEUE_BITS 3 // determines the number of custom messages client can write to a usercmd
|
#define SCRIPT_NETMSG_QUEUE_BITS 3 // determines the number of custom messages client can write to a usercmd
|
||||||
#define SCRIPT_NETMSG_HEADER_BITS (sizeof(word) << 3)
|
#define SCRIPT_NETMSG_HEADER_BITS (sizeof(unsigned int) << 3)
|
||||||
#define SCRIPT_NETMSG_STRING_SIZE 512
|
#define SCRIPT_NETMSG_STRING_SIZE 512
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "cbase.h"
|
#include "cbase.h"
|
||||||
#include "tier1/fmtstr.h"
|
#include "tier1/fmtstr.h"
|
||||||
|
#include "tier1/utlvector.h"
|
||||||
#include "weapon_custom_scripted.h"
|
#include "weapon_custom_scripted.h"
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
@ -179,7 +180,7 @@ bool CWeaponCustomScripted::RunWeaponHook( ScriptHook_t &hook, HSCRIPT &cached,
|
|||||||
{
|
{
|
||||||
if ( !cached )
|
if ( !cached )
|
||||||
{
|
{
|
||||||
if ( hook.CanRunInScope( m_ScriptScope ) )
|
if ( m_ScriptScope.IsInitialized() && hook.CanRunInScope( m_ScriptScope ) )
|
||||||
{
|
{
|
||||||
cached = hook.m_hFunc;
|
cached = hook.m_hFunc;
|
||||||
}
|
}
|
||||||
@ -187,6 +188,7 @@ bool CWeaponCustomScripted::RunWeaponHook( ScriptHook_t &hook, HSCRIPT &cached,
|
|||||||
|
|
||||||
if (cached)
|
if (cached)
|
||||||
{
|
{
|
||||||
|
hook.m_hFunc = cached;
|
||||||
return hook.Call( m_ScriptScope, retVal, pArgs, false );
|
return hook.Call( m_ScriptScope, retVal, pArgs, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,13 +200,6 @@ bool CWeaponCustomScripted::RunWeaponHook( ScriptHook_t &hook, HSCRIPT &cached,
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CWeaponCustomScripted::Spawn( void )
|
void CWeaponCustomScripted::Spawn( void )
|
||||||
{
|
{
|
||||||
#ifdef CLIENT_DLL
|
|
||||||
if (m_iszClientScripts[0] != '\0' && ValidateScriptScope())
|
|
||||||
{
|
|
||||||
RunScriptFile( m_iszClientScripts );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BaseClass::Spawn();
|
BaseClass::Spawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,7 +329,7 @@ void CWeaponCustomScripted::ItemPreFrame( void )
|
|||||||
{
|
{
|
||||||
SIMPLE_VOID_OVERRIDE( ItemPreFrame, NULL );
|
SIMPLE_VOID_OVERRIDE( ItemPreFrame, NULL );
|
||||||
|
|
||||||
BaseClass::ItemPostFrame();
|
BaseClass::ItemPreFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWeaponCustomScripted::ItemPostFrame( void )
|
void CWeaponCustomScripted::ItemPostFrame( void )
|
||||||
@ -432,7 +427,7 @@ void CWeaponCustomScripted::SecondaryAttack( void )
|
|||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define ACTIVITY_FUNC_OVERRIDE( name ) ScriptVariant_t retVal; \
|
#define ACTIVITY_FUNC_OVERRIDE( name ) ScriptVariant_t retVal; \
|
||||||
if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal ) && retVal.m_bool == false) \
|
if (RunWeaponHook( g_Hook_##name, m_Func_##name, &retVal ) && !retVal.IsNull()) \
|
||||||
{ \
|
{ \
|
||||||
if (retVal.m_type == FIELD_INTEGER) \
|
if (retVal.m_type == FIELD_INTEGER) \
|
||||||
{ \
|
{ \
|
||||||
@ -586,6 +581,36 @@ int CWeaponCustomScripted::WeaponMeleeAttack2Condition( float flDot, float flDis
|
|||||||
|
|
||||||
return BaseClass::WeaponMeleeAttack2Condition( flDot, flDist );
|
return BaseClass::WeaponMeleeAttack2Condition( flDot, flDist );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VScriptWeaponCustomData_s
|
||||||
|
{
|
||||||
|
char cScripts[256];
|
||||||
|
|
||||||
|
bool Parse(KeyValues* pKVWeapon)
|
||||||
|
{
|
||||||
|
Q_strncpy(cScripts, pKVWeapon->GetString("vscript_file"), 256);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_CUSTOM_WEAPON_FACTORY(vscript, CWeaponCustomScripted, VScriptWeaponCustomData_s);
|
||||||
|
void CWeaponCustomScripted::InitCustomWeaponFromData(const void* pData, const char* pszWeaponScript)
|
||||||
|
{
|
||||||
|
Q_FileBase(pszWeaponScript, m_iszWeaponScriptName.GetForModify(), 256);
|
||||||
|
Q_strncpy(m_iszClientScripts.GetForModify(), static_cast<const VScriptWeaponCustomData_s *> (pData)->cScripts, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern ConVar sv_script_think_interval;
|
||||||
|
#else
|
||||||
|
void CWeaponCustomScripted::OnDataChanged(DataUpdateType_t type)
|
||||||
|
{
|
||||||
|
BaseClass::OnDataChanged(type);
|
||||||
|
|
||||||
|
if (!m_ScriptScope.IsInitialized())
|
||||||
|
{
|
||||||
|
RunVScripts();
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -604,3 +629,96 @@ int CWeaponCustomScripted::ActivityListCount( void )
|
|||||||
|
|
||||||
return BaseClass::ActivityListCount();
|
return BaseClass::ActivityListCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWeaponCustomScripted::RunVScripts()
|
||||||
|
{
|
||||||
|
#ifdef CLIENT_DLL
|
||||||
|
if (m_iszClientScripts[0] != '\0' && ValidateScriptScope())
|
||||||
|
{
|
||||||
|
RunScriptFile(m_iszClientScripts);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (m_iszVScripts == NULL_STRING && m_iszClientScripts[0] == '\0')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
if (g_pScriptVM == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ValidateScriptScope();
|
||||||
|
|
||||||
|
// All functions we want to have call chained instead of overwritten
|
||||||
|
// by other scripts in this entities list.
|
||||||
|
static const char* sCallChainFunctions[] =
|
||||||
|
{
|
||||||
|
"OnPostSpawn",
|
||||||
|
"Precache"
|
||||||
|
};
|
||||||
|
|
||||||
|
ScriptLanguage_t language = g_pScriptVM->GetLanguage();
|
||||||
|
|
||||||
|
// Make a call chainer for each in this entities scope
|
||||||
|
for (int j = 0; j < ARRAYSIZE(sCallChainFunctions); ++j)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (language == SL_PYTHON)
|
||||||
|
{
|
||||||
|
// UNDONE - handle call chaining in python
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else if (language == SL_SQUIRREL)
|
||||||
|
{
|
||||||
|
//TODO: For perf, this should be precompiled and the %s should be passed as a parameter
|
||||||
|
HSCRIPT hCreateChainScript = g_pScriptVM->CompileScript(CFmtStr("%sCallChain <- CSimpleCallChainer(\"%s\", self.GetScriptScope(), true)", sCallChainFunctions[j], sCallChainFunctions[j]));
|
||||||
|
g_pScriptVM->Run(hCreateChainScript, (HSCRIPT)m_ScriptScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlStringList szScripts;
|
||||||
|
if (m_iszVScripts != NULL_STRING)
|
||||||
|
{
|
||||||
|
V_SplitString(STRING(m_iszVScripts), " ", szScripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_iszClientScripts[0] != '\0')
|
||||||
|
{
|
||||||
|
szScripts.AddToHead(strdup(m_iszClientScripts.Get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < szScripts.Count(); i++)
|
||||||
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CGMsg(0, CON_GROUP_VSCRIPT, "%s executing script: %s\n", GetDebugName(), szScripts[i]);
|
||||||
|
#else
|
||||||
|
Log("%s executing script: %s\n", GetDebugName(), szScripts[i]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RunScriptFile(szScripts[i], IsWorld());
|
||||||
|
|
||||||
|
for (int j = 0; j < ARRAYSIZE(sCallChainFunctions); ++j)
|
||||||
|
{
|
||||||
|
if (language == SL_PYTHON)
|
||||||
|
{
|
||||||
|
// UNDONE - handle call chaining in python
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else if (language == SL_SQUIRREL)
|
||||||
|
{
|
||||||
|
//TODO: For perf, this should be precompiled and the %s should be passed as a parameter.
|
||||||
|
HSCRIPT hRunPostScriptExecute = g_pScriptVM->CompileScript(CFmtStr("%sCallChain.PostScriptExecute()", sCallChainFunctions[j]));
|
||||||
|
g_pScriptVM->Run(hRunPostScriptExecute, (HSCRIPT)m_ScriptScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_iszScriptThinkFunction != NULL_STRING)
|
||||||
|
{
|
||||||
|
SetContextThink(&CBaseEntity::ScriptThink, gpGlobals->curtime + sv_script_think_interval.GetFloat(), "ScriptThink");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
@ -14,6 +14,8 @@
|
|||||||
#include "basecombatweapon_shared.h"
|
#include "basecombatweapon_shared.h"
|
||||||
#ifdef CLIENT_DLL
|
#ifdef CLIENT_DLL
|
||||||
#include "vscript_client.h"
|
#include "vscript_client.h"
|
||||||
|
#else
|
||||||
|
#include "mapbase/custom_weapon_factory.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The base class of the scripted weapon is game-specific.
|
// The base class of the scripted weapon is game-specific.
|
||||||
@ -32,6 +34,9 @@
|
|||||||
HSCRIPT m_Func_##name;
|
HSCRIPT m_Func_##name;
|
||||||
|
|
||||||
class CWeaponCustomScripted : public SCRIPTED_WEAPON_DERIVED_FROM
|
class CWeaponCustomScripted : public SCRIPTED_WEAPON_DERIVED_FROM
|
||||||
|
#ifndef CLIENT_DLL
|
||||||
|
, public ICustomWeapon
|
||||||
|
#endif // !CLIENT_DLL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DECLARE_CLASS( CWeaponCustomScripted, SCRIPTED_WEAPON_DERIVED_FROM );
|
DECLARE_CLASS( CWeaponCustomScripted, SCRIPTED_WEAPON_DERIVED_FROM );
|
||||||
@ -45,6 +50,8 @@ public:
|
|||||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||||
bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen );
|
bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen );
|
||||||
|
|
||||||
|
void RunVScripts();
|
||||||
|
|
||||||
// Base script has a function for this
|
// Base script has a function for this
|
||||||
//void Precache( void );
|
//void Precache( void );
|
||||||
|
|
||||||
@ -106,6 +113,11 @@ public:
|
|||||||
int WeaponRangeAttack2Condition( float flDot, float flDist );
|
int WeaponRangeAttack2Condition( float flDot, float flDist );
|
||||||
int WeaponMeleeAttack1Condition( float flDot, float flDist );
|
int WeaponMeleeAttack1Condition( float flDot, float flDist );
|
||||||
int WeaponMeleeAttack2Condition( float flDot, float flDist );
|
int WeaponMeleeAttack2Condition( float flDot, float flDist );
|
||||||
|
|
||||||
|
// Inherited via ICustomWeapon
|
||||||
|
virtual void InitCustomWeaponFromData(const void* pData, const char* pszWeaponScript);
|
||||||
|
#else
|
||||||
|
void OnDataChanged(DataUpdateType_t type);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ALLOW_SCRIPT_ACCESS();
|
ALLOW_SCRIPT_ACCESS();
|
||||||
|
@ -453,8 +453,7 @@ void RunAddonScripts()
|
|||||||
|
|
||||||
// mapspawn_addon
|
// mapspawn_addon
|
||||||
char fullpath[MAX_PATH];
|
char fullpath[MAX_PATH];
|
||||||
Q_snprintf( fullpath, sizeof( fullpath ), "%sscripts/vscripts/mapspawn_addon", path );
|
Q_ComposeFileName( path, "scripts/vscripts/mapspawn_addon", fullpath, sizeof( fullpath ) );
|
||||||
Q_FixSlashes( fullpath );
|
|
||||||
|
|
||||||
VScriptRunScriptAbsolute( fullpath, NULL, false, folderName );
|
VScriptRunScriptAbsolute( fullpath, NULL, false, folderName );
|
||||||
}
|
}
|
||||||
|
@ -408,6 +408,7 @@ FileWeaponInfo_t::FileWeaponInfo_t()
|
|||||||
m_flSwaySpeedScale = 1.0f;
|
m_flSwaySpeedScale = 1.0f;
|
||||||
szDroppedModel[0] = 0;
|
szDroppedModel[0] = 0;
|
||||||
m_bUsesHands = false;
|
m_bUsesHands = false;
|
||||||
|
m_nWeaponRestriction = WPNRESTRICT_NONE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,6 +416,14 @@ FileWeaponInfo_t::FileWeaponInfo_t()
|
|||||||
extern ConVar hud_fastswitch;
|
extern ConVar hud_fastswitch;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
const char* pWeaponRestrictions[NUM_WEAPON_RESTRICTION_TYPES] = {
|
||||||
|
"none",
|
||||||
|
"player_only",
|
||||||
|
"npc_only",
|
||||||
|
};
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
void FileWeaponInfo_t::Parse( KeyValues *pKeyValuesData, const char *szWeaponName )
|
void FileWeaponInfo_t::Parse( KeyValues *pKeyValuesData, const char *szWeaponName )
|
||||||
{
|
{
|
||||||
// Okay, we tried at least once to look this up...
|
// Okay, we tried at least once to look this up...
|
||||||
@ -483,6 +492,19 @@ void FileWeaponInfo_t::Parse( KeyValues *pKeyValuesData, const char *szWeaponNam
|
|||||||
Q_strncpy( szDroppedModel, pKeyValuesData->GetString( "droppedmodel" ), MAX_WEAPON_STRING );
|
Q_strncpy( szDroppedModel, pKeyValuesData->GetString( "droppedmodel" ), MAX_WEAPON_STRING );
|
||||||
|
|
||||||
m_bUsesHands = ( pKeyValuesData->GetInt( "uses_hands", 0 ) != 0 ) ? true : false;
|
m_bUsesHands = ( pKeyValuesData->GetInt( "uses_hands", 0 ) != 0 ) ? true : false;
|
||||||
|
|
||||||
|
const char* pszRestrictString = pKeyValuesData->GetString("usage_restriction", nullptr);
|
||||||
|
if (pszRestrictString)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_WEAPON_RESTRICTION_TYPES; i++)
|
||||||
|
{
|
||||||
|
if (V_stricmp(pszRestrictString, pWeaponRestrictions[i]) == 0)
|
||||||
|
{
|
||||||
|
m_nWeaponRestriction = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MAPBASE // Mapbase makes weapons in the same slot & position swap each other out, which is a feature mods can intentionally use.
|
#ifndef MAPBASE // Mapbase makes weapons in the same slot & position swap each other out, which is a feature mods can intentionally use.
|
||||||
|
@ -58,6 +58,17 @@ int GetWeaponSoundFromString( const char *pszString );
|
|||||||
class CHudTexture;
|
class CHudTexture;
|
||||||
class KeyValues;
|
class KeyValues;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
enum WeaponUsageRestricions_e
|
||||||
|
{
|
||||||
|
WPNRESTRICT_NONE = 0,
|
||||||
|
WPNRESTRICT_PLAYER_ONLY,
|
||||||
|
WPNRESTRICT_NPCS_ONLY,
|
||||||
|
|
||||||
|
NUM_WEAPON_RESTRICTION_TYPES
|
||||||
|
};
|
||||||
|
#endif // MAPBASE
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Contains the data read from the weapon's script file.
|
// Purpose: Contains the data read from the weapon's script file.
|
||||||
// It's cached so we only read each weapon's script file once.
|
// It's cached so we only read each weapon's script file once.
|
||||||
@ -125,6 +136,8 @@ public:
|
|||||||
char szDroppedModel[MAX_WEAPON_STRING]; // Model of this weapon when dropped on the ground
|
char szDroppedModel[MAX_WEAPON_STRING]; // Model of this weapon when dropped on the ground
|
||||||
|
|
||||||
bool m_bUsesHands;
|
bool m_bUsesHands;
|
||||||
|
|
||||||
|
int m_nWeaponRestriction;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// CLIENT DLL
|
// CLIENT DLL
|
||||||
|
@ -102,8 +102,22 @@ enum soundlevel_t
|
|||||||
#define MAX_SNDLVL_VALUE ((1<<MAX_SNDLVL_BITS)-1)
|
#define MAX_SNDLVL_VALUE ((1<<MAX_SNDLVL_BITS)-1)
|
||||||
|
|
||||||
|
|
||||||
#define ATTN_TO_SNDLVL( a ) (soundlevel_t)(int)((a) ? (50 + 20 / ((float)a)) : 0 )
|
inline soundlevel_t ATTN_TO_SNDLVL(float a)
|
||||||
#define SNDLVL_TO_ATTN( a ) ((a > 50) ? (20.0f / (float)(a - 50)) : 4.0 )
|
{
|
||||||
|
soundlevel_t sndlvl = soundlevel_t::SNDLVL_NONE;
|
||||||
|
|
||||||
|
if (a >= 0.0f)
|
||||||
|
{
|
||||||
|
sndlvl = soundlevel_t(float(soundlevel_t::SNDLVL_50dB) + float(soundlevel_t::SNDLVL_20dB) / a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sndlvl;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float SNDLVL_TO_ATTN(soundlevel_t s)
|
||||||
|
{
|
||||||
|
return (s > soundlevel_t::SNDLVL_50dB)? (20.0f / float(s - soundlevel_t::SNDLVL_50dB)) : 4.0f;
|
||||||
|
}
|
||||||
|
|
||||||
// This is a limit due to network encoding.
|
// This is a limit due to network encoding.
|
||||||
// It encodes attenuation * 64 in 8 bits, so the maximum is (255 / 64)
|
// It encodes attenuation * 64 in 8 bits, so the maximum is (255 / 64)
|
||||||
|
@ -1281,8 +1281,8 @@ PLATFORM_INTERFACE bool Is64BitOS();
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// General Mapbase version constants compiled into projects for versioning purposes
|
// General Mapbase version constants compiled into projects for versioning purposes
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define MAPBASE_VERSION "7.1"
|
#define MAPBASE_VERSION "7.2"
|
||||||
#define MAPBASE_VER_INT 7100 // For use in #if in a similar fashion to macros like _MSC_VER
|
#define MAPBASE_VER_INT 7200 // For use in #if in a similar fashion to macros like _MSC_VER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +61,11 @@ public:
|
|||||||
int GetNumFrames();
|
int GetNumFrames();
|
||||||
void SetFrame( int nFrame );
|
void SetFrame( int nFrame );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void SetRotation( int iRotation );
|
||||||
|
#else
|
||||||
void SetRotation( int iRotation ) { m_iRotation = iRotation; }
|
void SetRotation( int iRotation ) { m_iRotation = iRotation; }
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void PaintBackground();
|
virtual void PaintBackground();
|
||||||
|
@ -33,7 +33,7 @@ static CUtlSymbolTable g_ScriptSymbols(0, 128, true);
|
|||||||
|
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
// Allows animation sequences to be overridden by map-specific files
|
// Allows animation sequences to be overridden by map-specific files
|
||||||
extern bool g_bUsingCustomHudAnimations;
|
bool g_bUsingCustomHudAnimations = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// singleton accessor for animation controller for use by the vgui controls
|
// singleton accessor for animation controller for use by the vgui controls
|
||||||
|
@ -73,6 +73,13 @@ void ImagePanel::OnSizeChanged(int newWide, int newTall)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ImagePanel::SetImage(IImage *image)
|
void ImagePanel::SetImage(IImage *image)
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( image )
|
||||||
|
{
|
||||||
|
image->SetRotation( m_iRotation );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_pImage = image;
|
m_pImage = image;
|
||||||
Repaint();
|
Repaint();
|
||||||
}
|
}
|
||||||
@ -471,3 +478,15 @@ void ImagePanel::SetFrame( int nFrame )
|
|||||||
|
|
||||||
return m_pImage->SetFrame( nFrame );
|
return m_pImage->SetFrame( nFrame );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void ImagePanel::SetRotation( int iRotation )
|
||||||
|
{
|
||||||
|
m_iRotation = iRotation;
|
||||||
|
|
||||||
|
if ( m_pImage )
|
||||||
|
{
|
||||||
|
m_pImage->SetRotation( m_iRotation );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -206,19 +206,28 @@ void CScriptKeyValues::ScriptReleaseKeyValues( )
|
|||||||
m_pKeyValues = NULL;
|
m_pKeyValues = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptKeyValues::TableToSubKeys( HSCRIPT hTable )
|
void KeyValues_TableToSubKeys( HSCRIPT hTable, KeyValues *pKV )
|
||||||
{
|
{
|
||||||
int nIterator = -1;
|
int nIterator = -1;
|
||||||
ScriptVariant_t varKey, varValue;
|
ScriptVariant_t varKey, varValue;
|
||||||
while ((nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &varKey, &varValue )) != -1)
|
while ((nIterator = g_pScriptVM->GetKeyValue( hTable, nIterator, &varKey, &varValue )) != -1)
|
||||||
|
{
|
||||||
|
if ( varKey.m_type == FIELD_CSTRING )
|
||||||
{
|
{
|
||||||
switch ( varValue.m_type )
|
switch ( varValue.m_type )
|
||||||
{
|
{
|
||||||
case FIELD_CSTRING: m_pKeyValues->SetString( varKey.m_pszString, varValue.m_pszString ); break;
|
case FIELD_CSTRING: pKV->SetString( varKey.m_pszString, varValue.m_pszString ); break;
|
||||||
case FIELD_INTEGER: m_pKeyValues->SetInt( varKey.m_pszString, varValue.m_int ); break;
|
case FIELD_INTEGER: pKV->SetInt( varKey.m_pszString, varValue.m_int ); break;
|
||||||
case FIELD_FLOAT: m_pKeyValues->SetFloat( varKey.m_pszString, varValue.m_float ); break;
|
case FIELD_FLOAT: pKV->SetFloat( varKey.m_pszString, varValue.m_float ); break;
|
||||||
case FIELD_BOOLEAN: m_pKeyValues->SetBool( varKey.m_pszString, varValue.m_bool ); break;
|
case FIELD_BOOLEAN: pKV->SetBool( varKey.m_pszString, varValue.m_bool ); break;
|
||||||
case FIELD_VECTOR: m_pKeyValues->SetString( varKey.m_pszString, CFmtStr( "%f %f %f", varValue.m_pVector->x, varValue.m_pVector->y, varValue.m_pVector->z ) ); break;
|
case FIELD_VECTOR: pKV->SetString( varKey.m_pszString, CFmtStr( "%f %f %f", varValue.m_pVector->x, varValue.m_pVector->y, varValue.m_pVector->z ) ); break;
|
||||||
|
case FIELD_HSCRIPT:
|
||||||
|
{
|
||||||
|
KeyValues *subKey = pKV->FindKey( varKey.m_pszString, true );
|
||||||
|
KeyValues_TableToSubKeys( varValue, subKey );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pScriptVM->ReleaseValue( varKey );
|
g_pScriptVM->ReleaseValue( varKey );
|
||||||
@ -226,18 +235,37 @@ void CScriptKeyValues::TableToSubKeys( HSCRIPT hTable )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScriptKeyValues::SubKeysToTable( HSCRIPT hTable )
|
void KeyValues_SubKeysToTable( KeyValues *pKV, HSCRIPT hTable )
|
||||||
{
|
{
|
||||||
FOR_EACH_SUBKEY( m_pKeyValues, key )
|
FOR_EACH_SUBKEY( pKV, key )
|
||||||
{
|
{
|
||||||
switch ( key->GetDataType() )
|
switch ( key->GetDataType() )
|
||||||
{
|
{
|
||||||
case KeyValues::TYPE_STRING: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetString() ); break;
|
case KeyValues::TYPE_STRING: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetString() ); break;
|
||||||
case KeyValues::TYPE_INT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetInt() ); break;
|
case KeyValues::TYPE_INT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetInt() ); break;
|
||||||
case KeyValues::TYPE_FLOAT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetFloat() ); break;
|
case KeyValues::TYPE_FLOAT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetFloat() ); break;
|
||||||
|
case KeyValues::TYPE_NONE:
|
||||||
|
{
|
||||||
|
ScriptVariant_t subTable;
|
||||||
|
g_pScriptVM->CreateTable( subTable );
|
||||||
|
g_pScriptVM->SetValue( hTable, key->GetName(), subTable );
|
||||||
|
KeyValues_SubKeysToTable( key, subTable );
|
||||||
|
g_pScriptVM->ReleaseValue( subTable );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptKeyValues::TableToSubKeys( HSCRIPT hTable )
|
||||||
|
{
|
||||||
|
KeyValues_TableToSubKeys( hTable, m_pKeyValues );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptKeyValues::SubKeysToTable( HSCRIPT hTable )
|
||||||
|
{
|
||||||
|
KeyValues_SubKeysToTable( m_pKeyValues, hTable );
|
||||||
|
}
|
||||||
|
|
||||||
HSCRIPT CScriptKeyValues::ScriptFindOrCreateKey( const char *pszName )
|
HSCRIPT CScriptKeyValues::ScriptFindOrCreateKey( const char *pszName )
|
||||||
{
|
{
|
||||||
|
@ -118,16 +118,15 @@ class CSimpleCallChainer
|
|||||||
|
|
||||||
function PostScriptExecute()
|
function PostScriptExecute()
|
||||||
{
|
{
|
||||||
local func;
|
if ( prefix in scope )
|
||||||
try {
|
{
|
||||||
func = scope[prefix];
|
local func = scope[prefix];
|
||||||
} catch(e) {
|
if ( typeof func == "function" )
|
||||||
return;
|
{
|
||||||
}
|
|
||||||
if (typeof(func) != "function")
|
|
||||||
return;
|
|
||||||
chain.push(func);
|
chain.push(func);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Call()
|
function Call()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user