Merge pull request #110 from mapbase-source/develop

Mapbase v6.3
This commit is contained in:
Blixibon 2021-03-16 18:29:36 -05:00 committed by GitHub
commit 264ee2b04f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
79 changed files with 4223 additions and 694 deletions

7
README
View File

@ -40,8 +40,8 @@ or complicated code changes accessible and easy to use for level designers and o
If you believe any content in Mapbase originates from any leak or unauthorized source (from Valve or otherwise), please contact Blixibon immediately.
Mapbase is intended to be usable by everyone, including licensed Source projects and Steam mods. ***
The Alien Swarm SDK was used to backport features and code from newer branches of Source into a Source 2013/Half-Life 2 environment.
Mapbase also implements some of Tony Sergi's code changes from the Source 2007 SDK codebase. Both SDKs are publicly distributed by Valve and are available on Steam.
-- The Alien Swarm SDK was used to backport features and code from newer branches of Source into a Source 2013/Half-Life 2 environment.
-- Mapbase also implements some of Tony Sergi's code changes from the Source 2007 SDK codebase. Both SDKs are publicly distributed by Valve and are available on Steam.
Some of the features backported from the Alien Swarm SDK (e.g. game instructor, particle rain) require assets from later versions of Source in order to work properly.
The required assets have been backported from Alien Swarm and Left 4 Dead for the release build. They are not available in the code repository.
@ -100,11 +100,13 @@ Direct contributions:
- Combine lock hardware on door01_left.mdl created by Kralich (This is asset-based and not reflected in the code)
- npc_vehicledriver fixes provided by CrAzY
- npc_combine cover behavior patches provided by iohnnyboy
- logic_playmovie icon created by URAKOLOUY5 (This is asset-based and not reflected in the code)
== Contributions from samisalreadytaken:
=-- https://github.com/mapbase-source/source-sdk-2013/pull/47 (VScript utility/consistency changes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/59 (New VScript functions and singletons based on API documentation in later Source/Source 2 games)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/80 (More VScript changes, including support for extremely flexible client/server messaging)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/105 (VScript fixes and optimizations, Vector class extensions, custom convars/commands)
//---------------------------------------------------------------------------------------------------------------------------------------------------
@ -117,6 +119,7 @@ Other sources:
-- https://github.com/ValveSoftware/source-sdk-2013/pull/401 (func_rot_button "Starts locked" flag fix)
-- https://github.com/ValveSoftware/source-sdk-2013/pull/391 (VBSP func_detail smoothing group fix)
-- https://github.com/ValveSoftware/source-sdk-2013/pull/362 (npc_manhack npc_maker fix; Adjusted for formatting and save/restore in Mapbase)
-- https://github.com/Petercov/Source-PlusPlus/commit/ecdf50c48cd31dec4dbdb7fea2d0780e7f0dd8ec (used as a guide for porting the Alien Swarm SDK response system)
- https://github.com/momentum-mod/game/blob/1d066180b3bf74830c51e6914d46c40b0bea1fc2/mp/src/game/server/player.cpp#L6543 (spec_goto fix)
- Poison zombie barnacle crash fix implemented based on a snippet from HL2: Plus posted by Agent Agrimar on Discord (Mapbase makes the barnacle recognize it as poison just like poison headcrabs)
- https://gamebanana.com/skins/172192 (Airboat handling fix; This is asset-based and not reflected in the code)

View File

@ -293,6 +293,7 @@ BEGIN_ENT_SCRIPTDESC( C_ClientRagdoll, C_BaseAnimating, "Client-side ragdolls" )
END_SCRIPTDESC();
ScriptHook_t C_BaseAnimating::g_Hook_OnClientRagdoll;
ScriptHook_t C_BaseAnimating::g_Hook_FireEvent;
#endif
BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-side" )
@ -346,6 +347,13 @@ BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-si
BEGIN_SCRIPTHOOK( C_BaseAnimating::g_Hook_OnClientRagdoll, "OnClientRagdoll", FIELD_VOID, "Called when this entity turns into a client-side ragdoll." )
DEFINE_SCRIPTHOOK_PARAM( "ragdoll", FIELD_HSCRIPT )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( C_BaseAnimating::g_Hook_FireEvent, "FireEvent", FIELD_BOOLEAN, "Called when handling animation events. Return false to cancel base handling." )
DEFINE_SCRIPTHOOK_PARAM( "origin", FIELD_VECTOR )
DEFINE_SCRIPTHOOK_PARAM( "angles", FIELD_VECTOR )
DEFINE_SCRIPTHOOK_PARAM( "event", FIELD_INTEGER )
DEFINE_SCRIPTHOOK_PARAM( "options", FIELD_CSTRING )
END_SCRIPTHOOK()
#endif
END_SCRIPTDESC();
@ -3651,7 +3659,11 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
flEventCycle,
gpGlobals->curtime );
}
#ifdef MAPBASE_VSCRIPT
if (ScriptHookFireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() ) == false)
continue;
#endif
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
}
@ -3684,6 +3696,11 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
gpGlobals->curtime );
}
#ifdef MAPBASE_VSCRIPT
if (ScriptHookFireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() ) == false)
continue;
#endif
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
}
}
@ -3691,6 +3708,26 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
m_flPrevEventCycle = flEventCycle;
}
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BaseAnimating::ScriptHookFireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
if (m_ScriptScope.IsInitialized() && g_Hook_FireEvent.CanRunInScope(m_ScriptScope))
{
// origin, angles, event, options
ScriptVariant_t args[] = { origin, angles, event, options };
ScriptVariant_t returnValue = true;
g_Hook_FireEvent.Call( m_ScriptScope, &returnValue, args );
return returnValue.m_bool;
}
return true;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Parses a muzzle effect event and sends it out for drawing
// Input : *options - event parameters in text format

View File

@ -164,6 +164,10 @@ public:
virtual void FireObsoleteEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual const char* ModifyEventParticles( const char* token ) { return token; }
#ifdef MAPBASE_VSCRIPT
bool ScriptHookFireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
#endif
#if defined ( SDK_DLL ) || defined ( HL2MP )
virtual void ResetEventsParity() { m_nPrevResetEventsParity = -1; } // used to force animation events to function on players so the muzzleflashes and other events occur
// so new functions don't have to be made to parse the models like CSS does in ProcessMuzzleFlashEvent
@ -477,6 +481,7 @@ public:
HSCRIPT ScriptBecomeRagdollOnClient();
static ScriptHook_t g_Hook_OnClientRagdoll;
static ScriptHook_t g_Hook_FireEvent;
float ScriptGetPoseParameter(const char* szName);
#endif

View File

@ -451,6 +451,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelName, "GetModelName", "Returns the name of the model" )
DEFINE_SCRIPTFUNC_NAMED( ScriptStopSound, "StopSound", "Stops a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptEmitSound, "EmitSound", "Plays a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( VScriptPrecacheScriptSound, "PrecacheSoundScript", "Precache a sound for later playing." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSoundDuration, "GetSoundDuration", "Returns float duration of the sound. Takes soundname and optional actormodelname." )
@ -472,6 +473,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( GetAbsAngles, "GetAngles", "Get entity pitch, yaw, roll as a vector" )
DEFINE_SCRIPTFUNC_NAMED( SetAbsAngles, "SetAngles", "Set entity pitch, yaw, roll" )
DEFINE_SCRIPTFUNC( SetSize, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMins, "GetBoundingMins", "Get a vector containing min bounds, centered on object" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMaxs, "GetBoundingMaxs", "Get a vector containing max bounds, centered on object" )
@ -541,7 +543,13 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( IsBaseCombatWeapon, "IsWeapon", "Returns true if this entity is a weapon." )
DEFINE_SCRIPTFUNC( IsWorld, "Returns true if this entity is the world." )
DEFINE_SCRIPTFUNC( SetModel, "Set client-only entity model" )
//DEFINE_SCRIPTFUNC_NAMED( ScriptInitializeAsClientEntity, "InitializeAsClientEntity", "" )
DEFINE_SCRIPTFUNC_NAMED( Remove, "Destroy", "Remove clientside entity" )
DEFINE_SCRIPTFUNC_NAMED( GetEntityIndex, "entindex", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." )
#endif
END_SCRIPTDESC();
@ -578,6 +586,7 @@ BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
RecvPropInt(RECVINFO(m_clrRender)),
#ifdef MAPBASE
RecvPropInt(RECVINFO(m_iViewHideFlags)),
RecvPropBool(RECVINFO(m_bDisableFlashlight)),
#endif
RecvPropInt(RECVINFO(m_iTeamNum)),
RecvPropInt(RECVINFO(m_CollisionGroup)),
@ -1333,6 +1342,15 @@ void C_BaseEntity::Term()
{
g_pScriptVM->RemoveInstance( m_hScriptInstance );
m_hScriptInstance = NULL;
#ifdef MAPBASE_VSCRIPT
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
HSCRIPT h = m_ScriptThinkFuncs[i]->m_hfnThink;
if ( h ) g_pScriptVM->ReleaseScript( h );
}
m_ScriptThinkFuncs.PurgeAndDeleteElements();
#endif
}
}
@ -1683,6 +1701,11 @@ bool C_BaseEntity::ShouldReceiveProjectedTextures( int flags )
if ( IsEffectActive( EF_NODRAW ) )
return false;
#ifdef MAPBASE
if ( m_bDisableFlashlight )
return false;
#endif
if( flags & SHADOW_FLAGS_FLASHLIGHT )
{
if ( GetRenderMode() > kRenderNormal && GetRenderColor().a == 0 )

View File

@ -161,6 +161,16 @@ struct thinkfunc_t
int m_nLastThinkTick;
};
#ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t
{
int m_nNextThinkTick;
HSCRIPT m_hfnThink;
unsigned short m_iContextHash;
bool m_bNoParam;
};
#endif
#define CREATE_PREDICTED_ENTITY( className ) \
C_BaseEntity::CreatePredictedEntityByName( className, __FILE__, __LINE__ );
@ -1173,6 +1183,7 @@ public:
#ifdef MAPBASE_VSCRIPT
const char* ScriptGetModelName( void ) const { return STRING(GetModelName()); }
void ScriptStopSound(const char* soundname);
void ScriptEmitSound(const char* soundname);
float ScriptSoundDuration(const char* soundname, const char* actormodel);
@ -1378,6 +1389,7 @@ public:
#ifdef MAPBASE
int m_iViewHideFlags;
bool m_bDisableFlashlight;
#endif
private:
@ -1518,6 +1530,15 @@ protected:
CUtlVector< thinkfunc_t > m_aThinkFunctions;
int m_iCurrentThinkContext;
#ifdef MAPBASE_VSCRIPT
public:
void ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float time );
void ScriptContextThink();
private:
CUtlVector< scriptthinkfunc_t* > m_ScriptThinkFuncs;
public:
#endif
// Object eye position
Vector m_vecViewOffset;

View File

@ -0,0 +1,26 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//
//=====================================================================================//
#include "cbase.h"
#include "c_movie_display.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_MovieDisplay, DT_MovieDisplay, CMovieDisplay )
RecvPropBool( RECVINFO( m_bEnabled ) ),
RecvPropBool( RECVINFO( m_bLooping ) ),
RecvPropString( RECVINFO( m_szMovieFilename ) ),
RecvPropString( RECVINFO( m_szGroupName ) ),
END_RECV_TABLE()
C_MovieDisplay::C_MovieDisplay()
{
}
C_MovieDisplay::~C_MovieDisplay()
{
}

View File

@ -0,0 +1,34 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef C_MOVIE_DISPLAY_H
#define C_MOVIE_DISPLAY_H
#include "cbase.h"
class C_MovieDisplay : public C_BaseEntity
{
public:
DECLARE_CLASS( C_MovieDisplay, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_MovieDisplay();
~C_MovieDisplay();
bool IsEnabled( void ) const { return m_bEnabled; }
bool IsLooping( void ) const { return m_bLooping; }
const char *GetMovieFilename( void ) const { return m_szMovieFilename; }
const char *GetGroupName( void ) const { return m_szGroupName; }
private:
bool m_bEnabled;
bool m_bLooping;
char m_szMovieFilename[128];
char m_szGroupName[128];
};
#endif //C_MOVIE_DISPLAY_H

View File

@ -49,6 +49,8 @@ public:
#endif
#ifdef MAPBASE_VSCRIPT
void ClientThink() { ScriptContextThink(); }
// -2 = Use server language
ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)(m_iScriptLanguageClient != -2 ? m_iScriptLanguageClient : m_iScriptLanguageServer); }
#endif

View File

@ -274,6 +274,8 @@ void ProcessCacheUsedMaterials()
}
}
void VGui_ClearVideoPanels();
// String tables
INetworkStringTable *g_pStringTableParticleEffectNames = NULL;
INetworkStringTable *g_StringTableEffectDispatch = NULL;
@ -1217,6 +1219,8 @@ void CHLClient::Shutdown( void )
g_pSixenseInput = NULL;
#endif
VGui_ClearVideoPanels();
C_BaseAnimating::ShutdownBoneSetupThreadPool();
ClientWorldFactoryShutdown();

View File

@ -31,6 +31,9 @@ $Project
$File "c_postprocesscontroller.cpp"
$File "c_postprocesscontroller.h"
$File "c_env_dof_controller.cpp"
$File "c_movie_display.cpp"
$File "c_movie_display.h"
$File "vgui_movie_display.cpp"
$Folder "Mapbase"
{
@ -57,6 +60,7 @@ $Project
$File "mapbase\c_func_fake_worldportal.cpp"
$File "mapbase\c_func_fake_worldportal.h"
$File "mapbase\c_point_glow.cpp"
$File "mapbase\c_vgui_text_display.cpp"
}
$Folder "HL2 DLL"

View File

@ -0,0 +1,259 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose: Displays easy, flexible VGui text. Mapbase equivalent of point_worldtext.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "panelmetaclassmgr.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include <vgui/IInput.h>
#include <vgui/IPanel.h>
#include <vgui/IVGui.h>
#include "ienginevgui.h"
#include "c_vguiscreen.h"
#include "vgui_bitmapbutton.h"
#include "vgui_bitmappanel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// vgui_text_display
//-----------------------------------------------------------------------------
class C_VGuiTextDisplay : public C_BaseEntity
{
public:
DECLARE_CLASS( C_VGuiTextDisplay, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_VGuiTextDisplay();
~C_VGuiTextDisplay();
virtual void PostDataUpdate( DataUpdateType_t updateType );
bool IsEnabled( void ) const { return m_bEnabled; }
const char *GetDisplayText( void ) const { return m_szDisplayText; }
const char *GetFontName( void ) const { return m_szFont; }
int GetResolution( void ) const { return m_iResolution; }
vgui::Label::Alignment GetContentAlignment() const { return m_iContentAlignment; }
bool NeedsTextUpdate() { return m_bTextNeedsUpdate; }
void UpdatedText() { m_bTextNeedsUpdate = false; }
private:
bool m_bEnabled;
char m_szDisplayText[256];
vgui::Label::Alignment m_iContentAlignment;
char m_szFont[64];
int m_iResolution;
bool m_bTextNeedsUpdate;
};
IMPLEMENT_CLIENTCLASS_DT( C_VGuiTextDisplay, DT_VGuiTextDisplay, CVGuiTextDisplay )
RecvPropBool( RECVINFO( m_bEnabled ) ),
RecvPropString( RECVINFO( m_szDisplayText ) ),
RecvPropInt( RECVINFO( m_iContentAlignment ) ),
RecvPropString( RECVINFO( m_szFont ) ),
RecvPropInt( RECVINFO( m_iResolution ) ),
END_RECV_TABLE()
C_VGuiTextDisplay::C_VGuiTextDisplay()
{
}
C_VGuiTextDisplay::~C_VGuiTextDisplay()
{
}
void C_VGuiTextDisplay::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
// For now, always update
m_bTextNeedsUpdate = true;
}
using namespace vgui;
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class C_TextDisplayPanel : public CVGuiScreenPanel
{
DECLARE_CLASS( C_TextDisplayPanel, CVGuiScreenPanel );
public:
C_TextDisplayPanel( vgui::Panel *parent, const char *panelName );
~C_TextDisplayPanel( void );
virtual void ApplySchemeSettings( IScheme *pScheme );
void UpdateText();
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick( void );
virtual void Paint( void );
private:
CHandle<C_VGuiScreen> m_hVGUIScreen;
CHandle<C_VGuiTextDisplay> m_hScreenEntity;
// VGUI specifics
Label *m_pDisplayTextLabel;
};
DECLARE_VGUI_SCREEN_FACTORY( C_TextDisplayPanel, "text_display_panel" );
CUtlVector <C_TextDisplayPanel *> g_TextDisplays;
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
C_TextDisplayPanel::C_TextDisplayPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "C_TextDisplayPanel"/*, vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/WorldTextPanel.res", "WorldTextPanel" )*/ )
{
// Add ourselves to the global list of movie displays
g_TextDisplays.AddToTail( this );
}
//-----------------------------------------------------------------------------
// Purpose: Clean up the movie
//-----------------------------------------------------------------------------
C_TextDisplayPanel::~C_TextDisplayPanel( void )
{
// Remove ourselves from the global list of movie displays
g_TextDisplays.FindAndRemove( this );
}
//-----------------------------------------------------------------------------
// Purpose: Setup our scheme
//-----------------------------------------------------------------------------
void C_TextDisplayPanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
/*
m_pDisplayTextLabel->SetFgColor( Color( 255, 255, 255, 255 ) );
m_pDisplayTextLabel->SetText( "" );
m_pDisplayTextLabel->SetVisible( false );
*/
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TextDisplayPanel::UpdateText()
{
color32 clr = m_hScreenEntity->GetRenderColor();
m_pDisplayTextLabel->SetFgColor( Color( clr.r, clr.g, clr.b, clr.a ) );
m_pDisplayTextLabel->SetText( m_hScreenEntity->GetDisplayText() );
//SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() );
SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
//m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() );
Label::Alignment iAlignment = m_hScreenEntity->GetContentAlignment();
m_pDisplayTextLabel->SetContentAlignment( iAlignment );
bool bWrap = true;
bool bCenterWrap = false;
switch (iAlignment)
{
// Center wrap if centered
case Label::Alignment::a_north:
case Label::Alignment::a_center:
case Label::Alignment::a_south:
bCenterWrap = true;
break;
// HACKHACK: Don't wrap if using an east alignment
case Label::Alignment::a_northeast:
case Label::Alignment::a_east:
case Label::Alignment::a_southeast:
bWrap = false;
break;
}
m_pDisplayTextLabel->SetWrap( bWrap );
m_pDisplayTextLabel->SetCenterWrap( bCenterWrap );
//Msg( "Resolution is %i\n", m_hScreenEntity->GetResolution() );
const char *pszFontName = m_hScreenEntity->GetFontName();
if (pszFontName && pszFontName[0] != '\0')
{
HFont font = scheme()->GetIScheme( GetScheme() )->GetFont( pszFontName );
m_pDisplayTextLabel->SetFont( font );
}
m_pDisplayTextLabel->SetVisible( true );
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool C_TextDisplayPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
if ( !BaseClass::Init( pKeyValues, pInitData ) )
return false;
// Make sure we get ticked...
vgui::ivgui()->AddTickSignal( GetVPanel() );
m_pDisplayTextLabel = dynamic_cast<vgui::Label*>(FindChildByName( "TextDisplay" ));
// Save this for simplicity later on
m_hVGUIScreen = dynamic_cast<C_VGuiScreen *>( GetEntity() );
if ( m_hVGUIScreen != NULL )
{
// Also get the associated entity
m_hScreenEntity = dynamic_cast<C_VGuiTextDisplay *>(m_hVGUIScreen->GetOwnerEntity());
UpdateText();
}
return true;
}
//-----------------------------------------------------------------------------
// Update the display string
//-----------------------------------------------------------------------------
void C_TextDisplayPanel::OnTick()
{
if (m_hScreenEntity->NeedsTextUpdate())
{
UpdateText();
m_hScreenEntity->UpdatedText();
}
BaseClass::OnTick();
}
ConVar r_vguitext_bg( "r_vguitext_bg", "0" );
//-----------------------------------------------------------------------------
// Purpose: Update and draw the frame
//-----------------------------------------------------------------------------
void C_TextDisplayPanel::Paint( void )
{
// Black out the background (we could omit drawing under the video surface, but this is straight-forward)
if ( r_vguitext_bg.GetBool() )
{
surface()->DrawSetColor( 0, 0, 0, 255 );
surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() );
//surface()->DrawSetColor( 64, 64, 64, 255 );
//surface()->DrawFilledRect( 0, 0, m_pDisplayTextLabel->GetWide(), m_pDisplayTextLabel->GetTall() );
}
// Parent's turn
BaseClass::Paint();
}

View File

@ -234,14 +234,6 @@ CPanelMetaClassMgrImp::CPanelMetaClassMgrImp() : m_PanelTypeDict( true, 0, 32 )
CPanelMetaClassMgrImp::~CPanelMetaClassMgrImp()
{
#ifdef MAPBASE // VDC Memory Leak Fixes
while (m_MetaClassKeyValues.Count()>0)
{
if (m_MetaClassKeyValues[0])
m_MetaClassKeyValues[0]->deleteThis();
m_MetaClassKeyValues.RemoveAt(0);
}
#endif
}

View File

@ -0,0 +1,437 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "cbase.h"
#include "c_vguiscreen.h"
#include "vgui_controls/Label.h"
#include "vgui_BitmapPanel.h"
#include <vgui/IVGUI.h>
#include "c_slideshow_display.h"
#include "ienginevgui.h"
#include "fmtstr.h"
#include "vgui_controls/ImagePanel.h"
#include <vgui/ISurface.h>
#include "video/ivideoservices.h"
#include "engine/ienginesound.h"
#include "VGUIMatSurface/IMatSystemSurface.h"
#include "c_movie_display.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
using namespace vgui;
struct VideoPlaybackInfo_t
{
VideoPlaybackInfo_t( void ) :
m_pMaterial ( NULL ),
m_nSourceHeight(0), m_nSourceWidth(0),
m_flU(0.0f),m_flV(0.0f) {}
IMaterial *m_pMaterial;
int m_nSourceHeight, m_nSourceWidth; // Source movie's dimensions
float m_flU, m_flV; // U,V ranges for video on its sheet
};
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CMovieDisplayScreen : public CVGuiScreenPanel
{
DECLARE_CLASS( CMovieDisplayScreen, CVGuiScreenPanel );
public:
CMovieDisplayScreen( vgui::Panel *parent, const char *panelName );
~CMovieDisplayScreen( void );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick( void );
virtual void Paint( void );
private:
bool IsActive( void );
void SetupMovie( void );
void UpdateMovie( void );
bool BeginPlayback( const char *pFilename );
void CalculatePlaybackDimensions( int nSrcWidth, int nSrcHeight );
inline void GetPanelPos( int &xpos, int &ypos )
{
xpos = ( (float) ( GetWide() - m_nPlaybackWidth ) / 2 );
ypos = ( (float) ( GetTall() - m_nPlaybackHeight ) / 2 );
}
private:
// BINK playback info
IVideoMaterial *m_VideoMaterial;
VideoPlaybackInfo_t m_playbackInfo;
CHandle<C_VGuiScreen> m_hVGUIScreen;
CHandle<C_MovieDisplay> m_hScreenEntity;
int m_nTextureId;
int m_nPlaybackHeight; // Playback dimensions (proper ration adjustments)
int m_nPlaybackWidth;
bool m_bBlackBackground;
bool m_bSlaved;
bool m_bInitialized;
bool m_bLastActiveState; // HACK: I'd rather get a real callback...
// VGUI specifics
Label *m_pDisplayTextLabel;
Color m_cDefault;
Color m_cInvisible;
bool bIsAlreadyVisible;
};
DECLARE_VGUI_SCREEN_FACTORY( CMovieDisplayScreen, "movie_display_screen" );
CUtlVector <CMovieDisplayScreen *> g_MovieDisplays;
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CMovieDisplayScreen::CMovieDisplayScreen( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CMovieDisplayScreen", vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/MovieDisplayScreen.res", "MovieDisplayScreen" ) )
{
m_pDisplayTextLabel = new vgui::Label( this, "NumberDisplay", "testing!");
m_VideoMaterial = NULL;
m_nTextureId = -1;
m_bBlackBackground = true;
m_bSlaved = false;
m_bInitialized = false;
// Add ourselves to the global list of movie displays
g_MovieDisplays.AddToTail( this );
m_bLastActiveState = IsActive();
}
//-----------------------------------------------------------------------------
// Purpose: Clean up the movie
//-----------------------------------------------------------------------------
CMovieDisplayScreen::~CMovieDisplayScreen( void )
{
if ( g_pVideo != NULL && m_VideoMaterial != NULL )
{
g_pVideo->DestroyVideoMaterial( m_VideoMaterial );
m_VideoMaterial = NULL;
}
// Clean up our texture reference
g_pMatSystemSurface->DestroyTextureID( m_nTextureId );
// Remove ourselves from the global list of movie displays
g_MovieDisplays.FindAndRemove( this );
}
//-----------------------------------------------------------------------------
// Purpose: Setup our scheme
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::ApplySchemeSettings( IScheme *pScheme )
{
assert( pScheme );
m_cDefault = Color( 255, 255, 255, 255 );
m_cInvisible = Color( 0, 0, 0, 0 );
m_pDisplayTextLabel->SetFgColor( m_cDefault );
m_pDisplayTextLabel->SetText( "" );
m_pDisplayTextLabel->SetVisible( false );
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CMovieDisplayScreen::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Make sure we get ticked...
vgui::ivgui()->AddTickSignal( GetVPanel() );
if ( !BaseClass::Init( pKeyValues, pInitData ) )
return false;
// Save this for simplicity later on
m_hVGUIScreen = dynamic_cast<C_VGuiScreen *>( GetEntity() );
if ( m_hVGUIScreen != NULL )
{
// Also get the associated entity
m_hScreenEntity = dynamic_cast<C_MovieDisplay *>(m_hVGUIScreen->GetOwnerEntity());
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Helper function to check our active state
//-----------------------------------------------------------------------------
bool CMovieDisplayScreen::IsActive( void )
{
bool bScreenActive = false;
if ( m_hVGUIScreen != NULL )
{
bScreenActive = m_hVGUIScreen->IsActive();
}
return bScreenActive;
}
//-----------------------------------------------------------------------------
// Purpose: Either become the master of a group of screens, or become a slave to another
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::SetupMovie( void )
{
// Only bother if we haven't been setup yet
if ( m_bInitialized )
return;
const char *szGroupName = m_hScreenEntity->GetGroupName();
CMovieDisplayScreen *pMasterScreen = NULL;
for ( int i = 0; i < g_MovieDisplays.Count(); i++ )
{
// Must be valid and not us
if ( g_MovieDisplays[i] == NULL || g_MovieDisplays[i] == this )
continue;
// Must have an associated movie entity
if ( g_MovieDisplays[i]->m_hScreenEntity == NULL )
continue;
// Must have a group name to care
if ( szGroupName[0] == NULL )
continue;
// Group names must match!
// FIXME: Use an ID instead?
const char *szTestGroupName = g_MovieDisplays[i]->m_hScreenEntity->GetGroupName();
if ( Q_strnicmp( szTestGroupName, szGroupName, 128 ) )
continue;
// See if we've found a master display
if ( g_MovieDisplays[i]->m_bInitialized && g_MovieDisplays[i]->m_bSlaved == false )
{
m_bSlaved = true;
// Share the info from the master
m_playbackInfo = g_MovieDisplays[i]->m_playbackInfo;
// We need to calculate our own playback dimensions as we may be a different size than our parent
CalculatePlaybackDimensions( m_playbackInfo.m_nSourceWidth, m_playbackInfo.m_nSourceHeight );
// Bind our texture
m_nTextureId = surface()->CreateNewTextureID( true );
g_pMatSystemSurface->DrawSetTextureMaterial( m_nTextureId, m_playbackInfo.m_pMaterial );
// Hold this as the master screen
pMasterScreen = g_MovieDisplays[i];
break;
}
}
// We need to try again, we have no screen entity!
if ( m_hScreenEntity == NULL )
return;
// No master found, become one
if ( pMasterScreen == NULL )
{
const char *szFilename = m_hScreenEntity->GetMovieFilename();
BeginPlayback( szFilename );
m_bSlaved = false;
}
// Done
m_bInitialized = true;
}
//-----------------------------------------------------------------------------
// Purpose: Deal with the details of the video playback
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::UpdateMovie( void )
{
// Only the master in a group updates the bink file
if ( m_bSlaved )
return;
if ( m_VideoMaterial == NULL )
return;
// Get the current activity state of the screen
bool bScreenActive = IsActive();
// Pause if the game has paused
if ( engine->IsPaused() || engine->Con_IsVisible() )
{
bScreenActive = false;
}
// See if we've changed our activity state
if ( bScreenActive != m_bLastActiveState )
{
m_VideoMaterial->SetPaused( !bScreenActive );
}
// Updated
m_bLastActiveState = bScreenActive;
// Update the frame if we're currently enabled
if ( bScreenActive )
{
// Update our frame
if ( m_VideoMaterial->Update() == false )
{
// Issue a close command
// OnVideoOver();
// StopPlayback();
}
}
}
//-----------------------------------------------------------------------------
// Update the display string
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::OnTick()
{
BaseClass::OnTick();
// Create our playback or slave to another screen already playing
SetupMovie();
// Now update the movie
UpdateMovie();
}
//-----------------------------------------------------------------------------
// Purpose: Adjust the playback dimensions to properly account for our screen dimensions
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::CalculatePlaybackDimensions( int nSrcWidth, int nSrcHeight )
{
float flFrameRatio = ( (float) GetWide() / (float) GetTall() );
float flVideoRatio = ( (float) nSrcWidth / (float) nSrcHeight );
if ( flVideoRatio > flFrameRatio )
{
m_nPlaybackWidth = GetWide();
m_nPlaybackHeight = ( GetWide() / flVideoRatio );
}
else if ( flVideoRatio < flFrameRatio )
{
m_nPlaybackWidth = ( GetTall() * flVideoRatio );
m_nPlaybackHeight = GetTall();
}
else
{
m_nPlaybackWidth = GetWide();
m_nPlaybackHeight = GetTall();
}
}
//-----------------------------------------------------------------------------
// Purpose: Begins playback of a movie
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CMovieDisplayScreen::BeginPlayback( const char *pFilename )
{
// need working video services
if ( g_pVideo == NULL )
return false;
// Create a new video material
if ( m_VideoMaterial != NULL )
{
g_pVideo->DestroyVideoMaterial( m_VideoMaterial );
m_VideoMaterial = NULL;
}
// Create a globally unique name for this material
char szMaterialName[256];
// Append our group name if we have one
const char *szGroupName = m_hScreenEntity->GetGroupName();
if ( szGroupName[0] != NULL )
{
Q_snprintf( szMaterialName, sizeof(szMaterialName), "%s_%s", pFilename, szGroupName );
}
else
{
Q_strncpy( szMaterialName, pFilename, sizeof(szMaterialName) );
}
const char *pszMaterialName = CFmtStrN<128>( "VideoMaterial_", m_hScreenEntity->GetEntityName() );
m_VideoMaterial = g_pVideo->CreateVideoMaterial( pszMaterialName, pFilename, "GAME",
VideoPlaybackFlags::DEFAULT_MATERIAL_OPTIONS,
VideoSystem::DETERMINE_FROM_FILE_EXTENSION/*, m_bAllowAlternateMedia*/ );
if ( m_VideoMaterial == NULL )
return false;
m_VideoMaterial->SetMuted( true ); // FIXME: Allow?
if ( m_hScreenEntity->IsLooping() )
{
m_VideoMaterial->SetLooping( true );
}
if ( m_VideoMaterial->HasAudio() )
{
// We want to be the sole audio source
enginesound->NotifyBeginMoviePlayback();
}
// Get our basic info from the movie
m_VideoMaterial->GetVideoImageSize( &m_playbackInfo.m_nSourceWidth, &m_playbackInfo.m_nSourceHeight );
m_VideoMaterial->GetVideoTexCoordRange( &m_playbackInfo.m_flU, &m_playbackInfo.m_flV );
m_playbackInfo.m_pMaterial = m_VideoMaterial->GetMaterial();
// Get our playback dimensions
CalculatePlaybackDimensions( m_playbackInfo.m_nSourceWidth, m_playbackInfo.m_nSourceHeight );
// Bind our texture
m_nTextureId = surface()->CreateNewTextureID( true );
g_pMatSystemSurface->DrawSetTextureMaterial( m_nTextureId, m_playbackInfo.m_pMaterial );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Update and draw the frame
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::Paint( void )
{
// Masters must keep the video updated
if ( m_bSlaved == false && m_VideoMaterial == NULL )
{
BaseClass::Paint();
return;
}
// Sit in the "center"
int xpos, ypos;
GetPanelPos( xpos, ypos );
// Black out the background (we could omit drawing under the video surface, but this is straight-forward)
if ( m_bBlackBackground )
{
surface()->DrawSetColor( 0, 0, 0, 255 );
surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() );
}
// Draw it
surface()->DrawSetTexture( m_nTextureId );
surface()->DrawSetColor( 255, 255, 255, 255 );
surface()->DrawTexturedSubRect( xpos, ypos, xpos+m_nPlaybackWidth, ypos+m_nPlaybackHeight, 0.0f, 0.0f, m_playbackInfo.m_flU, m_playbackInfo.m_flV );
// Parent's turn
BaseClass::Paint();
}

View File

@ -16,20 +16,59 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
static CUtlVector< VideoPanel * > g_vecVideoPanels;
// Thiis is a hack due to the fact that the user can type quit with the video panel up, but it's parented to the GameUI dll root panel, which is already gone so
// we would crash in the destructor
void VGui_ClearVideoPanels()
{
for ( int i = g_vecVideoPanels.Count() - 1; i >= 0; --i )
{
if ( g_vecVideoPanels[ i ] )
{
delete g_vecVideoPanels[ i ];
}
}
g_vecVideoPanels.RemoveAll();
}
struct VideoPanelParms_t
{
VideoPanelParms_t( bool _interrupt = true, bool _loop = false, bool _mute = false )
{
bAllowInterrupt = _interrupt;
bLoop = _loop;
bMute = _mute;
}
bool bAllowInterrupt;
bool bLoop;
bool bMute;
//float flFadeIn;
//float flFadeOut;
};
VideoPanel::VideoPanel( unsigned int nXPos, unsigned int nYPos, unsigned int nHeight, unsigned int nWidth, bool allowAlternateMedia ) :
BaseClass( NULL, "VideoPanel" ),
m_VideoMaterial( NULL ),
m_nPlaybackWidth( 0 ),
m_nPlaybackHeight( 0 ),
m_bAllowAlternateMedia( allowAlternateMedia )
m_nShutdownCount( 0 ),
m_bLooping( false ),
m_bStopAllSounds( true ),
m_bAllowInterruption( true ),
m_bAllowAlternateMedia( allowAlternateMedia ),
m_bStarted( false )
{
#ifdef MAPBASE
vgui::VPANEL pParent = enginevgui->GetPanel( PANEL_ROOT );
#else
vgui::VPANEL pParent = enginevgui->GetPanel( PANEL_GAMEUIDLL );
#endif
SetParent( pParent );
SetVisible( false );
@ -53,6 +92,11 @@ VideoPanel::VideoPanel( unsigned int nXPos, unsigned int nYPos, unsigned int nHe
SetScheme(vgui::scheme()->LoadSchemeFromFile( "resource/VideoPanelScheme.res", "VideoPanelScheme"));
LoadControlSettings("resource/UI/VideoPanel.res");
// Let us update
vgui::ivgui()->AddTickSignal( GetVPanel() );
g_vecVideoPanels.AddToTail( this );
}
//-----------------------------------------------------------------------------
@ -60,6 +104,8 @@ VideoPanel::VideoPanel( unsigned int nXPos, unsigned int nYPos, unsigned int nHe
//-----------------------------------------------------------------------------
VideoPanel::~VideoPanel( void )
{
g_vecVideoPanels.FindAndRemove( this );
SetParent( (vgui::Panel *) NULL );
// Shut down this video, destroy the video material
@ -70,13 +116,39 @@ VideoPanel::~VideoPanel( void )
}
}
//-----------------------------------------------------------------------------
// Purpose: Keeps a tab on when the movie is ending and allows a frame to pass to prevent threading issues
//-----------------------------------------------------------------------------
void VideoPanel::OnTick( void )
{
if ( m_nShutdownCount > 0 )
{
m_nShutdownCount++;
if ( m_nShutdownCount > 10 )
{
OnClose();
m_nShutdownCount = 0;
}
}
BaseClass::OnTick();
}
void VideoPanel::OnVideoOver()
{
StopPlayback();
}
//-----------------------------------------------------------------------------
// Purpose: Begins playback of a movie
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool VideoPanel::BeginPlayback( const char *pFilename )
{
// Who the heck hacked this in?
if ( !pFilename || pFilename[ 0 ] == '\0' )
return false;
#ifdef _X360
XVIDEO_MODE videoMode;
XGetVideoMode( &videoMode );
@ -106,9 +178,25 @@ bool VideoPanel::BeginPlayback( const char *pFilename )
if ( m_VideoMaterial == NULL )
return false;
if ( m_bLooping )
{
m_VideoMaterial->SetLooping( true );
}
#ifdef MAPBASE
if ( m_bMuted )
{
m_VideoMaterial->SetMuted( true );
}
#endif
m_bStarted = true;
// We want to be the sole audio source
// FIXME: This may not always be true!
enginesound->NotifyBeginMoviePlayback();
if ( m_bStopAllSounds )
{
enginesound->NotifyBeginMoviePlayback();
}
int nWidth, nHeight;
m_VideoMaterial->GetVideoImageSize( &nWidth, &nHeight );
@ -168,9 +256,10 @@ void VideoPanel::DoModal( void )
//-----------------------------------------------------------------------------
void VideoPanel::OnKeyCodeTyped( vgui::KeyCode code )
{
if ( code == KEY_ESCAPE )
bool bInterruptKeyPressed = ( code == KEY_ESCAPE );
if ( m_bAllowInterruption && bInterruptKeyPressed )
{
OnClose();
StopPlayback();
}
else
{
@ -181,34 +270,54 @@ void VideoPanel::OnKeyCodeTyped( vgui::KeyCode code )
//-----------------------------------------------------------------------------
// Purpose: Handle keys that should cause us to close
//-----------------------------------------------------------------------------
void VideoPanel::OnKeyCodePressed( vgui::KeyCode code )
void VideoPanel::OnKeyCodePressed( vgui::KeyCode keycode )
{
vgui::KeyCode code = GetBaseButtonCode( keycode );
// All these keys will interrupt playback
bool bInterruptKeyPressed = ( code == KEY_ESCAPE ||
code == KEY_BACKQUOTE ||
code == KEY_SPACE ||
code == KEY_ENTER ||
code == KEY_XBUTTON_A ||
code == KEY_XBUTTON_B ||
code == KEY_XBUTTON_X ||
code == KEY_XBUTTON_Y ||
code == KEY_XBUTTON_START ||
code == KEY_XBUTTON_BACK );
// These keys cause the panel to shutdown
if ( code == KEY_ESCAPE ||
code == KEY_BACKQUOTE ||
code == KEY_SPACE ||
code == KEY_ENTER ||
code == KEY_XBUTTON_A ||
code == KEY_XBUTTON_B ||
code == KEY_XBUTTON_X ||
code == KEY_XBUTTON_Y ||
code == KEY_XBUTTON_START ||
code == KEY_XBUTTON_BACK )
if ( m_bAllowInterruption && bInterruptKeyPressed )
{
OnClose();
StopPlayback();
}
else
{
BaseClass::OnKeyCodePressed( code );
BaseClass::OnKeyCodePressed( keycode );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void VideoPanel::StopPlayback( void )
{
SetVisible( false );
// Start the deferred shutdown process
m_nShutdownCount = 1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void VideoPanel::OnClose( void )
{
enginesound->NotifyEndMoviePlayback();
if ( m_bStopAllSounds )
{
enginesound->NotifyEndMoviePlayback();
}
BaseClass::OnClose();
if ( vgui::input()->GetAppModalSurface() == GetVPanel() )
@ -224,7 +333,6 @@ void VideoPanel::OnClose( void )
engine->ClientCmd( m_szExitCommand );
}
SetVisible( false );
MarkForDeletion();
}
@ -247,26 +355,52 @@ void VideoPanel::Paint( void )
if ( m_VideoMaterial == NULL )
return;
float alpha = ((float)GetFgColor()[3]/255.0f);
#ifdef MAPBASE
if (m_flFadeIn != 0.0f || m_flFadeOut != 0.0f)
{
// GetCurrentVideoTime() and GetVideoDuration() are borked
float flFrameCount = m_VideoMaterial->GetFrameCount();
float flEnd = flFrameCount / m_VideoMaterial->GetVideoFrameRate().GetFPS();
float flTime = ((float)(m_VideoMaterial->GetCurrentFrame()) / flFrameCount) * flEnd;
float flFadeOutDelta = (flEnd - m_flFadeOut);
if (flTime <= m_flFadeIn)
{
alpha = (flTime / m_flFadeIn);
}
else if (flTime >= flFadeOutDelta)
{
alpha = (1.0f - ((flTime - flFadeOutDelta) / m_flFadeOut));
}
}
#endif
if ( m_VideoMaterial->Update() == false )
{
// Issue a close command
OnVideoOver();
OnClose();
//OnClose();
}
// Sit in the "center"
int xpos, ypos;
GetPanelPos( xpos, ypos );
LocalToScreen( xpos, ypos );
// Black out the background (we could omit drawing under the video surface, but this is straight-forward)
if ( m_bBlackBackground )
{
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawSetColor( 0, 0, 0, alpha * 255.0f );
vgui::surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() );
}
// Draw the polys to draw this out
CMatRenderContextPtr pRenderContext( materials );
#ifdef MAPBASE
pRenderContext->ClearColor4ub( 255, 255, 255, alpha * 255.0f );
#endif
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
@ -306,8 +440,6 @@ void VideoPanel::Paint( void )
flTopY = FLerp( 1, -1, 0, vh ,flTopY );
flBottomY = FLerp( 1, -1, 0, vh, flBottomY );
float alpha = ((float)GetFgColor()[3]/255.0f);
for ( int corner=0; corner<4; corner++ )
{
bool bLeft = (corner==0) || (corner==3);
@ -340,16 +472,37 @@ void VideoPanel::Paint( void )
bool VideoPanel_Create( unsigned int nXPos, unsigned int nYPos,
unsigned int nWidth, unsigned int nHeight,
const char *pVideoFilename,
const char *pExitCommand /*= NULL*/)
const char *pExitCommand /*= NULL*/,
const VideoPanelParms_t &parms )
{
// Create the base video panel
VideoPanel *pVideoPanel = new VideoPanel( nXPos, nYPos, nHeight, nWidth, false );
VideoPanel *pVideoPanel = new VideoPanel( nXPos, nYPos, nHeight, nWidth );
if ( pVideoPanel == NULL )
return false;
// Toggle if we want the panel to allow interruption
pVideoPanel->SetAllowInterrupt( parms.bAllowInterrupt );
// Set the command we'll call (if any) when the video is interrupted or completes
pVideoPanel->SetExitCommand( pExitCommand );
#ifdef MAPBASE
// Toggle if we want the panel to loop (inspired by Portal 2)
pVideoPanel->SetLooping( parms.bLoop );
// Toggle if we want the panel to be muted
pVideoPanel->SetMuted( parms.bMute );
// TODO: Unique "Stop All Sounds" parameter
if (parms.bMute)
{
pVideoPanel->SetStopAllSounds( false );
}
// Fade parameters (unfinished)
//pVideoPanel->SetFade( parms.flFadeIn, parms.flFadeOut );
#endif
// Start it going
if ( pVideoPanel->BeginPlayback( pVideoFilename ) == false )
{
@ -364,8 +517,29 @@ bool VideoPanel_Create( unsigned int nXPos, unsigned int nYPos,
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback (Debug) -
// user must include file extension
// Purpose: Create a video panel with the supplied commands
//-----------------------------------------------------------------------------
void CreateVideoPanel( const char *lpszFilename, const char *lpszExitCommand, int nWidth, int nHeight, VideoPanelParms_t &parms )
{
char strFullpath[MAX_PATH];
Q_strncpy( strFullpath, "media/", MAX_PATH ); // Assume we must play out of the media directory
char strFilename[MAX_PATH];
Q_StripExtension( lpszFilename, strFilename, MAX_PATH );
Q_strncat( strFullpath, lpszFilename, MAX_PATH );
// Use the full screen size if they haven't specified an override
unsigned int nScreenWidth = ( nWidth != 0 ) ? nWidth : ScreenWidth();
unsigned int nScreenHeight = ( nHeight != 0 ) ? nHeight : ScreenHeight();
// Create the panel and go!
if ( VideoPanel_Create( 0, 0, nScreenWidth, nScreenHeight, strFullpath, lpszExitCommand, parms ) == false )
{
Warning( "Unable to play video: %s\n", strFullpath );
}
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback
//-----------------------------------------------------------------------------
CON_COMMAND( playvideo, "Plays a video: <filename> [width height]" )
@ -375,30 +549,32 @@ CON_COMMAND( playvideo, "Plays a video: <filename> [width height]" )
unsigned int nScreenWidth = Q_atoi( args[2] );
unsigned int nScreenHeight = Q_atoi( args[3] );
char strFullpath[MAX_PATH];
Q_strncpy( strFullpath, "media/", MAX_PATH ); // Assume we must play out of the media directory
char strFilename[MAX_PATH];
Q_StripExtension( args[1], strFilename, MAX_PATH );
Q_strncat( strFullpath, args[1], MAX_PATH );
if ( nScreenWidth == 0 )
{
nScreenWidth = ScreenWidth();
}
if ( nScreenHeight == 0 )
{
nScreenHeight = ScreenHeight();
}
// Create the panel and go!
if ( VideoPanel_Create( 0, 0, nScreenWidth, nScreenHeight, strFullpath ) == false )
{
Warning( "Unable to play video: %s\n", strFullpath );
}
// New struct; functionally identical
VideoPanelParms_t parms;
CreateVideoPanel( args[1], NULL, nScreenWidth, nScreenHeight, parms );
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback
//-----------------------------------------------------------------------------
CON_COMMAND( playvideo_nointerrupt, "Plays a video without ability to skip: <filename> [width height]" )
{
if ( args.ArgC() < 2 )
return;
unsigned int nScreenWidth = Q_atoi( args[2] );
unsigned int nScreenHeight = Q_atoi( args[3] );
// New struct; functionally identical
VideoPanelParms_t parms( false );
CreateVideoPanel( args[1], NULL, nScreenWidth, nScreenHeight, parms );
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback and fire a command on completion
//-----------------------------------------------------------------------------
@ -408,21 +584,78 @@ CON_COMMAND( playvideo_exitcommand, "Plays a video and fires and exit command wh
if ( args.ArgC() < 2 )
return;
unsigned int nScreenWidth = ScreenWidth();
unsigned int nScreenHeight = ScreenHeight();
char strFullpath[MAX_PATH];
Q_strncpy( strFullpath, "media/", MAX_PATH ); // Assume we must play out of the media directory
char strFilename[MAX_PATH];
Q_StripExtension( args[1], strFilename, MAX_PATH );
Q_strncat( strFullpath, args[1], MAX_PATH );
// Pull out the exit command we want to use
char *pExitCommand = Q_strstr( args.GetCommandString(), args[2] );
// Create the panel and go!
if ( VideoPanel_Create( 0, 0, nScreenWidth, nScreenHeight, strFullpath, pExitCommand ) == false )
// New struct; functionally identical
VideoPanelParms_t parms;
CreateVideoPanel( args[1], pExitCommand, 0, 0, parms );
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback and fire a command on completion
//-----------------------------------------------------------------------------
CON_COMMAND( playvideo_exitcommand_nointerrupt, "Plays a video (without interruption) and fires and exit command when it is stopped or finishes: <filename> <exit command>" )
{
if ( args.ArgC() < 2 )
return;
// Pull out the exit command we want to use
char *pExitCommand = Q_strstr( args.GetCommandString(), args[2] );
// New struct; functionally identical
VideoPanelParms_t parms( false );
CreateVideoPanel( args[1], pExitCommand, 0, 0, parms );
}
//-----------------------------------------------------------------------------
// Purpose: Cause all playback to stop
//-----------------------------------------------------------------------------
CON_COMMAND( stopvideos, "Stops all videos playing to the screen" )
{
FOR_EACH_VEC( g_vecVideoPanels, itr )
{
Warning( "Unable to play video: %s\n", strFullpath );
engine->ClientCmd( pExitCommand );
g_vecVideoPanels[itr]->StopPlayback();
}
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback and fire a command on completion
//-----------------------------------------------------------------------------
CON_COMMAND( playvideo_complex, "Plays a video with various parameters to simplify logic_playmovie: <filename> <exit command> <no interrupt> <looping> <fade in> <fade out>" )
{
if ( args.ArgC() < 2 )
return;
// Pull out the exit command we want to use
char *pExitCommand = Q_strstr( args.GetCommandString(), args[2] );
// Parameters
VideoPanelParms_t parms;
if (args.ArgC() >= 3)
parms.bAllowInterrupt = atoi( args[3] ) != 0;
if (args.ArgC() >= 4)
parms.bLoop = atoi( args[4] ) != 0;
if (args.ArgC() >= 5)
parms.bMute = atoi( args[5] ) != 0;
//if (args.ArgC() >= 5)
// parms.flFadeIn = atof( args[5] );
//if (args.ArgC() >= 6)
// parms.flFadeOut = atof( args[6] );
// Stop a softlock
if (parms.bAllowInterrupt == false && parms.bLoop)
{
Warning( "WARNING: Tried to play video set to be uninterruptible and looping. This would cause a softlock because the video loops forever and there's no way to stop it.\n" );
return;
}
CreateVideoPanel( args[1], pExitCommand, 0, 0, parms );
}

View File

@ -45,14 +45,22 @@ public:
}
bool BeginPlayback( const char *pFilename );
void StopPlayback( void );
void SetBlackBackground( bool bBlack ){ m_bBlackBackground = bBlack; }
void SetAllowInterrupt( bool bAllowInterrupt ) { m_bAllowInterruption = bAllowInterrupt; }
void SetStopAllSounds( bool bStopAllSounds ) { m_bStopAllSounds = bStopAllSounds; }
#ifdef MAPBASE
void SetLooping( bool bLooping ) { m_bLooping = bLooping; }
void SetMuted( bool bMuted ) { m_bMuted = bMuted; }
void SetFade( float flStartFade, float flEndFade ) { m_flFadeIn = flStartFade; m_flFadeOut = flEndFade; }
#endif
protected:
virtual void OnTick( void ) { BaseClass::OnTick(); }
virtual void OnTick( void );
virtual void OnCommand( const char *pcCommand ) { BaseClass::OnCommand( pcCommand ); }
virtual void OnVideoOver(){}
virtual void OnVideoOver();
protected:
IVideoMaterial *m_VideoMaterial;
@ -65,8 +73,19 @@ protected:
float m_flU; // U,V ranges for video on its sheet
float m_flV;
bool m_bLooping;
#ifdef MAPBASE
float m_flFadeIn;
float m_flFadeOut;
bool m_bMuted;
#endif
bool m_bStopAllSounds;
bool m_bAllowInterruption;
bool m_bBlackBackground;
bool m_bAllowAlternateMedia;
int m_nShutdownCount;
bool m_bStarted;
};

View File

@ -461,6 +461,11 @@ bool DoIncludeScript( const char *pszScript, HSCRIPT hScope )
}
#ifdef MAPBASE_VSCRIPT
static float FrameTime()
{
return gpGlobals->frametime;
}
static bool Con_IsVisible()
{
return engine->Con_IsVisible();
@ -585,6 +590,7 @@ bool VScriptClientInit()
ScriptRegisterFunction( g_pScriptVM, DoUniqueString, SCRIPT_ALIAS( "UniqueString", "Generate a string guaranteed to be unique across the life of the script VM, with an optional root string." ) );
ScriptRegisterFunction( g_pScriptVM, DoIncludeScript, "Execute a script (internal)" );
#ifdef MAPBASE_VSCRIPT
ScriptRegisterFunction( g_pScriptVM, FrameTime, "Get the time spent on the client in the last frame" );
ScriptRegisterFunction( g_pScriptVM, Con_IsVisible, "Returns true if the console is visible" );
ScriptRegisterFunction( g_pScriptVM, ScreenWidth, "Width of the screen in pixels" );
ScriptRegisterFunction( g_pScriptVM, ScreenHeight, "Height of the screen in pixels" );

View File

@ -5,18 +5,26 @@ static char g_Script_vscript_client[] = R"vscript(
//
//=============================================================================
local DoUniqueString = DoUniqueString
local DoDispatchParticleEffect = DoDispatchParticleEffect
function UniqueString( string = "" )
{
return DoUniqueString( string.tostring() );
return DoUniqueString( "" + string );
}
function IncludeScript( name, scope = null )
{
if ( scope == null )
if ( !scope )
{
scope = this;
}
return ::DoIncludeScript( name, scope );
}
function DispatchParticleEffect( particleName, origin, angles, entity = null )
{
DoDispatchParticleEffect( particleName, origin, angles, entity );
}
)vscript";

View File

@ -427,6 +427,11 @@ void CAnimationLayer::DispatchAnimEvents( CBaseAnimating *eventHandler, CBaseAni
event.eventtime = pOwner->m_flAnimTime + (flCycle - m_flCycle) / flCycleRate + pOwner->GetAnimTimeInterval();
}
#ifdef MAPBASE_VSCRIPT
if (eventHandler->m_ScriptScope.IsInitialized() && eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
continue;
#endif
// Msg( "dispatch %d (%d : %.2f)\n", index - 1, event.event, event.eventtime );
eventHandler->HandleAnimEvent( &event );
}

View File

@ -212,6 +212,10 @@ static ConCommand creditsdone("creditsdone", CreditsDone_f );
extern ConVar sv_unlockedchapters;
#ifdef MAPBASE
extern int Mapbase_GetChapterCount();
#endif
void CCredits::OnRestore()
{
BaseClass::OnRestore();
@ -226,6 +230,10 @@ void CCredits::OnRestore()
void CCredits::RollOutroCredits()
{
#ifdef MAPBASE
// Don't set this if we're using Mapbase chapters or if sv_unlockedchapters is already greater than 15
if (Mapbase_GetChapterCount() <= 0 && sv_unlockedchapters.GetInt() < 15)
#endif
sv_unlockedchapters.SetValue( "15" );
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();

View File

@ -303,10 +303,11 @@ CSimpleSimTimer CAI_BaseNPC::m_AnyUpdateEnemyPosTimer;
#ifdef MAPBASE_VSCRIPT
// TODO: Better placement?
ScriptHook_t g_Hook_QueryHearSound;
ScriptHook_t g_Hook_QuerySeeEntity;
ScriptHook_t g_Hook_TranslateActivity;
ScriptHook_t g_Hook_TranslateSchedule;
ScriptHook_t CAI_BaseNPC::g_Hook_QueryHearSound;
ScriptHook_t CAI_BaseNPC::g_Hook_QuerySeeEntity;
ScriptHook_t CAI_BaseNPC::g_Hook_TranslateActivity;
ScriptHook_t CAI_BaseNPC::g_Hook_TranslateSchedule;
ScriptHook_t CAI_BaseNPC::g_Hook_GetActualShootPosition;
#endif
//
@ -10687,6 +10688,19 @@ void CAI_BaseNPC::CollectShotStats( const Vector &vecShootOrigin, const Vector &
//-----------------------------------------------------------------------------
Vector CAI_BaseNPC::GetActualShootPosition( const Vector &shootOrigin )
{
#ifdef MAPBASE_VSCRIPT
if (m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope(m_ScriptScope))
{
ScriptVariant_t functionReturn;
ScriptVariant_t args[] = { shootOrigin, ToHScript( GetEnemy() ) };
if (g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ))
{
if (functionReturn.m_type == FIELD_VECTOR && functionReturn.m_pVector->LengthSqr() != 0.0f)
return *functionReturn.m_pVector;
}
}
#endif
// Project the target's location into the future.
Vector vecEnemyLKP = GetEnemyLKP();
Vector vecEnemyOffset = GetEnemy()->BodyTarget( shootOrigin ) - GetEnemy()->GetAbsOrigin();
@ -12075,20 +12089,24 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
//
// Hooks
//
BEGIN_SCRIPTHOOK( g_Hook_QueryHearSound, "QueryHearSound", FIELD_BOOLEAN, "Called when the NPC is deciding whether to hear a CSound or not." )
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_QueryHearSound, "QueryHearSound", FIELD_BOOLEAN, "Called when the NPC is deciding whether to hear a CSound or not." )
DEFINE_SCRIPTHOOK_PARAM( "sound", FIELD_HSCRIPT )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( g_Hook_QuerySeeEntity, "QuerySeeEntity", FIELD_BOOLEAN, "Called when the NPC is deciding whether to see an entity or not." )
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_QuerySeeEntity, "QuerySeeEntity", FIELD_BOOLEAN, "Called when the NPC is deciding whether to see an entity or not." )
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( g_Hook_TranslateActivity, "NPC_TranslateActivity", FIELD_VARIANT, "Called when the NPC is translating their current activity. The activity is provided in both string and ID form. Should return either an activity string or an activity ID. Return -1 to not translate." )
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_TranslateActivity, "NPC_TranslateActivity", FIELD_VARIANT, "Called when the NPC is translating their current activity. The activity is provided in both string and ID form. Should return either an activity string or an activity ID. Return -1 to not translate." )
DEFINE_SCRIPTHOOK_PARAM( "activity", FIELD_CSTRING )
DEFINE_SCRIPTHOOK_PARAM( "activity_id", FIELD_INTEGER )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( g_Hook_TranslateSchedule, "NPC_TranslateSchedule", FIELD_VARIANT, "Called when the NPC is translating their current schedule. The schedule is provided in both string and ID form. Should return either a schedule string or a schedule ID. Return -1 to not translate." )
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_TranslateSchedule, "NPC_TranslateSchedule", FIELD_VARIANT, "Called when the NPC is translating their current schedule. The schedule is provided in both string and ID form. Should return either a schedule string or a schedule ID. Return -1 to not translate." )
DEFINE_SCRIPTHOOK_PARAM( "schedule", FIELD_CSTRING )
DEFINE_SCRIPTHOOK_PARAM( "schedule_id", FIELD_INTEGER )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_GetActualShootPosition, "GetActualShootPosition", FIELD_VOID, "Called when the NPC is getting their actual shoot position, using the default shoot position as the parameter. (NOTE: NPCs which override this themselves might not always use this hook!)" )
DEFINE_SCRIPTHOOK_PARAM( "shootOrigin", FIELD_VECTOR )
DEFINE_SCRIPTHOOK_PARAM( "target", FIELD_HSCRIPT )
END_SCRIPTHOOK()
END_SCRIPTDESC();
#endif

View File

@ -98,6 +98,11 @@ extern bool AIStrongOpt( void );
#ifdef MAPBASE
// Defines Mapbase's extended NPC response system usage.
#define EXPANDED_RESPONSE_SYSTEM_USAGE
// Use the model keyvalue if it is defined
#define DefaultOrCustomModel(defaultModel) GetModelName() != NULL_STRING ? STRING(GetModelName()) : defaultModel
#else
#define DefaultOrCustomModel() defaultModel
#endif
#ifdef EXPANDED_RESPONSE_SYSTEM_USAGE
@ -1237,6 +1242,8 @@ public:
int ScriptGetActivityID() { return GetActivity(); }
void ScriptSetActivity( const char *szActivity ) { SetActivity( (Activity)GetActivityID( szActivity ) ); }
void ScriptSetActivityID( int iActivity ) { SetActivity((Activity)iActivity); }
int ScriptTranslateActivity( const char *szActivity ) { return TranslateActivity( (Activity)GetActivityID( szActivity ) ); }
int ScriptTranslateActivityID( int iActivity ) { return TranslateActivity( (Activity)iActivity ); }
const char* VScriptGetSchedule();
int VScriptGetScheduleID();
@ -2304,6 +2311,15 @@ public:
CUtlVector<AIScheduleChoice_t> m_ScheduleHistory;
#endif//AI_MONITOR_FOR_OSCILLATION
#ifdef MAPBASE_VSCRIPT
static ScriptHook_t g_Hook_QueryHearSound;
static ScriptHook_t g_Hook_QuerySeeEntity;
static ScriptHook_t g_Hook_TranslateActivity;
static ScriptHook_t g_Hook_TranslateSchedule;
static ScriptHook_t g_Hook_GetActualShootPosition;
static ScriptHook_t g_Hook_OverrideMove;
#endif
private:
// Break into pieces!

View File

@ -1210,7 +1210,7 @@ void CAI_Expresser::SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... )
}
else
{
CGMsg( 1, CON_GROUP_CHOREO "%s", string );
CGMsg( 1, CON_GROUP_CHOREO, "%s", string );
}
UTIL_LogPrintf( string );
}

View File

@ -284,6 +284,7 @@ END_SEND_TABLE()
#ifdef MAPBASE_VSCRIPT
ScriptHook_t CBaseAnimating::g_Hook_OnServerRagdoll;
ScriptHook_t CBaseAnimating::g_Hook_HandleAnimEvent;
#endif
BEGIN_ENT_SCRIPTDESC( CBaseAnimating, CBaseEntity, "Animating models" )
@ -342,6 +343,10 @@ BEGIN_ENT_SCRIPTDESC( CBaseAnimating, CBaseEntity, "Animating models" )
DEFINE_SCRIPTHOOK_PARAM( "ragdoll", FIELD_HSCRIPT )
DEFINE_SCRIPTHOOK_PARAM( "submodel", FIELD_BOOLEAN )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( CBaseAnimating::g_Hook_HandleAnimEvent, "HandleAnimEvent", FIELD_BOOLEAN, "Called when handling animation events. Return false to cancel base handling." )
DEFINE_SCRIPTHOOK_PARAM( "event", FIELD_HSCRIPT )
END_SCRIPTHOOK()
#endif
END_SCRIPTDESC();
@ -1243,6 +1248,11 @@ void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler )
event.eventtime = m_flAnimTime + (flCycle - GetCycle()) / flCycleRate + GetAnimTimeInterval();
}
#ifdef MAPBASE_VSCRIPT
if (eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
continue;
#endif
/*
if (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)
{
@ -1273,6 +1283,29 @@ void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler )
}
}
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBaseAnimating::ScriptHookHandleAnimEvent( animevent_t *pEvent )
{
if (m_ScriptScope.IsInitialized() && g_Hook_HandleAnimEvent.CanRunInScope(m_ScriptScope))
{
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( pEvent );
// event
ScriptVariant_t args[] = { hEvent };
ScriptVariant_t returnValue = true;
g_Hook_HandleAnimEvent.Call( m_ScriptScope, &returnValue, args );
g_pScriptVM->RemoveInstance( hEvent );
return returnValue.m_bool;
}
return true;
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------

View File

@ -144,6 +144,9 @@ public:
bool HasAnimEvent( int nSequence, int nEvent );
virtual void DispatchAnimEvents ( CBaseAnimating *eventHandler ); // Handle events that have happend since last time called up until X seconds into the future
virtual void HandleAnimEvent( animevent_t *pEvent );
#ifdef MAPBASE_VSCRIPT
bool ScriptHookHandleAnimEvent( animevent_t *pEvent );
#endif
int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName );
inline int LookupPoseParameter( const char *szName ) { return LookupPoseParameter(GetModelPtr(), szName); }
@ -211,6 +214,7 @@ public:
void SetSkin( int iSkin ) { m_nSkin = iSkin; }
static ScriptHook_t g_Hook_OnServerRagdoll;
static ScriptHook_t g_Hook_HandleAnimEvent;
#endif
// These return the attachment in the space of the entity

View File

@ -284,6 +284,7 @@ IMPLEMENT_SERVERCLASS_ST_NOBASE( CBaseEntity, DT_BaseEntity )
#ifdef MAPBASE
// Keep consistent with VIEW_ID_COUNT in viewrender.h
SendPropInt (SENDINFO(m_iViewHideFlags), 9, SPROP_UNSIGNED ),
SendPropBool (SENDINFO(m_bDisableFlashlight) ),
#endif
SendPropInt (SENDINFO(m_iTeamNum), TEAMNUM_NUM_BITS, 0),
SendPropInt (SENDINFO(m_CollisionGroup), 5, SPROP_UNSIGNED),
@ -1915,6 +1916,7 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity )
DEFINE_GLOBAL_KEYFIELD( m_nModelIndex, FIELD_SHORT, "modelindex" ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_iViewHideFlags, FIELD_INTEGER, "viewhideflags" ),
DEFINE_KEYFIELD( m_bDisableFlashlight, FIELD_BOOLEAN, "disableflashlight" ),
#endif
#if !defined( NO_ENTITY_PREDICTION )
// DEFINE_FIELD( m_PredictableID, CPredictableId ),
@ -2148,6 +2150,8 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity )
DEFINE_INPUTFUNC( FIELD_INTEGER, "RemoveEffects", InputRemoveEffects ),
DEFINE_INPUTFUNC( FIELD_VOID, "EnableDraw", InputDrawEntity ),
DEFINE_INPUTFUNC( FIELD_VOID, "DisableDraw", InputUndrawEntity ),
DEFINE_INPUTFUNC( FIELD_VOID, "EnableReceivingFlashlight", InputEnableReceivingFlashlight ),
DEFINE_INPUTFUNC( FIELD_VOID, "DisableReceivingFlashlight", InputDisableReceivingFlashlight ),
DEFINE_INPUTFUNC( FIELD_INTEGER, "AddEFlags", InputAddEFlags ),
DEFINE_INPUTFUNC( FIELD_INTEGER, "RemoveEFlags", InputRemoveEFlags ),
DEFINE_INPUTFUNC( FIELD_INTEGER, "AddSolidFlags", InputAddSolidFlags ),
@ -2218,6 +2222,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
DEFINE_SCRIPTFUNC( SetModel, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelName, "GetModelName", "Returns the name of the model" )
DEFINE_SCRIPTFUNC_NAMED( ScriptStopSound, "StopSound", "Stops a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptEmitSound, "EmitSound", "Plays a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( VScriptPrecacheScriptSound, "PrecacheSoundScript", "Precache a sound for later playing." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSoundDuration, "GetSoundDuration", "Returns float duration of the sound. Takes soundname and optional actormodelname.")
@ -2262,6 +2267,9 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
DEFINE_SCRIPTFUNC( ApplyAbsVelocityImpulse, "" )
DEFINE_SCRIPTFUNC( ApplyLocalAngularVelocityImpulse, "" )
DEFINE_SCRIPTFUNC( BodyTarget, "" )
DEFINE_SCRIPTFUNC( HeadTarget, "" )
#endif
DEFINE_SCRIPTFUNC_NAMED( GetAbsVelocity, "GetVelocity", "" )
@ -2278,11 +2286,11 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
DEFINE_SCRIPTFUNC_NAMED( ScriptSetAngles, "SetAngles", "Set entity pitch, yaw, roll")
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAngles, "GetAngles", "Get entity pitch, yaw, roll as a vector")
DEFINE_SCRIPTFUNC_NAMED( ScriptSetSize, "SetSize", "" )
DEFINE_SCRIPTFUNC( SetSize, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMins, "GetBoundingMins", "Get a vector containing min bounds, centered on object")
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMaxs, "GetBoundingMaxs", "Get a vector containing max bounds, centered on object")
DEFINE_SCRIPTFUNC_NAMED( ScriptUtilRemove, "Destroy", "" )
DEFINE_SCRIPTFUNC_NAMED( Remove, "Destroy", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetOwner, "SetOwner", "" )
DEFINE_SCRIPTFUNC_NAMED( GetTeamNumber, "GetTeam", "" )
DEFINE_SCRIPTFUNC_NAMED( ChangeTeam, "SetTeam", "" )
@ -2583,10 +2591,10 @@ void CBaseEntity::UpdateOnRemove( void )
#ifdef MAPBASE_VSCRIPT
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
HSCRIPT h = m_ScriptThinkFuncs[i].m_hfnThink;
HSCRIPT h = m_ScriptThinkFuncs[i]->m_hfnThink;
if ( h ) g_pScriptVM->ReleaseScript( h );
}
m_ScriptThinkFuncs.Purge();
m_ScriptThinkFuncs.PurgeAndDeleteElements();
#endif // MAPBASE_VSCRIPT
}
}
@ -8264,6 +8272,22 @@ void CBaseEntity::InputUndrawEntity( inputdata_t& inputdata )
AddEffects(EF_NODRAW);
}
//-----------------------------------------------------------------------------
// Purpose: Inspired by the Portal 2 input of the same name.
//-----------------------------------------------------------------------------
void CBaseEntity::InputEnableReceivingFlashlight( inputdata_t& inputdata )
{
m_bDisableFlashlight = false;
}
//-----------------------------------------------------------------------------
// Purpose: Inspired by the Portal 2 input of the same name.
//-----------------------------------------------------------------------------
void CBaseEntity::InputDisableReceivingFlashlight( inputdata_t& inputdata )
{
m_bDisableFlashlight = true;
}
//-----------------------------------------------------------------------------
// Purpose: Adds eflags.
//-----------------------------------------------------------------------------
@ -8644,173 +8668,6 @@ void CBaseEntity::ScriptStopThinkFunction()
m_iszScriptThinkFunction = NULL_STRING;
SetContextThink( NULL, TICK_NEVER_THINK, "ScriptThink" );
}
static inline void ScriptStopContextThink( scriptthinkfunc_t *context )
{
g_pScriptVM->ReleaseScript( context->m_hfnThink );
context->m_hfnThink = NULL;
context->m_nNextThinkTick = TICK_NEVER_THINK;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptContextThink()
{
float flNextThink = FLT_MAX;
int nScheduledTick = 0;
for ( int i = m_ScriptThinkFuncs.Count(); i--; )
{
scriptthinkfunc_t *cur = &m_ScriptThinkFuncs[i];
if ( cur->m_nNextThinkTick == TICK_NEVER_THINK )
continue;
if ( cur->m_nNextThinkTick > gpGlobals->tickcount )
{
// There is more to execute, don't stop thinking if the rest are done.
// also find the shortest schedule
if ( !nScheduledTick || nScheduledTick > cur->m_nNextThinkTick )
{
nScheduledTick = cur->m_nNextThinkTick;
}
continue;
}
ScriptVariant_t varReturn;
if ( cur->m_bNoParam )
{
if ( g_pScriptVM->Call( cur->m_hfnThink, NULL, true, &varReturn ) == SCRIPT_ERROR )
{
ScriptStopContextThink(cur);
m_ScriptThinkFuncs.Remove(i);
continue;
}
}
else
{
if ( g_pScriptVM->Call( cur->m_hfnThink, NULL, true, &varReturn, m_hScriptInstance ) == SCRIPT_ERROR )
{
ScriptStopContextThink(cur);
m_ScriptThinkFuncs.Remove(i);
continue;
}
}
float flReturn;
if ( !varReturn.AssignTo( &flReturn ) )
{
ScriptStopContextThink(cur);
m_ScriptThinkFuncs.Remove(i);
continue;
}
if ( flReturn < 0.0f )
{
ScriptStopContextThink(cur);
m_ScriptThinkFuncs.Remove(i);
continue;
}
// find the shortest delay
if ( flReturn < flNextThink )
{
flNextThink = flReturn;
}
cur->m_nNextThinkTick = TIME_TO_TICKS( gpGlobals->curtime + flReturn );
}
if ( flNextThink < FLT_MAX )
{
SetNextThink( gpGlobals->curtime + flNextThink, "ScriptContextThink" );
}
else if ( nScheduledTick )
{
SetNextThink( TICKS_TO_TIME( nScheduledTick ), "ScriptContextThink" );
}
else
{
SetNextThink( TICK_NEVER_THINK, "ScriptContextThink" );
}
}
// see ScriptSetThink
static bool s_bScriptContextThinkNoParam = false;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float flTime )
{
scriptthinkfunc_t th;
V_memset( &th, 0x0, sizeof(scriptthinkfunc_t) );
unsigned short hash = ( szContext && *szContext ) ? HashString( szContext ) : 0;
bool bFound = false;
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
scriptthinkfunc_t f = m_ScriptThinkFuncs[i];
if ( hash == f.m_iContextHash )
{
th = f;
m_ScriptThinkFuncs.Remove(i); // reorder
bFound = true;
break;
}
}
if ( hFunc )
{
float nextthink = gpGlobals->curtime + flTime;
th.m_bNoParam = s_bScriptContextThinkNoParam;
th.m_hfnThink = hFunc;
th.m_iContextHash = hash;
th.m_nNextThinkTick = TIME_TO_TICKS( nextthink );
m_ScriptThinkFuncs.AddToHead( th );
int nexttick = GetNextThinkTick( RegisterThinkContext( "ScriptContextThink" ) );
// sooner than next think
if ( nexttick <= 0 || nexttick > th.m_nNextThinkTick )
{
SetContextThink( &CBaseEntity::ScriptContextThink, nextthink, "ScriptContextThink" );
}
}
// null func input, think exists
else if ( bFound )
{
ScriptStopContextThink( &th );
}
}
//-----------------------------------------------------------------------------
// m_bNoParam and s_bScriptContextThinkNoParam exist only to keep backwards compatibility
// and are an alternative to this script closure:
//
// function CBaseEntity::SetThink( func, time )
// {
// SetContextThink( "", function(_){ return func() }, time )
// }
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptSetThink( HSCRIPT hFunc, float time )
{
s_bScriptContextThinkNoParam = true;
ScriptSetContextThink( NULL, hFunc, time );
s_bScriptContextThinkNoParam = false;
}
void CBaseEntity::ScriptStopThink()
{
ScriptSetContextThink( NULL, NULL, 0.0f );
}
#endif // MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------

View File

@ -341,9 +341,9 @@ struct thinkfunc_t
#ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t
{
int m_nNextThinkTick;
HSCRIPT m_hfnThink;
unsigned short m_iContextHash;
int m_nNextThinkTick;
bool m_bNoParam;
};
#endif
@ -762,6 +762,8 @@ public:
void InputRemoveEffects( inputdata_t &inputdata );
void InputDrawEntity( inputdata_t &inputdata );
void InputUndrawEntity( inputdata_t &inputdata );
void InputEnableReceivingFlashlight( inputdata_t &inputdata );
void InputDisableReceivingFlashlight( inputdata_t &inputdata );
void InputAddEFlags( inputdata_t &inputdata );
void InputRemoveEFlags( inputdata_t &inputdata );
void InputAddSolidFlags( inputdata_t &inputdata );
@ -928,6 +930,9 @@ public:
//
// This was partly inspired by Underhell's keyvalue that allows entities to only render in mirrors and cameras.
CNetworkVar( int, m_iViewHideFlags );
// Disables receiving projected textures. Based on a keyvalue from later Source games.
CNetworkVar( bool, m_bDisableFlashlight );
#endif
// was pev->rendercolor
@ -2003,7 +2008,7 @@ public:
void ScriptStopThink();
void ScriptContextThink();
private:
CUtlVector< scriptthinkfunc_t > m_ScriptThinkFuncs;
CUtlVector< scriptthinkfunc_t* > m_ScriptThinkFuncs;
public:
#endif
const char* GetScriptId();
@ -2034,8 +2039,10 @@ public:
const Vector& ScriptGetAngles(void) { static Vector vec; QAngle qa = GetAbsAngles(); vec.x = qa.x; vec.y = qa.y; vec.z = qa.z; return vec; }
#endif
#ifndef MAPBASE_VSCRIPT
void ScriptSetSize(const Vector& mins, const Vector& maxs) { UTIL_SetSize(this, mins, maxs); }
void ScriptUtilRemove(void) { UTIL_Remove(this); }
#endif
void ScriptSetOwner(HSCRIPT hEntity) { SetOwnerEntity(ToEnt(hEntity)); }
void ScriptSetOrigin(const Vector& v) { Teleport(&v, NULL, NULL); }
void ScriptSetForward(const Vector& v) { QAngle angles; VectorAngles(v, angles); Teleport(NULL, &angles, NULL); }
@ -2061,6 +2068,7 @@ public:
const char* ScriptGetModelName(void) const;
HSCRIPT ScriptGetModelKeyValues(void);
void ScriptStopSound(const char* soundname);
void ScriptEmitSound(const char* soundname);
float ScriptSoundDuration(const char* soundname, const char* actormodel);

View File

@ -450,6 +450,11 @@ protected:
bool m_bSolidBsp; // Brush is SOLID_BSP
#ifdef MAPBASE
int m_iMinPitch = 30; // FANPITCHMIN
int m_iMaxPitch = 100; // FANPITCHMAX
#endif
public:
Vector m_vecClientOrigin;
QAngle m_vecClientAngles;
@ -472,6 +477,10 @@ BEGIN_DATADESC( CFuncRotating )
DEFINE_FIELD( m_angStart, FIELD_VECTOR ),
DEFINE_FIELD( m_bStopAtStartPos, FIELD_BOOLEAN ),
DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_iMinPitch, FIELD_INTEGER, "minpitch" ),
DEFINE_KEYFIELD( m_iMaxPitch, FIELD_INTEGER, "maxpitch" ),
#endif
// Function Pointers
DEFINE_FUNCTION( SpinUpMove ),
@ -823,8 +832,14 @@ void CFuncRotating::HurtTouch ( CBaseEntity *pOther )
}
#ifdef MAPBASE
// In Mapbase, use the keyvalues instead
#define FANPITCHMIN m_iMinPitch
#define FANPITCHMAX m_iMaxPitch
#else
#define FANPITCHMIN 30
#define FANPITCHMAX 100
#endif
//-----------------------------------------------------------------------------

View File

@ -850,7 +850,7 @@ void CEventQueue::Dump( void )
// Purpose: adds the action into the correct spot in the priority queue, targeting entity via string name
//-----------------------------------------------------------------------------
#ifdef MAPBASE_VSCRIPT
intptr_t
int
#else
void
#endif
@ -874,6 +874,7 @@ CEventQueue::AddEvent( const char *target, const char *targetInput, variant_t Va
AddEvent( newEvent );
#ifdef MAPBASE_VSCRIPT
Assert( sizeof(EventQueuePrioritizedEvent_t*) == sizeof(int) );
return reinterpret_cast<intptr_t>(newEvent); // POINTER_TO_INT
#endif
}
@ -882,7 +883,7 @@ CEventQueue::AddEvent( const char *target, const char *targetInput, variant_t Va
// Purpose: adds the action into the correct spot in the priority queue, targeting entity via pointer
//-----------------------------------------------------------------------------
#ifdef MAPBASE_VSCRIPT
intptr_t
int
#else
void
#endif
@ -906,6 +907,7 @@ CEventQueue::AddEvent( CBaseEntity *target, const char *targetInput, variant_t V
AddEvent( newEvent );
#ifdef MAPBASE_VSCRIPT
Assert( sizeof(EventQueuePrioritizedEvent_t*) == sizeof(int) );
return reinterpret_cast<intptr_t>(newEvent); // POINTER_TO_INT
#endif
}
@ -1293,7 +1295,7 @@ void CEventQueue::CancelEventsByInput( CBaseEntity *pTarget, const char *szInput
}
}
bool CEventQueue::RemoveEvent( intptr_t event )
bool CEventQueue::RemoveEvent( int event )
{
EventQueuePrioritizedEvent_t *pe = reinterpret_cast<EventQueuePrioritizedEvent_t*>(event); // INT_TO_POINTER
@ -1310,7 +1312,7 @@ bool CEventQueue::RemoveEvent( intptr_t event )
return false;
}
float CEventQueue::GetTimeLeft( intptr_t event )
float CEventQueue::GetTimeLeft( int event )
{
EventQueuePrioritizedEvent_t *pe = reinterpret_cast<EventQueuePrioritizedEvent_t*>(event); // INT_TO_POINTER

View File

@ -48,6 +48,7 @@ BEGIN_DATADESC( CEnvMicrophone )
DEFINE_KEYFIELD(m_iszLandmarkName, FIELD_STRING, "landmark"),
DEFINE_FIELD(m_hLandmark, FIELD_EHANDLE),
DEFINE_KEYFIELD(m_flPitchScale, FIELD_FLOAT, "PitchScale"),
DEFINE_KEYFIELD(m_flVolumeScale, FIELD_FLOAT, "VolumeScale"),
DEFINE_KEYFIELD(m_nChannel, FIELD_INTEGER, "channel"),
#endif
// DEFINE_FIELD(m_bAvoidFeedback, FIELD_BOOLEAN), // DONT SAVE
@ -61,6 +62,7 @@ BEGIN_DATADESC( CEnvMicrophone )
#ifdef MAPBASE
DEFINE_INPUTFUNC(FIELD_INTEGER, "SetDSPPreset", InputSetDSPPreset),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPitchScale", InputSetPitchScale ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetVolumeScale", InputSetVolumeScale ),
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetChannel", InputSetChannel ),
#endif
@ -272,6 +274,15 @@ void CEnvMicrophone::InputSetPitchScale( inputdata_t &inputdata )
m_flPitchScale = inputdata.value.Float();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &inputdata -
//-----------------------------------------------------------------------------
void CEnvMicrophone::InputSetVolumeScale( inputdata_t &inputdata )
{
m_flVolumeScale = inputdata.value.Float();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &inputdata -
@ -545,11 +556,13 @@ MicrophoneResult_t CEnvMicrophone::SoundPlayed( int entindex, const char *soundn
EmitSound_t ep;
#ifdef MAPBASE
ep.m_nChannel = m_nChannel;
if (m_flVolumeScale != 1.0f)
ep.m_flVolume = (flVolume * m_flVolumeScale);
#else
ep.m_nChannel = CHAN_STATIC;
ep.m_flVolume = flVolume;
#endif
ep.m_pSoundName = soundname;
ep.m_flVolume = flVolume;
ep.m_SoundLevel = soundlevel;
ep.m_nFlags = iFlags;
#ifdef MAPBASE

View File

@ -57,6 +57,7 @@ public:
#ifdef MAPBASE
void InputSetDSPPreset( inputdata_t &inputdata );
void InputSetPitchScale( inputdata_t &inputdata );
void InputSetVolumeScale( inputdata_t &inputdata );
void InputSetChannel( inputdata_t &inputdata );
#endif
@ -88,6 +89,7 @@ private:
string_t m_iszLandmarkName;
EHANDLE m_hLandmark;
float m_flPitchScale = 1.0f;
float m_flVolumeScale = 1.0f;
int m_nChannel = CHAN_STATIC;
#endif

View File

@ -41,8 +41,8 @@ class CEventQueue
public:
// pushes an event into the queue, targeting a string name (m_iName), or directly by a pointer
#ifdef MAPBASE_VSCRIPT
intptr_t AddEvent( const char *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
intptr_t AddEvent( CBaseEntity *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
int AddEvent( const char *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
int AddEvent( CBaseEntity *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
#else
void AddEvent( const char *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
void AddEvent( CBaseEntity *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
@ -73,8 +73,8 @@ public:
#ifdef MAPBASE_VSCRIPT
void CancelEventsByInput( CBaseEntity *pTarget, const char *szInput );
bool RemoveEvent( intptr_t event );
float GetTimeLeft( intptr_t event );
bool RemoveEvent( int event );
float GetTimeLeft( int event );
#endif // MAPBASE_VSCRIPT
private:

View File

@ -91,6 +91,7 @@ BEGIN_DATADESC( CBounceBomb )
DEFINE_KEYFIELD( m_iInitialState, FIELD_INTEGER, "InitialState" ),
DEFINE_KEYFIELD( m_bCheapWarnSound, FIELD_BOOLEAN, "CheapWarnSound" ),
DEFINE_KEYFIELD( m_iLOSMask, FIELD_INTEGER, "LOSMask" ),
DEFINE_INPUT( m_bUnavoidable, FIELD_BOOLEAN, "SetUnavoidable" ),
#endif
DEFINE_KEYFIELD( m_iModification, FIELD_INTEGER, "Modification" ),
@ -1485,6 +1486,18 @@ CBasePlayer *CBounceBomb::HasPhysicsAttacker( float dt )
return NULL;
}
//---------------------------------------------------------
//---------------------------------------------------------
bool CBounceBomb::ShouldBeAvoidedByCompanions()
{
#ifdef MAPBASE
if (m_bUnavoidable)
return false;
#endif
return !IsPlayerPlaced() && IsAwake();
}
//---------------------------------------------------------
//---------------------------------------------------------
void CBounceBomb::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason )

View File

@ -72,6 +72,9 @@ public:
bool IsPlayerPlaced() { return m_bPlacedByPlayer; }
// Determines whether companions should treat the mine as a navigation obstacle and avoid it
bool ShouldBeAvoidedByCompanions();
bool CreateVPhysics()
{
VPhysicsInitNormal( SOLID_VPHYSICS, 0, false );
@ -125,6 +128,8 @@ private:
// Allows control over the mask used in LOS
int m_iLOSMask;
bool m_bUnavoidable;
#endif
bool m_bPlacedByPlayer;

View File

@ -278,6 +278,7 @@ public:
CUtlDict<string_t, int> m_QueuedKV;
int m_MaxArmor = 100;
int m_SuitZoomFOV = 25;
#endif
bool PassesDamageFilter( const CTakeDamageInfo &info );
@ -1760,7 +1761,11 @@ void CHL2_Player::ToggleZoom(void)
//-----------------------------------------------------------------------------
void CHL2_Player::StartZooming( void )
{
#ifdef MAPBASE
int iFOV = GetPlayerProxy() ? GetPlayerProxy()->m_SuitZoomFOV : 25;
#else
int iFOV = 25;
#endif
if ( SetFOV( this, iFOV, 0.4f ) )
{
m_HL2Local.m_bZooming = true;
@ -4615,6 +4620,7 @@ BEGIN_DATADESC( CLogicPlayerProxy )
DEFINE_INPUTFUNC( FIELD_STRING, "SetPlayerModel", InputSetPlayerModel ),
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawExternally", InputSetPlayerDrawExternally ),
DEFINE_INPUT( m_MaxArmor, FIELD_INTEGER, "SetMaxInputArmor" ),
DEFINE_INPUT( m_SuitZoomFOV, FIELD_INTEGER, "SetSuitZoomFOV" ),
#endif
DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ),
END_DATADESC()

View File

@ -277,17 +277,17 @@ void CNPC_Antlion::Spawn( void )
#ifdef HL2_EPISODIC
if ( IsWorker() )
{
SetModel( ANTLION_WORKER_MODEL );
SetModel( DefaultOrCustomModel(ANTLION_WORKER_MODEL) );
AddSpawnFlags( SF_NPC_LONG_RANGE );
SetBloodColor( BLOOD_COLOR_ANTLION_WORKER );
}
else
{
SetModel( ANTLION_MODEL );
SetModel( DefaultOrCustomModel(ANTLION_MODEL) );
SetBloodColor( BLOOD_COLOR_ANTLION );
}
#else
SetModel( ANTLION_MODEL );
SetModel( DefaultOrCustomModel(ANTLION_MODEL) );
SetBloodColor( BLOOD_COLOR_YELLOW );
#endif // HL2_EPISODIC

View File

@ -678,7 +678,7 @@ void CNPC_AntlionGuard::UpdateOnRemove( void )
//-----------------------------------------------------------------------------
void CNPC_AntlionGuard::Precache( void )
{
PrecacheModel( ANTLIONGUARD_MODEL );
PrecacheModel( DefaultOrCustomModel( ANTLIONGUARD_MODEL ) );
PrecacheScriptSound( "NPC_AntlionGuard.Shove" );
PrecacheScriptSound( "NPC_AntlionGuard.HitHard" );
@ -779,7 +779,7 @@ void CNPC_AntlionGuard::Spawn( void )
{
Precache();
SetModel( ANTLIONGUARD_MODEL );
SetModel( DefaultOrCustomModel( ANTLIONGUARD_MODEL ) );
// Switch our skin (for now), if we're the cavern guard
if ( m_bCavernBreed )

View File

@ -266,7 +266,7 @@ void CNPC_Barnacle::Spawn()
{
Precache( );
SetModel( "models/barnacle.mdl" );
SetModel( DefaultOrCustomModel( "models/barnacle.mdl" ) );
UTIL_SetSize( this, Vector(-16, -16, -40), Vector(16, 16, 0) );
SetSolid( SOLID_BBOX );
@ -2375,7 +2375,7 @@ const impactdamagetable_t &CNPC_Barnacle::GetPhysicsImpactDamageTable( void )
//=========================================================
void CNPC_Barnacle::Precache()
{
PrecacheModel("models/barnacle.mdl");
PrecacheModel( DefaultOrCustomModel( "models/barnacle.mdl" ) );
// Precache all gibs
for ( int i=0; i < ARRAYSIZE(m_szGibNames); i++ )

View File

@ -2433,7 +2433,7 @@ void CBaseHeadcrab::CreateDust( bool placeDecal )
//-----------------------------------------------------------------------------
void CHeadcrab::Precache( void )
{
PrecacheModel( "models/headcrabclassic.mdl" );
PrecacheModel( DefaultOrCustomModel( "models/headcrabclassic.mdl" ) );
PrecacheScriptSound( "NPC_HeadCrab.Gib" );
PrecacheScriptSound( "NPC_HeadCrab.Idle" );
@ -2455,7 +2455,7 @@ void CHeadcrab::Precache( void )
void CHeadcrab::Spawn( void )
{
Precache();
SetModel( "models/headcrabclassic.mdl" );
SetModel( DefaultOrCustomModel( "models/headcrabclassic.mdl" ) );
BaseClass::Spawn();
@ -2570,7 +2570,7 @@ END_DATADESC()
//-----------------------------------------------------------------------------
void CFastHeadcrab::Precache( void )
{
PrecacheModel( "models/headcrab.mdl" );
PrecacheModel( DefaultOrCustomModel( "models/headcrab.mdl" ) );
PrecacheScriptSound( "NPC_FastHeadcrab.Idle" );
PrecacheScriptSound( "NPC_FastHeadcrab.Alert" );
@ -2589,7 +2589,7 @@ void CFastHeadcrab::Precache( void )
void CFastHeadcrab::Spawn( void )
{
Precache();
SetModel( "models/headcrab.mdl" );
SetModel( DefaultOrCustomModel( "models/headcrab.mdl" ) );
BaseClass::Spawn();
@ -3089,7 +3089,7 @@ void CBlackHeadcrab::TelegraphSound( void )
void CBlackHeadcrab::Spawn( void )
{
Precache();
SetModel( "models/headcrabblack.mdl" );
SetModel( DefaultOrCustomModel( "models/headcrabblack.mdl" ) );
BaseClass::Spawn();
@ -3106,7 +3106,7 @@ void CBlackHeadcrab::Spawn( void )
//-----------------------------------------------------------------------------
void CBlackHeadcrab::Precache( void )
{
PrecacheModel( "models/headcrabblack.mdl" );
PrecacheModel( DefaultOrCustomModel( "models/headcrabblack.mdl" ) );
PrecacheScriptSound( "NPC_BlackHeadcrab.Telegraph" );
PrecacheScriptSound( "NPC_BlackHeadcrab.Attack" );

View File

@ -2193,9 +2193,9 @@ void CNPC_Manhack::Precache(void)
//
// Model.
//
PrecacheModel("models/manhack.mdl");
PrecacheModel( DefaultOrCustomModel( "models/manhack.mdl" ) );
PrecacheModel( MANHACK_GLOW_SPRITE );
PropBreakablePrecacheAll( MAKE_STRING("models/manhack.mdl") );
PropBreakablePrecacheAll( MAKE_STRING( DefaultOrCustomModel( "models/manhack.mdl" ) ) );
PrecacheScriptSound( "NPC_Manhack.Die" );
PrecacheScriptSound( "NPC_Manhack.Bat" );
@ -2389,7 +2389,7 @@ void CNPC_Manhack::Spawn(void)
AddSpawnFlags( SF_NPC_FADE_CORPSE );
#endif // _XBOX
SetModel( "models/manhack.mdl" );
SetModel( DefaultOrCustomModel( "models/manhack.mdl" ) );
SetHullType(HULL_TINY_CENTERED);
SetHullSizeNormal();

View File

@ -3423,7 +3423,7 @@ bool CNPC_PlayerCompanion::OverrideMove( float flInterval )
else if ( pEntity->m_iClassname == iszBounceBomb )
{
CBounceBomb *pBomb = static_cast<CBounceBomb *>(pEntity);
if ( pBomb && !pBomb->IsPlayerPlaced() && pBomb->IsAwake() )
if ( pBomb && pBomb->ShouldBeAvoidedByCompanions() )
{
UTIL_TraceLine( WorldSpaceCenter(), pEntity->WorldSpaceCenter(), MASK_BLOCKLOS, pEntity, COLLISION_GROUP_NONE, &tr );
if (tr.fraction == 1.0 && !tr.startsolid)

View File

@ -256,11 +256,11 @@ void CNPC_CScanner::Spawn(void)
if( m_bIsClawScanner )
{
SetModel( "models/shield_scanner.mdl");
SetModel( DefaultOrCustomModel( "models/shield_scanner.mdl" ) );
}
else
{
SetModel( "models/combine_scanner.mdl");
SetModel( DefaultOrCustomModel( "models/combine_scanner.mdl" ) );
}
m_iHealth = sk_scanner_health.GetFloat();
@ -565,7 +565,7 @@ void CNPC_CScanner::Precache(void)
// Model
if( m_bIsClawScanner )
{
PrecacheModel("models/shield_scanner.mdl");
PrecacheModel( DefaultOrCustomModel( "models/shield_scanner.mdl" ) );
PrecacheModel("models/gibs/Shield_Scanner_Gib1.mdl");
PrecacheModel("models/gibs/Shield_Scanner_Gib2.mdl");
@ -591,7 +591,7 @@ void CNPC_CScanner::Precache(void)
}
else
{
PrecacheModel("models/combine_scanner.mdl");
PrecacheModel( DefaultOrCustomModel( "models/combine_scanner.mdl" ) );
PrecacheModel("models/gibs/scanner_gib01.mdl" );
PrecacheModel("models/gibs/scanner_gib02.mdl" );

View File

@ -278,7 +278,7 @@ void CNPC_Stalker::Spawn( void )
{
Precache( );
SetModel( "models/stalker.mdl" );
SetModel( DefaultOrCustomModel( "models/stalker.mdl" ) );
SetHullType(HULL_HUMAN);
SetHullSizeNormal();
@ -321,7 +321,7 @@ void CNPC_Stalker::Spawn( void )
//-----------------------------------------------------------------------------
void CNPC_Stalker::Precache( void )
{
PrecacheModel("models/stalker.mdl");
PrecacheModel( DefaultOrCustomModel( "models/stalker.mdl" ) );
PrecacheModel("sprites/laser.vmt");
PrecacheModel("sprites/redglow1.vmt");

View File

@ -395,6 +395,9 @@ BEGIN_DATADESC( CNPC_Strider )
DEFINE_INPUTFUNC( FIELD_VOID, "EnableMinigun", InputEnableMinigun ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "StopShootingMinigunForSeconds", InputStopShootingMinigunForSeconds ),
DEFINE_INPUTFUNC( FIELD_VOID, "DisableCrouch", InputDisableCrouch ),
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_VOID, "EnableCrouch", InputEnableCrouch ),
#endif
DEFINE_INPUTFUNC( FIELD_VOID, "DisableMoveToLOS", InputDisableMoveToLOS ),
DEFINE_INPUTFUNC( FIELD_STRING, "DisableCollisionWith", InputDisableCollisionWith ),
DEFINE_INPUTFUNC( FIELD_STRING, "EnableCollisionWith", InputEnableCollisionWith ),
@ -2362,6 +2365,15 @@ void CNPC_Strider::InputDisableCrouch( inputdata_t &inputdata )
m_bDontCrouch = true;
}
#ifdef MAPBASE
//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_Strider::InputEnableCrouch( inputdata_t &inputdata )
{
m_bDontCrouch = false;
}
#endif
//---------------------------------------------------------
//---------------------------------------------------------
void CNPC_Strider::InputDisableMoveToLOS( inputdata_t &inputdata )

View File

@ -171,6 +171,9 @@ public:
void InputDisableAggressiveBehavior( inputdata_t &inputdata );
void InputStopShootingMinigunForSeconds( inputdata_t &inputdata );
void InputDisableCrouch( inputdata_t &inputdata );
#ifdef MAPBASE
void InputEnableCrouch( inputdata_t &inputdata );
#endif
void InputDisableMoveToLOS( inputdata_t &inputdata );
void InputExplode( inputdata_t &inputdata );
void InputScaleGroundSpeed( inputdata_t &inputdata );

View File

@ -304,7 +304,7 @@ CNPC_CeilingTurret::~CNPC_CeilingTurret( void )
//-----------------------------------------------------------------------------
void CNPC_CeilingTurret::Precache( void )
{
PrecacheModel( CEILING_TURRET_MODEL );
PrecacheModel( DefaultOrCustomModel( CEILING_TURRET_MODEL ) );
PrecacheModel( CEILING_TURRET_GLOW_SPRITE );
// Activities
@ -347,7 +347,7 @@ void CNPC_CeilingTurret::Spawn( void )
{
Precache();
SetModel( CEILING_TURRET_MODEL );
SetModel( DefaultOrCustomModel( CEILING_TURRET_MODEL ) );
BaseClass::Spawn();

View File

@ -69,7 +69,7 @@ END_DATADESC()
void CNPC_GroundTurret::Precache( void )
{
PrecacheModel( GROUNDTURRET_BEAM_SPRITE );
PrecacheModel( "models/combine_turrets/ground_turret.mdl" );
PrecacheModel( DefaultOrCustomModel( "models/combine_turrets/ground_turret.mdl" ) );
PrecacheScriptSound( "NPC_CeilingTurret.Deploy" );
m_ShotSounds = PrecacheScriptSound( "NPC_FloorTurret.ShotSounds" );
@ -88,7 +88,7 @@ void CNPC_GroundTurret::Spawn( void )
{
Precache();
UTIL_SetModel( this, "models/combine_turrets/ground_turret.mdl" );
UTIL_SetModel( this, DefaultOrCustomModel( "models/combine_turrets/ground_turret.mdl" ) );
SetNavType( NAV_FLY );
SetSolid( SOLID_VPHYSICS );

View File

@ -334,6 +334,10 @@ private:
bool IsPlayerAllySniper();
#ifdef MAPBASE
const Vector &GetPaintCursor() { return m_vecPaintCursor; }
#endif
private:
/// This is the variable from which m_flPaintTime gets set.
@ -403,6 +407,9 @@ private:
DEFINE_CUSTOM_AI;
DECLARE_DATADESC();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
};
@ -500,6 +507,26 @@ BEGIN_DATADESC( CProtoSniper )
END_DATADESC()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( CProtoSniper, CAI_BaseNPC, "Combine sniper NPC." )
DEFINE_SCRIPTFUNC( GetBulletSpeed, "" )
DEFINE_SCRIPTFUNC( GetBulletOrigin, "" )
DEFINE_SCRIPTFUNC( ScopeGlint, "" )
DEFINE_SCRIPTFUNC( GetPositionParameter, "" )
DEFINE_SCRIPTFUNC( IsSweepingRandomly, "" )
DEFINE_SCRIPTFUNC( FindFrustratedShot, "" )
DEFINE_SCRIPTFUNC( IsLaserOn, "" )
DEFINE_SCRIPTFUNC( LaserOn, "" )
DEFINE_SCRIPTFUNC( LaserOff, "" )
DEFINE_SCRIPTFUNC( GetPaintCursor, "Get the point the sniper is currently aiming at." )
END_SCRIPTDESC()
#endif
//=========================================================
@ -2588,6 +2615,19 @@ Vector CProtoSniper::DesiredBodyTarget( CBaseEntity *pTarget )
// By default, aim for the center
Vector vecTarget = pTarget->WorldSpaceCenter();
#ifdef MAPBASE_VSCRIPT
if (m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope(m_ScriptScope))
{
ScriptVariant_t functionReturn;
ScriptVariant_t args[] = { GetBulletOrigin(), ToHScript( pTarget ) };
if (g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ))
{
if (functionReturn.m_type == FIELD_VECTOR && functionReturn.m_pVector->LengthSqr() != 0.0f)
return *functionReturn.m_pVector;
}
}
#endif
float flTimeSinceLastMiss = gpGlobals->curtime - m_flTimeLastShotMissed;
if( pTarget->GetFlags() & FL_CLIENT )

View File

@ -0,0 +1,136 @@
//===== Copyright © 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose: Plays a movie and reports on finish
//
//===========================================================================//
#include "cbase.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CLogicPlayMovie : public CLogicalEntity
{
public:
DECLARE_CLASS( CLogicPlayMovie, CLogicalEntity );
DECLARE_DATADESC();
CLogicPlayMovie( void ) { }
~CLogicPlayMovie( void ) { }
virtual void Precache( void );
virtual void Spawn( void );
private:
void InputPlayMovie( inputdata_t &data );
#ifdef MAPBASE
void InputStopMovie( inputdata_t &data );
#endif
void InputMovieFinished( inputdata_t &data );
string_t m_strMovieFilename;
bool m_bAllowUserSkip;
#ifdef MAPBASE
bool m_bLooping;
bool m_bMuted;
bool m_bPlayingVideo;
#endif
COutputEvent m_OnPlaybackFinished;
};
LINK_ENTITY_TO_CLASS( logic_playmovie, CLogicPlayMovie );
BEGIN_DATADESC( CLogicPlayMovie )
DEFINE_KEYFIELD( m_strMovieFilename, FIELD_STRING, "MovieFilename" ),
DEFINE_KEYFIELD( m_bAllowUserSkip, FIELD_BOOLEAN, "allowskip" ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_bLooping, FIELD_BOOLEAN, "loopvideo" ),
DEFINE_KEYFIELD( m_bMuted, FIELD_BOOLEAN, "mute" ),
DEFINE_FIELD( m_bPlayingVideo, FIELD_BOOLEAN ),
#endif
DEFINE_INPUTFUNC( FIELD_VOID, "PlayMovie", InputPlayMovie ),
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_VOID, "StopMovie", InputStopMovie ),
#endif
DEFINE_INPUTFUNC( FIELD_VOID, "__MovieFinished", InputMovieFinished ),
DEFINE_OUTPUT( m_OnPlaybackFinished, "OnPlaybackFinished" ),
END_DATADESC()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicPlayMovie::Precache( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicPlayMovie::Spawn( void )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicPlayMovie::InputPlayMovie( inputdata_t &data )
{
// Build the hacked string
char szClientCmd[256];
Q_snprintf( szClientCmd, sizeof(szClientCmd),
"playvideo_complex %s \"ent_fire %s __MovieFinished\" %d %d %d\n",
STRING(m_strMovieFilename),
GetEntityNameAsCStr(),
m_bAllowUserSkip,
#ifdef MAPBASE
m_bLooping,
m_bMuted
#else
0,
0
#endif
);
// Send it on
engine->ServerCommand( szClientCmd );
#ifdef MAPBASE
m_bPlayingVideo = true;
#endif
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicPlayMovie::InputStopMovie( inputdata_t &data )
{
if (m_bPlayingVideo)
{
// Send it on
engine->ServerCommand( "stopvideos\n" );
}
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CLogicPlayMovie::InputMovieFinished( inputdata_t &data )
{
// Simply fire our output
m_OnPlaybackFinished.FireOutput( this, this );
#ifdef MAPBASE
m_bPlayingVideo = false;
#endif
}

View File

@ -0,0 +1,437 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose: Displays easy, flexible VGui text. Mapbase equivalent of point_worldtext.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "vguiscreen.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define SF_TESTDISPLAY_START_DISABLED (1 << 0)
//-----------------------------------------------------------------------------
// vgui_text_display
//-----------------------------------------------------------------------------
class CVGuiTextDisplay : public CBaseEntity
{
public:
DECLARE_CLASS( CVGuiTextDisplay, CBaseEntity );
DECLARE_DATADESC();
DECLARE_SERVERCLASS();
CVGuiTextDisplay();
virtual ~CVGuiTextDisplay();
virtual bool KeyValue( const char *szKeyName, const char *szValue );
virtual int UpdateTransmitState();
virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways );
virtual void Spawn( void );
virtual void Precache( void );
virtual void OnRestore( void );
void ScreenVisible( bool bVisible );
void Disable( void );
void Enable( void );
void InputDisable( inputdata_t &inputdata );
void InputEnable( inputdata_t &inputdata );
void InputToggle( inputdata_t &inputdata );
void InputSetMessage( inputdata_t &inputdata );
void InputSetTextAlignment( inputdata_t &inputdata );
void InputSetFont( inputdata_t &inputdata );
void InputSetResolution( inputdata_t &inputdata );
void InputSetTextSize( inputdata_t &inputdata );
private:
// Control panel
void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName );
void GetControlPanelClassName( int nPanelIndex, const char *&pPanelName );
void SpawnControlPanels( void );
void RestoreControlPanels( void );
private:
CNetworkVar( bool, m_bEnabled );
CNetworkString( m_szDisplayText, 256 );
CNetworkVar( int, m_iContentAlignment );
CNetworkString( m_szFont, 64 );
CNetworkVar( int, m_iResolution );
float m_flTextSize;
//CNetworkColor32( m_DisplayColor ); // Use render color
bool m_bDoFullTransmit;
CHandle<CVGuiScreen> m_hScreen;
};
LINK_ENTITY_TO_CLASS( vgui_text_display, CVGuiTextDisplay );
//-----------------------------------------------------------------------------
// Save/load
//-----------------------------------------------------------------------------
BEGIN_DATADESC( CVGuiTextDisplay )
DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ),
DEFINE_AUTO_ARRAY_KEYFIELD( m_szDisplayText, FIELD_CHARACTER, "message" ),
DEFINE_KEYFIELD( m_iContentAlignment, FIELD_INTEGER, "alignment" ),
DEFINE_AUTO_ARRAY_KEYFIELD( m_szFont, FIELD_CHARACTER, "font" ),
DEFINE_KEYFIELD( m_iResolution, FIELD_INTEGER, "resolution" ),
DEFINE_KEYFIELD( m_flTextSize, FIELD_FLOAT, "textsize" ),
DEFINE_FIELD( m_bDoFullTransmit, FIELD_BOOLEAN ),
DEFINE_FIELD( m_hScreen, FIELD_EHANDLE ),
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
DEFINE_INPUTFUNC( FIELD_STRING, "SetMessage", InputSetMessage ),
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTextAlignment", InputSetTextAlignment ),
DEFINE_INPUTFUNC( FIELD_STRING, "SetFont", InputSetFont ),
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetResolution", InputSetResolution ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPanelSize", InputSetTextSize ),
END_DATADESC()
IMPLEMENT_SERVERCLASS_ST( CVGuiTextDisplay, DT_VGuiTextDisplay )
SendPropBool( SENDINFO( m_bEnabled ) ),
SendPropString( SENDINFO( m_szDisplayText ) ),
SendPropInt( SENDINFO( m_iContentAlignment ) ),
SendPropString( SENDINFO( m_szFont ) ),
SendPropInt( SENDINFO( m_iResolution ) ),
END_SEND_TABLE()
CVGuiTextDisplay::CVGuiTextDisplay()
{
m_flTextSize = 100.0f;
m_iResolution = 200;
m_iContentAlignment = 7; // a_south
}
CVGuiTextDisplay::~CVGuiTextDisplay()
{
DestroyVGuiScreen( m_hScreen.Get() );
}
//-----------------------------------------------------------------------------
// Read in Hammer data
//-----------------------------------------------------------------------------
bool CVGuiTextDisplay::KeyValue( const char *szKeyName, const char *szValue )
{
// NOTE: Have to do these separate because they set two values instead of one
if( FStrEq( szKeyName, "angles" ) )
{
Assert( GetMoveParent() == NULL );
QAngle angles;
UTIL_StringToVector( angles.Base(), szValue );
// Because the vgui screen basis is strange (z is front, y is up, x is right)
// we need to rotate the typical basis before applying it
VMatrix mat, rotation, tmp;
MatrixFromAngles( angles, mat );
MatrixBuildRotationAboutAxis( rotation, Vector( 0, 1, 0 ), 90 );
MatrixMultiply( mat, rotation, tmp );
MatrixBuildRotateZ( rotation, 90 );
MatrixMultiply( tmp, rotation, mat );
MatrixToAngles( mat, angles );
SetAbsAngles( angles );
}
else if( FStrEq( szKeyName, "message" ) )
{
Q_strcpy( m_szDisplayText.GetForModify(), szValue );
}
else if( FStrEq( szKeyName, "font" ) )
{
Q_strcpy( m_szFont.GetForModify(), szValue );
}
else if( FStrEq( szKeyName, "color" ) )
{
// Use render color
return BaseClass::KeyValue( "rendercolor", szValue );
}
else
return BaseClass::KeyValue( szKeyName, szValue );
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CVGuiTextDisplay::UpdateTransmitState()
{
if ( m_bDoFullTransmit )
{
m_bDoFullTransmit = false;
return SetTransmitState( FL_EDICT_ALWAYS );
}
return SetTransmitState( FL_EDICT_FULLCHECK );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways )
{
// Are we already marked for transmission?
if ( pInfo->m_pTransmitEdict->Get( entindex() ) )
return;
BaseClass::SetTransmit( pInfo, bAlways );
// Force our screen to be sent too.
m_hScreen->SetTransmit( pInfo, bAlways );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::Spawn( void )
{
Precache();
BaseClass::Spawn();
m_bEnabled = !HasSpawnFlags( SF_TESTDISPLAY_START_DISABLED );
SpawnControlPanels();
ScreenVisible( m_bEnabled );
m_bDoFullTransmit = true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::Precache( void )
{
BaseClass::Precache();
PrecacheVGuiScreen( "text_display_panel" );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::OnRestore( void )
{
BaseClass::OnRestore();
RestoreControlPanels();
ScreenVisible( m_bEnabled );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::ScreenVisible( bool bVisible )
{
// Set its active state
m_hScreen->SetActive( bVisible );
if ( bVisible )
{
m_hScreen->RemoveEffects( EF_NODRAW );
}
else
{
m_hScreen->AddEffects( EF_NODRAW );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::Disable( void )
{
if ( !m_bEnabled )
return;
m_bEnabled = false;
ScreenVisible( false );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::Enable( void )
{
if ( m_bEnabled )
return;
m_bEnabled = true;
ScreenVisible( true );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::InputDisable( inputdata_t &inputdata )
{
Disable();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::InputEnable( inputdata_t &inputdata )
{
Enable();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::InputToggle( inputdata_t &inputdata )
{
m_bEnabled ? Disable() : Enable();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::InputSetMessage( inputdata_t &inputdata )
{
Q_strcpy( m_szDisplayText.GetForModify(), inputdata.value.String() );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::InputSetTextAlignment( inputdata_t &inputdata )
{
m_iContentAlignment = inputdata.value.Int();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::InputSetFont( inputdata_t &inputdata )
{
Q_strcpy( m_szFont.GetForModify(), inputdata.value.String() );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::InputSetResolution( inputdata_t &inputdata )
{
m_iResolution = inputdata.value.Int();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::InputSetTextSize( inputdata_t &inputdata )
{
m_flTextSize = inputdata.value.Float();
if (m_hScreen)
{
m_hScreen->SetActualSize( m_flTextSize, m_flTextSize );
m_hScreen->SetLocalOrigin( m_hScreen->CollisionProp()->OBBCenter() * -1.0f );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName )
{
pPanelName = "text_display_panel";
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::GetControlPanelClassName( int nPanelIndex, const char *&pPanelName )
{
pPanelName = "vgui_screen";
}
//-----------------------------------------------------------------------------
// This is called by the base object when it's time to spawn the control panels
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::SpawnControlPanels()
{
int nPanel;
for ( nPanel = 0; true; ++nPanel )
{
const char *pScreenName;
GetControlPanelInfo( nPanel, pScreenName );
if (!pScreenName)
continue;
const char *pScreenClassname;
GetControlPanelClassName( nPanel, pScreenClassname );
if ( !pScreenClassname )
continue;
float flWidth = m_flTextSize;
float flHeight = m_flTextSize;
CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, this, this, 0 );
pScreen->ChangeTeam( GetTeamNumber() );
pScreen->SetActualSize( flWidth, flHeight );
pScreen->SetLocalOrigin( pScreen->CollisionProp()->OBBCenter() * -1.0f );
pScreen->SetActive( true );
pScreen->MakeVisibleOnlyToTeammates( false );
pScreen->SetTransparency( true );
m_hScreen = pScreen;
return;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CVGuiTextDisplay::RestoreControlPanels( void )
{
int nPanel;
for ( nPanel = 0; true; ++nPanel )
{
const char *pScreenName;
GetControlPanelInfo( nPanel, pScreenName );
if (!pScreenName)
continue;
const char *pScreenClassname;
GetControlPanelClassName( nPanel, pScreenClassname );
if ( !pScreenClassname )
continue;
CVGuiScreen *pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( NULL, pScreenClassname );
while ( ( pScreen && pScreen->GetOwnerEntity() != this ) || Q_strcmp( pScreen->GetPanelName(), pScreenName ) != 0 )
{
pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( pScreen, pScreenClassname );
}
if ( pScreen )
{
m_hScreen = pScreen;
m_hScreen->SetActive( true );
}
return;
}
}

View File

@ -0,0 +1,372 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose: Allows movies to be played as a VGUI screen in the world
//
//=====================================================================================//
#include "cbase.h"
#include "EnvMessage.h"
#include "fmtstr.h"
#include "vguiscreen.h"
#include "filesystem.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
class CMovieDisplay : public CBaseEntity
{
public:
DECLARE_CLASS( CMovieDisplay, CBaseEntity );
DECLARE_DATADESC();
DECLARE_SERVERCLASS();
virtual ~CMovieDisplay();
virtual bool KeyValue( const char *szKeyName, const char *szValue );
virtual int UpdateTransmitState();
virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways );
virtual void Spawn( void );
virtual void Precache( void );
virtual void OnRestore( void );
void ScreenVisible( bool bVisible );
void Disable( void );
void Enable( void );
void InputDisable( inputdata_t &inputdata );
void InputEnable( inputdata_t &inputdata );
void InputSetDisplayText( inputdata_t &inputdata );
private:
// Control panel
void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName );
void GetControlPanelClassName( int nPanelIndex, const char *&pPanelName );
void SpawnControlPanels( void );
void RestoreControlPanels( void );
private:
CNetworkVar( bool, m_bEnabled );
CNetworkVar( bool, m_bLooping );
CNetworkString( m_szDisplayText, 128 );
// Filename of the movie to play
CNetworkString( m_szMovieFilename, 128 );
string_t m_strMovieFilename;
// "Group" name. Screens of the same group name will play the same movie at the same time
// Effectively this lets multiple screens tune to the same "channel" in the world
CNetworkString( m_szGroupName, 128 );
string_t m_strGroupName;
int m_iScreenWidth;
int m_iScreenHeight;
bool m_bDoFullTransmit;
CHandle<CVGuiScreen> m_hScreen;
};
LINK_ENTITY_TO_CLASS( vgui_movie_display, CMovieDisplay );
//-----------------------------------------------------------------------------
// Save/load
//-----------------------------------------------------------------------------
BEGIN_DATADESC( CMovieDisplay )
DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ),
DEFINE_AUTO_ARRAY_KEYFIELD( m_szDisplayText, FIELD_CHARACTER, "displaytext" ),
DEFINE_AUTO_ARRAY( m_szMovieFilename, FIELD_CHARACTER ),
DEFINE_KEYFIELD( m_strMovieFilename, FIELD_STRING, "moviefilename" ),
DEFINE_AUTO_ARRAY( m_szGroupName, FIELD_CHARACTER ),
DEFINE_KEYFIELD( m_strGroupName, FIELD_STRING, "groupname" ),
DEFINE_KEYFIELD( m_iScreenWidth, FIELD_INTEGER, "width" ),
DEFINE_KEYFIELD( m_iScreenHeight, FIELD_INTEGER, "height" ),
DEFINE_KEYFIELD( m_bLooping, FIELD_BOOLEAN, "looping" ),
DEFINE_FIELD( m_bDoFullTransmit, FIELD_BOOLEAN ),
DEFINE_FIELD( m_hScreen, FIELD_EHANDLE ),
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
DEFINE_INPUTFUNC( FIELD_STRING, "SetDisplayText", InputSetDisplayText ),
END_DATADESC()
IMPLEMENT_SERVERCLASS_ST( CMovieDisplay, DT_MovieDisplay )
SendPropBool( SENDINFO( m_bEnabled ) ),
SendPropBool( SENDINFO( m_bLooping ) ),
SendPropString( SENDINFO( m_szMovieFilename ) ),
SendPropString( SENDINFO( m_szGroupName ) ),
END_SEND_TABLE()
CMovieDisplay::~CMovieDisplay()
{
DestroyVGuiScreen( m_hScreen.Get() );
}
//-----------------------------------------------------------------------------
// Read in Hammer data
//-----------------------------------------------------------------------------
bool CMovieDisplay::KeyValue( const char *szKeyName, const char *szValue )
{
// NOTE: Have to do these separate because they set two values instead of one
if( FStrEq( szKeyName, "angles" ) )
{
Assert( GetMoveParent() == NULL );
QAngle angles;
UTIL_StringToVector( angles.Base(), szValue );
// Because the vgui screen basis is strange (z is front, y is up, x is right)
// we need to rotate the typical basis before applying it
VMatrix mat, rotation, tmp;
MatrixFromAngles( angles, mat );
MatrixBuildRotationAboutAxis( rotation, Vector( 0, 1, 0 ), 90 );
MatrixMultiply( mat, rotation, tmp );
MatrixBuildRotateZ( rotation, 90 );
MatrixMultiply( tmp, rotation, mat );
MatrixToAngles( mat, angles );
SetAbsAngles( angles );
return true;
}
return BaseClass::KeyValue( szKeyName, szValue );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CMovieDisplay::UpdateTransmitState()
{
if ( m_bDoFullTransmit )
{
m_bDoFullTransmit = false;
return SetTransmitState( FL_EDICT_ALWAYS );
}
return SetTransmitState( FL_EDICT_FULLCHECK );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways )
{
// Are we already marked for transmission?
if ( pInfo->m_pTransmitEdict->Get( entindex() ) )
return;
BaseClass::SetTransmit( pInfo, bAlways );
// Force our screen to be sent too.
m_hScreen->SetTransmit( pInfo, bAlways );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::Spawn( void )
{
// Move the strings into a networkable form
Q_strcpy( m_szMovieFilename.GetForModify(), m_strMovieFilename.ToCStr() );
Q_strcpy( m_szGroupName.GetForModify(), m_strGroupName.ToCStr() );
Precache();
BaseClass::Spawn();
m_bEnabled = false;
SpawnControlPanels();
ScreenVisible( m_bEnabled );
m_bDoFullTransmit = true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::Precache( void )
{
BaseClass::Precache();
PrecacheVGuiScreen( "video_display_screen" );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::OnRestore( void )
{
BaseClass::OnRestore();
RestoreControlPanels();
ScreenVisible( m_bEnabled );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::ScreenVisible( bool bVisible )
{
// Set its active state
m_hScreen->SetActive( bVisible );
if ( bVisible )
{
m_hScreen->RemoveEffects( EF_NODRAW );
}
else
{
m_hScreen->AddEffects( EF_NODRAW );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::Disable( void )
{
if ( !m_bEnabled )
return;
m_bEnabled = false;
ScreenVisible( false );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::Enable( void )
{
if ( m_bEnabled )
return;
m_bEnabled = true;
ScreenVisible( true );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::InputDisable( inputdata_t &inputdata )
{
Disable();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::InputEnable( inputdata_t &inputdata )
{
Enable();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::InputSetDisplayText( inputdata_t &inputdata )
{
Q_strcpy( m_szDisplayText.GetForModify(), inputdata.value.String() );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName )
{
pPanelName = "movie_display_screen";
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::GetControlPanelClassName( int nPanelIndex, const char *&pPanelName )
{
pPanelName = "vgui_screen";
}
//-----------------------------------------------------------------------------
// This is called by the base object when it's time to spawn the control panels
//-----------------------------------------------------------------------------
void CMovieDisplay::SpawnControlPanels()
{
int nPanel;
for ( nPanel = 0; true; ++nPanel )
{
const char *pScreenName;
GetControlPanelInfo( nPanel, pScreenName );
if (!pScreenName)
continue;
const char *pScreenClassname;
GetControlPanelClassName( nPanel, pScreenClassname );
if ( !pScreenClassname )
continue;
float flWidth = m_iScreenWidth;
float flHeight = m_iScreenHeight;
CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, this, this, 0 );
pScreen->ChangeTeam( GetTeamNumber() );
pScreen->SetActualSize( flWidth, flHeight );
pScreen->SetActive( true );
pScreen->MakeVisibleOnlyToTeammates( false );
pScreen->SetTransparency( true );
m_hScreen = pScreen;
return;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CMovieDisplay::RestoreControlPanels( void )
{
int nPanel;
for ( nPanel = 0; true; ++nPanel )
{
const char *pScreenName;
GetControlPanelInfo( nPanel, pScreenName );
if (!pScreenName)
continue;
const char *pScreenClassname;
GetControlPanelClassName( nPanel, pScreenClassname );
if ( !pScreenClassname )
continue;
CVGuiScreen *pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( NULL, pScreenClassname );
while ( ( pScreen && pScreen->GetOwnerEntity() != this ) || Q_strcmp( pScreen->GetPanelName(), pScreenName ) != 0 )
{
pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( pScreen, pScreenClassname );
}
if ( pScreen )
{
m_hScreen = pScreen;
m_hScreen->SetActive( true );
}
return;
}
}

View File

@ -526,8 +526,8 @@ BEGIN_ENT_SCRIPTDESC( CBasePlayer, CBaseCombatCharacter, "The player entity." )
DEFINE_SCRIPTFUNC( GetButtonForced, "Gets the player's currently forced buttons." )
DEFINE_SCRIPTFUNC( GetFOV, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetFOVOwner, "GetFOVOwner", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetFOV, "SetFOV", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetFOVOwner, "GetFOVOwner", "Gets current view owner." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetFOV, "SetFOV", "Sets player FOV regardless of view owner." )
DEFINE_SCRIPTFUNC( ViewPunch, "Punches the player's view with the specified vector." )
DEFINE_SCRIPTFUNC( SetMuzzleFlashTime, "Sets the player's muzzle flash time for AI." )
@ -5251,6 +5251,11 @@ void CBasePlayer::Spawn( void )
m_vecSmoothedVelocity = vec3_origin;
InitVCollision( GetAbsOrigin(), GetAbsVelocity() );
if ( !g_pGameRules->IsMultiplayer() && g_pScriptVM )
{
g_pScriptVM->SetValue( "player", GetScriptInstance() );
}
#if !defined( TF_DLL )
IGameEvent *event = gameeventmanager->CreateEvent( "player_spawn" );
@ -5275,11 +5280,6 @@ void CBasePlayer::Spawn( void )
UpdateLastKnownArea();
m_weaponFiredTimer.Invalidate();
if ( !g_pGameRules->IsMultiplayer() && g_pScriptVM )
{
g_pScriptVM->SetValue( "player", GetScriptInstance() );
}
}
void CBasePlayer::Activate( void )

View File

@ -75,6 +75,12 @@ private:
float m_flHDRColorScale;
int m_nMinDXLevel;
#ifdef MAPBASE
float m_flHaloScale;
string_t m_iszHaloMaterial;
string_t m_iszSpotlightMaterial;
#endif
public:
COutputEvent m_OnOn, m_OnOff; ///< output fires when turned on, off
};
@ -98,6 +104,11 @@ BEGIN_DATADESC( CPointSpotlight )
DEFINE_KEYFIELD( m_flSpotlightGoalWidth,FIELD_FLOAT, "SpotlightWidth"),
DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ),
DEFINE_KEYFIELD( m_nMinDXLevel, FIELD_INTEGER, "mindxlevel" ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_flHaloScale, FIELD_FLOAT, "HaloScale" ),
DEFINE_KEYFIELD( m_iszHaloMaterial, FIELD_STRING, "HaloMaterial" ),
DEFINE_KEYFIELD( m_iszSpotlightMaterial, FIELD_STRING, "SpotlightMaterial" ),
#endif
// Inputs
DEFINE_INPUTFUNC( FIELD_VOID, "LightOn", InputLightOn ),
@ -127,6 +138,9 @@ CPointSpotlight::CPointSpotlight()
#endif
m_flHDRColorScale = 1.0f;
m_nMinDXLevel = 0;
#ifdef MAPBASE
m_flHaloScale = 60.0f;
#endif
}
#ifdef MAPBASE
@ -148,8 +162,23 @@ void CPointSpotlight::Precache(void)
BaseClass::Precache();
// Sprites.
#ifdef MAPBASE
if (m_iszHaloMaterial == NULL_STRING)
{
m_iszHaloMaterial = AllocPooledString( "sprites/light_glow03.vmt" );
}
if (m_iszSpotlightMaterial == NULL_STRING)
{
m_iszSpotlightMaterial = AllocPooledString( "sprites/glow_test02.vmt" );
}
m_nHaloSprite = PrecacheModel( STRING( m_iszHaloMaterial ) );
PrecacheModel( STRING( m_iszSpotlightMaterial ) );
#else
m_nHaloSprite = PrecacheModel("sprites/light_glow03.vmt");
PrecacheModel( "sprites/glow_test02.vmt" );
#endif
}
@ -367,13 +396,21 @@ void CPointSpotlight::SpotlightCreate(void)
}
//m_hSpotlight = CBeam::BeamCreate( "sprites/spotlight.vmt", m_flSpotlightGoalWidth );
#ifdef MAPBASE
m_hSpotlight = CBeam::BeamCreate( STRING(m_iszSpotlightMaterial), m_flSpotlightGoalWidth );
#else
m_hSpotlight = CBeam::BeamCreate( "sprites/glow_test02.vmt", m_flSpotlightGoalWidth );
#endif
// Set the temporary spawnflag on the beam so it doesn't save (we'll recreate it on restore)
m_hSpotlight->SetHDRColorScale( m_flHDRColorScale );
m_hSpotlight->AddSpawnFlags( SF_BEAM_TEMPORARY );
m_hSpotlight->SetColor( m_clrRender->r, m_clrRender->g, m_clrRender->b );
m_hSpotlight->SetHaloTexture(m_nHaloSprite);
#ifdef MAPBASE
m_hSpotlight->SetHaloScale(m_flHaloScale);
#else
m_hSpotlight->SetHaloScale(60);
#endif
m_hSpotlight->SetEndWidth(m_flSpotlightGoalWidth);
m_hSpotlight->SetBeamFlags( (FBEAM_SHADEOUT|FBEAM_NOTILE) );
m_hSpotlight->SetBrightness( 64 );

View File

@ -3461,7 +3461,10 @@ void CSceneEntity::StartEvent( float currenttime, CChoreoScene *scene, CChoreoEv
if ( IsMultiplayer() )
break;
DispatchStartPermitResponses( scene, pActor, event );
if ( pActor )
{
DispatchStartPermitResponses( scene, pActor, event );
}
}
break;
default:
@ -3619,7 +3622,10 @@ void CSceneEntity::EndEvent( float currenttime, CChoreoScene *scene, CChoreoEven
if ( IsMultiplayer() )
break;
DispatchEndPermitResponses( scene, pActor, event );
if ( pActor )
{
DispatchEndPermitResponses( scene, pActor, event );
}
}
break;
default:

View File

@ -27,6 +27,8 @@ $Project
$File "postprocesscontroller.h"
$File "env_dof_controller.cpp"
$File "env_dof_controller.h"
$File "logic_playmovie.cpp"
$File "movie_display.cpp"
$Folder "Mapbase"
{
@ -74,6 +76,7 @@ $Project
$File "mapbase\SystemConvarMod.cpp"
$File "mapbase\SystemConvarMod.h"
$File "mapbase\variant_tools.h"
$File "mapbase\vgui_text_display.cpp"
$File "mapbase\logic_eventlistener.cpp"
$File "mapbase\logic_register_activator.cpp"

View File

@ -110,6 +110,11 @@ public:
{
return ToHScript( gEntList.FindEntityByClassnameWithin( ToEnt( hStartEntity ), szName, vecMins, vecMaxs ) );
}
HSCRIPT FindByClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, const char *classname )
{
return ToHScript( gEntList.FindEntityClassNearestFacing( origin, facing, threshold, const_cast<char*>(classname) ) );
}
#endif
private:
} g_ScriptEntityIterator;
@ -132,6 +137,7 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptEntityIterator, "CEntities", SCRIPT_SINGLETO
DEFINE_SCRIPTFUNC( FindByClassnameWithin, "Find entities by class name within a radius. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC( FindByClassnameWithinBox, "Find entities by class name within an AABB. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
DEFINE_SCRIPTFUNC( FindByClassNearestFacing, "Find the nearest entity along the facing direction from the given origin within the angular threshold with the given classname." )
#endif
END_SCRIPTDESC();
@ -265,11 +271,6 @@ static int MaxPlayers()
return gpGlobals->maxClients;
}
static float IntervalPerTick()
{
return gpGlobals->interval_per_tick;
}
static int GetLoadType()
{
return gpGlobals->eLoadType;
@ -328,7 +329,11 @@ static void DoEntFire( const char *pszTarget, const char *pszAction, const char
// ent_fire point_servercommand command "rcon_password mynewpassword"
if ( gpGlobals->maxClients > 1 && V_stricmp( target, "point_servercommand" ) == 0 )
{
#ifdef MAPBASE_VSCRIPT
return 0;
#else
return;
#endif
}
if ( *pszAction )
@ -447,12 +452,6 @@ static float GetEntityIOEventTimeLeft( int event )
{
return g_EventQueue.GetTimeLeft(event);
}
// vscript_server.nut adds this to the base CConvars class
static const char *ScriptGetClientConvarValue( const char *pszConVar, int entindex )
{
return engine->GetClientConVarValue( entindex, pszConVar );
}
#endif // MAPBASE_VSCRIPT
bool VScriptServerInit()
@ -537,7 +536,6 @@ bool VScriptServerInit()
#ifdef MAPBASE_VSCRIPT
ScriptRegisterFunction( g_pScriptVM, SendToConsoleServer, "Send a string to the server console as a command" );
ScriptRegisterFunction( g_pScriptVM, MaxPlayers, "Get the maximum number of players allowed on this server" );
ScriptRegisterFunction( g_pScriptVM, IntervalPerTick, "Get the interval used between each tick" );
ScriptRegisterFunction( g_pScriptVM, GetLoadType, "Get the way the current game was loaded (corresponds to the MapLoad enum)" );
ScriptRegisterFunction( g_pScriptVM, DoEntFire, SCRIPT_ALIAS( "EntFire", "Generate an entity i/o event" ) );
ScriptRegisterFunction( g_pScriptVM, DoEntFireByInstanceHandle, SCRIPT_ALIAS( "EntFireByHandle", "Generate an entity i/o event. First parameter is an entity instance." ) );
@ -545,7 +543,6 @@ bool VScriptServerInit()
ScriptRegisterFunction( g_pScriptVM, CancelEntityIOEvent, "Remove entity I/O event." );
ScriptRegisterFunction( g_pScriptVM, GetEntityIOEventTimeLeft, "Get time left on entity I/O event." );
ScriptRegisterFunction( g_pScriptVM, ScriptGetClientConvarValue, SCRIPT_HIDE );
#else
ScriptRegisterFunction( g_pScriptVM, DoEntFire, SCRIPT_ALIAS( "EntFire", "Generate and entity i/o event" ) );
ScriptRegisterFunctionNamed( g_pScriptVM, DoEntFireByInstanceHandle, "EntFireByHandle", "Generate and entity i/o event. First parameter is an entity instance." );

View File

@ -5,15 +5,14 @@ static char g_Script_vscript_server[] = R"vscript(
//
//=============================================================================
local DoEntFire = ::DoEntFire
local DoEntFireByInstanceHandle = ::DoEntFireByInstanceHandle
local DoDispatchParticleEffect = ::DoDispatchParticleEffect
local DoUniqueString = ::DoUniqueString
local ScriptGetClientConvarValue = ::ScriptGetClientConvarValue
local DoEntFire = DoEntFire
local DoEntFireByInstanceHandle = DoEntFireByInstanceHandle
local DoDispatchParticleEffect = DoDispatchParticleEffect
local DoUniqueString = DoUniqueString
function UniqueString( string = "" )
{
return DoUniqueString( string.tostring() );
return DoUniqueString( "" + string );
}
function EntFire( target, action, value = null, delay = 0.0, activator = null, caller = null )
@ -36,7 +35,7 @@ function EntFire( target, action, value = null, delay = 0.0, activator = null, c
}
}
return DoEntFire( target.tostring(), action.tostring(), value.tostring(), delay, activator, caller );
return DoEntFire( "" + target, "" + action, "" + value, delay, activator, caller );
}
function EntFireByHandle( target, action, value = null, delay = 0.0, activator = null, caller = null )
@ -59,7 +58,7 @@ function EntFireByHandle( target, action, value = null, delay = 0.0, activator =
}
}
return DoEntFireByInstanceHandle( target, action.tostring(), value.tostring(), delay, activator, caller );
return DoEntFireByInstanceHandle( target, "" + action, "" + value, delay, activator, caller );
}
function DispatchParticleEffect( particleName, origin, angles, entity = null )
@ -67,12 +66,6 @@ function DispatchParticleEffect( particleName, origin, angles, entity = null )
DoDispatchParticleEffect( particleName, origin, angles, entity );
}
// CConvars is declared within the library
function CConvars::GetClientConvarValue(cvar,idx)
{
return ScriptGetClientConvarValue(cvar,idx);
}
__Documentation.RegisterHelp( "CConvars::GetClientConvarValue", "CConvars::GetClientConvarValue(string, int)", "Returns the convar value for the entindex as a string. Only works with client convars with the FCVAR_USERINFO flag." );
function __ReplaceClosures( script, scope )

View File

@ -1226,6 +1226,11 @@ void CBaseEntity::ScriptEmitSound( const char *soundname )
EmitSound( soundname );
}
void CBaseEntity::ScriptStopSound( const char *soundname )
{
StopSound( soundname );
}
float CBaseEntity::ScriptSoundDuration( const char *soundname, const char *actormodel )
{
float duration = CBaseEntity::GetSoundDuration( soundname, actormodel );

View File

@ -2712,4 +2712,296 @@ HSCRIPT CBaseEntity::ScriptGetPhysicsObject( void )
else
return NULL;
}
static inline void ScriptStopContextThink( scriptthinkfunc_t *context )
{
Assert( context->m_hfnThink );
g_pScriptVM->ReleaseScript( context->m_hfnThink );
context->m_hfnThink = NULL;
//context->m_nNextThinkTick = TICK_NEVER_THINK;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptContextThink()
{
float flNextThink = FLT_MAX;
int nScheduledTick = 0;
for ( int i = 0; i < m_ScriptThinkFuncs.Count(); ++i )
{
scriptthinkfunc_t *cur = m_ScriptThinkFuncs[i];
if ( cur->m_nNextThinkTick == TICK_NEVER_THINK )
{
continue;
}
if ( cur->m_nNextThinkTick > gpGlobals->tickcount )
{
// There is more to execute, don't stop thinking if the rest are done.
// Find the shortest schedule
if ( !nScheduledTick || nScheduledTick > cur->m_nNextThinkTick )
{
nScheduledTick = cur->m_nNextThinkTick;
}
continue;
}
#ifdef _DEBUG
// going to run the script func
cur->m_nNextThinkTick = 0;
#endif
ScriptVariant_t varReturn;
if ( !cur->m_bNoParam )
{
ScriptVariant_t arg = m_hScriptInstance;
if ( g_pScriptVM->ExecuteFunction( cur->m_hfnThink, &arg, 1, &varReturn, NULL, true ) == SCRIPT_ERROR )
{
cur->m_nNextThinkTick = TICK_NEVER_THINK;
continue;
}
}
else
{
if ( g_pScriptVM->ExecuteFunction( cur->m_hfnThink, NULL, 0, &varReturn, NULL, true ) == SCRIPT_ERROR )
{
cur->m_nNextThinkTick = TICK_NEVER_THINK;
continue;
}
}
if ( cur->m_nNextThinkTick == TICK_NEVER_THINK )
{
// stopped from script while thinking
continue;
}
float flReturn;
if ( !varReturn.AssignTo( &flReturn ) )
{
cur->m_nNextThinkTick = TICK_NEVER_THINK;
continue;
}
if ( flReturn < 0.0f )
{
cur->m_nNextThinkTick = TICK_NEVER_THINK;
continue;
}
if ( flReturn < flNextThink )
{
flNextThink = flReturn;
}
cur->m_nNextThinkTick = TIME_TO_TICKS( gpGlobals->curtime + flReturn );
}
// deferred safe removal
for ( int i = 0; i < m_ScriptThinkFuncs.Count(); )
{
if ( m_ScriptThinkFuncs[i]->m_nNextThinkTick == TICK_NEVER_THINK )
{
ScriptStopContextThink( m_ScriptThinkFuncs[i] );
delete m_ScriptThinkFuncs[i];
m_ScriptThinkFuncs.Remove(i);
}
else ++i;
}
bool bNewNext = flNextThink < FLT_MAX;
#ifdef _DEBUG
#ifdef GAME_DLL
int nNextThinkTick = GetNextThinkTick("ScriptContextThink"); // -1
#else
int nNextThinkTick = GetNextThinkTick(); // 0
#endif
if ( ( nNextThinkTick <= 0 ) || ( nNextThinkTick >= nScheduledTick ) || ( nNextThinkTick == gpGlobals->tickcount ) )
{
#endif
if ( nScheduledTick )
{
float flScheduledTime = TICKS_TO_TIME( nScheduledTick );
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, flScheduledTime );
}
else
{
flNextThink = flScheduledTime;
}
}
else
{
if ( bNewNext )
{
flNextThink = gpGlobals->curtime + flNextThink;
}
else
{
#ifdef GAME_DLL
flNextThink = TICK_NEVER_THINK;
#else
flNextThink = CLIENT_THINK_NEVER;
#endif
}
}
#ifdef _DEBUG
}
else
{
// Next think was set (from script) to a sooner tick while thinking?
Assert(0);
if ( nScheduledTick )
{
int nNextSchedule = min( nScheduledTick, nNextThinkTick );
float flNextSchedule = TICKS_TO_TIME( nNextSchedule );
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, flNextSchedule );
}
else
{
flNextThink = flNextSchedule;
}
}
else
{
float nextthink = TICKS_TO_TIME( nNextThinkTick );
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, nextthink );
}
else
{
flNextThink = nextthink;
}
}
}
#endif
#ifdef GAME_DLL
SetNextThink( flNextThink, "ScriptContextThink" );
#else
SetNextClientThink( flNextThink );
#endif
}
// see ScriptSetThink
static bool s_bScriptContextThinkNoParam = false;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float flTime )
{
#ifdef CLIENT_DLL
// Context thinking is not yet supported on client, entities can only have 1 think function.
// C_World does not have one by default, so it is safe to set its.
if ( !IsWorld() )
{
g_pScriptVM->RaiseException("SetContextThink is only supported on C_World");
return;
}
#endif
scriptthinkfunc_t *pf = NULL;
unsigned short hash = ( szContext && *szContext ) ? HashString( szContext ) : 0;
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
scriptthinkfunc_t *f = m_ScriptThinkFuncs[i];
if ( hash == f->m_iContextHash )
{
pf = f;
break;
}
}
if ( hFunc )
{
// add new
if ( !pf )
{
pf = new scriptthinkfunc_t;
m_ScriptThinkFuncs.SetGrowSize(1);
m_ScriptThinkFuncs.AddToTail( pf );
pf->m_bNoParam = s_bScriptContextThinkNoParam;
pf->m_iContextHash = hash;
}
// update existing
else
{
#ifdef _DEBUG
if ( pf->m_nNextThinkTick == 0 )
{
Warning("Script think ('%s') was changed while it was thinking!\n", szContext);
}
#endif
g_pScriptVM->ReleaseScript( pf->m_hfnThink );
}
float nextthink = gpGlobals->curtime + flTime;
pf->m_hfnThink = hFunc;
pf->m_nNextThinkTick = TIME_TO_TICKS( nextthink );
#ifdef GAME_DLL
int nexttick = GetNextThinkTick( RegisterThinkContext( "ScriptContextThink" ) );
#else
int nexttick = GetNextThinkTick();
#endif
// sooner than next think
if ( nexttick <= 0 || nexttick > pf->m_nNextThinkTick )
{
#ifdef GAME_DLL
SetContextThink( &CBaseEntity::ScriptContextThink, nextthink, "ScriptContextThink" );
#else
SetNextClientThink( nextthink );
#endif
}
}
// null func input, think exists
else if ( pf )
{
pf->m_nNextThinkTick = TICK_NEVER_THINK;
}
}
//-----------------------------------------------------------------------------
// m_bNoParam and s_bScriptContextThinkNoParam exist only to keep backwards compatibility
// and are an alternative to this script closure:
//
// function CBaseEntity::SetThink( func, time )
// {
// SetContextThink( "", function(_){ return func() }, time )
// }
//-----------------------------------------------------------------------------
#ifndef CLIENT_DLL
void CBaseEntity::ScriptSetThink( HSCRIPT hFunc, float time )
{
s_bScriptContextThinkNoParam = true;
ScriptSetContextThink( NULL, hFunc, time );
s_bScriptContextThinkNoParam = false;
}
void CBaseEntity::ScriptStopThink()
{
ScriptSetContextThink( NULL, NULL, 0.0f );
}
#endif
#endif

View File

@ -71,7 +71,7 @@ ConVar mapbase_load_actbusy("mapbase_load_actbusy", "1", FCVAR_ARCHIVE, "Should
#ifdef GAME_DLL
// This cvar should change with each Mapbase update
ConVar mapbase_version( "mapbase_version", "6.2", FCVAR_NONE, "The version of Mapbase currently being used in this mod." );
ConVar mapbase_version( "mapbase_version", "6.3", FCVAR_NONE, "The version of Mapbase currently being used in this mod." );
extern void MapbaseGameLog_Init();
@ -178,7 +178,7 @@ public:
#ifdef GAME_DLL
if (g_bMapContainsCustomTalker && mapbase_flush_talker.GetBool())
{
CGMsg( 1, "Mapbase Misc.", "Mapbase: Reloading response system to flush custom talker\n" );
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Mapbase: Reloading response system to flush custom talker\n" );
ReloadResponseSystem();
g_bMapContainsCustomTalker = false;
}
@ -188,7 +188,7 @@ public:
virtual void LevelInitPreEntity()
{
#ifdef GAME_DLL
CGMsg( 0, "Mapbase Misc.", "Mapbase system loaded\n" );
CGMsg( 0, CON_GROUP_MAPBASE_MISC, "Mapbase system loaded\n" );
#endif
// Checks gameinfo.txt for Mapbase-specific options
@ -212,8 +212,11 @@ public:
RefreshMapName();
// Shared Mapbase localization file
// Shared Mapbase scripts to avoid overwriting mod files
g_pVGuiLocalize->AddFile( "resource/mapbase_%language%.txt" );
#ifdef CLIENT_DLL
PanelMetaClassMgr()->LoadMetaClassDefinitionFile( "scripts/vgui_screens_mapbase.txt" );
#endif
}
virtual void OnRestore()
@ -352,11 +355,11 @@ public:
return;
}
CGMsg( 1, "Mapbase Misc.", "===== Mapbase Manifest: Loading manifest file %s =====\n", file );
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "===== Mapbase Manifest: Loading manifest file %s =====\n", file );
AddManifestFile(pKV, false);
CGMsg( 1, "Mapbase Misc.", "==============================================================================\n" );
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "==============================================================================\n" );
pKV->deleteThis();
}
@ -553,6 +556,11 @@ CUtlVector<MODCHAPTER> *Mapbase_GetChapterList()
return &g_MapbaseChapterList;
}
int Mapbase_GetChapterCount()
{
return g_MapbaseChapterList.Count();
}
ThreeState_t Flashlight_GetLegacyVersionKey()
{
KeyValues *gameinfo = new KeyValues( "GameInfo" );
@ -591,7 +599,7 @@ public:
const char *scriptfile = STRING(m_target);
if ( filesystem->FileExists( scriptfile, "MOD" ) )
{
CGMsg(0, "Mapbase Misc.", "Mapbase: Adding manifest file \"%s\"\n", scriptfile);
CGMsg(0, CON_GROUP_MAPBASE_MISC, "Mapbase: Adding manifest file \"%s\"\n", scriptfile);
g_MapbaseSystem.AddManifestFile(scriptfile);
}
else

View File

@ -66,7 +66,7 @@ BEGIN_SCRIPTENUM( RenderMode, "Render modes used by Get/SetRenderMode" )
DEFINE_ENUMCONST_NAMED( kRenderTransAdd, "Additive", "" )
DEFINE_ENUMCONST_NAMED( kRenderEnvironmental, "Environmental", "" )
DEFINE_ENUMCONST_NAMED( kRenderTransAddFrameBlend, "AdditiveFractionalFrame", "" )
DEFINE_ENUMCONST_NAMED( kRenderTransAlphaAdd, "Alpha Add", "" )
DEFINE_ENUMCONST_NAMED( kRenderTransAlphaAdd, "AlphaAdd", "" )
DEFINE_ENUMCONST_NAMED( kRenderWorldGlow, "WorldSpaceGlow", "" )
DEFINE_ENUMCONST_NAMED( kRenderNone, "None", "" )

View File

@ -26,6 +26,7 @@
#include "con_nprint.h"
#include "particle_parse.h"
#include "npcevent.h"
#include "vscript_funcs_shared.h"
#include "vscript_singletons.h"
@ -164,18 +165,18 @@ HSCRIPT SpawnEntityFromTable( const char *pszClassname, HSCRIPT hKV )
HSCRIPT EntIndexToHScript( int index )
{
#ifdef GAME_DLL
edict_t *e = INDEXENT(index);
if ( e && !e->IsFree() )
{
return ToHScript( GetContainingEntity( e ) );
}
edict_t *e = INDEXENT(index);
if ( e && !e->IsFree() )
{
return ToHScript( GetContainingEntity( e ) );
}
#else // CLIENT_DLL
if ( index < NUM_ENT_ENTRIES )
{
return ToHScript( CBaseEntity::Instance( index ) );
}
if ( index < NUM_ENT_ENTRIES )
{
return ToHScript( CBaseEntity::Instance( index ) );
}
#endif
return NULL;
return NULL;
}
//-----------------------------------------------------------------------------
@ -501,6 +502,61 @@ FireBulletsInfo_t *GetFireBulletsInfoFromInfo( HSCRIPT hBulletsInfo )
return HScriptToClass<FireBulletsInfo_t>( hBulletsInfo );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CAnimEventTInstanceHelper g_AnimEventTInstanceHelper;
BEGIN_SCRIPTDESC_ROOT( animevent_t, "Handle for accessing animevent_t info." )
DEFINE_SCRIPT_INSTANCE_HELPER( &g_AnimEventTInstanceHelper )
END_SCRIPTDESC();
bool CAnimEventTInstanceHelper::Get( void *p, const char *pszKey, ScriptVariant_t &variant )
{
animevent_t *ani = ((animevent_t *)p);
if (FStrEq( pszKey, "event" ))
variant = ani->event;
else if (FStrEq( pszKey, "options" ))
variant = ani->options;
else if (FStrEq( pszKey, "cycle" ))
variant = ani->cycle;
else if (FStrEq( pszKey, "eventtime" ))
variant = ani->eventtime;
else if (FStrEq( pszKey, "type" ))
variant = ani->type;
else if (FStrEq( pszKey, "source" ))
variant = ToHScript(ani->pSource);
else
return false;
return true;
}
bool CAnimEventTInstanceHelper::Set( void *p, const char *pszKey, ScriptVariant_t &variant )
{
animevent_t *ani = ((animevent_t *)p);
if (FStrEq( pszKey, "event" ))
ani->event = variant;
else if (FStrEq( pszKey, "options" ))
ani->options = variant;
else if (FStrEq( pszKey, "cycle" ))
ani->cycle = variant;
else if (FStrEq( pszKey, "eventtime" ))
ani->eventtime = variant;
else if (FStrEq( pszKey, "type" ))
ani->type = variant;
else if (FStrEq( pszKey, "source" ))
{
CBaseEntity *pEnt = ToEnt( variant.m_hScript );
if (pEnt)
ani->pSource = pEnt->GetBaseAnimating();
}
else
return false;
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
@ -740,20 +796,29 @@ void NPrint( int pos, const char* fmt )
void NXPrint( int pos, int r, int g, int b, bool fixed, float ftime, const char* fmt )
{
static con_nprint_t *info = new con_nprint_t;
con_nprint_t info;
info->index = pos;
info->time_to_live = ftime;
info->color[0] = r / 255.f;
info->color[1] = g / 255.f;
info->color[2] = b / 255.f;
info->fixed_width_font = fixed;
info.index = pos;
info.time_to_live = ftime;
info.color[0] = r / 255.f;
info.color[1] = g / 255.f;
info.color[2] = b / 255.f;
info.fixed_width_font = fixed;
engine->Con_NXPrintf(info, fmt);
// delete info;
engine->Con_NXPrintf( &info, fmt );
}
static float IntervalPerTick()
{
return gpGlobals->interval_per_tick;
}
static int GetFrameCount()
{
return gpGlobals->framecount;
}
//=============================================================================
//=============================================================================
@ -850,6 +915,9 @@ void RegisterSharedScriptFunctions()
#endif
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsServer, "IsServer", "Returns true if the script is being run on the server." );
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsClient, "IsClient", "Returns true if the script is being run on the client." );
ScriptRegisterFunction( g_pScriptVM, IntervalPerTick, "Simulation tick interval" );
ScriptRegisterFunction( g_pScriptVM, GetFrameCount, "Absolute frame counter" );
//ScriptRegisterFunction( g_pScriptVM, GetTickCount, "Simulation ticks" );
RegisterScriptSingletons();
}

View File

@ -121,4 +121,13 @@ private:
HSCRIPT m_planeAccessor;
};
//-----------------------------------------------------------------------------
// Exposes animevent_t to VScript
//-----------------------------------------------------------------------------
class CAnimEventTInstanceHelper : public IScriptInstanceHelper
{
bool Get( void *p, const char *pszKey, ScriptVariant_t &variant );
bool Set( void *p, const char *pszKey, ScriptVariant_t &variant );
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@
// $NoKeywords: $
//=============================================================================
#ifndef VSCRIPT_SINGLETONS
#define VSCRIPT_SINGLETONS
#ifndef VSCRIPT_SINGLETONS_H
#define VSCRIPT_SINGLETONS_H
#ifdef _WIN32
#pragma once
#endif
@ -29,21 +29,24 @@ class CNetMsgScriptHelper : public CAutoGameSystem
class CNetMsgScriptHelper
#endif
{
#ifdef CLIENT_DLL
public:
bool m_bWriteReady; // dt ready to send
#endif
private:
#ifdef GAME_DLL
CRecipientFilter m_filter;
bf_read *m_MsgIn;
CRecipientFilter m_filter;
#else
bf_read m_MsgIn;
#endif
HSCRIPT m_Hooks;
bf_write m_MsgOut;
byte m_MsgData[ PAD_NUMBER( SCRIPT_NETMSG_DATA_SIZE, 4 ) ];
HSCRIPT m_Hooks;
public:
#ifdef CLIENT_DLL
bool m_bWriteReady; // dt ready to send
CNetMsgScriptHelper() : m_Hooks(NULL), m_bWriteReady(false) {}
#else
CNetMsgScriptHelper() : m_Hooks(NULL) {}
@ -58,9 +61,9 @@ public:
void InitPostVM();
#ifdef GAME_DLL
void RecieveMessage( bf_read *msg, CBaseEntity *pPlayer );
void ReceiveMessage( bf_read *msg, CBaseEntity *pPlayer );
#else
void RecieveMessage( bf_read &msg );
void ReceiveMessage( bf_read &msg );
#endif
void WriteToBuffer( bf_write *bf );
@ -72,7 +75,7 @@ public:
#else
void Send();
#endif
void Recieve( const char *msg, HSCRIPT func );
void Receive( const char *msg, HSCRIPT func );
#ifdef GAME_DLL
inline void DoSendUserMsg( CRecipientFilter *filter, int type );
@ -100,14 +103,14 @@ public:
void WriteShort( int iValue ); // 16 bit short
void WriteWord( int iValue ); // 16 bit unsigned short
void WriteLong( int iValue ); // 32 bit long
void WriteFloat( float flValue );
void WriteNormal( float flValue ); // 12 bit
void WriteFloat( float flValue ); // 32 bit float
void WriteNormal( float flValue ); // 12 bit (1 + NORMAL_FRACTIONAL_BITS)
void WriteAngle( float flValue ); // 8 bit unsigned char
void WriteCoord( float flValue );
void WriteVec3Coord( const Vector& rgflValue );
void WriteVec3Normal( const Vector& rgflValue ); // 27 bit ( 3 + 2 * (1 + NORMAL_FRACTIONAL_BITS) )
void WriteAngles( const QAngle& rgflValue );
void WriteString( const char *sz ); // max 512 bytes at once
void WriteString( const char *sz );
void WriteBool( bool bValue ); // 1 bit
void WriteEntity( HSCRIPT hEnt ); // 11 bit (entindex)
void WriteEHandle( HSCRIPT hEnt ); // 32 bit long

View File

@ -5,8 +5,8 @@
// $NoKeywords: $
//=============================================================================
#ifndef VSCRIPT_FUNCS_MATH
#define VSCRIPT_FUNCS_MATH
#ifndef WEAPON_CUSTOM_SCRIPTED_H
#define WEAPON_CUSTOM_SCRIPTED_H
#ifdef _WIN32
#pragma once
#endif

View File

@ -335,7 +335,7 @@ void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from )
#if defined( MAPBASE_VSCRIPT ) && defined( GAME_DLL )
if ( buf->ReadOneBit() )
{
g_ScriptNetMsg->RecieveMessage( buf, pPlayer );
g_ScriptNetMsg->ReceiveMessage( buf, pPlayer );
}
#endif

View File

@ -440,13 +440,17 @@ ISaveRestoreBlockHandler *GetVScriptSaveRestoreBlockHandler()
bool CBaseEntityScriptInstanceHelper::ToString( void *p, char *pBuf, int bufSize )
{
CBaseEntity *pEntity = (CBaseEntity *)p;
#ifdef CLIENT_DLL
if ( pEntity->GetEntityName() && pEntity->GetEntityName()[0] )
#else
if ( pEntity->GetEntityName() != NULL_STRING )
#endif
{
V_snprintf( pBuf, bufSize, "([%d] %s: %s)", pEntity->entindex(), STRING(pEntity->m_iClassname), STRING( pEntity->GetEntityName() ) );
V_snprintf( pBuf, bufSize, "([%d] %s: %s)", pEntity->entindex(), pEntity->GetClassname(), STRING( pEntity->GetEntityName() ) );
}
else
{
V_snprintf( pBuf, bufSize, "([%d] %s)", pEntity->entindex(), STRING(pEntity->m_iClassname) );
V_snprintf( pBuf, bufSize, "([%d] %s)", pEntity->entindex(), pEntity->GetClassname() );
}
return true;
}

View File

@ -301,6 +301,10 @@ private:
ICommandCallback *m_pCommandCallback;
};
#ifdef MAPBASE_VSCRIPT
// Allow late modification of the completion callback.
public:
#endif
union
{
FnCommandCompletionCallback m_fnCompletionCallback;
@ -308,6 +312,9 @@ private:
};
bool m_bHasCompletionCallback : 1;
#ifdef MAPBASE_VSCRIPT
private:
#endif
bool m_bUsingNewCommandCallback : 1;
bool m_bUsingCommandCallbackInterface : 1;
};

View File

@ -17,21 +17,23 @@
//static const Color CON_COLOR_DEV_VERBOSE( 192, 128, 192, 255 );
// General
#define CON_GROUP_MAPBASE_MISC "Mapbase Misc."
#define CON_GROUP_PHYSICS "Physics"
#define CON_GROUP_MAPBASE_MISC 0 // "Mapbase Misc."
#define CON_GROUP_PHYSICS 1 // "Physics"
// Server
#define CON_GROUP_IO_SYSTEM "I/O System"
#define CON_GROUP_NPC_AI "NPC AI"
#define CON_GROUP_NPC_SCRIPTS "NPC Scripts"
#define CON_GROUP_CHOREO "Choreo"
#define CON_GROUP_IO_SYSTEM 2 // "Entity I/O"
#define CON_GROUP_NPC_AI 3 // "NPC AI"
#define CON_GROUP_NPC_SCRIPTS 4 // "NPC Scripts"
#define CON_GROUP_CHOREO 5 // "Choreo"
// VScript
#define CON_GROUP_VSCRIPT "VScript"
#define CON_GROUP_VSCRIPT_PRINT "VScript Print"
#define CON_GROUP_VSCRIPT 6 // "VScript"
#define CON_GROUP_VSCRIPT_PRINT 7 // "VScript Print"
#define CON_GROUP_MAX 8 // must always be at the end
// Mapbase console group message.
void CGMsg( int level, const char *pszGroup, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
void CGMsg( int level, int nGroup, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
#define CGWarning CGMsg

View File

@ -749,9 +749,6 @@ struct ScriptEnumDesc_t
#define DEFINE_SCRIPTHOOK_PARAM( paramName, type ) pHook->AddParameter( paramName, type );
// Define actual parameters instead of global variables
#define DEFINE_SCRIPTHOOK_REALPARAM( paramName, type )
#define END_SCRIPTHOOK() \
pDesc->m_Hooks.AddToTail(pHook); \
}
@ -944,7 +941,7 @@ public:
#endif
#ifdef MAPBASE_VSCRIPT
// virtual void CreateArray(ScriptVariant_t &arr, int size = 0) = 0;
virtual void CreateArray(ScriptVariant_t &arr, int size = 0) = 0;
virtual bool ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) = 0;
#endif

View File

@ -65,46 +65,35 @@ DEFINE_CON_GROUP_CVAR( vscript_print, "80 186 255", "Messages from VScript's 'pr
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define DEFINE_CON_GROUP(name, codename) { name, &con_group_##codename##_color }
#define DEFINE_CON_GROUP(id, name, codename) { name, &con_group_##codename##_color }
ConGroup_t g_ConGroups[] = {
ConGroup_t g_ConGroups[CON_GROUP_MAX] = {
// General
DEFINE_CON_GROUP( CON_GROUP_MAPBASE_MISC, mapbase_misc ),
DEFINE_CON_GROUP( CON_GROUP_PHYSICS, physics ),
DEFINE_CON_GROUP( CON_GROUP_MAPBASE_MISC, "Mapbase misc.", mapbase_misc ),
DEFINE_CON_GROUP( CON_GROUP_PHYSICS, "Physics", physics ),
// Server
DEFINE_CON_GROUP( CON_GROUP_IO_SYSTEM, inputoutput ),
DEFINE_CON_GROUP( CON_GROUP_NPC_AI, npc_ai ),
DEFINE_CON_GROUP( CON_GROUP_NPC_SCRIPTS, npc_scripts ),
DEFINE_CON_GROUP( CON_GROUP_CHOREO, choreo ),
DEFINE_CON_GROUP( CON_GROUP_IO_SYSTEM, "Entity IO", inputoutput ),
DEFINE_CON_GROUP( CON_GROUP_NPC_AI, "NPC AI", npc_ai ),
DEFINE_CON_GROUP( CON_GROUP_NPC_SCRIPTS, "NPC scripts", npc_scripts ),
DEFINE_CON_GROUP( CON_GROUP_CHOREO, "Choreo", choreo ),
// VScript
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT, vscript ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT_PRINT, vscript_print ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT, "VScript", vscript ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT_PRINT, "VScript print", vscript_print ),
};
void CV_ColorChanged( IConVar *pConVar, const char *pOldString, float flOldValue )
{
for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++)
for (int i = 0; i < CON_GROUP_MAX; i++)
{
// Reset the alpha to indicate it needs to be refreshed
g_ConGroups[i]._clr[3] = 0;
}
}
ConGroup_t *FindConGroup( const char *pszGroup )
{
for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++)
{
if (V_strcmp(pszGroup, g_ConGroups[i].pszName) == 0)
return &g_ConGroups[i];
}
return NULL;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@ -113,7 +102,7 @@ ConVar con_group_include_name( "con_group_include_name", "0", FCVAR_NONE, "Inclu
CON_COMMAND( con_group_list, "Prints a list of all console groups." )
{
Msg( "============================================================\n" );
for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++)
for (int i = 0; i < CON_GROUP_MAX; i++)
{
Msg( " # " );
ConColorMsg( g_ConGroups[i].GetColor(), "%s", g_ConGroups[i].pszName );
@ -146,7 +135,7 @@ CON_COMMAND( con_group_toggle, "Toggles a console group." )
}
*/
void CGMsg( int level, const char *pszGroup, const tchar* pMsg, ... )
void CGMsg( int level, int nGroup, const tchar* pMsg, ... )
{
// Return early if we're not at this level
if (!IsSpewActive("developer", level))
@ -158,22 +147,21 @@ void CGMsg( int level, const char *pszGroup, const tchar* pMsg, ... )
Q_vsnprintf( string, sizeof(string), pMsg, argptr );
va_end( argptr );
ConGroup_t *pGroup = FindConGroup( pszGroup );
if (pGroup)
Assert( nGroup >= 0 );
Assert( nGroup < CON_GROUP_MAX );
ConGroup_t *pGroup = &g_ConGroups[nGroup];
/*if (pGroup->bDisabled)
{
/*if (pGroup->bDisabled)
{
// Do nothing
}
else*/ if (con_group_include_name.GetBool())
{
ConColorMsg( level, pGroup->GetColor(), "[%s] %s", pGroup->pszName, string );
}
else
{
ConColorMsg( level, pGroup->GetColor(), string );
}
// Do nothing
}
else*/ if (con_group_include_name.GetBool())
{
ConColorMsg(level, pGroup->GetColor(), "[%s] %s", pGroup->pszName, string);
}
else
DevMsg( level, string );
{
ConColorMsg(level, pGroup->GetColor(), string);
}
}

View File

@ -1247,7 +1247,7 @@ int RunVBSP( int argc, char **argv )
}
char szCommand[512];
_snprintf( szCommand, sizeof( szCommand ), "PrintHelp( \"%s\" );", pszArg1 );
_snprintf( szCommand, sizeof( szCommand ), "__Documentation.PrintHelp( \"%s\" );", pszArg1 );
g_pScriptVM->Run( szCommand );
}
else

View File

@ -83,6 +83,7 @@ static HSCRIPT VMFKV_LoadFromFile( const char *szFile )
KeyValues *pKV = new KeyValues( szFile );
if ( !pKV->LoadFromFile( g_pFullFileSystem, pszFullName, NULL ) )
{
pKV->deleteThis();
return NULL;
}

View File

@ -11,6 +11,7 @@
#include "vbsp.h"
#include "map.h"
#include "fgdlib/fgdlib.h"
#include "convar.h"
#include "vscript_vbsp.h"
#include "vscript_vbsp.nut"
@ -183,6 +184,28 @@ BEGIN_SCRIPTDESC_ROOT( CMapFile, "Map file" )
END_SCRIPTDESC();
static float cvar_getf( const char* sz )
{
ConVarRef cvar(sz);
if ( cvar.IsFlagSet( FCVAR_SERVER_CANNOT_QUERY ) )
return NULL;
return cvar.GetFloat();
}
static bool cvar_setf( const char* sz, float val )
{
ConVarRef cvar(sz);
if ( !cvar.IsValid() )
return false;
if ( cvar.IsFlagSet( FCVAR_SERVER_CANNOT_QUERY ) )
return false;
cvar.SetValue(val);
return true;
}
static const char *GetSource()
{
return source;
@ -244,6 +267,9 @@ bool VScriptVBSPInit()
{
Log( "VSCRIPT VBSP: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() );
ScriptRegisterFunction( g_pScriptVM, cvar_getf, "Gets the value of the given cvar, as a float." );
ScriptRegisterFunction( g_pScriptVM, cvar_setf, "Sets the value of the given cvar, as a float." );
ScriptRegisterFunction( g_pScriptVM, GetSource, "Gets the base directory of the first map loaded." );
ScriptRegisterFunction( g_pScriptVM, GetMapBase, "Gets the base name of the first map loaded." );
ScriptRegisterFunction( g_pScriptVM, GetMainMap, "Gets the first map loaded." );

View File

@ -50,100 +50,6 @@ static void ScriptColorPrintL( int r, int g, int b, const char *pszMsg )
ConColorMsg( clr, "%s\n", pszMsg );
}
//=============================================================================
//
// Convar Lookup
//
//=============================================================================
class CScriptConvarLookup
{
public:
float GetFloat( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetFloat();
}
int GetInt( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetInt();
}
bool GetBool( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetBool();
}
const char *GetStr( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetString();
}
const char *GetDefaultValue( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetDefault();
}
bool IsFlagSet( const char *pszConVar, int nFlags )
{
ConVarRef cvar( pszConVar );
return cvar.IsFlagSet( nFlags );
}
void SetFloat( const char *pszConVar, float value )
{
SetValue( pszConVar, value );
}
void SetInt( const char *pszConVar, int value )
{
SetValue( pszConVar, value );
}
void SetBool( const char *pszConVar, bool value )
{
SetValue( pszConVar, value );
}
void SetStr( const char *pszConVar, const char *value )
{
SetValue( pszConVar, value );
}
template <typename T>
void SetValue( const char *pszConVar, T value )
{
ConVarRef cvar( pszConVar );
if (!cvar.IsValid())
return;
// FCVAR_NOT_CONNECTED can be used to protect specific convars from nefarious interference
if (cvar.IsFlagSet(FCVAR_NOT_CONNECTED))
return;
cvar.SetValue( value );
}
private:
} g_ScriptConvarLookup;
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptConvarLookup, "CConvars", SCRIPT_SINGLETON "Provides an interface for getting and setting convars." )
DEFINE_SCRIPTFUNC( GetFloat, "Returns the convar as a float. May return null if no such convar." )
DEFINE_SCRIPTFUNC( GetInt, "Returns the convar as an int. May return null if no such convar." )
DEFINE_SCRIPTFUNC( GetBool, "Returns the convar as a bool. May return null if no such convar." )
DEFINE_SCRIPTFUNC( GetStr, "Returns the convar as a string. May return null if no such convar." )
DEFINE_SCRIPTFUNC( GetDefaultValue, "Returns the convar's default value as a string. May return null if no such convar." )
DEFINE_SCRIPTFUNC( IsFlagSet, "Returns the convar's flags. May return null if no such convar." )
DEFINE_SCRIPTFUNC( SetFloat, "Sets the value of the convar as a float." )
DEFINE_SCRIPTFUNC( SetInt, "Sets the value of the convar as an int." )
DEFINE_SCRIPTFUNC( SetBool, "Sets the value of the convar as a bool." )
DEFINE_SCRIPTFUNC( SetStr, "Sets the value of the convar as a string." )
END_SCRIPTDESC();
//=============================================================================
//
@ -203,6 +109,7 @@ BEGIN_SCRIPTDESC_ROOT( CScriptKeyValues, "Wrapper class over KeyValues instance"
DEFINE_SCRIPTFUNC_NAMED( ScriptReleaseKeyValues, "ReleaseKeyValues", "Given a root KeyValues object, release its contents" );
DEFINE_SCRIPTFUNC( TableToSubKeys, "Converts a script table to KeyValues." );
DEFINE_SCRIPTFUNC( SubKeysToTable, "Converts to script table." );
DEFINE_SCRIPTFUNC_NAMED( ScriptFindOrCreateKey, "FindOrCreateKey", "Given a KeyValues object and a key name, find or create a KeyValues object associated with the key name" );
@ -319,6 +226,19 @@ void CScriptKeyValues::TableToSubKeys( HSCRIPT hTable )
}
}
void CScriptKeyValues::SubKeysToTable( HSCRIPT hTable )
{
FOR_EACH_SUBKEY( m_pKeyValues, key )
{
switch ( key->GetDataType() )
{
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_FLOAT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetFloat() ); break;
}
}
}
HSCRIPT CScriptKeyValues::ScriptFindOrCreateKey( const char *pszName )
{
KeyValues *pKeyValues = m_pKeyValues->FindKey(pszName, true);
@ -529,7 +449,6 @@ void RegisterBaseBindings( IScriptVM *pVM )
//-----------------------------------------------------------------------------
pVM->RegisterInstance( &g_ScriptConvarLookup, "Convars" );
pVM->RegisterInstance( &g_ScriptGlobalSys, "GlobalSys" );
//-----------------------------------------------------------------------------

View File

@ -35,6 +35,7 @@ public:
// Functions below are new with Mapbase
void TableToSubKeys( HSCRIPT hTable );
void SubKeysToTable( HSCRIPT hTable );
HSCRIPT ScriptFindOrCreateKey( const char *pszName );

View File

@ -181,7 +181,7 @@ END_SCRIPTDESC();
bool CScriptQuaternionInstanceHelper::ToString( void *p, char *pBuf, int bufSize )
{
Quaternion *pQuat = ((Quaternion *)p);
V_snprintf( pBuf, bufSize, "(quaternion: (%f, %f, %f, %f))", pQuat->x, pQuat->y, pQuat->z, pQuat->w );
V_snprintf( pBuf, bufSize, "(Quaternion %p [%f %f %f %f])", (void*)pQuat, pQuat->x, pQuat->y, pQuat->z, pQuat->w );
return true;
}
@ -390,6 +390,11 @@ float ScriptCalcDistanceToLineSegment( const Vector &point, const Vector &vLineA
return CalcDistanceToLineSegment( point, vLineA, vLineB );
}
inline float ScriptExponentialDecay( float decayTo, float decayTime, float dt )
{
return ExponentialDecay( decayTo, decayTime, dt );
}
void RegisterMathBaseBindings( IScriptVM *pVM )
{
ScriptRegisterConstantNamed( pVM, ((float)(180.f / M_PI_F)), "RAD2DEG", "" );
@ -453,4 +458,12 @@ void RegisterMathBaseBindings( IScriptVM *pVM )
ScriptRegisterFunctionNamed( pVM, ScriptCalcClosestPointOnLine, "CalcClosestPointOnLine", "Returns the closest point on a line." );
ScriptRegisterFunctionNamed( pVM, ScriptCalcDistanceToLineSegment, "CalcDistanceToLineSegment", "Returns the distance to a line segment." );
ScriptRegisterFunctionNamed( pVM, ScriptCalcClosestPointOnLineSegment, "CalcClosestPointOnLineSegment", "Returns the closest point on a line segment." );
ScriptRegisterFunction( pVM, SimpleSplineRemapVal, "remaps a value in [startInterval, startInterval+rangeInterval] from linear to spline using SimpleSpline" );
ScriptRegisterFunction( pVM, SimpleSplineRemapValClamped, "remaps a value in [startInterval, startInterval+rangeInterval] from linear to spline using SimpleSpline" );
ScriptRegisterFunction( pVM, Bias, "The curve is biased towards 0 or 1 based on biasAmt, which is between 0 and 1." );
ScriptRegisterFunction( pVM, Gain, "Gain is similar to Bias, but biasAmt biases towards or away from 0.5." );
ScriptRegisterFunction( pVM, SmoothCurve, "SmoothCurve maps a 0-1 value into another 0-1 value based on a cosine wave" );
ScriptRegisterFunction( pVM, SmoothCurve_Tweak, "SmoothCurve peaks at flPeakPos, flPeakSharpness controls the sharpness of the peak" );
ScriptRegisterFunctionNamed( pVM, ScriptExponentialDecay, "ExponentialDecay", "decayTo is factor the value should decay to in decayTime" );
}

View File

@ -214,7 +214,7 @@ public:
virtual bool ClearValue(HSCRIPT hScope, const char* pszKey) override;
virtual bool ClearValue( HSCRIPT hScope, ScriptVariant_t pKey ) override;
// virtual void CreateArray(ScriptVariant_t &arr, int size = 0) override;
virtual void CreateArray(ScriptVariant_t &arr, int size = 0) override;
virtual bool ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) override;
//----------------------------------------------------------------------------
@ -270,7 +270,7 @@ namespace SQVector
return 0;
}
SQInteger Get(HSQUIRRELVM vm)
SQInteger _get(HSQUIRRELVM vm)
{
const char* key = nullptr;
sq_getstring(vm, 2, &key);
@ -296,7 +296,7 @@ namespace SQVector
return 1;
}
SQInteger Set(HSQUIRRELVM vm)
SQInteger _set(HSQUIRRELVM vm)
{
const char* key = nullptr;
sq_getstring(vm, 2, &key);
@ -328,7 +328,7 @@ namespace SQVector
return 0;
}
SQInteger Add(HSQUIRRELVM vm)
SQInteger _add(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
@ -350,7 +350,7 @@ namespace SQVector
return 1;
}
SQInteger Sub(HSQUIRRELVM vm)
SQInteger _sub(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
@ -372,23 +372,20 @@ namespace SQVector
return 1;
}
SQInteger Multiply(HSQUIRRELVM vm)
SQInteger _multiply(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, float) or (Vector, Vector)");
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
SQObjectType paramType = sq_gettype(vm, 2);
float s = 0.0;
Vector* v2 = nullptr;
if ((paramType & SQOBJECT_NUMERIC) &&
SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)))
if ( SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)) )
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
@ -399,8 +396,7 @@ namespace SQVector
return 1;
}
else if (paramType == OT_INSTANCE &&
SQ_SUCCEEDED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
else if ( SQ_SUCCEEDED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v2, TYPETAG_VECTOR)) )
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
@ -413,27 +409,24 @@ namespace SQVector
}
else
{
return sq_throwerror(vm, "Expected (Vector, float) or (Vector, Vector)");
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
}
SQInteger Divide(HSQUIRRELVM vm)
SQInteger _divide(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, float) or (Vector, Vector)");
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
SQObjectType paramType = sq_gettype(vm, 2);
float s = 0.0;
Vector* v2 = nullptr;
if ((paramType & SQOBJECT_NUMERIC) &&
SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)))
if ( SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)) )
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
@ -444,8 +437,7 @@ namespace SQVector
return 1;
}
else if (paramType == OT_INSTANCE &&
SQ_SUCCEEDED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
else if ( SQ_SUCCEEDED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v2, TYPETAG_VECTOR)) )
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
@ -458,10 +450,221 @@ namespace SQVector
}
else
{
return sq_throwerror(vm, "Expected (Vector, float) or (Vector, Vector)");
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
}
SQInteger _unm(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 1 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector)");
}
v1->Negate();
return 1;
}
// multi purpose - copy from input vector, or init with 3 float input
SQInteger Set(HSQUIRRELVM vm)
{
SQInteger top = sq_gettop(vm);
Vector* v1 = nullptr;
if ( top < 2 || SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) )
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
Vector* v2 = nullptr;
if ( SQ_SUCCEEDED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)) )
{
if ( top != 2 )
return sq_throwerror(vm, "Expected (Vector, Vector)");
VectorCopy( *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
float x, y, z;
if ( top == 4 &&
SQ_SUCCEEDED(sq_getfloat(vm, 2, &x)) &&
SQ_SUCCEEDED(sq_getfloat(vm, 3, &y)) &&
SQ_SUCCEEDED(sq_getfloat(vm, 4, &z)) )
{
v1->Init( x, y, z );
sq_pop( vm, 3 );
return 1;
}
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
SQInteger Add(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
VectorAdd( *v1, *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
SQInteger Subtract(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
VectorSubtract( *v1, *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
SQInteger Multiply(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
Vector* v2 = nullptr;
if ( SQ_SUCCEEDED(sq_getinstanceup( vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR )) )
{
VectorMultiply( *v1, *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
float flInput;
if ( SQ_SUCCEEDED(sq_getfloat( vm, 2, &flInput )) )
{
VectorMultiply( *v1, flInput, *v1 );
sq_remove( vm, -1 );
return 1;
}
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
SQInteger Divide(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
Vector* v2 = nullptr;
if ( SQ_SUCCEEDED(sq_getinstanceup( vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR )) )
{
VectorDivide( *v1, *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
float flInput;
if ( SQ_SUCCEEDED(sq_getfloat( vm, 2, &flInput )) )
{
VectorDivide( *v1, flInput, *v1 );
sq_remove( vm, -1 );
return 1;
}
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
SQInteger DistTo(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
sq_pushfloat( vm, v1->DistTo(*v2) );
return 1;
}
SQInteger DistToSqr(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
sq_pushfloat( vm, v1->DistToSqr(*v2) );
return 1;
}
SQInteger IsEqualTo(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) < 2 || // bother checking > 3?
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)) )
{
return sq_throwerror(vm, "Expected (Vector, Vector, float)");
}
float tolerance = 0.0f;
sq_getfloat( vm, 3, &tolerance );
sq_pushbool( vm, VectorsAreEqual( *v1, *v2, tolerance ) );
return 1;
}
SQInteger Length(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
@ -557,30 +760,23 @@ namespace SQVector
SQInteger Scale(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
float s = 0.0f;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)))
{
return sq_throwerror(vm, "Expected (Vector, float)");
}
float s = 0.0;
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
SQUserPointer p;
sq_getinstanceup(vm, -1, &p, 0);
new(p) Vector((*v1) * s);
sq_remove(vm, -2);
if (SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)))
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
SQUserPointer p;
sq_getinstanceup(vm, -1, &p, 0);
new(p) Vector((*v1) * s);
sq_remove(vm, -2);
return 1;
}
else
{
return sq_throwerror(vm, "Expected (Vector, float)");
}
return 1;
}
SQInteger Dot(HSQUIRRELVM vm)
@ -613,6 +809,42 @@ namespace SQVector
return 1;
}
SQInteger FromKVString(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
const char* szInput;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getstring(vm, 2, &szInput)) )
{
return sq_throwerror(vm, "Expected (Vector, string)");
}
float x = 0.0f, y = 0.0f, z = 0.0f;
if ( sscanf( szInput, "%f %f %f", &x, &y, &z ) < 3 ) // UTIL_StringToVector
{
// Don't throw, return null while invalidating the input vector.
// This allows the user to easily check for input errors without halting.
//return sq_throwerror(vm, "invalid KV string");
sq_pushnull(vm);
*v1 = vec3_invalid;
return 1;
}
v1->x = x;
v1->y = y;
v1->z = z;
// return input vector
sq_remove( vm, -1 );
return 1;
}
SQInteger Cross(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
@ -635,6 +867,25 @@ namespace SQVector
return 1;
}
SQInteger WithinAABox(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* mins = nullptr;
Vector* maxs = nullptr;
if (sq_gettop(vm) != 3 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&mins, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 3, (SQUserPointer*)&maxs, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector, Vector)");
}
sq_pushbool( vm, v1->WithinAABox( *mins, *maxs ) );
return 1;
}
SQInteger ToString(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
@ -645,7 +896,7 @@ namespace SQVector
return sq_throwerror(vm, "Expected (Vector)");
}
sqstd_pushstringf(vm, "(vector: (%f, %f, %f))", v1->x, v1->y, v1->z);
sqstd_pushstringf(vm, "(Vector %p [%f %f %f])", (void*)v1, v1->x, v1->y, v1->z);
return 1;
}
@ -701,22 +952,33 @@ namespace SQVector
static const SQRegFunction funcs[] = {
{_SC("constructor"), Construct,0,nullptr},
{_SC("_get"), Get, 2, _SC(".s")},
{_SC("_set"), Set, 3, _SC(".sn")},
{_SC("_add"), Add, 2, _SC("..")},
{_SC("_sub"), Sub, 2, _SC("..")},
{_SC("_mul"), Multiply, 2, _SC("..")},
{_SC("_div"), Divide, 2, _SC("..")},
{_SC("_get"), _get, 2, _SC(".s")},
{_SC("_set"), _set, 3, _SC(".sn")},
{_SC("_add"), _add, 2, _SC("..")},
{_SC("_sub"), _sub, 2, _SC("..")},
{_SC("_mul"), _multiply, 2, _SC("..")},
{_SC("_div"), _divide, 2, _SC("..")},
{_SC("_unm"), _unm, 1, _SC(".")},
{_SC("Set"), Set, -2, _SC("..nn")},
{_SC("Add"), Add, 2, _SC("..")},
{_SC("Subtract"), Subtract, 2, _SC("..")},
{_SC("Multiply"), Multiply, 2, _SC("..")},
{_SC("Divide"), Divide, 2, _SC("..")},
{_SC("DistTo"), DistTo, 2, _SC("..")},
{_SC("DistToSqr"), DistToSqr, 2, _SC("..")},
{_SC("IsEqualTo"), IsEqualTo, -2, _SC("..n")},
{_SC("Length"), Length, 1, _SC(".")},
{_SC("LengthSqr"), LengthSqr, 1, _SC(".")},
{_SC("Length2D"), Length2D, 1, _SC(".")},
{_SC("Length2DSqr"), Length2DSqr, 1, _SC(".")},
{_SC("Normalized"), Normalized, 1, _SC(".")},
{_SC("Norm"), Norm, 1, _SC(".")},
{_SC("Scale"), Scale, 2, _SC("..")},
{_SC("Scale"), Scale, 2, _SC(".n")}, // identical to _multiply
{_SC("Dot"), Dot, 2, _SC("..")},
{_SC("Cross"), Cross, 2, _SC("..")},
{_SC("WithinAABox"), WithinAABox, 3, _SC("...")},
{_SC("ToKVString"), ToKVString, 1, _SC(".")},
{_SC("FromKVString"), FromKVString, 2, _SC(".s")},
{_SC("_tostring"), ToString, 1, _SC(".")},
{_SC("_typeof"), TypeOf, 1, _SC(".")},
{_SC("_nexti"), Nexti, 2, _SC("..")},
@ -2698,7 +2960,7 @@ bool SquirrelVM::ClearValue(HSCRIPT hScope, ScriptVariant_t pKey)
return true;
}
/*
void SquirrelVM::CreateArray(ScriptVariant_t &arr, int size)
{
SquirrelSafeCheck safeCheck(vm_);
@ -2713,16 +2975,14 @@ void SquirrelVM::CreateArray(ScriptVariant_t &arr, int size)
arr = (HSCRIPT)obj;
}
*/
bool SquirrelVM::ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val)
{
SquirrelSafeCheck safeCheck(vm_);
HSQOBJECT arr = *(HSQOBJECT*)hArray;
if ( !sq_isarray(arr) )
return false;
HSQOBJECT *arr = (HSQOBJECT*)hArray;
sq_pushobject(vm_, arr);
sq_pushobject(vm_, *arr);
PushVariant(vm_, val);
bool ret = sq_arrayappend(vm_, -2) == SQ_OK;
sq_pop(vm_, 1);

View File

@ -65,6 +65,22 @@ function AngleDistance( next, cur )
return delta
}
function FLerp( f1, f2, i1, i2, x )
{
return f1+(f2-f1)*(x-i1)/(i2-i1);
}
function Lerp( f, A, B )
{
return A + ( B - A ) * f
}
function SimpleSpline( f )
{
local ff = f * f;
return 3.0 * ff - 2.0 * ff * f;
}
function printl( text )
{
return ::print(text + "\n");