mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-07-30 17:11:52 +03:00
Merge Mapbase v8.0 into the MP branch
This commit is contained in:
commit
0d7c5b4fd3
20
README.md
20
README.md
@ -52,6 +52,7 @@ Mapbase uses content from the following non-Source SDK 2013 Valve games or SDKs:
|
||||
-- Alien Swarm (Used to port assets from the aforementioned SDK code features, e.g. game instructor icons)
|
||||
-- Left 4 Dead (Used to port certain animations as well as assets from the aforementioned SDK code features, e.g. particle rain)
|
||||
-- Half-Life: Source (Used to port friction tool textures)
|
||||
-- Half-Life 2: Survivor (Used to port Gordon Freeman model)
|
||||
|
||||
Valve allows assets from these titles to be distributed for modding purposes. Note that ported assets are only used in the release build, not the code repository.
|
||||
|
||||
@ -118,6 +119,7 @@ Direct contributions:
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/245 (ViewPunch random fix by Mr0maks)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/248 (soundlevel_t conversation warning fix by Mechami)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/266 ("OnPhysGunPull" output in CPhysicsProp by rlenhub)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/281 (npc_combinedropship DropStrider input by Bronzehawk75)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/292 (env_headcrabcanister random spawn type by arbabf)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/293 (Restore text selection code by SanyaSho)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/294 (SDK_LightmappedGeneric editor blend swap fix by azzyr)
|
||||
@ -133,17 +135,27 @@ Direct contributions:
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/391 (VRAD -extrapasses command by Unusuario2)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/393 (Additional VBSP options doc by Unusuario2)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/397 (Viewmodel camera bone by Nbc66)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/412 (Compile tool negative threads support by Unusuario2)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/414 (VRAD %alphatexture by SirYodaJedi)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/415 (Parallax corrected cubemaps optimization and fix by Zeldaboy14 and White_Red_Dragons)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/418 (Server ragdoll death poses by AnOldLady)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/419 (npc_helicopter removal crash fix by Wikot235)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/420 (sk_combine_head_dmg_multiplier cvar by Wikot235)
|
||||
- https://github.com/mapbase-source/source-sdk-2013/pull/422 (Expanded HL2 NPC custom model support by Maestra Fenix [committed by Blixibon])
|
||||
- https://github.com/mapbase-source/mapbase-game-src/pull/1 (Advanced video options duplicate field name fix by arbabf; This is asset-based and not reflected in the code)
|
||||
- https://github.com/mapbase-source/mapbase-game-src/pull/2 (gameinfo.txt typo fix by CarePackage17; This is asset-based and not reflected in the code)
|
||||
- https://github.com/mapbase-source/mapbase-game-src/pull/3 (HudMessage cutoff fix by arbabf; This is asset-based and not reflected in the code)
|
||||
- Demo autorecord code provided by Klems
|
||||
- cc_emit crash fix provided by 1upD
|
||||
- npc_barnacle poison zombie crash fix provided by Agrimar
|
||||
- Custom HL2 ammo crate models created by Rykah (Textures created by Blixibon; This is asset-based and, aside from the SLAM crate, not reflected in the code)
|
||||
- Combine lock hardware on door01_left.mdl created by Kralich (This is asset-based and not reflected in the code)
|
||||
- npc_vehicledriver fixes provided by CrAzY
|
||||
- npc_combine cover behavior patches provided by iohnnyboy
|
||||
- logic_playmovie icon created by URAKOLOUY5 (This is asset-based and not reflected in the code)
|
||||
- Dropship APC save/load fix provided by Cvoxulary
|
||||
- c_arms support on HL2 viewmodels by Inaki and ReverendV92 (This is asset-based and not reflected in the code)
|
||||
- Custom c_arms for HL2 characters by Notewell (This is asset-based and not reflected in the code)
|
||||
|
||||
== Contributions from samisalreadytaken:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/47 (VScript utility/consistency changes)
|
||||
@ -166,8 +178,14 @@ Direct contributions:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/260 (CScriptNetPropManager rewrite)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/261 (Misc VScript additions)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/279 (weapon_custom_scripted fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/302 (VScript debugger)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/331 (VScript leak fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/332 (Fix OOB access)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/411 (VScript debugger cleanup)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/423 (GetPropFloatArray Vector indexing fix)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/431 (VScript save/restore and debugger fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/441 (VScript instance helper fallback)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/447 (Update VScript sqdbg)
|
||||
|
||||
== Contributions from z33ky:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux compilation fixes)
|
||||
@ -184,6 +202,7 @@ Direct contributions:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/320 (Fix ScriptHook_t initialization order)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/321 (Prevent return of dangling Vector/QAngle to VScript)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/322 (Small Mapbase fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/436 (VScript member function call safety)
|
||||
|
||||
== Contributions from Petercov:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/182 (NPCs load dynamic interactions from all animation MDLs)
|
||||
@ -194,6 +213,7 @@ Direct contributions:
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/230 (Caption fixes)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/231 (Sentence source bug fix)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/264 (Outputs for vgui_screen)
|
||||
=-- https://github.com/mapbase-source/source-sdk-2013/pull/427 (CBaseCombatWeapon::WeaponClassFromString typo fix [committed by vizzys])
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -49,6 +49,8 @@ $Project
|
||||
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\matchers.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\matchers.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\game_timer.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\game_timer.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT]
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT]
|
||||
|
@ -16,6 +16,7 @@ $Project
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_hl2.cpp" [$MAPBASE_VSCRIPT]
|
||||
$File "mapbase\c_weapon_custom_hl2.cpp"
|
||||
$File "mapbase\hud_generic_timer.cpp"
|
||||
}
|
||||
|
||||
$Folder "HL2 DLL"
|
||||
|
511
src/game/client/mapbase/hud_generic_timer.cpp
Normal file
511
src/game/client/mapbase/hud_generic_timer.cpp
Normal file
@ -0,0 +1,511 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: Generic timer HUD element for HL2-based mods
|
||||
//
|
||||
// Author: Blixibon
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "hud.h"
|
||||
#include "hud_macros.h"
|
||||
#include "hudelement.h"
|
||||
#include "hud_numericdisplay.h"
|
||||
#include "iclientmode.h"
|
||||
#include <vgui/ILocalize.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include <vgui_controls/AnimationController.h>
|
||||
#include <vgui_controls/EditablePanel.h>
|
||||
#include "baseviewport.h"
|
||||
#include "mapbase/game_timer.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern bool g_bAnyGameTimerActive;
|
||||
|
||||
ConVar hud_timer_max_bars( "hud_timer_max_bars", "15" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Timer panel
|
||||
//-----------------------------------------------------------------------------
|
||||
class CHudGenericGameTimer : public CHudElement, public vgui::Panel
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CHudGenericGameTimer, vgui::Panel );
|
||||
|
||||
public:
|
||||
CHudGenericGameTimer( const char *pElementName );
|
||||
virtual void Init( void );
|
||||
virtual void VidInit( void );
|
||||
virtual void Reset( void );
|
||||
virtual void OnThink();
|
||||
virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
|
||||
virtual bool ShouldDraw( void );
|
||||
virtual void Paint();
|
||||
|
||||
C_GameTimer *GetTimer();
|
||||
bool FindTimer();
|
||||
|
||||
void SetDisplayValue( int value ) { m_iValue = value; }
|
||||
void SetLabelText( const wchar_t *text );
|
||||
|
||||
virtual void PaintNumbers( vgui::HFont font, int xpos, int ypos );
|
||||
virtual void PaintBars( int xpos, int ypos, int wide );
|
||||
|
||||
int GetTimerIndex() const { return m_iTimerIndex; }
|
||||
|
||||
private:
|
||||
void SetTimerLabel( void );
|
||||
|
||||
private:
|
||||
|
||||
int m_iTimerIndex;
|
||||
|
||||
bool m_bTimerDisplayed;
|
||||
bool m_bPlayingFadeout;
|
||||
float m_flShutoffTime;
|
||||
|
||||
bool m_bTimerPaused;
|
||||
bool m_bTimerWarned;
|
||||
|
||||
int m_iValue;
|
||||
int m_iTimerMaxLength;
|
||||
bool m_bShowTimeRemaining;
|
||||
int m_nProgressBarMax;
|
||||
int m_nProgressBarOverride;
|
||||
float m_flOverrideX, m_flOverrideY;
|
||||
wchar_t m_LabelText[32];
|
||||
|
||||
int m_nLabelWidth, m_nLabelHeight;
|
||||
int m_nTimerWidth, m_nTimerHeight;
|
||||
|
||||
CPanelAnimationVarAliasType( float, m_flMinWidth, "MinWidth", "100", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flBorder, "Border", "24", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flLabelTimerSpacing, "LabelTimerSpacing", "2", "proportional_float" );
|
||||
|
||||
CPanelAnimationVarAliasType( float, m_flBarHeight, "BarHeight", "5", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flBarChunkGap, "BarChunkGap", "3", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flBarVerticalGap, "BarVerticalGap", "8", "proportional_float" );
|
||||
CPanelAnimationVar( int, m_iBarDisabledAlpha, "BarDisabledAlpha", "70" );
|
||||
|
||||
CPanelAnimationVar( float, m_flBlur, "Blur", "0" );
|
||||
|
||||
CPanelAnimationVar( vgui::HFont, m_hNumberFont, "NumberFont", "HudHintTextLarge" );
|
||||
CPanelAnimationVar( vgui::HFont, m_hNumberGlowFont, "NumberGlowFont", "HudHintTextLarge" );
|
||||
CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "HudHintTextSmall" );
|
||||
};
|
||||
|
||||
DECLARE_HUDELEMENT( CHudGenericGameTimer );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CHudGenericGameTimer::CHudGenericGameTimer( const char *pElementName )
|
||||
: CHudElement( pElementName ),
|
||||
BaseClass( NULL, "HudGenericGameTimer" )
|
||||
{
|
||||
Panel *pParent = g_pClientMode->GetViewport();
|
||||
SetParent( pParent );
|
||||
|
||||
SetHiddenBits( HIDEHUD_MISCSTATUS );
|
||||
|
||||
m_iTimerIndex = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::Init()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::Reset()
|
||||
{
|
||||
SetDisplayValue( 0 );
|
||||
SetAlpha( 0 );
|
||||
|
||||
m_flShutoffTime = 0.0f;
|
||||
m_bTimerDisplayed = false;
|
||||
m_iTimerIndex = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::VidInit()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::OnThink()
|
||||
{
|
||||
C_BasePlayer *local = C_BasePlayer::GetLocalPlayer();
|
||||
if ( !local )
|
||||
{
|
||||
// Not ready to init!
|
||||
return;
|
||||
}
|
||||
|
||||
// If our timer has been disabled, close the menu
|
||||
C_GameTimer *pTimer = GetTimer();
|
||||
if ( !pTimer || pTimer->IsDisabled() || pTimer->IsMarkedForDeletion() )
|
||||
{
|
||||
if ( m_flShutoffTime == 0.0f )
|
||||
{
|
||||
m_flShutoffTime = gpGlobals->curtime + 1.0f;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerClose" );
|
||||
}
|
||||
m_iTimerIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check pause state
|
||||
if ( m_bTimerPaused && !pTimer->IsTimerPaused() )
|
||||
{
|
||||
m_bTimerPaused = false;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerPulse" );
|
||||
}
|
||||
else if ( pTimer->IsTimerPaused() )
|
||||
{
|
||||
m_bTimerPaused = true;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerPulseOnce" );
|
||||
}
|
||||
|
||||
float flTimeRemaining = floorf( pTimer->GetTimeRemaining() );
|
||||
|
||||
// Check warn state
|
||||
float flWarnTime = pTimer->GetWarnTime();
|
||||
|
||||
if (flWarnTime > 0.0f)
|
||||
{
|
||||
if ( m_bTimerWarned && flTimeRemaining > flWarnTime )
|
||||
{
|
||||
// Turn back to normal
|
||||
m_bTimerWarned = false;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerUnwarn" );
|
||||
}
|
||||
else if ( flTimeRemaining <= flWarnTime )
|
||||
{
|
||||
// Turn red
|
||||
m_bTimerWarned = true;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "GenericGameTimerWarn" );
|
||||
}
|
||||
}
|
||||
|
||||
SetDisplayValue( flTimeRemaining );
|
||||
|
||||
m_iTimerMaxLength = pTimer->GetTimerMaxLength();
|
||||
m_bShowTimeRemaining = pTimer->ShowTimeRemaining();
|
||||
|
||||
m_nProgressBarMax = pTimer->GetProgressBarMaxSegments();
|
||||
if (m_nProgressBarMax == -1)
|
||||
{
|
||||
// Default to timer max length
|
||||
m_nProgressBarMax = min( m_iTimerMaxLength, hud_timer_max_bars.GetInt() );
|
||||
}
|
||||
|
||||
m_nProgressBarOverride = pTimer->GetProgressBarOverride();
|
||||
|
||||
pTimer->GetPositionOverride( m_flOverrideX, m_flOverrideY );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: hud scheme settings
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||||
{
|
||||
BaseClass::ApplySchemeSettings( pScheme );
|
||||
|
||||
SetPaintBackgroundEnabled( false );
|
||||
|
||||
// set our size
|
||||
int screenWide, screenTall;
|
||||
int x, y;
|
||||
GetPos( x, y );
|
||||
GetHudSize( screenWide, screenTall );
|
||||
SetBounds( 0, y, screenWide, screenTall - y );
|
||||
|
||||
// Start with a 0:00 timer
|
||||
m_nTimerWidth = (vgui::surface()->GetCharacterWidth( m_hNumberFont, '0' ) * 3);
|
||||
m_nTimerWidth += vgui::surface()->GetCharacterWidth( m_hNumberFont, ':' );
|
||||
|
||||
m_nTimerHeight = vgui::surface()->GetFontTall( m_hNumberFont );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudGenericGameTimer::ShouldDraw( void )
|
||||
{
|
||||
if ( !CHudElement::ShouldDraw() )
|
||||
return false;
|
||||
|
||||
if ( !m_bTimerDisplayed )
|
||||
{
|
||||
// Check if we should find a new timer
|
||||
if ( g_bAnyGameTimerActive )
|
||||
{
|
||||
if ( FindTimer() )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for if menu is set to disappear
|
||||
if ( m_flShutoffTime > 0 && m_flShutoffTime <= gpGlobals->curtime )
|
||||
{
|
||||
// times up, shutoff
|
||||
m_bTimerDisplayed = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( m_flOverrideX == -1.0f && m_flOverrideY == -1.0f )
|
||||
{
|
||||
// Don't overlap with the weapon selection HUD
|
||||
vgui::Panel *pWeaponSelection = GetParent()->FindChildByName( "HudWeaponSelection" );
|
||||
if ( pWeaponSelection && pWeaponSelection->IsVisible() )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
inline C_GameTimer *CHudGenericGameTimer::GetTimer()
|
||||
{
|
||||
if (m_iTimerIndex <= 0)
|
||||
return NULL;
|
||||
|
||||
// Need to do a dynamic_cast because this entity index could've been replaced since it was last used
|
||||
return dynamic_cast<C_GameTimer*>(C_BaseEntity::Instance( m_iTimerIndex ));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudGenericGameTimer::FindTimer()
|
||||
{
|
||||
// Find a new timer
|
||||
for ( int i = 0; i < IGameTimerAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
C_GameTimer *pTimer = static_cast<C_GameTimer *>( IGameTimerAutoList::AutoList()[i] );
|
||||
if ( !pTimer->IsDisabled() && !pTimer->IsMarkedForDeletion() )
|
||||
{
|
||||
m_iTimerIndex = pTimer->entindex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
C_GameTimer *pTimer = GetTimer();
|
||||
if ( pTimer )
|
||||
{
|
||||
// New timer selected, set the caption
|
||||
wchar_t wszLabelText[128];
|
||||
const wchar_t *wLocalizedItem = g_pVGuiLocalize->Find( pTimer->GetTimerCaption() );
|
||||
if (wLocalizedItem)
|
||||
{
|
||||
V_wcsncpy( wszLabelText, wLocalizedItem, sizeof( wszLabelText ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pTimer->GetTimerCaption(), wszLabelText, sizeof( wszLabelText ) );
|
||||
}
|
||||
SetLabelText( wszLabelText );
|
||||
|
||||
m_flShutoffTime = 0;
|
||||
m_bTimerDisplayed = true;
|
||||
m_bTimerPaused = pTimer->IsTimerPaused();
|
||||
m_bTimerWarned = false;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_bTimerPaused ? "GenericGameTimerShow" : "GenericGameTimerShowFlash" );
|
||||
|
||||
SetDisplayValue( ceil( pTimer->GetTimeRemaining() ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: data accessor
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::SetLabelText( const wchar_t *text )
|
||||
{
|
||||
wcsncpy( m_LabelText, text, sizeof( m_LabelText ) / sizeof( wchar_t ) );
|
||||
m_LabelText[(sizeof( m_LabelText ) / sizeof( wchar_t )) - 1] = 0;
|
||||
|
||||
m_nLabelWidth = 0;
|
||||
m_nLabelHeight = 0;
|
||||
|
||||
if (m_LabelText[0] != '\0')
|
||||
{
|
||||
int nLabelLen = V_wcslen( m_LabelText );
|
||||
for (int ch = 0; ch < nLabelLen; ch++)
|
||||
{
|
||||
m_nLabelWidth += vgui::surface()->GetCharacterWidth( m_hTextFont, m_LabelText[ch] );
|
||||
}
|
||||
|
||||
m_nLabelHeight = vgui::surface()->GetFontTall( m_hTextFont );
|
||||
m_nLabelHeight += m_flLabelTimerSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: paints a number at the specified position
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::PaintNumbers( vgui::HFont font, int xpos, int ypos )
|
||||
{
|
||||
vgui::surface()->DrawSetTextFont(font);
|
||||
|
||||
int nTimeToDisplay = m_iValue;
|
||||
|
||||
if ( !m_bShowTimeRemaining )
|
||||
{
|
||||
nTimeToDisplay = m_iTimerMaxLength - nTimeToDisplay;
|
||||
}
|
||||
|
||||
int nMinutes = 0;
|
||||
int nSeconds = 0;
|
||||
wchar_t unicode[6];
|
||||
|
||||
if (nTimeToDisplay <= 0)
|
||||
{
|
||||
nMinutes = 0;
|
||||
nSeconds = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nMinutes = nTimeToDisplay / 60;
|
||||
nSeconds = nTimeToDisplay % 60;
|
||||
}
|
||||
|
||||
V_snwprintf( unicode, ARRAYSIZE(unicode), L"%d:%02d", nMinutes, nSeconds );
|
||||
|
||||
vgui::surface()->DrawSetTextPos( xpos, ypos );
|
||||
vgui::surface()->DrawUnicodeString( unicode );
|
||||
|
||||
// draw the overbright blur
|
||||
for (float fl = m_flBlur; fl > 0.0f; fl -= 1.0f)
|
||||
{
|
||||
if (fl >= 1.0f)
|
||||
{
|
||||
vgui::surface()->DrawSetTextPos( xpos, ypos );
|
||||
vgui::surface()->DrawUnicodeString( unicode );
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw a percentage of the last one
|
||||
Color col = GetFgColor();
|
||||
col[3] *= fl;
|
||||
vgui::surface()->DrawSetTextColor( col );
|
||||
vgui::surface()->DrawSetTextPos( xpos, ypos );
|
||||
vgui::surface()->DrawUnicodeString( unicode );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: paints bars at the specified position
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::PaintBars( int xpos, int ypos, int wide )
|
||||
{
|
||||
// get bar chunks
|
||||
int barChunkWidth = (wide / m_nProgressBarMax) - m_flBarChunkGap;
|
||||
|
||||
int enabledChunks;
|
||||
if (m_nProgressBarOverride > -1)
|
||||
enabledChunks = m_nProgressBarOverride;
|
||||
else
|
||||
{
|
||||
enabledChunks = (int)floorf( ((float)m_iValue / (float)m_iTimerMaxLength) * (float)m_nProgressBarMax );
|
||||
if (!m_bShowTimeRemaining)
|
||||
{
|
||||
enabledChunks = m_nProgressBarMax - enabledChunks;
|
||||
}
|
||||
}
|
||||
|
||||
// draw the suit power bar
|
||||
vgui::surface()->DrawSetColor( GetFgColor() );
|
||||
for (int i = 0; i < enabledChunks; i++)
|
||||
{
|
||||
vgui::surface()->DrawFilledRect( xpos, ypos, xpos + barChunkWidth, ypos + m_flBarHeight );
|
||||
xpos += (barChunkWidth + m_flBarChunkGap);
|
||||
}
|
||||
// draw the exhausted portion of the bar.
|
||||
Color clrExhausted = GetFgColor();
|
||||
clrExhausted[3] = ((float)clrExhausted[3] / 255.0f) * m_iBarDisabledAlpha;
|
||||
vgui::surface()->DrawSetColor( clrExhausted );
|
||||
for (int i = enabledChunks; i < m_nProgressBarMax; i++)
|
||||
{
|
||||
vgui::surface()->DrawFilledRect( xpos, ypos, xpos + barChunkWidth, ypos + m_flBarHeight );
|
||||
xpos += (barChunkWidth + m_flBarChunkGap);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: renders the vgui panel
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudGenericGameTimer::Paint()
|
||||
{
|
||||
// Check for 00:00 timer
|
||||
int nTimerWidth = m_nTimerWidth;
|
||||
if (m_iValue > 600)
|
||||
nTimerWidth += vgui::surface()->GetCharacterWidth( m_hNumberFont, '0' );
|
||||
|
||||
// draw the background
|
||||
int wide = max( nTimerWidth, m_nLabelWidth ) + m_flBorder;
|
||||
if (m_flMinWidth > wide)
|
||||
wide = m_flMinWidth;
|
||||
|
||||
int tall = m_nTimerHeight + m_nLabelHeight + (m_flBorder/2);
|
||||
if (m_nProgressBarMax > 0)
|
||||
tall += m_flBarHeight + m_flBarVerticalGap;
|
||||
else
|
||||
tall += (m_flBorder/2);
|
||||
|
||||
int screenW, screenH;
|
||||
GetHudSize( screenW, screenH );
|
||||
|
||||
float flScalarX = (m_flOverrideX != -1.0f ? m_flOverrideX : 0.5f);
|
||||
float flScalarY = (m_flOverrideY != -1.0f ? m_flOverrideY : 0.05f);
|
||||
|
||||
int x = (screenW - wide) * flScalarX;
|
||||
int y = (screenH - tall) * flScalarY;
|
||||
|
||||
DrawBox( x, y, wide, tall, GetBgColor(), 1.0f);
|
||||
|
||||
y += (m_flBorder/2);
|
||||
|
||||
// draw our bars
|
||||
if (m_nProgressBarMax > 0)
|
||||
{
|
||||
int barX = x + (m_flBorder/2);
|
||||
PaintBars( barX, y, wide - m_flBorder );
|
||||
y += m_flBarVerticalGap;
|
||||
}
|
||||
|
||||
if (m_nLabelHeight > 0)
|
||||
{
|
||||
vgui::surface()->DrawSetTextFont( m_hTextFont );
|
||||
vgui::surface()->DrawSetTextColor( GetFgColor() );
|
||||
vgui::surface()->DrawSetTextPos( x + ((wide - m_nLabelWidth) * 0.5f), y );
|
||||
vgui::surface()->DrawUnicodeString( m_LabelText );
|
||||
y += m_nLabelHeight;
|
||||
}
|
||||
|
||||
// draw our numbers
|
||||
vgui::surface()->DrawSetTextColor( GetFgColor() );
|
||||
|
||||
int digitX = x + ((wide - nTimerWidth) * 0.5f);
|
||||
int digitY = y;
|
||||
PaintNumbers( m_hNumberFont, digitX, digitY );
|
||||
}
|
@ -37,6 +37,9 @@ char g_szPrelocalisedMenuString[MAX_MENU_STRING];
|
||||
|
||||
DECLARE_HUDELEMENT( CHudMenu );
|
||||
DECLARE_HUD_MESSAGE( CHudMenu, ShowMenu );
|
||||
#ifdef MAPBASE
|
||||
DECLARE_HUD_MESSAGE( CHudMenu, ShowMenuComplex );
|
||||
#endif
|
||||
|
||||
//
|
||||
//-----------------------------------------------------
|
||||
@ -71,6 +74,9 @@ CHudMenu::CHudMenu( const char *pElementName ) :
|
||||
void CHudMenu::Init( void )
|
||||
{
|
||||
HOOK_HUD_MESSAGE( CHudMenu, ShowMenu );
|
||||
#ifdef MAPBASE
|
||||
HOOK_HUD_MESSAGE( CHudMenu, ShowMenuComplex );
|
||||
#endif
|
||||
|
||||
m_bMenuTakesInput = false;
|
||||
m_bMenuDisplayed = false;
|
||||
@ -81,6 +87,24 @@ void CHudMenu::Init( void )
|
||||
Reset();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenu::LevelInit()
|
||||
{
|
||||
CHudElement::LevelInit();
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_bMapDefinedMenu)
|
||||
{
|
||||
// Fixes menu retaining on level change/reload
|
||||
// TODO: Would non-map menus benefit from this as well?
|
||||
m_bMenuTakesInput = false;
|
||||
m_bMenuDisplayed = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -114,7 +138,11 @@ void CHudMenu::OnThink()
|
||||
float flSelectionTimeout = MENU_SELECTION_TIMEOUT;
|
||||
|
||||
// If we've been open for a while without input, hide
|
||||
#ifdef MAPBASE
|
||||
if ( m_bMenuDisplayed && ( gpGlobals->curtime - m_flSelectionTime > flSelectionTimeout && !m_bMapDefinedMenu ) )
|
||||
#else
|
||||
if ( m_bMenuDisplayed && ( gpGlobals->curtime - m_flSelectionTime > flSelectionTimeout ) )
|
||||
#endif
|
||||
{
|
||||
m_bMenuDisplayed = false;
|
||||
}
|
||||
@ -130,11 +158,24 @@ bool CHudMenu::ShouldDraw( void )
|
||||
return false;
|
||||
|
||||
// check for if menu is set to disappear
|
||||
if ( m_flShutoffTime > 0 && m_flShutoffTime <= gpGlobals->realtime )
|
||||
if ( m_flShutoffTime > 0 )
|
||||
{
|
||||
// times up, shutoff
|
||||
m_bMenuDisplayed = false;
|
||||
return false;
|
||||
#ifdef MAPBASE
|
||||
if ( m_bMapDefinedMenu && !m_bPlayingFadeout && (m_flShutoffTime - m_flOpenCloseTime) <= GetMenuTime() )
|
||||
{
|
||||
// Begin closing the menu
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "MenuClose" );
|
||||
m_bMenuTakesInput = false;
|
||||
m_bPlayingFadeout = true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ( m_flShutoffTime <= GetMenuTime() )
|
||||
{
|
||||
// times up, shutoff
|
||||
m_bMenuDisplayed = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return draw;
|
||||
@ -169,23 +210,21 @@ void CHudMenu::Paint()
|
||||
return;
|
||||
|
||||
// center it
|
||||
int x = 20;
|
||||
int x = m_nBorder;
|
||||
|
||||
Color menuColor = m_MenuColor;
|
||||
Color itemColor = m_ItemColor;
|
||||
|
||||
int c = m_Processed.Count();
|
||||
|
||||
int border = 20;
|
||||
|
||||
int wide = m_nMaxPixels + border;
|
||||
int tall = m_nHeight + border;
|
||||
int wide = m_nMaxPixels + m_nBorder;
|
||||
int tall = m_nHeight + m_nBorder;
|
||||
|
||||
int y = ( ScreenHeight() - tall ) * 0.5f;
|
||||
|
||||
DrawBox( x - border/2, y - border/2, wide, tall, m_BoxColor, m_flSelectionAlphaOverride / 255.0f );
|
||||
DrawBox( x - m_nBorder/2, y - m_nBorder/2, wide, tall, m_BoxColor, m_flSelectionAlphaOverride / 255.0f );
|
||||
|
||||
//DrawTexturedBox( x - border/2, y - border/2, wide, tall, m_BoxColor, m_flSelectionAlphaOverride / 255.0f );
|
||||
//DrawTexturedBox( x - m_nBorder/2, y - m_nBorder/2, wide, tall, m_BoxColor, m_flSelectionAlphaOverride / 255.0f );
|
||||
|
||||
menuColor[3] = menuColor[3] * ( m_flSelectionAlphaOverride / 255.0f );
|
||||
itemColor[3] = itemColor[3] * ( m_flSelectionAlphaOverride / 255.0f );
|
||||
@ -195,7 +234,18 @@ void CHudMenu::Paint()
|
||||
ProcessedLine *line = &m_Processed[ i ];
|
||||
Assert( line );
|
||||
|
||||
Color clr = line->menuitem != 0 ? itemColor : menuColor;
|
||||
#ifdef MAPBASE
|
||||
bool isItem = true;
|
||||
if (line->menuitem == 0 && line->startchar < (MAX_MENU_STRING-1) && g_szMenuString[ line->startchar ] != L'0' && g_szMenuString[ line->startchar+1 ] != L'.')
|
||||
{
|
||||
// Can't use 0 directly because it gets conflated with the cancel item
|
||||
isItem = false;
|
||||
}
|
||||
#else
|
||||
bool isItem = line->menuitem != 0;
|
||||
#endif
|
||||
|
||||
Color clr = isItem ? itemColor : menuColor;
|
||||
|
||||
bool canblur = false;
|
||||
if ( line->menuitem != 0 &&
|
||||
@ -208,15 +258,15 @@ void CHudMenu::Paint()
|
||||
vgui::surface()->DrawSetTextColor( clr );
|
||||
|
||||
int drawLen = line->length;
|
||||
if ( line->menuitem != 0 )
|
||||
if (isItem)
|
||||
{
|
||||
drawLen *= m_flTextScan;
|
||||
}
|
||||
|
||||
vgui::surface()->DrawSetTextFont( line->menuitem != 0 ? m_hItemFont : m_hTextFont );
|
||||
vgui::surface()->DrawSetTextFont( isItem ? m_hItemFont : m_hTextFont );
|
||||
|
||||
PaintString( &g_szMenuString[ line->startchar ], drawLen,
|
||||
line->menuitem != 0 ? m_hItemFont : m_hTextFont, x, y );
|
||||
isItem ? m_hItemFont : m_hTextFont, x, y );
|
||||
|
||||
if ( canblur )
|
||||
{
|
||||
@ -242,6 +292,20 @@ void CHudMenu::Paint()
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
inline float CHudMenu::GetMenuTime( void )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// In singleplayer, use the curtime instead. This fixes issues with menus disappearing after pausing
|
||||
if (gpGlobals->maxClients <= 1)
|
||||
return gpGlobals->curtime;
|
||||
#endif
|
||||
|
||||
return gpGlobals->realtime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: selects an item from the menu
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -260,7 +324,7 @@ void CHudMenu::SelectMenuItem( int menu_item )
|
||||
|
||||
// remove the menu quickly
|
||||
m_bMenuTakesInput = false;
|
||||
m_flShutoffTime = gpGlobals->realtime + m_flOpenCloseTime;
|
||||
m_flShutoffTime = GetMenuTime() + m_flOpenCloseTime;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("MenuClose");
|
||||
}
|
||||
}
|
||||
@ -339,9 +403,20 @@ void CHudMenu::ProcessText( void )
|
||||
{
|
||||
ProcessedLine *l = &m_Processed[ i ];
|
||||
Assert( l );
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool isItem = true;
|
||||
if (l->menuitem == 0 && l->startchar < (MAX_MENU_STRING-1) && g_szMenuString[ l->startchar ] != L'0' && g_szMenuString[ l->startchar+1 ] != L'.')
|
||||
{
|
||||
// Can't use 0 directly because it gets conflated with the cancel item
|
||||
isItem = false;
|
||||
}
|
||||
#else
|
||||
bool isItem = l->menuitem != 0;
|
||||
#endif
|
||||
|
||||
int pixels = 0;
|
||||
vgui::HFont font = l->menuitem != 0 ? m_hItemFont : m_hTextFont;
|
||||
vgui::HFont font = isItem ? m_hItemFont : m_hTextFont;
|
||||
|
||||
for ( int ch = 0; ch < l->length; ch++ )
|
||||
{
|
||||
@ -364,7 +439,7 @@ void CHudMenu::ProcessText( void )
|
||||
void CHudMenu::HideMenu( void )
|
||||
{
|
||||
m_bMenuTakesInput = false;
|
||||
m_flShutoffTime = gpGlobals->realtime + m_flOpenCloseTime;
|
||||
m_flShutoffTime = GetMenuTime() + m_flOpenCloseTime;
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("MenuClose");
|
||||
}
|
||||
|
||||
@ -381,6 +456,11 @@ void CHudMenu::ShowMenu( const char * menuName, int validSlots )
|
||||
m_flShutoffTime = -1;
|
||||
m_bitsValidSlots = validSlots;
|
||||
m_fWaitingForMore = 0;
|
||||
m_nBorder = 20;
|
||||
#ifdef MAPBASE
|
||||
m_bMapDefinedMenu = false;
|
||||
m_bPlayingFadeout = false;
|
||||
#endif
|
||||
|
||||
Q_strncpy( g_szPrelocalisedMenuString, menuName, sizeof( g_szPrelocalisedMenuString ) );
|
||||
|
||||
@ -408,6 +488,11 @@ void CHudMenu::ShowMenu_KeyValueItems( KeyValues *pKV )
|
||||
m_flShutoffTime = -1;
|
||||
m_fWaitingForMore = 0;
|
||||
m_bitsValidSlots = 0;
|
||||
m_nBorder = 20;
|
||||
#ifdef MAPBASE
|
||||
m_bMapDefinedMenu = false;
|
||||
m_bPlayingFadeout = false;
|
||||
#endif
|
||||
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("MenuOpen");
|
||||
m_nSelectedItem = -1;
|
||||
@ -426,7 +511,11 @@ void CHudMenu::ShowMenu_KeyValueItems( KeyValues *pKV )
|
||||
const char *pszItem = item->GetName();
|
||||
const wchar_t *wLocalizedItem = g_pVGuiLocalize->Find( pszItem );
|
||||
|
||||
#ifdef MAPBASE
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"->%d. %ls\n", i+1, wLocalizedItem );
|
||||
#else
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"%d. %ls\n", i+1, wLocalizedItem );
|
||||
#endif
|
||||
nRemaining -= nCount;
|
||||
pWritePosition += nCount;
|
||||
|
||||
@ -436,7 +525,11 @@ void CHudMenu::ShowMenu_KeyValueItems( KeyValues *pKV )
|
||||
// put a cancel on the end
|
||||
m_bitsValidSlots |= (1<<9);
|
||||
|
||||
#ifdef MAPBASE
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"->0. %ls\n", g_pVGuiLocalize->Find( "#Cancel" ) );
|
||||
#else
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"0. %ls\n", g_pVGuiLocalize->Find( "#Cancel" ) );
|
||||
#endif
|
||||
nRemaining -= nCount;
|
||||
pWritePosition += nCount;
|
||||
|
||||
@ -465,8 +558,7 @@ void CHudMenu::MsgFunc_ShowMenu( bf_read &msg)
|
||||
|
||||
if ( DisplayTime > 0 )
|
||||
{
|
||||
m_flShutoffTime = m_flOpenCloseTime + DisplayTime + gpGlobals->realtime;
|
||||
|
||||
m_flShutoffTime = m_flOpenCloseTime + DisplayTime + GetMenuTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -511,8 +603,131 @@ void CHudMenu::MsgFunc_ShowMenu( bf_read &msg)
|
||||
}
|
||||
|
||||
m_fWaitingForMore = NeedMore;
|
||||
m_nBorder = 20;
|
||||
#ifdef MAPBASE
|
||||
m_bMapDefinedMenu = false;
|
||||
m_bPlayingFadeout = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar hud_menu_complex_border( "hud_menu_complex_border", "30" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Message handler for ShowMenu message with more options for game_menu
|
||||
// takes four values:
|
||||
// short : a bitfield of keys that are valid input
|
||||
// float : the duration, in seconds, the menu should stay up. -1 means it stays until something is chosen.
|
||||
// byte : a boolean, TRUE if there is more string yet to be received before displaying the menu, false if it's the last string
|
||||
// string: menu string to display
|
||||
// if this message is never received, then scores will simply be the combined totals of the players.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudMenu::MsgFunc_ShowMenuComplex( bf_read &msg)
|
||||
{
|
||||
m_bitsValidSlots = (short)msg.ReadWord();
|
||||
float DisplayTime = msg.ReadFloat();
|
||||
int NeedMore = msg.ReadByte();
|
||||
|
||||
m_nBorder = hud_menu_complex_border.GetInt();
|
||||
m_bMapDefinedMenu = true;
|
||||
m_bPlayingFadeout = false;
|
||||
|
||||
if ( DisplayTime > 0 )
|
||||
{
|
||||
m_flShutoffTime = m_flOpenCloseTime + DisplayTime + GetMenuTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flShutoffTime = -1;
|
||||
}
|
||||
|
||||
if ( m_bitsValidSlots > -1 )
|
||||
{
|
||||
char szString[2048];
|
||||
msg.ReadString( szString, sizeof(szString) );
|
||||
|
||||
if ( !m_fWaitingForMore ) // this is the start of a new menu
|
||||
{
|
||||
Q_strncpy( g_szPrelocalisedMenuString, szString, sizeof( g_szPrelocalisedMenuString ) );
|
||||
}
|
||||
else
|
||||
{ // append to the current menu string
|
||||
Q_strncat( g_szPrelocalisedMenuString, szString, sizeof( g_szPrelocalisedMenuString ), COPY_ALL_CHARACTERS );
|
||||
}
|
||||
|
||||
if ( !NeedMore )
|
||||
{
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("MenuOpenFlash");
|
||||
m_nSelectedItem = -1;
|
||||
|
||||
// we have the whole string, so we can localise it now
|
||||
wchar_t *pWritePosition = g_szMenuString;
|
||||
int nRemaining = sizeof( g_szMenuString ) / sizeof( wchar_t );
|
||||
int nCount;
|
||||
|
||||
char *pszToken = strtok( szString, "\n" );
|
||||
int nCurItem = 0;
|
||||
for (; pszToken != NULL; pszToken = strtok( NULL, "\n" ), nCurItem++)
|
||||
{
|
||||
if (!*pszToken || *pszToken == ' ')
|
||||
continue;
|
||||
|
||||
wchar_t wszMenuItem[128];
|
||||
|
||||
const wchar_t *wLocalizedItem = g_pVGuiLocalize->Find( pszToken );
|
||||
if (wLocalizedItem)
|
||||
{
|
||||
V_wcsncpy( wszMenuItem, wLocalizedItem, sizeof( wszMenuItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pszToken, wszMenuItem, sizeof( wszMenuItem ) );
|
||||
}
|
||||
|
||||
if (nCurItem == 0)
|
||||
{
|
||||
// First item is title
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"%ls\n", wszMenuItem );
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this item isn't valid, skip until it is
|
||||
//while (!(m_bitsValidSlots & (1 << nCurItem)) && nCurItem < 10)
|
||||
//{
|
||||
// nCurItem++;
|
||||
//}
|
||||
|
||||
if (nCurItem == 10)
|
||||
nCurItem = 0;
|
||||
|
||||
nCount = _snwprintf( pWritePosition, nRemaining, L"->%d. %ls\n", nCurItem, wszMenuItem );
|
||||
}
|
||||
|
||||
nRemaining -= nCount;
|
||||
pWritePosition += nCount;
|
||||
}
|
||||
|
||||
ProcessText();
|
||||
}
|
||||
|
||||
m_bMenuDisplayed = true;
|
||||
|
||||
if (m_bitsValidSlots > 0)
|
||||
m_bMenuTakesInput = true;
|
||||
else
|
||||
m_bMenuTakesInput = false;
|
||||
|
||||
m_flSelectionTime = gpGlobals->curtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
HideMenu();
|
||||
}
|
||||
|
||||
m_fWaitingForMore = NeedMore;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: hud scheme settings
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -26,10 +26,14 @@ class CHudMenu : public CHudElement, public vgui::Panel
|
||||
public:
|
||||
CHudMenu( const char *pElementName );
|
||||
void Init( void );
|
||||
void LevelInit( void );
|
||||
void VidInit( void );
|
||||
void Reset( void );
|
||||
virtual bool ShouldDraw( void );
|
||||
void MsgFunc_ShowMenu( bf_read &msg );
|
||||
#ifdef MAPBASE
|
||||
void MsgFunc_ShowMenuComplex( bf_read &msg );
|
||||
#endif
|
||||
void HideMenu( void );
|
||||
void ShowMenu( const char * menuName, int keySlot );
|
||||
void ShowMenu_KeyValueItems( KeyValues *pKV );
|
||||
@ -42,6 +46,8 @@ private:
|
||||
virtual void Paint();
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
|
||||
private:
|
||||
float GetMenuTime( void );
|
||||
|
||||
void ProcessText( void );
|
||||
|
||||
void PaintString( const wchar_t *text, int textlen, vgui::HFont& font, int x, int y );
|
||||
@ -59,6 +65,7 @@ private:
|
||||
|
||||
int m_nMaxPixels;
|
||||
int m_nHeight;
|
||||
int m_nBorder;
|
||||
|
||||
bool m_bMenuDisplayed;
|
||||
int m_bitsValidSlots;
|
||||
@ -69,6 +76,12 @@ private:
|
||||
|
||||
float m_flSelectionTime;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Indicates this menu is defined by game_menu
|
||||
bool m_bMapDefinedMenu;
|
||||
bool m_bPlayingFadeout;
|
||||
#endif
|
||||
|
||||
CPanelAnimationVar( float, m_flOpenCloseTime, "OpenCloseTime", "1" );
|
||||
|
||||
CPanelAnimationVar( float, m_flBlur, "Blur", "0" );
|
||||
|
@ -45,7 +45,7 @@ extern IScriptManager *scriptmanager;
|
||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
extern int vscript_debugger_port;
|
||||
ConVar script_connect_debugger_on_mapspawn_client( "script_connect_debugger_on_mapspawn_client", "0" );
|
||||
#endif
|
||||
|
||||
// #define VMPROFILE 1
|
||||
@ -765,10 +765,13 @@ bool VScriptClientInit()
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if ( vscript_debugger_port )
|
||||
if ( script_connect_debugger_on_mapspawn_client.GetInt() == 2 )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port, 10.0f );
|
||||
}
|
||||
else if ( script_connect_debugger_on_mapspawn_client.GetInt() != 0 )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||
vscript_debugger_port = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3045,7 +3045,7 @@ void CAI_BaseNPC::SetHeadDirection( const Vector &vTargetPos, float flInterval)
|
||||
//--------------------------------------
|
||||
// Set head yaw
|
||||
//--------------------------------------
|
||||
float flDesiredYaw = VecToYaw(vTargetPos - GetLocalOrigin()) - GetLocalAngles().y;
|
||||
float flDesiredYaw = VecToYaw(vTargetPos - GetAbsOrigin()) - GetAbsAngles().y;
|
||||
if (flDesiredYaw > 180)
|
||||
flDesiredYaw -= 360;
|
||||
if (flDesiredYaw < -180)
|
||||
@ -8005,7 +8005,7 @@ void CAI_BaseNPC::NPCInit ( void )
|
||||
|
||||
SetGravity(1.0); // Don't change
|
||||
m_takedamage = DAMAGE_YES;
|
||||
GetMotor()->SetIdealYaw( GetLocalAngles().y );
|
||||
GetMotor()->SetIdealYaw( GetAbsAngles().y );
|
||||
m_iMaxHealth = m_iHealth;
|
||||
m_lifeState = LIFE_ALIVE;
|
||||
SetIdealState( NPC_STATE_IDLE );// Assume npc will be idle, until proven otherwise
|
||||
@ -9657,7 +9657,7 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget )
|
||||
vecProjection.y = vecTarget.x;
|
||||
vecProjection.z = 0;
|
||||
|
||||
return UTIL_VecToYaw( vecProjection - GetLocalOrigin() );
|
||||
return UTIL_VecToYaw( vecProjection - GetAbsOrigin() );
|
||||
}
|
||||
else if ( GetNavigator()->GetMovementActivity() == ACT_STRAFE_RIGHT )
|
||||
{
|
||||
@ -9665,7 +9665,7 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget )
|
||||
vecProjection.y = vecTarget.x;
|
||||
vecProjection.z = 0;
|
||||
|
||||
return UTIL_VecToYaw( vecProjection - GetLocalOrigin() );
|
||||
return UTIL_VecToYaw( vecProjection - GetAbsOrigin() );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
// Allow hint nodes to override the yaw without needing to control AI
|
||||
@ -9676,7 +9676,7 @@ float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget )
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return UTIL_VecToYaw ( vecTarget - GetLocalOrigin() );
|
||||
return UTIL_VecToYaw ( vecTarget - GetAbsOrigin() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -9876,7 +9876,7 @@ void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent )
|
||||
//DevMsg( "Turned!\n" );
|
||||
SetIdealActivity( ACT_IDLE );
|
||||
Forget( bits_MEMORY_TURNING );
|
||||
SetBoneController( 0, GetLocalAngles().y );
|
||||
SetBoneController( 0, GetAbsAngles().y );
|
||||
IncrementInterpolationFrame();
|
||||
break;
|
||||
}
|
||||
@ -11155,7 +11155,7 @@ Vector CAI_BaseNPC::GetShootEnemyDir( const Vector &shootOrigin, bool bNoisy )
|
||||
else
|
||||
{
|
||||
Vector forward;
|
||||
AngleVectors( GetLocalAngles(), &forward );
|
||||
AngleVectors( GetAbsAngles(), &forward );
|
||||
return forward;
|
||||
}
|
||||
}
|
||||
@ -14193,7 +14193,7 @@ bool CAI_BaseNPC::OverrideMove( float flInterval )
|
||||
float CAI_BaseNPC::VecToYaw( const Vector &vecDir )
|
||||
{
|
||||
if (vecDir.x == 0 && vecDir.y == 0 && vecDir.z == 0)
|
||||
return GetLocalAngles().y;
|
||||
return GetAbsAngles().y;
|
||||
|
||||
return UTIL_VecToYaw( vecDir );
|
||||
}
|
||||
|
@ -1180,6 +1180,11 @@ public:
|
||||
|
||||
void SetDeathPose( const int &iDeathPose ) { m_iDeathPose = iDeathPose; }
|
||||
void SetDeathPoseFrame( const int &iDeathPoseFrame ) { m_iDeathFrame = iDeathPoseFrame; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
int GetDeathPose() { return m_iDeathPose; }
|
||||
int GetDeathPoseFrame() { return m_iDeathFrame; }
|
||||
#endif
|
||||
|
||||
void SelectDeathPose( const CTakeDamageInfo &info );
|
||||
virtual bool ShouldPickADeathPose( void ) { return true; }
|
||||
|
@ -964,7 +964,7 @@ void CAI_BaseNPC::StartTurn( float flDeltaYaw )
|
||||
{
|
||||
float flCurrentYaw;
|
||||
|
||||
flCurrentYaw = UTIL_AngleMod( GetLocalAngles().y );
|
||||
flCurrentYaw = UTIL_AngleMod( GetAbsAngles().y );
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( flCurrentYaw + flDeltaYaw ) );
|
||||
SetTurnActivity();
|
||||
}
|
||||
@ -1157,7 +1157,7 @@ void CAI_BaseNPC::StartScriptMoveToTargetTask( int task )
|
||||
{
|
||||
TaskFail(FAIL_NO_TARGET);
|
||||
}
|
||||
else if ( (m_hTargetEnt->GetAbsOrigin() - GetLocalOrigin()).Length() < 1 )
|
||||
else if ( (m_hTargetEnt->GetAbsOrigin() - GetAbsOrigin()).Length() < 1 )
|
||||
{
|
||||
TaskComplete();
|
||||
}
|
||||
@ -1622,7 +1622,7 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
break;
|
||||
|
||||
case TASK_SET_IDEAL_YAW_TO_CURRENT:
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( GetLocalAngles().y ) );
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( GetAbsAngles().y ) );
|
||||
TaskComplete();
|
||||
break;
|
||||
|
||||
@ -1776,7 +1776,7 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
{
|
||||
TaskFail(FAIL_NO_TARGET);
|
||||
}
|
||||
else if ( (pTarget->GetAbsOrigin() - GetLocalOrigin()).Length() < 1 )
|
||||
else if ( (pTarget->GetAbsOrigin() - GetAbsOrigin()).Length() < 1 )
|
||||
{
|
||||
TaskComplete();
|
||||
}
|
||||
@ -3021,7 +3021,7 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
{
|
||||
if ( m_hTargetEnt != NULL )
|
||||
{
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( m_hTargetEnt->GetLocalAngles().y ) );
|
||||
GetMotor()->SetIdealYaw( UTIL_AngleMod( m_hTargetEnt->GetAbsAngles().y ) );
|
||||
}
|
||||
|
||||
if ( m_scriptState != SCRIPT_CUSTOM_MOVE_TO_MARK )
|
||||
@ -3350,7 +3350,7 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
||||
pTarget = GetEnemy();
|
||||
if ( pTarget )
|
||||
{
|
||||
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin() , AI_KEEP_YAW_SPEED );
|
||||
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetAbsOrigin(), AI_KEEP_YAW_SPEED );
|
||||
}
|
||||
|
||||
if ( IsActivityFinished() )
|
||||
|
@ -1624,6 +1624,9 @@ void CHL2_Player::Spawn(void)
|
||||
|
||||
if (m_iszProtagonistName == NULL_STRING && *g_szDefaultProtagonist)
|
||||
m_iszProtagonistName = MAKE_STRING( g_szDefaultProtagonist );
|
||||
|
||||
if (m_iszProtagonistName != NULL_STRING)
|
||||
SetProtagonist( STRING( m_iszProtagonistName ) );
|
||||
#endif
|
||||
|
||||
//
|
||||
|
@ -256,7 +256,7 @@ END_DATADESC()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_PoisonZombie::Precache( void )
|
||||
{
|
||||
PrecacheModel("models/zombie/poison.mdl");
|
||||
PrecacheModel( DefaultOrCustomModel( "models/zombie/poison.mdl" ) );
|
||||
|
||||
PrecacheScriptSound( "NPC_PoisonZombie.Die" );
|
||||
PrecacheScriptSound( "NPC_PoisonZombie.ThrowWarn" );
|
||||
@ -509,7 +509,7 @@ void CNPC_PoisonZombie::SetZombieModel( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModel( "models/zombie/poison.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/zombie/poison.mdl" ) );
|
||||
SetHullType(HULL_HUMAN);
|
||||
}
|
||||
|
||||
|
@ -472,8 +472,8 @@ void CNPC_Antlion::Precache( void )
|
||||
#ifdef HL2_EPISODIC
|
||||
if ( IsWorker() )
|
||||
{
|
||||
PrecacheModel( ANTLION_WORKER_MODEL );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( ANTLION_WORKER_MODEL ) );
|
||||
PrecacheModel( DefaultOrCustomModel( ANTLION_WORKER_MODEL ) );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( DefaultOrCustomModel( ANTLION_WORKER_MODEL ) ) );
|
||||
UTIL_PrecacheOther( "grenade_spit" );
|
||||
PrecacheParticleSystem( "blood_impact_antlion_worker_01" );
|
||||
PrecacheParticleSystem( "antlion_gib_02" );
|
||||
@ -482,8 +482,8 @@ void CNPC_Antlion::Precache( void )
|
||||
else
|
||||
#endif // HL2_EPISODIC
|
||||
{
|
||||
PrecacheModel( ANTLION_MODEL );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( ANTLION_MODEL ) );
|
||||
PrecacheModel( DefaultOrCustomModel( ANTLION_MODEL ) );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( DefaultOrCustomModel( ANTLION_MODEL ) ) );
|
||||
PrecacheParticleSystem( "blood_impact_antlion_01" );
|
||||
PrecacheParticleSystem( "AntlionGib" );
|
||||
}
|
||||
|
@ -4055,9 +4055,12 @@ void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info )
|
||||
}
|
||||
|
||||
m_lifeState = LIFE_DYING;
|
||||
|
||||
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
|
||||
controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.1f );
|
||||
|
||||
if ( GetSleepState() != AISS_WAITING_FOR_INPUT )
|
||||
{
|
||||
CSoundEnvelopeController& controller = CSoundEnvelopeController::GetController();
|
||||
controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.1f );
|
||||
}
|
||||
|
||||
if( GetCrashPoint() == NULL )
|
||||
{
|
||||
|
@ -839,6 +839,9 @@ void CNPC_Citizen::SelectModel()
|
||||
}
|
||||
}
|
||||
|
||||
// Models selected this way must be unique to avoid conflicts in save/restore
|
||||
m_Type = CT_UNIQUE;
|
||||
|
||||
// Just set the model right here
|
||||
SetModelName( AllocPooledString( returnValue.m_pszString ) );
|
||||
return;
|
||||
|
@ -275,7 +275,7 @@ CNPC_CombineCamera::~CNPC_CombineCamera()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_CombineCamera::Precache()
|
||||
{
|
||||
PrecacheModel(COMBINE_CAMERA_MODEL);
|
||||
PrecacheModel( DefaultOrCustomModel( COMBINE_CAMERA_MODEL ) );
|
||||
PrecacheModel(COMBINE_CAMERA_GLOW_SPRITE);
|
||||
PrecacheModel(COMBINE_CAMERA_FLASH_SPRITE);
|
||||
|
||||
@ -304,8 +304,7 @@ void CNPC_CombineCamera::Precache()
|
||||
void CNPC_CombineCamera::Spawn()
|
||||
{
|
||||
Precache();
|
||||
|
||||
SetModel(COMBINE_CAMERA_MODEL);
|
||||
SetModel( DefaultOrCustomModel( COMBINE_CAMERA_MODEL ) );
|
||||
|
||||
m_pEyeFlash = CSprite::SpriteCreate(COMBINE_CAMERA_FLASH_SPRITE, GetLocalOrigin(), FALSE);
|
||||
m_pEyeFlash->SetTransparency(kRenderGlow, 255, 255, 255, 0, kRenderFxNoDissipation);
|
||||
|
@ -1110,7 +1110,7 @@ void CNPC_CombineDropship::Spawn( void )
|
||||
|
||||
// moving this after we've created m_hContainer so we can properly setup the
|
||||
// weapon_pitch and weapon_yaw pose parameter indexes in PopulatePoseParameters()
|
||||
SetModel( "models/combine_dropship.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/combine_dropship.mdl" ) );
|
||||
|
||||
// Setup our bbox
|
||||
if ( m_hContainer )
|
||||
@ -1191,7 +1191,7 @@ void CNPC_CombineDropship::Activate( void )
|
||||
void CNPC_CombineDropship::Precache( void )
|
||||
{
|
||||
// Models
|
||||
PrecacheModel("models/combine_dropship.mdl");
|
||||
PrecacheModel( DefaultOrCustomModel( "models/combine_dropship.mdl" ) );
|
||||
switch ( m_iCrateType )
|
||||
{
|
||||
case CRATE_SOLDIER:
|
||||
|
@ -564,11 +564,11 @@ void CNPC_CombineGunship::Spawn( void )
|
||||
|
||||
if ( HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) )
|
||||
{
|
||||
SetModel( "models/combine_helicopter.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/combine_helicopter.mdl" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModel( "models/gunship.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/gunship.mdl" ) );
|
||||
}
|
||||
|
||||
ExtractBbox( SelectHeaviestSequence( ACT_GUNSHIP_PATROL ), m_cullBoxMins, m_cullBoxMaxs );
|
||||
@ -690,12 +690,12 @@ void CNPC_CombineGunship::Precache( void )
|
||||
{
|
||||
if ( HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) )
|
||||
{
|
||||
PrecacheModel( "models/combine_helicopter.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/combine_helicopter.mdl" ) );
|
||||
Chopper_PrecacheChunks( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
PrecacheModel("models/gunship.mdl");
|
||||
PrecacheModel( DefaultOrCustomModel( "models/gunship.mdl" ) );
|
||||
}
|
||||
|
||||
PrecacheModel("sprites/lgtning.vmt");
|
||||
@ -725,7 +725,7 @@ void CNPC_CombineGunship::Precache( void )
|
||||
g_iGunshipEffectIndex = PrecacheModel( "sprites/physbeam.vmt" );
|
||||
}
|
||||
|
||||
PropBreakablePrecacheAll( MAKE_STRING("models/gunship.mdl") );
|
||||
PropBreakablePrecacheAll( MAKE_STRING( DefaultOrCustomModel( "models/gunship.mdl" ) ) );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
@ -38,6 +38,11 @@ ConVar sk_combine_guard_kick( "sk_combine_guard_kick", "0");
|
||||
ConVar combine_guard_spawn_health( "combine_guard_spawn_health", "1" );
|
||||
|
||||
extern ConVar sk_plr_dmg_buckshot;
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar sk_combine_head_dmg_multiplier( "sk_combine_head_dmg_multiplier", "2" );
|
||||
#endif
|
||||
|
||||
extern ConVar sk_plr_num_shotgun_pellets;
|
||||
|
||||
//Whether or not the combine should spawn health on death
|
||||
@ -222,8 +227,14 @@ float CNPC_CombineS::GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDama
|
||||
{
|
||||
case HITGROUP_HEAD:
|
||||
{
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Now you can change the multiplier of headshot damage in console!
|
||||
return sk_combine_head_dmg_multiplier.GetFloat();
|
||||
#else
|
||||
// Soldiers take double headshot damage
|
||||
return 2.0f;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,7 +455,7 @@ void CNPC_Dog::Spawn( void )
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetModel( "models/dog.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/dog.mdl" ) );
|
||||
|
||||
SetHullType( HULL_WIDE_HUMAN );
|
||||
SetHullSizeNormal();
|
||||
@ -638,7 +638,7 @@ void CNPC_Dog::PullObject( bool bMantain )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Dog::Precache( void )
|
||||
{
|
||||
PrecacheModel( "models/dog.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/dog.mdl" ) );
|
||||
|
||||
PrecacheScriptSound( "Weapon_PhysCannon.Launch" );
|
||||
|
||||
|
@ -396,7 +396,7 @@ static const char *s_pLegsModel = "models/gibs/fast_zombie_legs.mdl";
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFastZombie::Precache( void )
|
||||
{
|
||||
PrecacheModel("models/zombie/fast.mdl");
|
||||
PrecacheModel( DefaultOrCustomModel( "models/zombie/fast.mdl" ) );
|
||||
#ifdef HL2_EPISODIC
|
||||
PrecacheModel("models/zombie/Fast_torso.mdl");
|
||||
PrecacheScriptSound( "NPC_FastZombie.CarEnter1" );
|
||||
@ -773,7 +773,7 @@ void CFastZombie::SetZombieModel( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModel( "models/zombie/fast.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/zombie/fast.mdl" ) );
|
||||
SetHullType(HULL_HUMAN);
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ END_DATADESC()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Fisherman::SelectModel()
|
||||
{
|
||||
SetModelName( AllocPooledString( FISHERMAN_MODEL ) );
|
||||
SetModelName( AllocPooledString( DefaultOrCustomModel( FISHERMAN_MODEL ) ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -97,7 +97,7 @@ void CNPC_GMan::Spawn()
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetModel( "models/gman.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/gman.mdl" ) );
|
||||
|
||||
SetHullType(HULL_HUMAN);
|
||||
SetHullSizeNormal();
|
||||
@ -123,7 +123,7 @@ void CNPC_GMan::Spawn()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_GMan::Precache()
|
||||
{
|
||||
PrecacheModel( "models/gman.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/gman.mdl" ) );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ Activity CNPC_Monk::NPC_TranslateActivity( Activity eNewActivity )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Monk::Precache()
|
||||
{
|
||||
PrecacheModel( "models/Monk.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/Monk.mdl" ) );
|
||||
|
||||
PrecacheScriptSound( "NPC_Citizen.FootstepLeft" );
|
||||
PrecacheScriptSound( "NPC_Citizen.FootstepRight" );
|
||||
@ -317,7 +317,7 @@ void CNPC_Monk::Spawn()
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetModel( "models/Monk.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/Monk.mdl" ) );
|
||||
|
||||
SetHullType(HULL_HUMAN);
|
||||
SetHullSizeNormal();
|
||||
|
@ -99,7 +99,7 @@ void CNPC_Mossman::Spawn()
|
||||
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetModel( "models/mossman.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/mossman.mdl" ) );
|
||||
|
||||
SetHullType(HULL_HUMAN);
|
||||
SetHullSizeNormal();
|
||||
@ -124,7 +124,7 @@ void CNPC_Mossman::Spawn()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_Mossman::Precache()
|
||||
{
|
||||
PrecacheModel( "models/mossman.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/mossman.mdl" ) );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ void CZombie::Precache( void )
|
||||
{
|
||||
BaseClass::Precache();
|
||||
|
||||
PrecacheModel( "models/zombie/classic.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/zombie/classic.mdl" ) );
|
||||
PrecacheModel( "models/zombie/classic_torso.mdl" );
|
||||
PrecacheModel( "models/zombie/classic_legs.mdl" );
|
||||
|
||||
@ -515,7 +515,7 @@ void CZombie::SetZombieModel( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModel( "models/zombie/classic.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/zombie/classic.mdl" ) );
|
||||
SetHullType( HULL_HUMAN );
|
||||
}
|
||||
|
||||
|
@ -249,7 +249,7 @@ void CNPC_Zombine::Precache( void )
|
||||
{
|
||||
BaseClass::Precache();
|
||||
|
||||
PrecacheModel( "models/zombie/zombie_soldier.mdl" );
|
||||
PrecacheModel( DefaultOrCustomModel( "models/zombie/zombie_soldier.mdl" ) );
|
||||
|
||||
PrecacheScriptSound( "Zombie.FootstepRight" );
|
||||
PrecacheScriptSound( "Zombie.FootstepLeft" );
|
||||
@ -270,7 +270,7 @@ void CNPC_Zombine::Precache( void )
|
||||
|
||||
void CNPC_Zombine::SetZombieModel( void )
|
||||
{
|
||||
SetModel( "models/zombie/zombie_soldier.mdl" );
|
||||
SetModel( DefaultOrCustomModel( "models/zombie/zombie_soldier.mdl" ) );
|
||||
SetHullType( HULL_HUMAN );
|
||||
|
||||
SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, !m_fIsHeadless );
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "entityoutput.h"
|
||||
#ifdef MAPBASE
|
||||
#include "eventqueue.h"
|
||||
#include "saverestore_utlvector.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -824,3 +825,449 @@ void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TY
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Displays a custom number menu for player(s)
|
||||
//-----------------------------------------------------------------------------
|
||||
LINK_ENTITY_TO_CLASS( game_menu, CGameMenu );
|
||||
|
||||
BEGIN_DATADESC( CGameMenu )
|
||||
|
||||
DEFINE_UTLVECTOR( m_ActivePlayers, FIELD_EHANDLE ),
|
||||
DEFINE_UTLVECTOR( m_ActivePlayerTimes, FIELD_TIME ),
|
||||
|
||||
DEFINE_KEYFIELD( m_flDisplayTime, FIELD_FLOAT, "holdtime" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_iszTitle, FIELD_STRING, "Title" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_iszOption[0], FIELD_STRING, "Case01" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[1], FIELD_STRING, "Case02" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[2], FIELD_STRING, "Case03" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[3], FIELD_STRING, "Case04" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[4], FIELD_STRING, "Case05" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[5], FIELD_STRING, "Case06" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[6], FIELD_STRING, "Case07" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[7], FIELD_STRING, "Case08" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[8], FIELD_STRING, "Case09" ),
|
||||
DEFINE_KEYFIELD( m_iszOption[9], FIELD_STRING, "Case10" ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "ShowMenu", InputShowMenu ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "HideMenu", InputHideMenu ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "__DoRestore", InputDoRestore ),
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_OnCase[0], "OnCase01" ),
|
||||
DEFINE_OUTPUT( m_OnCase[1], "OnCase02" ),
|
||||
DEFINE_OUTPUT( m_OnCase[2], "OnCase03" ),
|
||||
DEFINE_OUTPUT( m_OnCase[3], "OnCase04" ),
|
||||
DEFINE_OUTPUT( m_OnCase[4], "OnCase05" ),
|
||||
DEFINE_OUTPUT( m_OnCase[5], "OnCase06" ),
|
||||
DEFINE_OUTPUT( m_OnCase[6], "OnCase07" ),
|
||||
DEFINE_OUTPUT( m_OnCase[7], "OnCase08" ),
|
||||
DEFINE_OUTPUT( m_OnCase[8], "OnCase09" ),
|
||||
DEFINE_OUTPUT( m_OnCase[9], "OnCase10" ),
|
||||
DEFINE_OUTPUT( m_OutValue, "OutValue" ),
|
||||
DEFINE_OUTPUT( m_OnTimeout, "OnTimeout" ),
|
||||
|
||||
DEFINE_THINKFUNC( TimeoutThink ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
IMPLEMENT_AUTO_LIST( IGameMenuAutoList );
|
||||
|
||||
static const char *s_pTimeoutContext = "TimeoutContext";
|
||||
|
||||
#define MENU_INFINITE_TIME -1.0f
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CGameMenu::CGameMenu()
|
||||
{
|
||||
m_flDisplayTime = 5.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
|
||||
// Do this a bit after we restore since the HUD might not be ready yet
|
||||
g_EventQueue.AddEvent( this, "__DoRestore", 0.4f, this, this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::InputDoRestore( inputdata_t &inputdata )
|
||||
{
|
||||
// Check if we should restore the menu on anyone
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get())
|
||||
{
|
||||
if (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME)
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddRecipient( static_cast<CBasePlayer*>( m_ActivePlayers[i].Get() ) );
|
||||
|
||||
ShowMenu( filter, m_ActivePlayerTimes[i] - gpGlobals->curtime );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove this player since it's no longer valid
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::TimeoutThink()
|
||||
{
|
||||
float flNextLowestTime = FLT_MAX;
|
||||
FOR_EACH_VEC( m_ActivePlayerTimes, i )
|
||||
{
|
||||
// If the player is still in our list, then they must not have selected an option
|
||||
if (m_ActivePlayerTimes[i] != MENU_INFINITE_TIME)
|
||||
{
|
||||
if (m_ActivePlayerTimes[i] <= gpGlobals->curtime)
|
||||
{
|
||||
m_OnTimeout.FireOutput( m_ActivePlayers[i], this );
|
||||
|
||||
// Remove this player since it's no longer valid
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
break;
|
||||
}
|
||||
else if (m_ActivePlayerTimes[i] < flNextLowestTime)
|
||||
{
|
||||
flNextLowestTime = m_ActivePlayerTimes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flNextLowestTime < FLT_MAX)
|
||||
{
|
||||
SetNextThink( flNextLowestTime, s_pTimeoutContext );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetContextThink( NULL, TICK_NEVER_THINK, s_pTimeoutContext );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::ShowMenu( CRecipientFilter &filter, float flDisplayTime )
|
||||
{
|
||||
// Before showing the menu, check each menu to see if there's already one being shown to one of our recipients
|
||||
for ( int i = 0; i < IGameMenuAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
CGameMenu *pMenu = static_cast<CGameMenu*>( IGameMenuAutoList::AutoList()[i] );
|
||||
if ( pMenu != this && pMenu->IsActive() )
|
||||
{
|
||||
for ( int j = 0; j < filter.GetRecipientCount(); j++ )
|
||||
{
|
||||
CBaseEntity *ent = CBaseEntity::Instance( filter.GetRecipientIndex( j ) );
|
||||
if ( pMenu->IsActiveOnTarget( ent ) )
|
||||
{
|
||||
Msg( "%s overriding menu %s for player %i\n", GetDebugName(), pMenu->GetDebugName(), j );
|
||||
pMenu->RemoveTarget( ent );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flDisplayTime == 0.0f)
|
||||
{
|
||||
flDisplayTime = m_flDisplayTime;
|
||||
}
|
||||
|
||||
char szString[512] = { 0 };
|
||||
int nBitsValidSlots = 0;
|
||||
|
||||
if (m_iszTitle != NULL_STRING)
|
||||
{
|
||||
V_strncat( szString, STRING( m_iszTitle ), sizeof( szString ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert space to tell menu code to skip
|
||||
V_strncat( szString, " ", sizeof( szString ) );
|
||||
}
|
||||
|
||||
// Insert newline even if there's no string
|
||||
V_strncat( szString, "\n", sizeof( szString ) );
|
||||
|
||||
// Populate the options
|
||||
for (int i = 0; i < MAX_MENU_OPTIONS; i++)
|
||||
{
|
||||
if (m_iszOption[i] != NULL_STRING)
|
||||
{
|
||||
nBitsValidSlots |= (1 << i);
|
||||
|
||||
V_strncat( szString, STRING( m_iszOption[i] ), sizeof( szString ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert space to tell menu code to skip
|
||||
V_strncat( szString, " ", sizeof( szString ) );
|
||||
}
|
||||
|
||||
// Insert newline even if there's no string
|
||||
V_strncat( szString, "\n", sizeof( szString ) );
|
||||
}
|
||||
|
||||
if (nBitsValidSlots <= 0 && m_iszTitle == NULL_STRING)
|
||||
{
|
||||
Warning( "%s ShowMenu: Can't show menu with no options or title\n", GetDebugName() );
|
||||
return;
|
||||
}
|
||||
|
||||
UserMessageBegin( filter, "ShowMenuComplex" );
|
||||
WRITE_WORD( nBitsValidSlots );
|
||||
WRITE_FLOAT( flDisplayTime );
|
||||
WRITE_BYTE( 0 );
|
||||
WRITE_STRING( szString );
|
||||
MessageEnd();
|
||||
|
||||
float flMenuTime;
|
||||
if (flDisplayTime <= 0.0f)
|
||||
{
|
||||
flMenuTime = MENU_INFINITE_TIME;
|
||||
}
|
||||
else
|
||||
{
|
||||
flMenuTime = gpGlobals->curtime + flDisplayTime;
|
||||
}
|
||||
|
||||
for ( int j = 0; j < filter.GetRecipientCount(); j++ )
|
||||
{
|
||||
CBaseEntity *ent = CBaseEntity::Instance( filter.GetRecipientIndex( j ) );
|
||||
|
||||
// Check if we already track this player. If not, make a new one
|
||||
bool bFound = false;
|
||||
FOR_EACH_VEC( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get() == ent)
|
||||
{
|
||||
m_ActivePlayerTimes[i] = flMenuTime;
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
m_ActivePlayers.AddToTail( ent );
|
||||
m_ActivePlayerTimes.AddToTail( flMenuTime );
|
||||
}
|
||||
}
|
||||
|
||||
if (GetNextThink( s_pTimeoutContext ) == TICK_NEVER_THINK)
|
||||
{
|
||||
SetContextThink( &CGameMenu::TimeoutThink, gpGlobals->curtime + flDisplayTime, s_pTimeoutContext );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::HideMenu( CRecipientFilter &filter )
|
||||
{
|
||||
UserMessageBegin( filter, "ShowMenuComplex" );
|
||||
WRITE_WORD( -1 );
|
||||
WRITE_FLOAT( 0.0f );
|
||||
WRITE_BYTE( 0 );
|
||||
WRITE_STRING( "" );
|
||||
MessageEnd();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::MenuSelected( int nSlot, CBaseEntity *pActivator )
|
||||
{
|
||||
if (nSlot <= 0 || nSlot > MAX_MENU_OPTIONS)
|
||||
{
|
||||
Warning( "%s: Invalid slot %i\n", GetDebugName(), nSlot );
|
||||
return;
|
||||
}
|
||||
|
||||
m_OnCase[nSlot-1].FireOutput( pActivator, this );
|
||||
m_OutValue.Set( nSlot, pActivator, this );
|
||||
|
||||
RemoveTarget( pActivator );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CGameMenu::IsActive()
|
||||
{
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get())
|
||||
{
|
||||
if (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove this player since it's no longer valid
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CGameMenu::IsActiveOnTarget( CBaseEntity *pPlayer )
|
||||
{
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get() == pPlayer)
|
||||
{
|
||||
if (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME)
|
||||
return true;
|
||||
|
||||
// Remove this player since it's no longer valid
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::RemoveTarget( CBaseEntity *pPlayer )
|
||||
{
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get() == pPlayer)
|
||||
{
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::InputShowMenu( inputdata_t &inputdata )
|
||||
{
|
||||
if (HasSpawnFlags( SF_GAMEMENU_ALLPLAYERS ))
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddAllPlayers();
|
||||
|
||||
ShowMenu( filter );
|
||||
}
|
||||
else
|
||||
{
|
||||
CBasePlayer *pPlayer = NULL;
|
||||
|
||||
// If we're in singleplayer, show the message to the player.
|
||||
if ( gpGlobals->maxClients == 1 )
|
||||
{
|
||||
pPlayer = UTIL_GetLocalPlayer();
|
||||
}
|
||||
// Otherwise show the message to the player that triggered us.
|
||||
else if ( inputdata.pActivator && inputdata.pActivator->IsNetClient() )
|
||||
{
|
||||
pPlayer = ToBasePlayer( inputdata.pActivator );
|
||||
}
|
||||
|
||||
if (pPlayer)
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddRecipient( pPlayer );
|
||||
|
||||
ShowMenu( filter );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameMenu::InputHideMenu( inputdata_t &inputdata )
|
||||
{
|
||||
if (HasSpawnFlags( SF_GAMEMENU_ALLPLAYERS ))
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
|
||||
FOR_EACH_VEC_BACK( m_ActivePlayers, i )
|
||||
{
|
||||
// Select all players in our list who are still active, and remove them
|
||||
if (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME)
|
||||
{
|
||||
filter.AddRecipient( static_cast<CBasePlayer*>(m_ActivePlayers[i].Get()) );
|
||||
}
|
||||
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
}
|
||||
|
||||
if (filter.GetRecipientCount() <= 0)
|
||||
return;
|
||||
|
||||
HideMenu( filter );
|
||||
}
|
||||
else
|
||||
{
|
||||
CBasePlayer *pPlayer = NULL;
|
||||
|
||||
// If we're in singleplayer, show the message to the player.
|
||||
if ( gpGlobals->maxClients == 1 )
|
||||
{
|
||||
pPlayer = UTIL_GetLocalPlayer();
|
||||
}
|
||||
// Otherwise show the message to the player that triggered us.
|
||||
else if ( inputdata.pActivator && inputdata.pActivator->IsNetClient() )
|
||||
{
|
||||
pPlayer = ToBasePlayer( inputdata.pActivator );
|
||||
}
|
||||
|
||||
if (!pPlayer)
|
||||
return;
|
||||
|
||||
// Verify that this player is in our list
|
||||
CRecipientFilter filter;
|
||||
FOR_EACH_VEC( m_ActivePlayers, i )
|
||||
{
|
||||
if (m_ActivePlayers[i].Get() == pPlayer && (m_ActivePlayerTimes[i] > gpGlobals->curtime || m_ActivePlayerTimes[i] == MENU_INFINITE_TIME))
|
||||
{
|
||||
filter.AddRecipient( pPlayer );
|
||||
|
||||
// Remove since the player won't have the menu anymore
|
||||
m_ActivePlayers.Remove( i );
|
||||
m_ActivePlayerTimes.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.GetRecipientCount() <= 0)
|
||||
return;
|
||||
|
||||
HideMenu( filter );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -9,7 +9,55 @@
|
||||
#ifndef MAPRULES_H
|
||||
#define MAPRULES_H
|
||||
|
||||
#ifdef MAPBASE
|
||||
#define MAX_MENU_OPTIONS 10
|
||||
|
||||
#define SF_GAMEMENU_ALLPLAYERS 0x0001
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Displays a custom number menu for player(s)
|
||||
//-----------------------------------------------------------------------------
|
||||
DECLARE_AUTO_LIST( IGameMenuAutoList );
|
||||
class CGameMenu : public CLogicalEntity, public IGameMenuAutoList
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CGameMenu, CLogicalEntity );
|
||||
DECLARE_DATADESC();
|
||||
CGameMenu();
|
||||
|
||||
void OnRestore();
|
||||
void InputDoRestore( inputdata_t &inputdata );
|
||||
|
||||
void TimeoutThink();
|
||||
|
||||
void ShowMenu( CRecipientFilter &filter, float flDisplayTime = 0.0f );
|
||||
void HideMenu( CRecipientFilter &filter );
|
||||
void MenuSelected( int nSlot, CBaseEntity *pActivator );
|
||||
|
||||
bool IsActive();
|
||||
bool IsActiveOnTarget( CBaseEntity *pPlayer );
|
||||
void RemoveTarget( CBaseEntity *pPlayer );
|
||||
|
||||
// Inputs
|
||||
void InputShowMenu( inputdata_t &inputdata );
|
||||
void InputHideMenu( inputdata_t &inputdata );
|
||||
|
||||
private:
|
||||
|
||||
CUtlVector<EHANDLE> m_ActivePlayers;
|
||||
CUtlVector<float> m_ActivePlayerTimes;
|
||||
|
||||
float m_flDisplayTime;
|
||||
|
||||
string_t m_iszTitle;
|
||||
string_t m_iszOption[MAX_MENU_OPTIONS];
|
||||
|
||||
// Outputs
|
||||
COutputEvent m_OnCase[MAX_MENU_OPTIONS]; // Fired for the option chosen
|
||||
COutputInt m_OutValue; // Outputs the option chosen
|
||||
COutputEvent m_OnTimeout; // Fires when no option was chosen in time
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // MAPRULES_H
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "hierarchy.h"
|
||||
#ifdef MAPBASE
|
||||
#include "decals.h"
|
||||
#include "death_pose.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -29,6 +30,7 @@
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ragdoll_autointeractions("ragdoll_autointeractions", "1", FCVAR_NONE, "Controls whether we should rely on hardcoded keyvalues or automatic flesh checks for ragdoll physgun interactions.");
|
||||
ConVar ai_death_pose_server_enabled("ai_death_pose_server_enabled", "1", FCVAR_NONE, "Toggles the death pose fix code, but for server ragdolls.");
|
||||
#define IsBody() VPhysicsIsFlesh()
|
||||
|
||||
ConVar ragdoll_always_allow_use( "ragdoll_always_allow_use", "0", FCVAR_NONE, "Allows all ragdolls to be used and, if they aren't explicitly set to prevent pickup, picked up." );
|
||||
@ -788,7 +790,11 @@ void CRagdollProp::SetOverlaySequence( Activity activity )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CRagdollProp::InitRagdoll( const Vector& forceVector, int forceBone, const Vector& forcePos, matrix3x4_t* pPrevBones, matrix3x4_t* pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll, bool bDeathPose )
|
||||
#else
|
||||
void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll )
|
||||
#endif
|
||||
{
|
||||
SetCollisionGroup( collisionGroup );
|
||||
|
||||
@ -811,7 +817,11 @@ void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const
|
||||
params.forceVector = forceVector;
|
||||
params.forceBoneIndex = forceBone;
|
||||
params.forcePosition = forcePos;
|
||||
#ifdef MAPBASE
|
||||
params.pCurrentBones = bDeathPose ? pPrevBones : pBoneToWorld;
|
||||
#else
|
||||
params.pCurrentBones = pBoneToWorld;
|
||||
#endif
|
||||
params.jointFrictionScale = 1.0;
|
||||
params.allowStretch = HasSpawnFlags(SF_RAGDOLLPROP_ALLOW_STRETCH);
|
||||
#ifdef MAPBASE
|
||||
@ -1492,6 +1502,43 @@ CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, con
|
||||
|
||||
float fPreviousCycle = clamp(pAnimating->GetCycle()-( dt * ( 1 / fSequenceDuration ) ),0.f,1.f);
|
||||
float fCurCycle = pAnimating->GetCycle();
|
||||
|
||||
#ifdef MAPBASE
|
||||
int deathpose = ACT_INVALID;
|
||||
int deathframe = 0;
|
||||
if (ai_death_pose_server_enabled.GetBool() && pAnimating->IsNPC()) {
|
||||
CAI_BaseNPC* npc = (CAI_BaseNPC*)pAnimating;
|
||||
if (npc) {
|
||||
deathpose = Activity(npc->GetDeathPose());
|
||||
deathframe = npc->GetDeathPoseFrame();
|
||||
}
|
||||
}
|
||||
if (deathpose != ACT_INVALID) {
|
||||
int currentSequence = pAnimating->GetSequence();
|
||||
|
||||
//Force pAnimating to position the deathpose
|
||||
pAnimating->SetSequence(deathpose);
|
||||
pAnimating->SetCycle((float)deathframe / MAX_DEATHPOSE_FRAMES);
|
||||
|
||||
//Store the position
|
||||
pAnimating->SetupBones(pBoneToWorldNext, BONE_USED_BY_ANYTHING);
|
||||
|
||||
//Restore the current sequence and cycle
|
||||
pAnimating->SetSequence(currentSequence);
|
||||
|
||||
pAnimating->SetCycle(fCurCycle);
|
||||
pAnimating->SetupBones(pBoneToWorld, BONE_USED_BY_ANYTHING);
|
||||
}
|
||||
else {
|
||||
// Get current bones positions
|
||||
pAnimating->SetupBones(pBoneToWorldNext, BONE_USED_BY_ANYTHING);
|
||||
// Get previous bones positions
|
||||
pAnimating->SetCycle(fPreviousCycle);
|
||||
pAnimating->SetupBones(pBoneToWorld, BONE_USED_BY_ANYTHING);
|
||||
// Restore current cycle
|
||||
pAnimating->SetCycle(fCurCycle);
|
||||
}
|
||||
#else
|
||||
// Get current bones positions
|
||||
pAnimating->SetupBones( pBoneToWorldNext, BONE_USED_BY_ANYTHING );
|
||||
// Get previous bones positions
|
||||
@ -1499,6 +1546,7 @@ CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, con
|
||||
pAnimating->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING );
|
||||
// Restore current cycle
|
||||
pAnimating->SetCycle( fCurCycle );
|
||||
#endif
|
||||
|
||||
// Reset previous bone flags
|
||||
pAnimating->ClearBoneCacheFlags( BCF_NO_ANIMATION_SKIP );
|
||||
@ -1573,7 +1621,11 @@ CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, con
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
pRagdoll->InitRagdoll(info.GetDamageForce(), forceBone, info.GetDamagePosition(), pBoneToWorld, pBoneToWorldNext, dt, collisionGroup, true, true, deathpose != ACT_INVALID);
|
||||
#else
|
||||
pRagdoll->InitRagdoll( info.GetDamageForce(), forceBone, info.GetDamagePosition(), pBoneToWorld, pBoneToWorldNext, dt, collisionGroup, true );
|
||||
#endif
|
||||
}
|
||||
|
||||
// Are we dissolving?
|
||||
|
@ -75,7 +75,11 @@ public:
|
||||
|
||||
// locals
|
||||
void InitRagdollAnimation( void );
|
||||
#ifdef MAPBASE
|
||||
void InitRagdoll( const Vector& forceVector, int forceBone, const Vector& forcePos, matrix3x4_t* pPrevBones, matrix3x4_t* pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll = true, bool bDeathPose = false );
|
||||
#else
|
||||
void InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll = true );
|
||||
#endif
|
||||
|
||||
void RecheckCollisionFilter( void );
|
||||
void SetDebrisThink();
|
||||
|
@ -48,6 +48,8 @@ $Project
|
||||
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\matchers.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\matchers.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\game_timer.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\game_timer.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT]
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT]
|
||||
|
@ -60,10 +60,6 @@ extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
extern CServerGameDLL g_ServerGameDLL;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
extern int vscript_debugger_port;
|
||||
#endif
|
||||
|
||||
// #define VMPROFILE 1
|
||||
|
||||
#ifdef VMPROFILE
|
||||
@ -3769,10 +3765,13 @@ REGISTER_SCRIPT_CONST_TABLE( Server )
|
||||
g_pScriptVM->SetValue( "Constants", vConstantsTable );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if ( vscript_debugger_port )
|
||||
if ( script_connect_debugger_on_mapspawn.GetInt() == 2 )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port, 10.0f );
|
||||
}
|
||||
else if ( script_connect_debugger_on_mapspawn.GetInt() != 0 )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||
vscript_debugger_port = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3793,10 +3792,12 @@ REGISTER_SCRIPT_CONST_TABLE( Server )
|
||||
GetWorldEntity()->RunVScripts();
|
||||
#endif
|
||||
|
||||
#ifndef MAPBASE_VSCRIPT
|
||||
if ( script_connect_debugger_on_mapspawn.GetBool() )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger();
|
||||
}
|
||||
#endif
|
||||
|
||||
VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" );
|
||||
|
||||
|
@ -1149,7 +1149,7 @@ WeaponClass_t CBaseCombatWeapon::WeaponClassFromString(const char *str)
|
||||
return WEPCLASS_RIFLE;
|
||||
else if (FStrEq(str, "WEPCLASS_SHOTGUN"))
|
||||
return WEPCLASS_SHOTGUN;
|
||||
else if (FStrEq(str, "WEPCLASS_HEAY"))
|
||||
else if (FStrEq(str, "WEPCLASS_HEAVY"))
|
||||
return WEPCLASS_HEAVY;
|
||||
|
||||
else if (FStrEq(str, "WEPCLASS_MELEE"))
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include "player_resource.h"
|
||||
#include "tactical_mission.h"
|
||||
#include "gamestats.h"
|
||||
#ifdef MAPBASE
|
||||
#include "maprules.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -621,6 +624,27 @@ bool CGameRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args )
|
||||
{
|
||||
if( GetVoiceGameMgr()->ClientCommand( static_cast<CBasePlayer*>(pEdict), args ) )
|
||||
return true;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( FStrEq( args[0], "menuselect" ) )
|
||||
{
|
||||
if ( args.ArgC() >= 2 )
|
||||
{
|
||||
int slot = atoi( args[1] );
|
||||
|
||||
// See if this is from a game_menu
|
||||
for ( int i = 0; i < IGameMenuAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
CGameMenu *pMenu = static_cast<CGameMenu*>( IGameMenuAutoList::AutoList()[i] );
|
||||
if ( pMenu->IsActiveOnTarget( pEdict ) )
|
||||
{
|
||||
pMenu->MenuSelected( slot, pEdict );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
|
658
src/game/shared/mapbase/game_timer.cpp
Normal file
658
src/game/shared/mapbase/game_timer.cpp
Normal file
@ -0,0 +1,658 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: Generic custom timer entity
|
||||
//
|
||||
// Author: Blixibon
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "game_timer.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
extern bool IsInCommentaryMode( void );
|
||||
|
||||
ConVar sv_game_menu_default_warn_frac( "sv_game_menu_default_warn_frac", "0.25", FCVAR_REPLICATED );
|
||||
|
||||
LINK_ENTITY_TO_CLASS( game_timer, CGameTimer );
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( GameTimer, DT_GameTimer )
|
||||
|
||||
BEGIN_NETWORK_TABLE_NOBASE( CGameTimer, DT_GameTimer )
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
RecvPropBool( RECVINFO( m_bTimerPaused ) ),
|
||||
RecvPropTime( RECVINFO( m_flTimerInitialLength ) ),
|
||||
RecvPropTime( RECVINFO( m_flTimerMaxLength ) ),
|
||||
RecvPropTime( RECVINFO( m_flTimeRemaining ) ),
|
||||
RecvPropTime( RECVINFO( m_flTimerEndTime ) ),
|
||||
RecvPropTime( RECVINFO( m_flWarnTime ) ),
|
||||
RecvPropBool( RECVINFO( m_bIsDisabled ) ),
|
||||
RecvPropBool( RECVINFO( m_bStartPaused ) ),
|
||||
RecvPropBool( RECVINFO( m_bShowTimeRemaining ) ),
|
||||
RecvPropInt( RECVINFO( m_nProgressBarMaxSegments ) ),
|
||||
RecvPropInt( RECVINFO( m_nProgressBarOverride ) ),
|
||||
RecvPropFloat( RECVINFO( m_flOverrideX ) ),
|
||||
RecvPropFloat( RECVINFO( m_flOverrideY ) ),
|
||||
RecvPropString( RECVINFO( m_szTimerCaption ) ),
|
||||
|
||||
RecvPropInt( RECVINFO( m_iTeamNum ) ),
|
||||
|
||||
#else
|
||||
|
||||
SendPropBool( SENDINFO( m_bTimerPaused ) ),
|
||||
SendPropTime( SENDINFO( m_flTimerInitialLength ) ),
|
||||
SendPropTime( SENDINFO( m_flTimerMaxLength ) ),
|
||||
SendPropTime( SENDINFO( m_flTimeRemaining ) ),
|
||||
SendPropTime( SENDINFO( m_flTimerEndTime ) ),
|
||||
SendPropTime( SENDINFO( m_flWarnTime ) ),
|
||||
SendPropBool( SENDINFO( m_bIsDisabled ) ),
|
||||
SendPropBool( SENDINFO( m_bStartPaused ) ),
|
||||
SendPropBool( SENDINFO( m_bShowTimeRemaining ) ),
|
||||
SendPropInt( SENDINFO( m_nProgressBarMaxSegments ) ),
|
||||
SendPropInt( SENDINFO( m_nProgressBarOverride ) ),
|
||||
SendPropFloat( SENDINFO( m_flOverrideX ) ),
|
||||
SendPropFloat( SENDINFO( m_flOverrideY ) ),
|
||||
SendPropString( SENDINFO( m_szTimerCaption ) ),
|
||||
|
||||
SendPropInt( SENDINFO( m_iTeamNum ), TEAMNUM_NUM_BITS, 0 ),
|
||||
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
BEGIN_DATADESC( CGameTimer )
|
||||
|
||||
DEFINE_KEYFIELD( m_flTimerInitialLength, FIELD_FLOAT, "timer_length" ),
|
||||
DEFINE_KEYFIELD( m_flTimerMaxLength, FIELD_FLOAT, "max_length" ),
|
||||
DEFINE_KEYFIELD( m_flWarnTime, FIELD_FLOAT, "warn_time" ),
|
||||
DEFINE_KEYFIELD( m_bIsDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
||||
DEFINE_KEYFIELD( m_bStartPaused, FIELD_BOOLEAN, "start_paused" ),
|
||||
DEFINE_KEYFIELD( m_bShowTimeRemaining, FIELD_BOOLEAN, "show_time_remaining" ),
|
||||
DEFINE_KEYFIELD( m_bDisableOnFinish, FIELD_BOOLEAN, "disable_on_finish" ),
|
||||
DEFINE_KEYFIELD( m_bShowInHUD, FIELD_BOOLEAN, "show_in_hud" ),
|
||||
DEFINE_KEYFIELD( m_nProgressBarMaxSegments, FIELD_INTEGER, "progress_bar_max" ),
|
||||
DEFINE_KEYFIELD( m_nProgressBarOverride, FIELD_INTEGER, "progress_bar_override" ),
|
||||
DEFINE_KEYFIELD( m_flOverrideX, FIELD_FLOAT, "x" ),
|
||||
DEFINE_KEYFIELD( m_flOverrideY, FIELD_FLOAT, "y" ),
|
||||
DEFINE_AUTO_ARRAY( m_szTimerCaption, FIELD_CHARACTER ),
|
||||
DEFINE_KEYFIELD( m_iszPlayerFilterName, FIELD_STRING, "PlayerFilter" ),
|
||||
DEFINE_FIELD( m_hPlayerFilter, FIELD_EHANDLE ),
|
||||
|
||||
DEFINE_FIELD( m_flTimerEndTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_flTimeRemaining, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_bTimerPaused, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_bStartedWarn, FIELD_BOOLEAN ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Pause", InputPause ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Resume", InputResume ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTime", InputSetTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "AddTime", InputAddTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "RemoveTime", InputRemoveTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Restart", InputRestart ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMaxTime", InputSetMaxTime ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTimerCaption", InputSetTimerCaption ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetProgressBarMaxSegments", InputSetProgressBarMaxSegments ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetProgressBarOverride", InputSetProgressBarOverride ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetX", InputSetX ),
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetY", InputSetY ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "GetTimeRemaining", InputGetTimeRemaining ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetPlayerFilter", InputSetPlayerFilter ),
|
||||
|
||||
DEFINE_OUTPUT( m_OnFinished, "OnFinished" ),
|
||||
DEFINE_OUTPUT( m_OnPaused, "OnPaused" ),
|
||||
DEFINE_OUTPUT( m_OnResumed, "OnResumed" ),
|
||||
DEFINE_OUTPUT( m_OnWarned, "OnWarned" ),
|
||||
DEFINE_OUTPUT( m_OnTick, "OnTick" ),
|
||||
DEFINE_OUTPUT( m_OnGetTimeRemaining, "OnGetTimeRemaining" ),
|
||||
|
||||
DEFINE_THINKFUNC( TimerThink ),
|
||||
|
||||
END_DATADESC();
|
||||
#endif
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
IMPLEMENT_AUTO_LIST( IGameTimerAutoList );
|
||||
#else
|
||||
#define TIMER_THINK "GameTimerThink"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CGameTimer::CGameTimer( void )
|
||||
{
|
||||
m_bIsDisabled = true;
|
||||
m_bTimerPaused = true;
|
||||
m_flTimeRemaining = 0;
|
||||
m_flTimerEndTime = 0;
|
||||
m_flWarnTime = -1.0f;
|
||||
m_bStartPaused = false;
|
||||
m_bShowTimeRemaining = true;
|
||||
m_flTimerInitialLength = 0;
|
||||
m_flTimerMaxLength = 0;
|
||||
m_nProgressBarMaxSegments = -1;
|
||||
m_nProgressBarOverride = -1;
|
||||
m_flOverrideX = m_flOverrideY = -1.0f;
|
||||
#ifndef CLIENT_DLL
|
||||
m_bDisableOnFinish = true;
|
||||
m_bShowInHUD = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CGameTimer::~CGameTimer( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::Spawn( void )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
if ( IsDisabled() ) // we need to get the data initialized before actually become disabled
|
||||
{
|
||||
m_bIsDisabled = false;
|
||||
SetTimeRemaining( m_flTimerInitialLength );
|
||||
m_bIsDisabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetTimeRemaining( m_flTimerInitialLength );
|
||||
if ( !m_bStartPaused )
|
||||
ResumeTimer();
|
||||
}
|
||||
|
||||
if ( m_iszPlayerFilterName != NULL_STRING )
|
||||
{
|
||||
m_hPlayerFilter = dynamic_cast<CBaseFilter *>(gEntList.FindEntityByName( NULL, m_iszPlayerFilterName, this ));
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
||||
bool CGameTimer::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "timer_caption" ) )
|
||||
{
|
||||
Q_strncpy( m_szTimerCaption.GetForModify(), szValue, MAX_GAME_TIMER_CAPTION );
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameTimer::GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen )
|
||||
{
|
||||
if ( FStrEq( szKeyName, "timer_caption" ) )
|
||||
{
|
||||
Q_snprintf( szValue, iMaxLen, "%s", m_szTimerCaption.Get() );
|
||||
return true;
|
||||
}
|
||||
return BaseClass::GetKeyValue( szKeyName, szValue, iMaxLen );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets the seconds left on the timer, paused or not.
|
||||
//-----------------------------------------------------------------------------
|
||||
float CGameTimer::GetTimeRemaining( void )
|
||||
{
|
||||
float flSecondsRemaining;
|
||||
|
||||
if ( m_bTimerPaused )
|
||||
{
|
||||
flSecondsRemaining = m_flTimeRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
flSecondsRemaining = m_flTimerEndTime - gpGlobals->curtime;
|
||||
}
|
||||
|
||||
if ( flSecondsRemaining < 0 )
|
||||
{
|
||||
flSecondsRemaining = 0.0f;
|
||||
}
|
||||
|
||||
return flSecondsRemaining;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Gets the timer's warning time
|
||||
//-----------------------------------------------------------------------------
|
||||
float CGameTimer::GetWarnTime( void )
|
||||
{
|
||||
if ( m_flWarnTime < 0 )
|
||||
{
|
||||
// TODO: All of the default warning stuff is on the client!!!
|
||||
return GetTimerMaxLength() * sv_game_menu_default_warn_frac.GetFloat();
|
||||
}
|
||||
|
||||
return m_flWarnTime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CGameTimer::GetTimerMaxLength( void )
|
||||
{
|
||||
if ( m_flTimerMaxLength )
|
||||
return m_flTimerMaxLength;
|
||||
|
||||
return m_flTimerInitialLength;
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
bool g_bAnyGameTimerActive = false;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_GameTimer::OnDataChanged( DataUpdateType_t updateType )
|
||||
{
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
|
||||
if ( !m_bIsDisabled )
|
||||
{
|
||||
g_bAnyGameTimerActive = true;
|
||||
}
|
||||
else if ( !m_bOldDisabled )
|
||||
{
|
||||
// Go through all of the timers and mark when one is active
|
||||
g_bAnyGameTimerActive = false;
|
||||
for ( int i = 0; i < IGameTimerAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
C_GameTimer *pTimer = static_cast<C_GameTimer *>( IGameTimerAutoList::AutoList()[i] );
|
||||
if ( !pTimer->IsDisabled() && !pTimer->IsMarkedForDeletion() )
|
||||
{
|
||||
g_bAnyGameTimerActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_bOldDisabled = m_bIsDisabled;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_GameTimer::UpdateOnRemove( void )
|
||||
{
|
||||
BaseClass::UpdateOnRemove();
|
||||
|
||||
// Update timer presence state
|
||||
g_bAnyGameTimerActive = false;
|
||||
for ( int i = 0; i < IGameTimerAutoList::AutoList().Count(); i++ )
|
||||
{
|
||||
C_GameTimer *pTimer = static_cast<C_GameTimer *>( IGameTimerAutoList::AutoList()[i] );
|
||||
if ( pTimer != this && !pTimer->IsDisabled() && !pTimer->IsMarkedForDeletion() )
|
||||
{
|
||||
g_bAnyGameTimerActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::TimerThink( void )
|
||||
{
|
||||
if ( IsDisabled() /*|| IsInCommentaryMode() || gpGlobals->eLoadType == MapLoad_Background*/ )
|
||||
{
|
||||
SetContextThink( &CGameTimer::TimerThink, gpGlobals->curtime + 0.05, TIMER_THINK );
|
||||
return;
|
||||
}
|
||||
|
||||
float flTime = GetTimeRemaining();
|
||||
|
||||
int nTick = (int)floorf( flTime );
|
||||
if (nTick != m_OnTick.Get())
|
||||
{
|
||||
m_OnTick.Set( nTick, this, this );
|
||||
}
|
||||
|
||||
if ( flTime <= 0.0f )
|
||||
{
|
||||
OnTimerFinished();
|
||||
PauseTimer();
|
||||
if (m_bDisableOnFinish)
|
||||
m_bIsDisabled = true;
|
||||
return;
|
||||
}
|
||||
else if ( flTime <= GetWarnTime() && !m_bStartedWarn)
|
||||
{
|
||||
OnTimerWarned();
|
||||
m_bStartedWarn = true;
|
||||
}
|
||||
|
||||
SetContextThink( &CGameTimer::TimerThink, gpGlobals->curtime + 0.05, TIMER_THINK );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: To set the initial timer duration
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::SetTimeRemaining( float flTime )
|
||||
{
|
||||
// make sure we don't go over our max length
|
||||
flTime = m_flTimerMaxLength > 0 ? MIN( flTime, m_flTimerMaxLength ) : flTime;
|
||||
|
||||
m_flTimeRemaining = flTime;
|
||||
m_flTimerEndTime = gpGlobals->curtime + m_flTimeRemaining;
|
||||
|
||||
if ( m_flTimeRemaining > m_flWarnTime )
|
||||
{
|
||||
m_bStartedWarn = false;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::OnTimerFinished()
|
||||
{
|
||||
m_OnFinished.FireOutput( this, this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::OnTimerWarned()
|
||||
{
|
||||
m_OnWarned.FireOutput( this, this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Timer is paused at round end, stops the countdown
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::PauseTimer( CBaseEntity *pActivator )
|
||||
{
|
||||
if ( IsDisabled() )
|
||||
return;
|
||||
|
||||
if ( m_bTimerPaused == false )
|
||||
{
|
||||
m_bTimerPaused = true;
|
||||
m_flTimeRemaining = m_flTimerEndTime - gpGlobals->curtime;
|
||||
|
||||
m_OnPaused.FireOutput( pActivator ? pActivator : this, this );
|
||||
|
||||
SetContextThink( NULL, TICK_NEVER_THINK, TIMER_THINK );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: To start or re-start the timer after a pause
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::ResumeTimer( CBaseEntity *pActivator )
|
||||
{
|
||||
if ( IsDisabled() )
|
||||
return;
|
||||
|
||||
if ( m_bTimerPaused == true )
|
||||
{
|
||||
m_bTimerPaused = false;
|
||||
m_flTimerEndTime = gpGlobals->curtime + m_flTimeRemaining;
|
||||
|
||||
m_OnResumed.FireOutput( pActivator ? pActivator : this, this );
|
||||
|
||||
TimerThink();
|
||||
|
||||
SetContextThink( &CGameTimer::TimerThink, gpGlobals->curtime + 0.05, TIMER_THINK );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Add seconds to the timer while it is running or paused
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::AddTimerSeconds( float flTimeToAdd )
|
||||
{
|
||||
if ( IsDisabled() )
|
||||
return;
|
||||
|
||||
if ( m_flTimerMaxLength > 0 )
|
||||
{
|
||||
// will adding this many seconds push us over our max length?
|
||||
if ( GetTimeRemaining() + flTimeToAdd > m_flTimerMaxLength)
|
||||
{
|
||||
// adjust to only add up to our max length
|
||||
flTimeToAdd = m_flTimerMaxLength - GetTimeRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_bTimerPaused )
|
||||
{
|
||||
m_flTimeRemaining += flTimeToAdd;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flTimerEndTime += flTimeToAdd;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Should we transmit it to the client?
|
||||
//-----------------------------------------------------------------------------
|
||||
int CGameTimer::UpdateTransmitState()
|
||||
{
|
||||
if ( !m_bShowInHUD )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_DONTSEND );
|
||||
}
|
||||
|
||||
if ( m_hPlayerFilter || GetTeamNumber() > TEAM_UNASSIGNED )
|
||||
{
|
||||
return SetTransmitState( FL_EDICT_FULLCHECK );
|
||||
}
|
||||
|
||||
return SetTransmitState( FL_EDICT_ALWAYS );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Which clients should we be transmitting to?
|
||||
//-----------------------------------------------------------------------------
|
||||
int CGameTimer::ShouldTransmit( const CCheckTransmitInfo *pInfo )
|
||||
{
|
||||
int result = BaseClass::ShouldTransmit( pInfo );
|
||||
|
||||
if ( result != FL_EDICT_DONTSEND )
|
||||
{
|
||||
CBaseEntity *pClient = (CBaseEntity *)(pInfo->m_pClientEnt->GetUnknown());
|
||||
if ( pClient )
|
||||
{
|
||||
if ( m_hPlayerFilter )
|
||||
{
|
||||
// Don't send to players who don't pass our filter
|
||||
if ( !m_hPlayerFilter->PassesFilter( this, pClient ) )
|
||||
return FL_EDICT_DONTSEND;
|
||||
}
|
||||
else if ( GetTeamNumber() > TEAM_UNASSIGNED )
|
||||
{
|
||||
// If we don't have an explicit filter, then just check if it's on the same team as us
|
||||
if ( pClient->GetTeamNumber() != GetTeamNumber() )
|
||||
return FL_EDICT_DONTSEND;
|
||||
}
|
||||
|
||||
return FL_EDICT_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputPause( inputdata_t &input )
|
||||
{
|
||||
PauseTimer( input.pActivator );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputResume( inputdata_t &input )
|
||||
{
|
||||
ResumeTimer( input.pActivator );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetTime( inputdata_t &input )
|
||||
{
|
||||
float flTime = input.value.Float();
|
||||
SetTimeRemaining( flTime );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputAddTime( inputdata_t &input )
|
||||
{
|
||||
float flTime = input.value.Float();
|
||||
AddTimerSeconds( flTime );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputRemoveTime( inputdata_t &input )
|
||||
{
|
||||
float flTime = input.value.Float();
|
||||
AddTimerSeconds( -flTime );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetMaxTime( inputdata_t &input )
|
||||
{
|
||||
float flTime = input.value.Float();
|
||||
m_flTimerMaxLength = flTime;
|
||||
|
||||
if (m_flTimerMaxLength > 0)
|
||||
{
|
||||
// make sure our current time is not above the max length
|
||||
if (GetTimeRemaining() > m_flTimerMaxLength)
|
||||
{
|
||||
SetTimeRemaining( m_flTimerMaxLength );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetTimerCaption( inputdata_t &input )
|
||||
{
|
||||
Q_strncpy( m_szTimerCaption.GetForModify(), input.value.String(), MAX_GAME_TIMER_CAPTION );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetProgressBarMaxSegments( inputdata_t &input )
|
||||
{
|
||||
m_nProgressBarMaxSegments = input.value.Int();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetProgressBarOverride( inputdata_t &input )
|
||||
{
|
||||
m_nProgressBarOverride = input.value.Int();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetX( inputdata_t &input )
|
||||
{
|
||||
m_flOverrideX = input.value.Float();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetY( inputdata_t &input )
|
||||
{
|
||||
m_flOverrideY = input.value.Float();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputRestart( inputdata_t &input )
|
||||
{
|
||||
SetTimeRemaining( m_flTimerInitialLength );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputGetTimeRemaining( inputdata_t &input )
|
||||
{
|
||||
m_OnGetTimeRemaining.Set( GetTimeRemaining(), input.pActivator, this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputEnable( inputdata_t &input )
|
||||
{
|
||||
if (GetTimeRemaining() == 0.0f)
|
||||
SetTimeRemaining( m_flTimerInitialLength );
|
||||
|
||||
m_bIsDisabled = false;
|
||||
if ( !m_bStartPaused )
|
||||
ResumeTimer( input.pActivator );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputDisable( inputdata_t &input )
|
||||
{
|
||||
PauseTimer( input.pActivator );
|
||||
m_bIsDisabled = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CGameTimer::InputSetPlayerFilter( inputdata_t &inputdata )
|
||||
{
|
||||
m_iszPlayerFilterName = inputdata.value.StringID();
|
||||
if ( m_iszPlayerFilterName != NULL_STRING )
|
||||
{
|
||||
m_hPlayerFilter = dynamic_cast<CBaseFilter *>(gEntList.FindEntityByName( NULL, m_iszPlayerFilterName, this ));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hPlayerFilter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
145
src/game/shared/mapbase/game_timer.h
Normal file
145
src/game/shared/mapbase/game_timer.h
Normal file
@ -0,0 +1,145 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: Generic custom timer entity
|
||||
//
|
||||
// Author: Blixibon
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_baseentity.h"
|
||||
#else
|
||||
#include "filters.h"
|
||||
#endif
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
DECLARE_AUTO_LIST( IGameTimerAutoList );
|
||||
|
||||
#define CGameTimer C_GameTimer
|
||||
#endif
|
||||
|
||||
#define MAX_GAME_TIMER_CAPTION 32
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Displays a custom timer
|
||||
//-----------------------------------------------------------------------------
|
||||
class CGameTimer : public CBaseEntity
|
||||
#ifdef CLIENT_DLL
|
||||
, public IGameTimerAutoList
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CGameTimer, CBaseEntity );
|
||||
DECLARE_NETWORKCLASS();
|
||||
#ifndef CLIENT_DLL
|
||||
DECLARE_DATADESC();
|
||||
#endif
|
||||
|
||||
CGameTimer();
|
||||
~CGameTimer();
|
||||
|
||||
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
|
||||
|
||||
void Spawn();
|
||||
#ifndef CLIENT_DLL
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
virtual bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen );
|
||||
#endif
|
||||
|
||||
// Based on teamplay_round_timer
|
||||
virtual float GetTimeRemaining( void );
|
||||
virtual float GetTimerMaxLength( void );
|
||||
virtual bool StartPaused( void ) { return m_bStartPaused; }
|
||||
bool ShowTimeRemaining( void ) { return m_bShowTimeRemaining; }
|
||||
float GetWarnTime( void );
|
||||
|
||||
const char *GetTimerCaption( void ) { return m_szTimerCaption.Get(); }
|
||||
|
||||
int GetProgressBarMaxSegments( void ) { return m_nProgressBarMaxSegments; }
|
||||
int GetProgressBarOverride( void ) { return m_nProgressBarOverride; }
|
||||
|
||||
bool OverridesPosition( void ) { return m_flOverrideX != -1.0f || m_flOverrideY != -1.0f; }
|
||||
void GetPositionOverride( float &flX, float &flY ) { flX = m_flOverrideX; flY = m_flOverrideY; }
|
||||
|
||||
bool IsDisabled( void ) { return m_bIsDisabled; }
|
||||
bool IsTimerPaused( void ) { return m_bTimerPaused; }
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
virtual void SetTimeRemaining( float flTime ); // Set the initial length of the timer
|
||||
virtual void AddTimerSeconds( float flTimeToAdd ); // Add time to an already running ( or paused ) timer
|
||||
virtual void OnTimerFinished();
|
||||
virtual void OnTimerWarned();
|
||||
virtual void PauseTimer( CBaseEntity *pActivator = NULL );
|
||||
virtual void ResumeTimer( CBaseEntity *pActivator = NULL );
|
||||
|
||||
void SetProgressBarMaxSegments( int nSegments ) { m_nProgressBarMaxSegments = nSegments; }
|
||||
void SetProgressBarOverride( int nSegments ) { m_nProgressBarOverride = nSegments; }
|
||||
|
||||
int UpdateTransmitState();
|
||||
|
||||
// Inputs
|
||||
void InputEnable( inputdata_t &input );
|
||||
void InputDisable( inputdata_t &input );
|
||||
void InputPause( inputdata_t &input );
|
||||
void InputResume( inputdata_t &input );
|
||||
void InputSetTime( inputdata_t &input );
|
||||
void InputAddTime( inputdata_t &input );
|
||||
void InputRemoveTime( inputdata_t &input );
|
||||
void InputRestart( inputdata_t &input );
|
||||
void InputSetMaxTime( inputdata_t &input );
|
||||
void InputSetTimerCaption( inputdata_t &input );
|
||||
void InputSetProgressBarMaxSegments( inputdata_t &input );
|
||||
void InputSetProgressBarOverride( inputdata_t &input );
|
||||
void InputSetX( inputdata_t &input );
|
||||
void InputSetY( inputdata_t &input );
|
||||
void InputGetTimeRemaining( inputdata_t &input );
|
||||
void InputSetPlayerFilter( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
void OnDataChanged( DataUpdateType_t updateType );
|
||||
void UpdateOnRemove( void );
|
||||
#else
|
||||
int ShouldTransmit( const CCheckTransmitInfo *pInfo );
|
||||
void TimerThink( void );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
CNetworkVar( bool, m_bIsDisabled );
|
||||
CNetworkVar( float, m_flTimerInitialLength );
|
||||
CNetworkVar( float, m_flTimerMaxLength );
|
||||
CNetworkVar( float, m_flTimerEndTime );
|
||||
CNetworkVar( float, m_flTimeRemaining );
|
||||
CNetworkVar( float, m_flWarnTime ); // Time at which timer turns red, starts ticking loudly, etc.
|
||||
CNetworkVar( int, m_nProgressBarMaxSegments ); // Overrides maximum segments in progress bar if greater than -1
|
||||
CNetworkVar( int, m_nProgressBarOverride ); // Overrides progress bar value if greater than -1
|
||||
CNetworkVar( float, m_flOverrideX );
|
||||
CNetworkVar( float, m_flOverrideY );
|
||||
CNetworkVar( bool, m_bTimerPaused );
|
||||
CNetworkVar( bool, m_bStartPaused );
|
||||
CNetworkVar( bool, m_bShowTimeRemaining );
|
||||
CNetworkString( m_szTimerCaption, MAX_GAME_TIMER_CAPTION );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
bool m_bOldDisabled;
|
||||
#else
|
||||
bool m_bStartedWarn;
|
||||
bool m_bDisableOnFinish;
|
||||
bool m_bShowInHUD; // TODO: ShowInHUD input? Would require client to know it shouldn't show the timer anymore
|
||||
|
||||
string_t m_iszPlayerFilterName;
|
||||
CHandle<CBaseFilter> m_hPlayerFilter;
|
||||
|
||||
// Outputs
|
||||
COutputEvent m_OnFinished;
|
||||
COutputEvent m_OnPaused;
|
||||
COutputEvent m_OnResumed;
|
||||
COutputEvent m_OnWarned;
|
||||
COutputInt m_OnTick;
|
||||
COutputFloat m_OnGetTimeRemaining;
|
||||
#endif
|
||||
};
|
@ -27,6 +27,9 @@
|
||||
#include "datacache/imdlcache.h"
|
||||
#ifdef CLIENT_DLL
|
||||
#include "input.h"
|
||||
#ifdef HL2MP
|
||||
#include "c_hl2mp_player.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern ConVar mp_facefronttime, mp_feetyawrate;
|
||||
@ -76,6 +79,13 @@ extern ConVar mp_facefronttime;
|
||||
|
||||
CMapbasePlayerAnimState::CMapbasePlayerAnimState( CBasePlayer *pPlayer ): m_pPlayer( pPlayer )
|
||||
{
|
||||
if (pPlayer)
|
||||
{
|
||||
m_nPoseAimYaw = pPlayer->LookupPoseParameter( "aim_yaw" );
|
||||
m_nPoseAimPitch = pPlayer->LookupPoseParameter( "aim_pitch" );
|
||||
m_nPoseHeadPitch = pPlayer->LookupPoseParameter( "head_pitch" );
|
||||
m_nPoseWeaponLower = pPlayer->LookupPoseParameter( "weapon_lower" );
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -288,6 +298,14 @@ void CMapbasePlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
|
||||
ComputeReloadSequence();
|
||||
ComputeWeaponSwitchSequence();
|
||||
ComputeRelaxSequence();
|
||||
|
||||
#if defined(HL2MP) && defined(CLIENT_DLL)
|
||||
C_HL2MP_Player *pHL2MPPlayer = static_cast<C_HL2MP_Player*>(GetOuter());
|
||||
if (pHL2MPPlayer)
|
||||
{
|
||||
pHL2MPPlayer->UpdateLookAt();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -343,6 +361,7 @@ void CMapbasePlayerAnimState::ClearAnimationState()
|
||||
m_bReloading = false;
|
||||
m_bWeaponSwitching = false;
|
||||
m_bWeaponRelaxing = false;
|
||||
m_flWeaponRelaxAmount = 0.0f;
|
||||
m_bPlayingMisc = false;
|
||||
m_flReloadBlendIn = 0.0f;
|
||||
m_flReloadBlendOut = 0.0f;
|
||||
@ -527,7 +546,7 @@ void CMapbasePlayerAnimState::ComputeRelaxSequence()
|
||||
|
||||
m_flWeaponRelaxAmount = clamp( m_flWeaponRelaxAmount, 0.0f, 1.0f );
|
||||
|
||||
GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "weapon_lower" ), m_flWeaponRelaxAmount );
|
||||
GetOuter()->SetPoseParameter( m_nPoseWeaponLower, m_flWeaponRelaxAmount );
|
||||
|
||||
/*int nPose = GetOuter()->LookupPoseParameter( "weapon_lower" );
|
||||
if (nPose != -1)
|
||||
@ -548,7 +567,7 @@ void CMapbasePlayerAnimState::ComputeRelaxSequence()
|
||||
}
|
||||
else if (bRelaxing)
|
||||
{
|
||||
GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "weapon_lower" ), 1.0f );
|
||||
GetOuter()->SetPoseParameter( m_nPoseWeaponLower, 1.0f );
|
||||
}
|
||||
|
||||
/*bool bEnabled = m_bWeaponRelaxing;
|
||||
@ -646,7 +665,7 @@ float CMapbasePlayerAnimState::SetOuterBodyYaw( float flValue )
|
||||
{
|
||||
float flAimPoseBlend = GetAimPoseBlend();
|
||||
|
||||
GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "aim_yaw" ), flValue * flAimPoseBlend );
|
||||
GetOuter()->SetPoseParameter( m_nPoseAimYaw, flValue * flAimPoseBlend );
|
||||
return CBasePlayerAnimState::SetOuterBodyYaw( flValue * (1.0f - flAimPoseBlend) );
|
||||
}
|
||||
|
||||
@ -667,7 +686,7 @@ void CMapbasePlayerAnimState::ComputePoseParam_BodyYaw( void )
|
||||
void CMapbasePlayerAnimState::ComputePoseParam_BodyLookYaw( void )
|
||||
{
|
||||
// See if we even have a blender for pitch
|
||||
int upper_body_yaw = GetOuter()->LookupPoseParameter( "aim_yaw" );
|
||||
int upper_body_yaw = m_nPoseAimYaw;
|
||||
if ( upper_body_yaw < 0 )
|
||||
{
|
||||
return;
|
||||
@ -815,8 +834,10 @@ void CMapbasePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr
|
||||
//float flAimPoseBlend = GetAimPoseBlend();
|
||||
|
||||
// See if we have a blender for pitch
|
||||
GetOuter()->SetPoseParameter( pStudioHdr, "aim_pitch", flPitch );
|
||||
GetOuter()->SetPoseParameter( pStudioHdr, "head_pitch", flPitch );
|
||||
if (m_nPoseAimPitch >= 0)
|
||||
GetOuter()->SetPoseParameter( pStudioHdr, m_nPoseAimPitch, flPitch );
|
||||
if (m_nPoseHeadPitch >= 0)
|
||||
GetOuter()->SetPoseParameter( pStudioHdr, m_nPoseHeadPitch, flPitch );
|
||||
|
||||
//ComputePoseParam_HeadPitch( pStudioHdr );
|
||||
}
|
||||
@ -826,9 +847,6 @@ void CMapbasePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMapbasePlayerAnimState::ComputePoseParam_HeadPitch( CStudioHdr *pStudioHdr )
|
||||
{
|
||||
// Get pitch from v_angle
|
||||
int iHeadPitch = GetOuter()->LookupPoseParameter("head_pitch");
|
||||
|
||||
float flPitch = m_flEyePitch;
|
||||
|
||||
if ( flPitch > 180.0f )
|
||||
@ -837,5 +855,5 @@ void CMapbasePlayerAnimState::ComputePoseParam_HeadPitch( CStudioHdr *pStudioHdr
|
||||
}
|
||||
flPitch = clamp( flPitch, -90, 90 );
|
||||
|
||||
GetOuter()->SetPoseParameter( pStudioHdr, iHeadPitch, flPitch );
|
||||
GetOuter()->SetPoseParameter( pStudioHdr, m_nPoseHeadPitch, flPitch );
|
||||
}
|
||||
|
@ -119,6 +119,8 @@ private:
|
||||
// until it completes.
|
||||
int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw).
|
||||
float m_flFireCycle;
|
||||
|
||||
int m_nPoseAimYaw, m_nPoseAimPitch, m_nPoseHeadPitch, m_nPoseWeaponLower;
|
||||
};
|
||||
|
||||
CMapbasePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer );
|
||||
|
@ -20,6 +20,8 @@ void HookMapbaseUserMessages( void )
|
||||
{
|
||||
// VScript
|
||||
//HOOK_MESSAGE( ScriptMsg ); // Hooked in CNetMsgScriptHelper
|
||||
|
||||
//HOOK_MESSAGE( ShowMenuComplex ); // Hooked in CHudMenu
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -28,6 +30,8 @@ void RegisterMapbaseUserMessages( void )
|
||||
// VScript
|
||||
usermessages->Register( "ScriptMsg", -1 ); // CNetMsgScriptHelper
|
||||
|
||||
usermessages->Register( "ShowMenuComplex", -1 ); // CHudMenu
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
// TODO: Better placement?
|
||||
HookMapbaseUserMessages();
|
||||
|
@ -176,11 +176,11 @@ void CProtagonistSystem::LoadProtagonistFile( const char *pszFile )
|
||||
else if (FStrEq( pszSubKeyName, "team" ))
|
||||
{
|
||||
#ifdef HL2MP
|
||||
if (FStrEq( pszSubKeyName, "combine" ))
|
||||
if (FStrEq( pSubKey->GetString(), "combine" ))
|
||||
{
|
||||
pProtag->nTeam = TEAM_COMBINE;
|
||||
}
|
||||
else if (FStrEq( pszSubKeyName, "rebels" ))
|
||||
else if (FStrEq( pSubKey->GetString(), "rebels" ))
|
||||
{
|
||||
pProtag->nTeam = TEAM_REBELS;
|
||||
}
|
||||
@ -188,7 +188,7 @@ void CProtagonistSystem::LoadProtagonistFile( const char *pszFile )
|
||||
#endif
|
||||
{
|
||||
// Try to get a direct integer
|
||||
pProtag->nTeam = atoi( pszSubKeyName );
|
||||
pProtag->nTeam = atoi( pSubKey->GetString() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -335,6 +335,12 @@ void CProtagonistSystem::PrecacheProtagonist( CBaseEntity *pSource, int nIdx )
|
||||
|
||||
ProtagonistData_t &pProtag = m_Protagonists[nIdx];
|
||||
|
||||
// Don't if it's already precached
|
||||
if (pProtag.bPrecached)
|
||||
return;
|
||||
|
||||
CBaseEntity::SetAllowPrecache( true );
|
||||
|
||||
// Playermodel
|
||||
if (pProtag.pszPlayerModel)
|
||||
{
|
||||
@ -358,6 +364,16 @@ void CProtagonistSystem::PrecacheProtagonist( CBaseEntity *pSource, int nIdx )
|
||||
pSource->PrecacheModel( pProtag.dictWpnData[i].pszVM );
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntity::SetAllowPrecache( false );
|
||||
|
||||
// Precache parents
|
||||
FOR_EACH_VEC( pProtag.vecParents, i )
|
||||
{
|
||||
PrecacheProtagonist( pSource, pProtag.vecParents[i] );
|
||||
}
|
||||
|
||||
pProtag.bPrecached = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -416,7 +432,6 @@ GetProtagParamBody( ResponseContexts, bool, GetProtagParamInner( ResponseConte
|
||||
int nLast = V_strlen( pszContexts )-1;
|
||||
if (pszContexts[nLast] == ',')
|
||||
{
|
||||
Msg( "Removing trailing comma from \"%s\"\n", pszContexts );
|
||||
pszContexts[nLast] = '\0';
|
||||
}
|
||||
}
|
||||
@ -681,6 +696,11 @@ void CProtagonistSystem::PrintProtagonistData()
|
||||
if (pProtag.pszPlayerModel)
|
||||
Msg( "\t\tPlayer model: \"%s\" (%i, %i)\n", pProtag.pszPlayerModel, pProtag.nPlayerSkin, pProtag.nPlayerBody );
|
||||
|
||||
#ifdef HL2MP
|
||||
if ( pProtag.nTeam != TEAM_ANY )
|
||||
Msg( "\t\tTeam: %i\n", pProtag.nTeam );
|
||||
#endif
|
||||
|
||||
for (int j = 0; j < NUM_HAND_RIG_TYPES; j++)
|
||||
{
|
||||
extern const char *pHandRigs[NUM_HAND_RIG_TYPES];
|
||||
|
@ -61,6 +61,9 @@ private:
|
||||
|
||||
// Multiplayer
|
||||
int nTeam = TEAM_ANY;
|
||||
|
||||
// Precached (used by system, not actual data)
|
||||
bool bPrecached = false;
|
||||
#endif
|
||||
|
||||
// Weapon Data
|
||||
|
@ -1244,17 +1244,20 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( pInfo->datatype == types::_VEC3 )
|
||||
index /= 3;
|
||||
unsigned int arraysize = pInfo->arraysize;
|
||||
|
||||
if ( index < 0 || (unsigned int)index >= pInfo->arraysize )
|
||||
if ( pInfo->datatype == types::_VEC3 )
|
||||
arraysize *= 3;
|
||||
|
||||
if ( index < 0 || (unsigned int)index >= arraysize )
|
||||
return -1;
|
||||
|
||||
switch ( pInfo->datatype )
|
||||
{
|
||||
case types::_VEC3:
|
||||
case types::_FLOAT:
|
||||
return *(float*)((char*)pEnt + pInfo->GetOffset( index ));
|
||||
case types::_VEC3:
|
||||
return ((float*)((char*)pEnt + pInfo->GetOffset( index / 3 )))[ index % 3 ];
|
||||
#ifdef GAME_DLL
|
||||
case types::_DAR_FLOAT:
|
||||
{
|
||||
@ -1286,19 +1289,24 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if ( pInfo->datatype == types::_VEC3 )
|
||||
index /= 3;
|
||||
unsigned int arraysize = pInfo->arraysize;
|
||||
|
||||
if ( index < 0 || (unsigned int)index >= pInfo->arraysize )
|
||||
if ( pInfo->datatype == types::_VEC3 )
|
||||
arraysize *= 3;
|
||||
|
||||
if ( index < 0 || (unsigned int)index >= arraysize )
|
||||
return;
|
||||
|
||||
switch ( pInfo->datatype )
|
||||
{
|
||||
case types::_VEC3:
|
||||
case types::_FLOAT:
|
||||
*(float*)((char*)pEnt + pInfo->GetOffset( index )) = value;
|
||||
NetworkStateChanged( pEnt, pInfo->GetOffset( index ) );
|
||||
break;
|
||||
case types::_VEC3:
|
||||
((float*)((char*)pEnt + pInfo->GetOffset( index / 3 )))[ index % 3 ] = value;
|
||||
NetworkStateChanged( pEnt, pInfo->GetOffset( index / 3 ) );
|
||||
break;
|
||||
#ifdef GAME_DLL
|
||||
case types::_DAR_FLOAT:
|
||||
{
|
||||
@ -5138,6 +5146,11 @@ bool CScriptConvarAccessor::Init()
|
||||
AddBlockedConVar( "cl_allowdownload" );
|
||||
AddBlockedConVar( "cl_allowupload" );
|
||||
AddBlockedConVar( "cl_downloadfilter" );
|
||||
#ifdef GAME_DLL
|
||||
AddBlockedConVar( "script_connect_debugger_on_mapspawn" );
|
||||
#else
|
||||
AddBlockedConVar( "script_connect_debugger_on_mapspawn_client" );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -64,7 +64,6 @@ private:
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// This is to ensure a dependency exists between the vscript library and the game DLLs
|
||||
extern int vscript_token;
|
||||
extern int vscript_debugger_port;
|
||||
int vscript_token_hack = vscript_token;
|
||||
#endif
|
||||
|
||||
@ -454,27 +453,14 @@ CON_COMMAND( script_debug, "Connect the vscript VM to the script debugger" )
|
||||
if ( !IsCommandIssuedByServerAdmin() )
|
||||
return;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#ifdef GAME_DLL
|
||||
int port = 1212;
|
||||
#else
|
||||
int port = 1213;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
vscript_debugger_port = port;
|
||||
CGMsg( 0, CON_GROUP_VSCRIPT, "VScript VM is not running, waiting for it to attach the debugger to port %d...\n", port );
|
||||
#else
|
||||
Log_Warning( LOG_VScript, "Scripting disabled or no server running\n" );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
g_pScriptVM->ConnectDebugger( port );
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||
#else
|
||||
g_pScriptVM->ConnectDebugger();
|
||||
#endif
|
||||
|
@ -191,6 +191,12 @@ class CBaseEntityScriptInstanceHelper : public IScriptInstanceHelper
|
||||
extern CBaseEntityScriptInstanceHelper g_BaseEntityScriptInstanceHelper;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#ifdef GAME_DLL
|
||||
const int vscript_debugger_port = 1212;
|
||||
#else
|
||||
const int vscript_debugger_port = 1213;
|
||||
#endif
|
||||
|
||||
void RegisterSharedScriptConstants();
|
||||
void RegisterSharedScriptFunctions();
|
||||
|
||||
|
@ -811,8 +811,8 @@ void DrawLightmappedGeneric_DX9_Internal(CBaseVSShader *pShader, IMaterialVar**
|
||||
(params[info.m_nBlendModulateTexture]->IsTexture() );
|
||||
bool hasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );
|
||||
#ifdef PARALLAX_CORRECTED_CUBEMAPS
|
||||
// Parallax cubemaps
|
||||
bool hasParallaxCorrection = params[info.m_nEnvmapParallax]->GetIntValue() > 0;
|
||||
// Parallax cubemaps. Check for envmap because if we don't, white splotchs can appear at certain viewing angles when mat_specular is 0.
|
||||
bool hasParallaxCorrection = params[info.m_nEnvmap]->IsDefined() && params[info.m_nEnvmapParallax]->GetIntValue() > 0;
|
||||
#endif
|
||||
|
||||
if ( hasFlashlight && !IsX360() )
|
||||
|
@ -229,6 +229,8 @@ union ScriptVariantTemporaryStorage_t
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
struct ScriptClassDesc_t;
|
||||
|
||||
struct ScriptFuncDescriptor_t
|
||||
{
|
||||
ScriptFuncDescriptor_t()
|
||||
@ -237,11 +239,13 @@ struct ScriptFuncDescriptor_t
|
||||
m_pszFunction = NULL;
|
||||
m_ReturnType = FIELD_TYPEUNKNOWN;
|
||||
m_pszDescription = NULL;
|
||||
m_pScriptClassDesc = NULL;
|
||||
}
|
||||
|
||||
const char *m_pszScriptName;
|
||||
const char *m_pszFunction;
|
||||
const char *m_pszDescription;
|
||||
ScriptClassDesc_t *m_pScriptClassDesc;
|
||||
ScriptDataType_t m_ReturnType;
|
||||
CUtlVector<ScriptDataType_t> m_Parameters;
|
||||
};
|
||||
@ -751,7 +755,7 @@ public:
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual bool ConnectDebugger( int port = 0 ) = 0;
|
||||
virtual bool ConnectDebugger( int port = 0, float timeout = 0.0f ) = 0;
|
||||
#else
|
||||
virtual bool ConnectDebugger() = 0;
|
||||
#endif
|
||||
|
@ -61,7 +61,7 @@ FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_TYPE_DEDUCER );
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER );
|
||||
|
||||
#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); }
|
||||
#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); (pDesc)->m_pScriptClassDesc = GetScriptDesc<class>(nullptr); }
|
||||
|
||||
#define ScriptInitFuncDescriptorNamed( pDesc, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, &func ); }
|
||||
#define ScriptInitFuncDescriptor( pDesc, func ) ScriptInitFuncDescriptorNamed( pDesc, func, #func )
|
||||
|
@ -112,7 +112,11 @@ WIN32
|
||||
===================================================================
|
||||
*/
|
||||
|
||||
#ifdef MAPBASE
|
||||
int numthreads = -(MAX_TOOL_THREADS + 1);
|
||||
#else
|
||||
int numthreads = -1;
|
||||
#endif
|
||||
CRITICAL_SECTION crit;
|
||||
static int enter;
|
||||
|
||||
@ -133,19 +137,37 @@ void SetLowPriority()
|
||||
SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
|
||||
}
|
||||
|
||||
|
||||
//Threads can be negative; if so, they will be subtracted from the total thread count.
|
||||
void ThreadSetDefault (void)
|
||||
{
|
||||
SYSTEM_INFO info;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (numthreads == -(MAX_TOOL_THREADS + 1)) // not set manually
|
||||
#else
|
||||
if (numthreads == -1) // not set manually
|
||||
#endif
|
||||
{
|
||||
GetSystemInfo (&info);
|
||||
numthreads = info.dwNumberOfProcessors;
|
||||
if (numthreads < 1 || numthreads > 32)
|
||||
#ifdef MAPBASE
|
||||
if (numthreads > 32)
|
||||
#else
|
||||
if (numthreads < 1 ||numthreads > 32)
|
||||
#endif
|
||||
numthreads = 1;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (numthreads <= 0)
|
||||
{
|
||||
GetSystemInfo(&info);
|
||||
numthreads = info.dwNumberOfProcessors + numthreads;
|
||||
if (numthreads <= 0)
|
||||
Error("\nIncrease the number of threads! Threads: %i, they cannot be negative or 0.\n", numthreads);
|
||||
}
|
||||
#endif
|
||||
|
||||
Msg ("%i threads\n", numthreads);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "fgdlib/fgdlib.h"
|
||||
#include "manifest.h"
|
||||
#ifdef PARALLAX_CORRECTED_CUBEMAPS
|
||||
#include "matrixinvert.h"
|
||||
#include "mathlib/vmatrix.h"
|
||||
#endif
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#include "vscript_vbsp.h"
|
||||
@ -1657,9 +1657,11 @@ ChunkFileResult_t CMapFile::LoadEntityCallback(CChunkFile *pFile, int nParam)
|
||||
//
|
||||
if (!strcmp("parallax_obb", pClassName))
|
||||
{
|
||||
matrix3x4_t obbMatrix, invObbMatrix;
|
||||
SetIdentityMatrix(obbMatrix);
|
||||
SetIdentityMatrix(invObbMatrix);
|
||||
//Originally was matrix3x2. Now we use built-in functions to the engine instead of a custom invert matrix
|
||||
VMatrix obbMatrix, invObbMatrix;
|
||||
MatrixSetIdentity(obbMatrix);
|
||||
MatrixSetIdentity(invObbMatrix);
|
||||
|
||||
|
||||
// Get corner and its 3 edges (scaled, local x, y, and z axes)
|
||||
mapbrush_t *brush = &mapbrushes[mapent->firstbrush];
|
||||
@ -1714,13 +1716,15 @@ ChunkFileResult_t CMapFile::LoadEntityCallback(CChunkFile *pFile, int nParam)
|
||||
x *= abs(DotProduct(diag, x));
|
||||
|
||||
// Build transformation matrix (what is needed to turn a [0,0,0] - [1,1,1] cube into this brush)
|
||||
MatrixSetColumn(x, 0, obbMatrix);
|
||||
MatrixSetColumn(y, 1, obbMatrix);
|
||||
MatrixSetColumn(z, 2, obbMatrix);
|
||||
MatrixSetColumn(corner, 3, obbMatrix);
|
||||
//Originally was MatrixSetColum. Since we use VMatrix now, changed to obbMatrix
|
||||
obbMatrix.SetForward(x);
|
||||
obbMatrix.SetLeft(y);
|
||||
obbMatrix.SetUp(z);
|
||||
obbMatrix.SetTranslation(corner);
|
||||
|
||||
//find inverse (we need the world to local matrix, "transformationmatrix" is kind of a misnomer)
|
||||
MatrixInversion(obbMatrix, invObbMatrix);
|
||||
//Originally was MatrixInversion. This is now using the built in functions, not relying on MatrixInversion and matrixinvert.h anymore
|
||||
MatrixInverseGeneral(obbMatrix, invObbMatrix);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,117 +0,0 @@
|
||||
// By Jason Yu-Tseh Chi
|
||||
// From http://chi3x10.wordpress.com/2008/05/28/calculate-matrix-inversion-in-c/
|
||||
// Modified to work with valve's matrix_3x4_t
|
||||
|
||||
#include "mathlib\mathlib.h"
|
||||
|
||||
// Calculate the cofactor of element (row,col)
|
||||
int GetMatrixMinor(float **src, float **dest, int row, int col, int order)
|
||||
{
|
||||
// Indicate which col and row is being copied to dest
|
||||
int colCount = 0, rowCount = 0;
|
||||
|
||||
for (int i = 0; i < order; i++)
|
||||
{
|
||||
if (i != row)
|
||||
{
|
||||
colCount = 0;
|
||||
for (int j = 0; j < order; j++)
|
||||
{
|
||||
// When j is not the element
|
||||
if (j != col)
|
||||
{
|
||||
dest[rowCount][colCount] = src[i][j];
|
||||
colCount++;
|
||||
}
|
||||
}
|
||||
rowCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Calculate the determinant recursively.
|
||||
double CalcMatrixDeterminant(float **mat, int order)
|
||||
{
|
||||
// Order must be >= 0
|
||||
// Stop the recursion when matrix is a single element
|
||||
if (order == 1)
|
||||
return mat[0][0];
|
||||
|
||||
// The determinant value
|
||||
float det = 0;
|
||||
|
||||
// Allocate the cofactor matrix
|
||||
float **minor;
|
||||
minor = new float*[order - 1];
|
||||
for (int i = 0; i<order - 1; i++)
|
||||
minor[i] = new float[order - 1];
|
||||
|
||||
for (int i = 0; i < order; i++)
|
||||
{
|
||||
// Get minor of element (0,i)
|
||||
GetMatrixMinor(mat, minor, 0, i, order);
|
||||
// The recusion is here!
|
||||
|
||||
det += (i % 2 == 1 ? -1.0 : 1.0) * mat[0][i] * CalcMatrixDeterminant(minor, order - 1);
|
||||
//det += pow( -1.0, i ) * mat[0][i] * CalcMatrixDeterminant( minor,order-1 );
|
||||
}
|
||||
|
||||
// Release memory
|
||||
for (int i = 0; i<order - 1; i++)
|
||||
delete[] minor[i];
|
||||
delete[] minor;
|
||||
|
||||
return det;
|
||||
}
|
||||
|
||||
// Matrix inversion
|
||||
void MatrixInversion(matrix3x4_t &in, matrix3x4_t &out)
|
||||
{
|
||||
float **A;
|
||||
A = new float*[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
A[i] = new float[4];
|
||||
int order = 4;
|
||||
|
||||
// Load in into A
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
A[i][j] = in[i][j];
|
||||
}
|
||||
}
|
||||
A[3][0] = A[3][1] = A[3][2] = 0;
|
||||
A[3][3] = 1;
|
||||
|
||||
// Get the determinant of a
|
||||
double det = 1.0 / CalcMatrixDeterminant((float**)A, order);
|
||||
|
||||
// Memory allocation
|
||||
float *temp = new float[(order - 1)*(order - 1)];
|
||||
float **minor = new float*[order - 1];
|
||||
for (int i = 0; i<order - 1; i++)
|
||||
minor[i] = temp + (i*(order - 1));
|
||||
|
||||
for (int j = 0; j<order; j++)
|
||||
{
|
||||
for (int i = 0; i<order; i++)
|
||||
{
|
||||
// Get the co-factor (matrix) of A(j,i)
|
||||
GetMatrixMinor((float**)A, minor, j, i, order);
|
||||
out[i][j] = det*CalcMatrixDeterminant(minor, order - 1);
|
||||
if ((i + j) % 2 == 1)
|
||||
out[i][j] = -out[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// Release memory
|
||||
for (int i = 0; i < 4; i++)
|
||||
delete A[i];
|
||||
delete A;
|
||||
//delete [] minor[0];
|
||||
delete[] temp;
|
||||
delete[] minor;
|
||||
}
|
@ -65,6 +65,7 @@ bool g_NodrawTriggers = false;
|
||||
bool g_DisableWaterLighting = false;
|
||||
bool g_bAllowDetailCracks = false;
|
||||
bool g_bNoVirtualMesh = false;
|
||||
bool g_bNoHiddenManifestMaps = false;
|
||||
#ifdef MAPBASE
|
||||
bool g_bNoDefaultCubemaps = true;
|
||||
bool g_bSkyboxCubemaps = false;
|
||||
@ -1175,6 +1176,10 @@ int RunVBSP( int argc, char **argv )
|
||||
{
|
||||
EnableFullMinidumps( true );
|
||||
}
|
||||
else if ( !Q_stricmp( argv[i], "-nohiddenmaps" ) )
|
||||
{
|
||||
g_bNoHiddenManifestMaps = true;
|
||||
}
|
||||
else if ( !Q_stricmp( argv[i], "-embed" ) && i < argc - 1 )
|
||||
{
|
||||
V_MakeAbsolutePath( g_szEmbedDir, sizeof( g_szEmbedDir ), argv[++i], "." );
|
||||
@ -1285,6 +1290,7 @@ int RunVBSP( int argc, char **argv )
|
||||
CmdLib_Cleanup();
|
||||
CmdLib_Exit( 1 );
|
||||
}
|
||||
#endif
|
||||
else if (argv[i][0] == '-')
|
||||
{
|
||||
Warning("VBSP: Unknown option \"%s\"\n\n", argv[i]);
|
||||
@ -1331,8 +1337,9 @@ int RunVBSP( int argc, char **argv )
|
||||
Warning(
|
||||
"Other options :\n"
|
||||
" -novconfig : Don't bring up graphical UI on vproject errors.\n"
|
||||
" -threads : Control the number of threads vbsp uses (defaults to the # of\n"
|
||||
" processors on your machine).\n"
|
||||
" -threads # : Control the number of threads vbsp uses (defaults to the #\n"
|
||||
" or processors on your machine).\n"
|
||||
" Threads can be negative; if so, they will be subtracted from the total thread count.\n"
|
||||
" -verboseentities: If -v is on, this disables verbose output for submodels.\n"
|
||||
" -noweld : Don't join face vertices together.\n"
|
||||
" -nocsg : Don't chop out intersecting brush areas.\n"
|
||||
|
@ -2467,11 +2467,13 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail )
|
||||
if ( ++i < argc )
|
||||
{
|
||||
numthreads = atoi (argv[i]);
|
||||
#ifndef MAPBASE //Mapbase allows threads to be negative, go to ThreadSetDefault(void) in threads.cpp for a explanation.
|
||||
if ( numthreads <= 0 )
|
||||
{
|
||||
Warning("Error: expected positive value after '-threads'\n" );
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2871,8 +2873,9 @@ void PrintUsage( int argc, char **argv )
|
||||
" -dump : Write debugging .txt files.\n"
|
||||
" -dumpnormals : Write normals to debug files.\n"
|
||||
" -dumptrace : Write ray-tracing environment to debug files.\n"
|
||||
" -threads : Control the number of threads vbsp uses (defaults to the #\n"
|
||||
" -threads # : Control the number of threads vrad uses (defaults to the #\n"
|
||||
" or processors on your machine).\n"
|
||||
" Threads can be negative; if so, they will be subtracted from the total thread count.\n"
|
||||
" -lights <file> : Load a lights file in addition to lights.rad and the\n"
|
||||
" level lights file.\n"
|
||||
" -noextra : Disable supersampling.\n"
|
||||
|
@ -703,9 +703,13 @@ public:
|
||||
if ( pVMT->LoadFromBuffer( pMaterialName, buf ) )
|
||||
{
|
||||
bFound = true;
|
||||
if ( pVMT->FindKey("$translucent") || pVMT->FindKey("$alphatest") )
|
||||
KeyValues *pBaseTexture = pVMT->FindKey("%alphatexture");
|
||||
if ( pBaseTexture || pVMT->FindKey("$alphatest") || pVMT->FindKey("$translucent") )
|
||||
{
|
||||
KeyValues *pBaseTexture = pVMT->FindKey("$basetexture");
|
||||
if ( !pBaseTexture )
|
||||
{
|
||||
pBaseTexture = pVMT->FindKey("$basetexture");
|
||||
}
|
||||
if ( pBaseTexture )
|
||||
{
|
||||
const char *pBaseTextureName = pBaseTexture->GetString();
|
||||
|
@ -1039,8 +1039,9 @@ void PrintUsage( int argc, char **argv )
|
||||
#ifdef MPI
|
||||
" -mpi_pw <pw> : Use a password to choose a specific set of VMPI workers.\n"
|
||||
#endif
|
||||
" -threads : Control the number of threads vbsp uses (defaults to the #\n"
|
||||
" -threads # : Control the number of threads vvis uses (defaults to the #\n"
|
||||
" or processors on your machine).\n"
|
||||
" Threads can be negative; if so, they will be subtracted from the total thread count.\n"
|
||||
" -nosort : Don't sort portals (sorting is an optimization).\n"
|
||||
" -tmpin : Make portals come from \\tmp\\<mapname>.\n"
|
||||
" -tmpout : Make portals come from \\tmp\\<mapname>.\n"
|
||||
|
19
src/vscript/sqdbg/LICENSE
Normal file
19
src/vscript/sqdbg/LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) samisalreadytaken
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -60,9 +60,14 @@ SQDBG_API int sqdbg_listen_socket( HSQDEBUGSERVER dbg, unsigned short port );
|
||||
SQDBG_API void sqdbg_frame( HSQDEBUGSERVER dbg );
|
||||
|
||||
// Copies the script to be able to source it to debugger clients
|
||||
SQDBG_API void sqdbg_on_script_compile( HSQDEBUGSERVER dbg, const SQChar *script, SQInteger size,
|
||||
SQDBG_API void sqdbg_on_script_compile( HSQDEBUGSERVER dbg,
|
||||
const SQChar *script, SQInteger scriptlen,
|
||||
const SQChar *sourcename, SQInteger sourcenamelen );
|
||||
|
||||
// Check if a client is connected to the debugger
|
||||
// Returns 0 if there is no client connected
|
||||
SQDBG_API int sqdbg_is_client_connected( HSQDEBUGSERVER dbg );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -106,6 +106,7 @@
|
||||
} while(0)
|
||||
#endif
|
||||
#define Verify( x ) Assert(x)
|
||||
#define STATIC_ASSERT( x ) static_assert( x, #x )
|
||||
#else
|
||||
#define DebuggerBreak() ((void)0)
|
||||
#define Assert( x ) ((void)0)
|
||||
@ -113,12 +114,15 @@
|
||||
#define AssertMsg1( x, msg, a1 ) ((void)0)
|
||||
#define AssertMsg2( x, msg, a1, a2 ) ((void)0)
|
||||
#define Verify( x ) x
|
||||
#define STATIC_ASSERT( x )
|
||||
#endif // _DEBUG
|
||||
|
||||
#endif
|
||||
|
||||
#include <tier0/dbg.h>
|
||||
|
||||
#define STATIC_ASSERT COMPILE_TIME_ASSERT
|
||||
|
||||
// Misdefined for GCC in platform.h
|
||||
#undef UNREACHABLE
|
||||
|
||||
|
@ -62,12 +62,12 @@ class json_array_t
|
||||
{
|
||||
public:
|
||||
const char *m_pBase;
|
||||
CScratch< JSON_SCRATCH_CHUNK_SIZE > *m_Allocator;
|
||||
CScratch< true, JSON_SCRATCH_CHUNK_SIZE > *m_Allocator;
|
||||
int *m_Elements;
|
||||
unsigned short m_nElementCount;
|
||||
unsigned short m_nElementsSize;
|
||||
|
||||
void Init( const char *base, CScratch< JSON_SCRATCH_CHUNK_SIZE > *allocator )
|
||||
void Init( const char *base, CScratch< true, JSON_SCRATCH_CHUNK_SIZE > *allocator )
|
||||
{
|
||||
m_pBase = base;
|
||||
m_Allocator = allocator;
|
||||
@ -96,7 +96,7 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int size() const
|
||||
int Size() const
|
||||
{
|
||||
return m_nElementCount;
|
||||
}
|
||||
@ -138,12 +138,12 @@ class json_table_t
|
||||
{
|
||||
public:
|
||||
const char *m_pBase;
|
||||
CScratch< JSON_SCRATCH_CHUNK_SIZE > *m_Allocator;
|
||||
CScratch< true, JSON_SCRATCH_CHUNK_SIZE > *m_Allocator;
|
||||
int *m_Elements;
|
||||
unsigned short m_nElementCount;
|
||||
unsigned short m_nElementsSize;
|
||||
|
||||
void Init( const char *base, CScratch< JSON_SCRATCH_CHUNK_SIZE > *allocator )
|
||||
void Init( const char *base, CScratch< true, JSON_SCRATCH_CHUNK_SIZE > *allocator )
|
||||
{
|
||||
m_pBase = base;
|
||||
m_Allocator = allocator;
|
||||
@ -266,11 +266,24 @@ public:
|
||||
bool Get( const string_t &key, json_array_t **out ) const { return GetArray( key, out ); }
|
||||
};
|
||||
|
||||
static inline void PutStrL( CBuffer *buffer, const string_t &str )
|
||||
static inline void PutStr( CBuffer *buffer, const string_t &str )
|
||||
{
|
||||
buffer->_base.Ensure( buffer->size() + str.len );
|
||||
memcpy( buffer->base() + buffer->size(), str.ptr, str.len );
|
||||
buffer->_size += str.len;
|
||||
buffer->base.Ensure( buffer->Size() + str.len );
|
||||
memcpy( buffer->Base() + buffer->Size(), str.ptr, str.len );
|
||||
buffer->size += str.len;
|
||||
|
||||
#ifdef SQDBG_VALIDATE_SENT_MSG
|
||||
for ( unsigned int i = 0; i < str.len; i++ )
|
||||
{
|
||||
if ( str.ptr[i] == '\\' && ( str.ptr[i+1] == '\\' || str.ptr[i+1] == '\"' ) )
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
AssertMsg( str.ptr[i] != '\\' && IN_RANGE_CHAR( str.ptr[i], 0x20, 0x7E ), "control char in json string" );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
@ -278,7 +291,7 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
const char *c = str.ptr;
|
||||
unsigned int i = str.len;
|
||||
|
||||
unsigned int len = 2 + i;
|
||||
unsigned int len = i;
|
||||
|
||||
if ( quote )
|
||||
len += 4;
|
||||
@ -287,18 +300,19 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
{
|
||||
switch ( *c )
|
||||
{
|
||||
case '\"': case '\\': case '\b':
|
||||
case '\f': case '\n': case '\r': case '\t':
|
||||
case '\\': case '\"':
|
||||
case '\a': case '\b': case '\f':
|
||||
case '\n': case '\r': case '\t': case '\v':
|
||||
len++;
|
||||
if ( quote )
|
||||
{
|
||||
len++;
|
||||
if ( *c == '\"' || *c == '\\' )
|
||||
if ( *c == '\\' || *c == '\"' )
|
||||
len++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ( !IN_RANGE_CHAR( *(unsigned char*)c, 0x20, 0x7E ) )
|
||||
if ( !IN_RANGE_CHAR( *c, 0x20, 0x7E ) )
|
||||
{
|
||||
int ret = IsValidUTF8( (unsigned char*)c, i + 1 );
|
||||
if ( ret != 0 )
|
||||
@ -321,16 +335,14 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
}
|
||||
}
|
||||
|
||||
buffer->_base.Ensure( buffer->size() + len );
|
||||
buffer->base.Ensure( buffer->Size() + len );
|
||||
|
||||
char *mem = buffer->base();
|
||||
unsigned int idx = buffer->size();
|
||||
char *mem = buffer->Base();
|
||||
unsigned int idx = buffer->Size();
|
||||
|
||||
c = str.ptr;
|
||||
i = str.len;
|
||||
|
||||
mem[idx++] = '\"';
|
||||
|
||||
if ( quote )
|
||||
{
|
||||
mem[idx++] = '\\';
|
||||
@ -343,6 +355,7 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
|
||||
switch ( *c )
|
||||
{
|
||||
case '\\':
|
||||
case '\"':
|
||||
mem[idx-1] = '\\';
|
||||
if ( quote )
|
||||
@ -350,15 +363,13 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
mem[idx++] = '\\';
|
||||
mem[idx++] = '\\';
|
||||
}
|
||||
mem[idx++] = '\"';
|
||||
mem[idx++] = *c;
|
||||
break;
|
||||
case '\\':
|
||||
case '\a':
|
||||
mem[idx-1] = '\\';
|
||||
if ( quote )
|
||||
{
|
||||
mem[idx++] = '\\';
|
||||
mem[idx++] = '\\';
|
||||
}
|
||||
mem[idx++] = '\\';
|
||||
mem[idx++] = 'a';
|
||||
break;
|
||||
case '\b':
|
||||
mem[idx-1] = '\\';
|
||||
@ -390,8 +401,14 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
mem[idx++] = '\\';
|
||||
mem[idx++] = 't';
|
||||
break;
|
||||
case '\v':
|
||||
mem[idx-1] = '\\';
|
||||
if ( quote )
|
||||
mem[idx++] = '\\';
|
||||
mem[idx++] = 'v';
|
||||
break;
|
||||
default:
|
||||
if ( !IN_RANGE_CHAR( *(unsigned char*)c, 0x20, 0x7E ) )
|
||||
if ( !IN_RANGE_CHAR( *c, 0x20, 0x7E ) )
|
||||
{
|
||||
int ret = IsValidUTF8( (unsigned char*)c, i + 1 );
|
||||
if ( ret != 0 )
|
||||
@ -410,7 +427,7 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
mem[idx++] = 'u';
|
||||
idx += printhex< true, false >(
|
||||
mem + idx,
|
||||
buffer->capacity() - idx,
|
||||
buffer->Capacity() - idx,
|
||||
(uint16_t)*(unsigned char*)c );
|
||||
}
|
||||
else
|
||||
@ -419,8 +436,8 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
mem[idx++] = 'x';
|
||||
idx += printhex< true, false >(
|
||||
mem + idx,
|
||||
buffer->capacity() - idx,
|
||||
(SQChar)*(unsigned char*)c );
|
||||
buffer->Capacity() - idx,
|
||||
(SQUnsignedChar)*(unsigned char*)c );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -433,9 +450,7 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
|
||||
mem[idx++] = '\"';
|
||||
}
|
||||
|
||||
mem[idx++] = '\"';
|
||||
|
||||
buffer->_size = idx;
|
||||
buffer->size = idx;
|
||||
}
|
||||
|
||||
#ifdef SQUNICODE
|
||||
@ -445,64 +460,127 @@ static inline void PutStr( CBuffer *buffer, const sqstring_t &str, bool quote )
|
||||
|
||||
if ( !quote )
|
||||
{
|
||||
len = 2 + UTF8Length< kUTFEscapeJSON >( str.ptr, str.len );
|
||||
len = UTF8Length< kUTFEscapeJSON >( str.ptr, str.len );
|
||||
}
|
||||
else
|
||||
{
|
||||
len = 2 + UTF8Length< kUTFEscapeQuoted >( str.ptr, str.len );
|
||||
len = UTF8Length< kUTFEscapeQuoted >( str.ptr, str.len );
|
||||
}
|
||||
|
||||
buffer->_base.Ensure( buffer->size() + len );
|
||||
buffer->base()[buffer->_size++] = '\"';
|
||||
buffer->base.Ensure( buffer->Size() + len );
|
||||
|
||||
if ( !quote )
|
||||
{
|
||||
len = SQUnicodeToUTF8< kUTFEscapeJSON >(
|
||||
buffer->base() + buffer->size(),
|
||||
buffer->capacity() - buffer->size(),
|
||||
buffer->Base() + buffer->Size(),
|
||||
buffer->Capacity() - buffer->Size(),
|
||||
str.ptr,
|
||||
str.len );
|
||||
}
|
||||
else
|
||||
{
|
||||
len = SQUnicodeToUTF8< kUTFEscapeQuoted >(
|
||||
buffer->base() + buffer->size(),
|
||||
buffer->capacity() - buffer->size(),
|
||||
buffer->Base() + buffer->Size(),
|
||||
buffer->Capacity() - buffer->Size(),
|
||||
str.ptr,
|
||||
str.len );
|
||||
}
|
||||
|
||||
buffer->_size += len;
|
||||
buffer->base()[buffer->_size++] = '\"';
|
||||
buffer->size += len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void PutChar( CBuffer *buffer, char c )
|
||||
{
|
||||
buffer->_base.Ensure( buffer->size() + 1 );
|
||||
buffer->base()[buffer->_size++] = c;
|
||||
buffer->base.Ensure( buffer->Size() + 1 );
|
||||
buffer->Base()[buffer->size++] = c;
|
||||
}
|
||||
|
||||
template < typename I >
|
||||
static inline void PutInt( CBuffer *buffer, I val, bool hex = false )
|
||||
static inline void PutInt( CBuffer *buffer, I val )
|
||||
{
|
||||
int len;
|
||||
buffer->_base.Ensure( buffer->size() + countdigits( val ) + 1 );
|
||||
|
||||
if ( !hex )
|
||||
{
|
||||
len = printint( buffer->base() + buffer->size(), buffer->capacity() - buffer->size(), val );
|
||||
}
|
||||
else
|
||||
{
|
||||
len = printhex< false >( buffer->base() + buffer->size(), buffer->capacity() - buffer->size(), val );
|
||||
}
|
||||
|
||||
buffer->_size += len;
|
||||
buffer->base.Ensure( buffer->Size() + countdigits( val ) + 1 );
|
||||
int len = printint( buffer->Base() + buffer->Size(), buffer->Capacity() - buffer->Size(), val );
|
||||
buffer->size += len;
|
||||
}
|
||||
|
||||
class wjson_table_t;
|
||||
class wjson_array_t;
|
||||
template < bool padding, typename I >
|
||||
static inline void PutHex( CBuffer *buffer, I val )
|
||||
{
|
||||
STATIC_ASSERT( IS_UNSIGNED( I ) );
|
||||
buffer->base.Ensure( buffer->Size() + countdigits<16>( val ) + 1 );
|
||||
int len = printhex< padding >( buffer->Base() + buffer->Size(), buffer->Capacity() - buffer->Size(), val );
|
||||
buffer->size += len;
|
||||
}
|
||||
|
||||
struct jstringbuf_t
|
||||
{
|
||||
CBuffer *m_pBuffer;
|
||||
|
||||
jstringbuf_t( CBuffer *b ) : m_pBuffer(b)
|
||||
{
|
||||
::PutChar( m_pBuffer, '\"' );
|
||||
}
|
||||
|
||||
~jstringbuf_t()
|
||||
{
|
||||
::PutChar( m_pBuffer, '\"' );
|
||||
}
|
||||
|
||||
jstringbuf_t( const jstringbuf_t &src );
|
||||
|
||||
void Seek( int i )
|
||||
{
|
||||
m_pBuffer->size += i;
|
||||
}
|
||||
|
||||
template < int SIZE >
|
||||
void Puts( const char (&str)[SIZE] )
|
||||
{
|
||||
::PutStr( m_pBuffer, str );
|
||||
}
|
||||
|
||||
void Puts( const conststring_t &str )
|
||||
{
|
||||
::PutStr( m_pBuffer, str );
|
||||
}
|
||||
|
||||
void Puts( const string_t &str, bool quote = false )
|
||||
{
|
||||
::PutStr( m_pBuffer, str, quote );
|
||||
}
|
||||
|
||||
#ifdef SQUNICODE
|
||||
void Puts( const sqstring_t &str, bool quote = false )
|
||||
{
|
||||
::PutStr( m_pBuffer, str, quote );
|
||||
}
|
||||
#endif
|
||||
|
||||
void Put( char c )
|
||||
{
|
||||
::PutChar( m_pBuffer, c );
|
||||
}
|
||||
|
||||
template < typename I >
|
||||
void PutInt( I val )
|
||||
{
|
||||
::PutInt( m_pBuffer, val );
|
||||
}
|
||||
|
||||
template < typename I >
|
||||
void PutHex( I val, bool padding = true )
|
||||
{
|
||||
if ( padding )
|
||||
{
|
||||
::PutHex< true >( m_pBuffer, val );
|
||||
}
|
||||
else
|
||||
{
|
||||
::PutHex< false >( m_pBuffer, val );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class wjson_t
|
||||
{
|
||||
@ -542,7 +620,7 @@ public:
|
||||
PutChar( m_pBuffer, ',' );
|
||||
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
PutStrL( m_pBuffer, key );
|
||||
PutStr( m_pBuffer, key );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
PutChar( m_pBuffer, ':' );
|
||||
}
|
||||
@ -556,26 +634,53 @@ public:
|
||||
void SetNull( const string_t &key )
|
||||
{
|
||||
PutKey( key );
|
||||
PutStrL( m_pBuffer, "null" );
|
||||
PutStr( m_pBuffer, "null" );
|
||||
}
|
||||
|
||||
void SetBool( const string_t &key, bool val )
|
||||
{
|
||||
PutKey( key );
|
||||
PutStrL( m_pBuffer, val ? string_t("true") : string_t("false") );
|
||||
PutStr( m_pBuffer, val ? string_t("true") : string_t("false") );
|
||||
}
|
||||
|
||||
jstringbuf_t SetStringAsBuf( const string_t &key )
|
||||
{
|
||||
PutKey( key );
|
||||
return { m_pBuffer };
|
||||
}
|
||||
|
||||
template < int SIZE >
|
||||
void SetString( const string_t &key, const char (&val)[SIZE] )
|
||||
{
|
||||
PutKey( key );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
PutStr( m_pBuffer, val );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
}
|
||||
|
||||
void SetString( const string_t &key, const conststring_t &val )
|
||||
{
|
||||
PutKey( key );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
PutStr( m_pBuffer, val );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
}
|
||||
|
||||
void SetString( const string_t &key, const string_t &val, bool quote = false )
|
||||
{
|
||||
PutKey( key );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
PutStr( m_pBuffer, val, quote );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
}
|
||||
|
||||
#ifdef SQUNICODE
|
||||
void SetString( const string_t &key, const sqstring_t &val, bool quote = false )
|
||||
{
|
||||
PutKey( key );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
PutStr( m_pBuffer, val, quote );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -593,7 +698,14 @@ public:
|
||||
PutKey( key );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
PutChar( m_pBuffer, '[' );
|
||||
PutInt( m_pBuffer, val, hex );
|
||||
if ( !hex )
|
||||
{
|
||||
PutInt( m_pBuffer, val );
|
||||
}
|
||||
else
|
||||
{
|
||||
PutHex< false >( m_pBuffer, cast_unsigned( I, val ) );
|
||||
}
|
||||
PutChar( m_pBuffer, ']' );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
}
|
||||
@ -637,7 +749,7 @@ public:
|
||||
|
||||
wjson_array_t( const wjson_array_t &src );
|
||||
|
||||
int size()
|
||||
int Size()
|
||||
{
|
||||
return m_nElementCount;
|
||||
}
|
||||
@ -665,7 +777,7 @@ public:
|
||||
PutChar( m_pBuffer, ',' );
|
||||
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
PutStrL( m_pBuffer, val );
|
||||
PutStr( m_pBuffer, val );
|
||||
PutChar( m_pBuffer, '\"' );
|
||||
}
|
||||
};
|
||||
@ -676,7 +788,7 @@ private:
|
||||
char *m_cur;
|
||||
char *m_end;
|
||||
char *m_start;
|
||||
CScratch< JSON_SCRATCH_CHUNK_SIZE > *m_Allocator;
|
||||
CScratch< true, JSON_SCRATCH_CHUNK_SIZE > *m_Allocator;
|
||||
char *m_error;
|
||||
|
||||
enum
|
||||
@ -693,7 +805,7 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
JSONParser( CScratch< JSON_SCRATCH_CHUNK_SIZE > *allocator, char *ptr, int len, json_table_t *pTable ) :
|
||||
JSONParser( CScratch< true, JSON_SCRATCH_CHUNK_SIZE > *allocator, char *ptr, int len, json_table_t *pTable ) :
|
||||
m_cur( ptr ),
|
||||
m_end( ptr + len + 1 ),
|
||||
m_start( ptr ),
|
||||
@ -710,7 +822,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
SetError( "expected '%c', got '0x%02x' @ %i", '{', Char(type), Index() );
|
||||
SetError( "expected '%c', got %s @ %i", '{', Char(type), Index() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -725,12 +837,30 @@ private:
|
||||
return m_cur - m_start;
|
||||
}
|
||||
|
||||
unsigned char Char( char token )
|
||||
char *Char( char token )
|
||||
{
|
||||
if ( token != Token_Error )
|
||||
return (unsigned char)token;
|
||||
char *buf;
|
||||
|
||||
return *(unsigned char*)m_cur;
|
||||
if ( token == Token_Error )
|
||||
token = *m_cur;
|
||||
|
||||
if ( IN_RANGE_CHAR( token, 0x20, 0x7E ) )
|
||||
{
|
||||
buf = m_Allocator->Alloc(4);
|
||||
buf[0] = '\'';
|
||||
buf[1] = token;
|
||||
buf[2] = '\'';
|
||||
buf[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = m_Allocator->Alloc(5);
|
||||
int i = printhex< true, true, false >( buf, 5, (unsigned char)token );
|
||||
Assert( i == 4 );
|
||||
buf[i] = 0;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void SetError( const char *fmt, ... )
|
||||
@ -752,6 +882,24 @@ private:
|
||||
m_error[len] = 0;
|
||||
}
|
||||
|
||||
bool IsValue( char token )
|
||||
{
|
||||
switch ( token )
|
||||
{
|
||||
case Token_String:
|
||||
case Token_Integer:
|
||||
case Token_Float:
|
||||
case Token_False:
|
||||
case Token_True:
|
||||
case Token_Null:
|
||||
case Token_Table:
|
||||
case Token_Array:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
char NextToken( string_t &token )
|
||||
{
|
||||
while ( m_cur < m_end )
|
||||
@ -776,37 +924,37 @@ private:
|
||||
return *m_cur++;
|
||||
|
||||
case 't':
|
||||
if ( m_cur + 4 >= m_end ||
|
||||
m_cur[1] != 'r' || m_cur[2] != 'u' || m_cur[3] != 'e' )
|
||||
if ( m_cur + 4 < m_end &&
|
||||
m_cur[1] == 'r' && m_cur[2] == 'u' && m_cur[3] == 'e' )
|
||||
{
|
||||
SetError( "expected %s @ %i", "\"true\"", Index() );
|
||||
return Token_Error;
|
||||
m_cur += 4;
|
||||
return Token_True;
|
||||
}
|
||||
|
||||
m_cur += 4;
|
||||
return Token_True;
|
||||
SetError( "expected %s @ %i", "\"true\"", Index() );
|
||||
return Token_Error;
|
||||
|
||||
case 'f':
|
||||
if ( m_cur + 5 >= m_end ||
|
||||
m_cur[1] != 'a' || m_cur[2] != 'l' || m_cur[3] != 's' || m_cur[4] != 'e' )
|
||||
if ( m_cur + 5 < m_end &&
|
||||
m_cur[1] == 'a' && m_cur[2] == 'l' && m_cur[3] == 's' && m_cur[4] == 'e' )
|
||||
{
|
||||
SetError( "expected %s @ %i", "\"false\"", Index() );
|
||||
return Token_Error;
|
||||
m_cur += 5;
|
||||
return Token_False;
|
||||
}
|
||||
|
||||
m_cur += 5;
|
||||
return Token_False;
|
||||
SetError( "expected %s @ %i", "\"false\"", Index() );
|
||||
return Token_Error;
|
||||
|
||||
case 'n':
|
||||
if ( m_cur + 4 >= m_end ||
|
||||
m_cur[1] != 'u' || m_cur[2] != 'l' || m_cur[3] != 'l' )
|
||||
if ( m_cur + 4 < m_end &&
|
||||
m_cur[1] == 'u' && m_cur[2] == 'l' && m_cur[3] == 'l' )
|
||||
{
|
||||
SetError( "expected %s @ %i", "\"null\"", Index() );
|
||||
return Token_Error;
|
||||
m_cur += 4;
|
||||
return Token_Null;
|
||||
}
|
||||
|
||||
m_cur += 4;
|
||||
return Token_Null;
|
||||
SetError( "expected %s @ %i", "\"null\"", Index() );
|
||||
return Token_Error;
|
||||
|
||||
default:
|
||||
return Token_Error;
|
||||
@ -829,12 +977,10 @@ private:
|
||||
return Token_Error;
|
||||
}
|
||||
|
||||
// end
|
||||
if ( *m_cur == '\"' )
|
||||
{
|
||||
*m_cur = 0;
|
||||
token.Assign( pStart, m_cur - pStart );
|
||||
m_cur++;
|
||||
*m_cur++ = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -857,7 +1003,7 @@ private:
|
||||
// Defer unescape until the end of the string is found
|
||||
switch ( *m_cur )
|
||||
{
|
||||
case '\"': case '\\': case '/':
|
||||
case '\\': case '\"': case '/':
|
||||
case 'b': case 'f':
|
||||
case 'n': case 'r': case 't':
|
||||
m_cur++;
|
||||
@ -876,7 +1022,7 @@ private:
|
||||
break;
|
||||
|
||||
default:
|
||||
SetError( "invalid escape char '0x%02x' @ %i", *(unsigned char*)m_cur, Index() );
|
||||
SetError( "invalid escape char 0x%02x @ %i", *(unsigned char*)m_cur, Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
}
|
||||
@ -895,6 +1041,7 @@ private:
|
||||
}
|
||||
|
||||
#define _shift( bytesWritten, bytesRead ) \
|
||||
Assert( (bytesWritten) < (bytesRead) ); \
|
||||
memmove( cur + (bytesWritten), cur + (bytesRead), end - ( cur + (bytesRead) ) ); \
|
||||
cur += (bytesWritten); \
|
||||
end -= (bytesRead) - (bytesWritten);
|
||||
@ -903,22 +1050,21 @@ private:
|
||||
{
|
||||
case '\\':
|
||||
shift_one:
|
||||
_shift( 0, 1 );
|
||||
cur++;
|
||||
_shift( 1, 2 );
|
||||
break;
|
||||
case '\"': goto shift_one;
|
||||
case '/': goto shift_one;
|
||||
case 'b': cur[1] = '\b'; goto shift_one;
|
||||
case 'f': cur[1] = '\f'; goto shift_one;
|
||||
case 'n': cur[1] = '\n'; goto shift_one;
|
||||
case 'r': cur[1] = '\r'; goto shift_one;
|
||||
case 't': cur[1] = '\t'; goto shift_one;
|
||||
case '\"': cur[0] = '\"'; goto shift_one;
|
||||
case '/': cur[0] = '/'; goto shift_one;
|
||||
case 'b': cur[0] = '\b'; goto shift_one;
|
||||
case 'f': cur[0] = '\f'; goto shift_one;
|
||||
case 'n': cur[0] = '\n'; goto shift_one;
|
||||
case 'r': cur[0] = '\r'; goto shift_one;
|
||||
case 't': cur[0] = '\t'; goto shift_one;
|
||||
case 'u':
|
||||
{
|
||||
unsigned int val;
|
||||
Verify( atox( { cur + 2, 4 }, &val ) );
|
||||
|
||||
if ( val <= 0xFF )
|
||||
if ( val <= 0x7F )
|
||||
{
|
||||
cur[0] = (char)val;
|
||||
|
||||
@ -993,7 +1139,7 @@ shift_one:
|
||||
if ( m_cur >= m_end )
|
||||
goto err_eof;
|
||||
}
|
||||
else if ( IN_RANGE_CHAR( *(unsigned char*)m_cur, '1', '9' ) )
|
||||
else if ( IN_RANGE_CHAR( *m_cur, '1', '9' ) )
|
||||
{
|
||||
do
|
||||
{
|
||||
@ -1001,11 +1147,11 @@ shift_one:
|
||||
if ( m_cur >= m_end )
|
||||
goto err_eof;
|
||||
}
|
||||
while ( IN_RANGE_CHAR( *(unsigned char*)m_cur, '0', '9' ) );
|
||||
while ( IN_RANGE_CHAR( *m_cur, '0', '9' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetError( "unexpected char '0x%02x' in number @ %i", *(unsigned char*)m_cur, Index() );
|
||||
SetError( "unexpected char 0x%02x in number @ %i", *(unsigned char*)m_cur, Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
|
||||
@ -1016,7 +1162,7 @@ shift_one:
|
||||
type = Token_Float;
|
||||
m_cur++;
|
||||
|
||||
while ( m_cur < m_end && IN_RANGE_CHAR( *(unsigned char*)m_cur, '0', '9' ) )
|
||||
while ( m_cur < m_end && IN_RANGE_CHAR( *m_cur, '0', '9' ) )
|
||||
m_cur++;
|
||||
|
||||
if ( m_cur >= m_end )
|
||||
@ -1039,7 +1185,7 @@ shift_one:
|
||||
goto err_eof;
|
||||
}
|
||||
|
||||
while ( m_cur < m_end && IN_RANGE_CHAR( *(unsigned char*)m_cur, '0', '9' ) )
|
||||
while ( m_cur < m_end && IN_RANGE_CHAR( *m_cur, '0', '9' ) )
|
||||
m_cur++;
|
||||
}
|
||||
|
||||
@ -1062,7 +1208,7 @@ err_eof:
|
||||
{
|
||||
if ( type != Token_String )
|
||||
{
|
||||
SetError( "expected %s, got '0x%02x' @ %i", "string", Char(type), Index() );
|
||||
SetError( "expected '%c', got %s @ %i", '\"', Char(type), Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
|
||||
@ -1070,7 +1216,7 @@ err_eof:
|
||||
|
||||
if ( type != ':' )
|
||||
{
|
||||
SetError( "expected '%c', got '0x%02x' @ %i", ':', Char(type), Index() );
|
||||
SetError( "expected '%c', got %s @ %i", ':', Char(type), Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
|
||||
@ -1083,9 +1229,9 @@ err_eof:
|
||||
type = NextToken( token );
|
||||
type = ParseValue( type, token, &kv->val );
|
||||
|
||||
if ( type == Token_Error )
|
||||
if ( !IsValue( type ) )
|
||||
{
|
||||
SetError( "invalid token '0x%02x' @ %i", Char(type), Index() );
|
||||
SetError( "invalid token %s @ %i", Char(type), Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
|
||||
@ -1101,7 +1247,7 @@ err_eof:
|
||||
}
|
||||
else
|
||||
{
|
||||
SetError( "expected '%c', got '0x%02x' @ %i", '}', Char(type), Index() );
|
||||
SetError( "expected '%c', got %s @ %i", '}', Char(type), Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
}
|
||||
@ -1116,9 +1262,9 @@ err_eof:
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ( type == Token_Error )
|
||||
if ( !IsValue( type ) )
|
||||
{
|
||||
SetError( "expected '%c', got '0x%02x' @ %i", ']', Char(type), Index() );
|
||||
SetError( "expected '%c', got %s @ %i", ']', Char(type), Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
|
||||
@ -1127,7 +1273,7 @@ err_eof:
|
||||
|
||||
if ( type == Token_Error )
|
||||
{
|
||||
SetError( "invalid token '0x%02x' @ %i", Char(type), Index() );
|
||||
SetError( "invalid token %s @ %i", Char(type), Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
|
||||
@ -1143,7 +1289,7 @@ err_eof:
|
||||
}
|
||||
else
|
||||
{
|
||||
SetError( "expected '%c', got '0x%02x' @ %i", ']', Char(type), Index() );
|
||||
SetError( "expected '%c', got %s @ %i", ']', Char(type), Index() );
|
||||
return Token_Error;
|
||||
}
|
||||
}
|
||||
@ -1154,7 +1300,7 @@ err_eof:
|
||||
switch ( type )
|
||||
{
|
||||
case Token_Integer:
|
||||
if ( token.len > FMT_INT_LEN )
|
||||
if ( token.len > FMT_UINT32_LEN + 1 )
|
||||
{
|
||||
SetError( "invalid integer literal @ %i", Index() );
|
||||
return Token_Error;
|
||||
@ -1192,7 +1338,7 @@ err_eof:
|
||||
value->type = JSON_NULL;
|
||||
return type;
|
||||
default:
|
||||
return type;
|
||||
return Token_Error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -602,6 +602,9 @@ public:
|
||||
|
||||
bool Listen()
|
||||
{
|
||||
if ( m_ServerSocket == INVALID_SOCKET )
|
||||
return false;
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
@ -839,7 +842,7 @@ public:
|
||||
m_pRecvBufPtr( m_pRecvBuf ),
|
||||
m_bWSAInit( false )
|
||||
{
|
||||
Assert( sizeof(m_pRecvBuf) <= ( 1 << ( sizeof(CMessagePool::message_t::len) * 8 ) ) );
|
||||
STATIC_ASSERT( sizeof(m_pRecvBuf) <= ( 1 << ( sizeof(CMessagePool::message_t::len) * 8 ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12,10 +12,10 @@
|
||||
|
||||
inline void DAP_Serialise( CBuffer *buffer )
|
||||
{
|
||||
Assert( buffer->size() > 0 && buffer->size() < INT_MAX );
|
||||
Assert( buffer->Size() > 0 && buffer->Size() < INT_MAX );
|
||||
|
||||
char *mem = buffer->base();
|
||||
int contentSize = buffer->size() - DAP_HEADER_MAXSIZE;
|
||||
char *mem = buffer->Base();
|
||||
int contentSize = buffer->Size() - DAP_HEADER_MAXSIZE;
|
||||
int digits = countdigits( contentSize );
|
||||
int padding = FMT_UINT32_LEN - digits;
|
||||
|
||||
@ -31,8 +31,8 @@ inline void DAP_Serialise( CBuffer *buffer )
|
||||
// add padding in the end to match
|
||||
padding--;
|
||||
digits++;
|
||||
buffer->_base.Ensure( buffer->size() + 1 );
|
||||
mem[buffer->_size++] = ' ';
|
||||
buffer->base.Ensure( buffer->Size() + 1 );
|
||||
mem[buffer->size++] = ' ';
|
||||
}
|
||||
|
||||
memcpy( mem, DAP_HEADER_CONTENTLENGTH ": ", STRLEN(DAP_HEADER_CONTENTLENGTH ": ") );
|
||||
@ -53,10 +53,10 @@ inline void DAP_Serialise( CBuffer *buffer )
|
||||
|
||||
inline void DAP_Free( CBuffer *buffer )
|
||||
{
|
||||
buffer->_size = 0;
|
||||
buffer->size = 0;
|
||||
}
|
||||
|
||||
static inline void ParseFieldName( const char *pMemEnd, char *pStart, int *len )
|
||||
static inline int ParseFieldName( const char *pMemEnd, char *pStart )
|
||||
{
|
||||
char *c = pStart;
|
||||
|
||||
@ -65,56 +65,39 @@ static inline void ParseFieldName( const char *pMemEnd, char *pStart, int *len )
|
||||
if ( IN_RANGE_CHAR( ((unsigned char*)c)[0], 0x20, 0x7E ) )
|
||||
{
|
||||
if ( c + 1 >= pMemEnd )
|
||||
{
|
||||
*len = -1;
|
||||
return;
|
||||
}
|
||||
return -1;
|
||||
|
||||
if ( c[0] == ':' )
|
||||
{
|
||||
if ( c[1] == ' ' )
|
||||
{
|
||||
*len = c - pStart;
|
||||
return;
|
||||
}
|
||||
return c - pStart;
|
||||
|
||||
*len = 0;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*len = 0;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ParseFieldValue( const char *pMemEnd, char *pStart, int *len )
|
||||
static inline int ParseFieldValue( const char *pMemEnd, char *pStart )
|
||||
{
|
||||
char *c = pStart;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ( c + 1 >= pMemEnd )
|
||||
{
|
||||
*len = -1;
|
||||
return;
|
||||
}
|
||||
return -1;
|
||||
|
||||
if ( c[0] == '\n' )
|
||||
{
|
||||
*len = 0;
|
||||
return;
|
||||
}
|
||||
return 0;
|
||||
|
||||
if ( c[0] == '\r' && c[1] == '\n' )
|
||||
{
|
||||
*len = c - pStart;
|
||||
return;
|
||||
}
|
||||
return c - pStart;
|
||||
|
||||
c++;
|
||||
}
|
||||
@ -128,8 +111,7 @@ inline bool DAP_ReadHeader( char **ppMsg, int *pLength )
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int len;
|
||||
ParseFieldName( pMemEnd, pMsg, &len );
|
||||
int len = ParseFieldName( pMemEnd, pMsg );
|
||||
|
||||
if ( len == 0 )
|
||||
goto invalid;
|
||||
@ -151,7 +133,7 @@ inline bool DAP_ReadHeader( char **ppMsg, int *pLength )
|
||||
if ( pMsg >= pMemEnd )
|
||||
return false;
|
||||
|
||||
if ( IN_RANGE_CHAR( *(unsigned char*)pMsg, '0', '9' ) )
|
||||
if ( IN_RANGE_CHAR( *pMsg, '0', '9' ) )
|
||||
{
|
||||
nContentLength = nContentLength * 10 + *pMsg - '0';
|
||||
pMsg++;
|
||||
@ -187,7 +169,7 @@ inline bool DAP_ReadHeader( char **ppMsg, int *pLength )
|
||||
ignore:
|
||||
pMsg += len + 2;
|
||||
|
||||
ParseFieldValue( pMemEnd, pMsg, &len );
|
||||
len = ParseFieldValue( pMemEnd, pMsg );
|
||||
|
||||
if ( len == 0 )
|
||||
goto invalid;
|
||||
@ -216,13 +198,13 @@ invalid:
|
||||
}
|
||||
|
||||
#ifdef SQDBG_VALIDATE_SENT_MSG
|
||||
inline void DAP_Test( CScratch< JSON_SCRATCH_CHUNK_SIZE > *scratch, CBuffer *buffer )
|
||||
inline void DAP_Test( CScratch< true, JSON_SCRATCH_CHUNK_SIZE > *scratch, CBuffer *buffer )
|
||||
{
|
||||
char *pMsg = buffer->base();
|
||||
int nLength = buffer->size();
|
||||
char *pMsg = buffer->Base();
|
||||
int nLength = buffer->Size();
|
||||
|
||||
bool res = DAP_ReadHeader( &pMsg, &nLength );
|
||||
Assert( res && nLength < buffer->size() );
|
||||
Assert( res && nLength < buffer->Size() );
|
||||
|
||||
if ( res )
|
||||
{
|
||||
@ -238,7 +220,7 @@ inline void DAP_Test( CScratch< JSON_SCRATCH_CHUNK_SIZE > *scratch, CBuffer *buf
|
||||
|
||||
#define _DAP_INIT_BUF( _buf ) \
|
||||
CBufTmpCache _bufcache( (_buf) ); \
|
||||
(_buf)->_size = DAP_HEADER_MAXSIZE; \
|
||||
(_buf)->size = DAP_HEADER_MAXSIZE; \
|
||||
(void)0
|
||||
|
||||
#define DAP_START_REQUEST( _seq, _cmd ) \
|
||||
@ -262,10 +244,10 @@ if ( IsClientConnected() ) \
|
||||
packet.SetBool( "success", _suc );
|
||||
|
||||
#define DAP_START_RESPONSE( _seq, _cmd ) \
|
||||
_DAP_START_RESPONSE( _seq, _cmd, true );
|
||||
_DAP_START_RESPONSE( _seq, _cmd, true )
|
||||
|
||||
#define DAP_ERROR_RESPONSE( _seq, _cmd ) \
|
||||
_DAP_START_RESPONSE( _seq, _cmd, false );
|
||||
_DAP_START_RESPONSE( _seq, _cmd, false )
|
||||
|
||||
#define DAP_ERROR_BODY( _id, _fmt ) \
|
||||
wjson_table_t body = packet.SetTable( "body" ); \
|
||||
@ -292,7 +274,7 @@ if ( IsClientConnected() ) \
|
||||
} \
|
||||
\
|
||||
DAP_Serialise( &m_SendBuf ); \
|
||||
Send( m_SendBuf.base(), m_SendBuf.size() ); \
|
||||
Send( m_SendBuf.Base(), m_SendBuf.Size() ); \
|
||||
DAP_Test( &m_ReadBuf, &m_SendBuf ); \
|
||||
DAP_Free( &m_SendBuf ); \
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -75,13 +75,35 @@ bool atox( string_t str, I *out );
|
||||
template < typename I >
|
||||
bool atoo( string_t str, I *out );
|
||||
|
||||
template < typename I >
|
||||
struct _as_unsigned { typedef I T; };
|
||||
|
||||
#ifdef SQUNICODE
|
||||
void CopyString( const string_t &src, sqstring_t *dst );
|
||||
void CopyString( const sqstring_t &src, string_t *dst );
|
||||
template <>
|
||||
struct _as_unsigned< int > { typedef unsigned int T; };
|
||||
|
||||
#ifdef _SQ64
|
||||
template <>
|
||||
struct _as_unsigned< SQInteger > { typedef SQUnsignedInteger T; };
|
||||
#endif
|
||||
template < typename T > void CopyString( const T &src, T *dst );
|
||||
template < typename T > void FreeString( T *dst );
|
||||
|
||||
#define as_unsigned_type( I ) typename _as_unsigned<I>::T
|
||||
#define cast_unsigned( I, v ) (as_unsigned_type(I)(v))
|
||||
#define IS_UNSIGNED( I ) ((I)0 < (I)-1)
|
||||
|
||||
|
||||
#define _isdigit( c ) \
|
||||
IN_RANGE_CHAR( c, '0', '9' )
|
||||
|
||||
#define _isxdigit( c ) \
|
||||
( IN_RANGE_CHAR( c, '0', '9' ) || \
|
||||
IN_RANGE_CHAR( c, 'A', 'F' ) || \
|
||||
IN_RANGE_CHAR( c, 'a', 'f' ) )
|
||||
|
||||
#define _isalpha( c ) \
|
||||
( IN_RANGE_CHAR( c, 'A', 'Z' ) || IN_RANGE_CHAR( c, 'a', 'z' ) )
|
||||
|
||||
#define _isalnum( c ) \
|
||||
( _isalpha(c) || _isdigit(c) )
|
||||
|
||||
#define IN_RANGE(c, min, max) \
|
||||
((uint32_t)((uint32_t)(c) - (uint32_t)(min)) <= (uint32_t)((max)-(min)))
|
||||
@ -249,51 +271,21 @@ struct string_t
|
||||
}
|
||||
#endif
|
||||
|
||||
template < int size >
|
||||
string_t( const char (&src)[size] ) :
|
||||
template < int SIZE >
|
||||
string_t( const char (&src)[SIZE] ) :
|
||||
ptr((char*)src),
|
||||
len(size-1)
|
||||
len(SIZE-1)
|
||||
{
|
||||
// input wasn't a string literal,
|
||||
// call ( src, size ) constructor instead
|
||||
Assert( strlen(src) == len );
|
||||
}
|
||||
|
||||
void Strip()
|
||||
template < int SIZE >
|
||||
bool StartsWith( const char (&other)[SIZE] ) const
|
||||
{
|
||||
char *end = ptr + len;
|
||||
|
||||
for ( char *c = ptr; c < end; c++ )
|
||||
{
|
||||
if ( *c == ' ' || *c == '\t' || *c == '\n' )
|
||||
{
|
||||
ptr++;
|
||||
len--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( char *c = end - 1; c >= ptr; c-- )
|
||||
{
|
||||
if ( *c == ' ' || *c == '\t' || *c == '\n' )
|
||||
{
|
||||
len--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template < int size >
|
||||
bool StartsWith( const char (&other)[size] ) const
|
||||
{
|
||||
if ( size-1 <= len && *ptr == *other )
|
||||
return !memcmp( ptr, other, size-1 );
|
||||
if ( SIZE-1 <= len && *ptr == *other )
|
||||
return !memcmp( ptr, other, SIZE-1 );
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -306,11 +298,11 @@ struct string_t
|
||||
return false;
|
||||
}
|
||||
|
||||
template < int size >
|
||||
bool IsEqualTo( const char (&other)[size] ) const
|
||||
template < int SIZE >
|
||||
bool IsEqualTo( const char (&other)[SIZE] ) const
|
||||
{
|
||||
if ( size-1 == len && *ptr == *other )
|
||||
return !memcmp( ptr, other, size-1 );
|
||||
if ( SIZE-1 == len && *ptr == *other )
|
||||
return !memcmp( ptr, other, SIZE-1 );
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -333,6 +325,14 @@ struct string_t
|
||||
|
||||
#ifdef SQUNICODE
|
||||
bool IsEqualTo( const sqstring_t &other ) const;
|
||||
#else
|
||||
bool IsEqualTo( const SQString *other ) const
|
||||
{
|
||||
if ( (SQUnsignedInteger)len == (SQUnsignedInteger)other->_len && *ptr == *other->_val )
|
||||
return !memcmp( ptr, other->_val, sq_rsl(len) );
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsEmpty() const
|
||||
@ -345,11 +345,11 @@ struct string_t
|
||||
return ( memchr( ptr, ch, len ) != NULL );
|
||||
}
|
||||
|
||||
template < int size >
|
||||
void Assign( const char (&src)[size] )
|
||||
template < int SIZE >
|
||||
void Assign( const char (&src)[SIZE] )
|
||||
{
|
||||
ptr = (char*)src;
|
||||
len = size - 1;
|
||||
len = SIZE - 1;
|
||||
Assert( strlen(src) == len );
|
||||
}
|
||||
|
||||
@ -373,6 +373,14 @@ private:
|
||||
string_t &operator=( const char *src );
|
||||
};
|
||||
|
||||
struct conststring_t : string_t
|
||||
{
|
||||
template < int SIZE >
|
||||
conststring_t( const char (&src)[SIZE] ) : string_t(src) {}
|
||||
|
||||
conststring_t() {}
|
||||
};
|
||||
|
||||
#ifdef SQUNICODE
|
||||
struct sqstring_t
|
||||
{
|
||||
@ -393,10 +401,10 @@ struct sqstring_t
|
||||
{
|
||||
}
|
||||
|
||||
template < int size >
|
||||
sqstring_t( const SQChar (&src)[size] ) :
|
||||
template < int SIZE >
|
||||
sqstring_t( const SQChar (&src)[SIZE] ) :
|
||||
ptr((SQChar*)src),
|
||||
len(size-1)
|
||||
len(SIZE-1)
|
||||
{
|
||||
Assert( scstrlen(src) == len );
|
||||
}
|
||||
@ -410,9 +418,10 @@ struct sqstring_t
|
||||
unsigned int i = 0;
|
||||
do
|
||||
{
|
||||
if ( ptr[i] > 0x7E || other.ptr[i] != (char)ptr[i] )
|
||||
if ( (SQUnsignedChar)ptr[i] > 0x7E || other.ptr[i] != (char)ptr[i] )
|
||||
{
|
||||
AssertMsg( ptr[i] <= 0x7E, "not implemented" );
|
||||
// > 0x7E can be reached through completions request
|
||||
// unicode identifiers are not supported, ignore them
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -434,7 +443,7 @@ struct sqstring_t
|
||||
|
||||
bool IsEqualTo( const SQString *other ) const
|
||||
{
|
||||
if ( len == other->_len && *ptr == *other->_val )
|
||||
if ( (SQUnsignedInteger)len == (SQUnsignedInteger)other->_len && *ptr == *other->_val )
|
||||
return !memcmp( ptr, other->_val, sq_rsl(len) );
|
||||
|
||||
return false;
|
||||
@ -445,11 +454,11 @@ struct sqstring_t
|
||||
return !len;
|
||||
}
|
||||
|
||||
template < int size >
|
||||
void Assign( const SQChar (&src)[size] )
|
||||
template < int SIZE >
|
||||
void Assign( const SQChar (&src)[SIZE] )
|
||||
{
|
||||
ptr = (SQChar*)src;
|
||||
len = size - 1;
|
||||
len = SIZE - 1;
|
||||
Assert( scstrlen(src) == len );
|
||||
}
|
||||
|
||||
@ -471,12 +480,12 @@ struct stringbufbase_t
|
||||
{
|
||||
char *ptr;
|
||||
unsigned int len;
|
||||
const int size;
|
||||
const unsigned int size;
|
||||
|
||||
stringbufbase_t( char *src, unsigned int size ) :
|
||||
stringbufbase_t( char *src, unsigned int nSize ) :
|
||||
ptr(src),
|
||||
len(0),
|
||||
size(size)
|
||||
size(nSize)
|
||||
{
|
||||
}
|
||||
|
||||
@ -563,6 +572,8 @@ struct stringbufbase_t
|
||||
template < typename I >
|
||||
void PutHex( I value, bool padding = true )
|
||||
{
|
||||
STATIC_ASSERT( IS_UNSIGNED( I ) );
|
||||
|
||||
int space = BytesLeft();
|
||||
|
||||
if ( space < 3 )
|
||||
@ -597,9 +608,9 @@ bool string_t::IsEqualTo( const sqstring_t &other ) const
|
||||
{
|
||||
// Used for comparing against locals and outers,
|
||||
// implement unicode conversion if locals can have unicode characters
|
||||
if ( other.ptr[i] > 0x7E || (char)other.ptr[i] != ptr[i] )
|
||||
if ( (SQUnsignedChar)other.ptr[i] > 0x7E || (char)other.ptr[i] != ptr[i] )
|
||||
{
|
||||
AssertMsg( other.ptr[i] <= 0x7E, "not implemented" );
|
||||
AssertMsg( (SQUnsignedChar)other.ptr[i] <= 0x7E, "not implemented" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -622,20 +633,6 @@ struct stringbuf_t : stringbufbase_t
|
||||
}
|
||||
};
|
||||
|
||||
#define _isdigit( c ) \
|
||||
IN_RANGE_CHAR(c, '0', '9')
|
||||
|
||||
#define _isxdigit( c ) \
|
||||
( IN_RANGE_CHAR(c, '0', '9') || \
|
||||
IN_RANGE_CHAR(c, 'A', 'F') || \
|
||||
IN_RANGE_CHAR(c, 'a', 'f') )
|
||||
|
||||
#define _isalpha( c ) \
|
||||
( IN_RANGE_CHAR(c, 'A', 'Z') || IN_RANGE_CHAR(c, 'a', 'z') )
|
||||
|
||||
#define _isalnum( c ) \
|
||||
( _isalpha(c) || _isdigit(c) )
|
||||
|
||||
template < int BASE = 10, typename I >
|
||||
inline int countdigits( I input )
|
||||
{
|
||||
@ -696,7 +693,7 @@ inline int printint( C *buf, int size, I value )
|
||||
value /= 10;
|
||||
buf[i--] = !neg ? ( '0' + c ) : ( '0' - c );
|
||||
}
|
||||
while ( value && i >= 0 );
|
||||
while ( value );
|
||||
|
||||
return len;
|
||||
}
|
||||
@ -704,10 +701,11 @@ inline int printint( C *buf, int size, I value )
|
||||
template < bool padding, bool prefix, bool uppercase, typename C, typename I >
|
||||
inline int printhex( C *buf, int size, I value )
|
||||
{
|
||||
STATIC_ASSERT( IS_UNSIGNED( as_unsigned_type( I ) ) );
|
||||
Assert( buf );
|
||||
Assert( size > 0 );
|
||||
|
||||
int len = ( prefix ? 2 : 0 ) + ( padding ? sizeof(I) * 2 : countdigits<16>( value ) );
|
||||
int len = ( prefix ? 2 : 0 ) + ( padding ? sizeof(I) * 2 : countdigits<16>( cast_unsigned( I, value ) ) );
|
||||
|
||||
if ( len > size )
|
||||
len = size;
|
||||
@ -716,11 +714,11 @@ inline int printhex( C *buf, int size, I value )
|
||||
|
||||
do
|
||||
{
|
||||
C c = value & 0xf;
|
||||
value >>= 4;
|
||||
C c = cast_unsigned( I, value ) & 0xf;
|
||||
*(as_unsigned_type(I)*)&value >>= 4;
|
||||
buf[i--] = c + ( ( c < 10 ) ? '0' : ( ( uppercase ? 'A' : 'a' ) - 10 ) );
|
||||
}
|
||||
while ( value && i >= 0 );
|
||||
while ( value );
|
||||
|
||||
if ( padding )
|
||||
{
|
||||
@ -746,6 +744,7 @@ inline int printhex( C *buf, int size, I value )
|
||||
template < typename C, typename I >
|
||||
inline int printoct( C *buf, int size, I value )
|
||||
{
|
||||
STATIC_ASSERT( IS_UNSIGNED( I ) );
|
||||
Assert( buf );
|
||||
Assert( size > 0 );
|
||||
|
||||
@ -762,7 +761,7 @@ inline int printoct( C *buf, int size, I value )
|
||||
value >>= 3;
|
||||
buf[i--] = '0' + c;
|
||||
}
|
||||
while ( value && i >= 0 );
|
||||
while ( value );
|
||||
|
||||
if ( i >= 0 )
|
||||
buf[i--] = '0';
|
||||
@ -789,7 +788,7 @@ inline bool atoi( string_t str, I *out )
|
||||
{
|
||||
unsigned char ch = *str.ptr;
|
||||
|
||||
if ( IN_RANGE_CHAR(ch, '0', '9') )
|
||||
if ( IN_RANGE_CHAR( ch, '0', '9' ) )
|
||||
{
|
||||
val *= 10;
|
||||
val += ch - '0';
|
||||
@ -820,17 +819,17 @@ inline bool atox( string_t str, I *out )
|
||||
{
|
||||
unsigned char ch = *str.ptr;
|
||||
|
||||
if ( IN_RANGE_CHAR(ch, '0', '9') )
|
||||
if ( IN_RANGE_CHAR( ch, '0', '9' ) )
|
||||
{
|
||||
val <<= 4;
|
||||
val += ch - '0';
|
||||
}
|
||||
else if ( IN_RANGE_CHAR(ch, 'A', 'F') )
|
||||
else if ( IN_RANGE_CHAR( ch, 'A', 'F' ) )
|
||||
{
|
||||
val <<= 4;
|
||||
val += ch - 'A' + 10;
|
||||
}
|
||||
else if ( IN_RANGE_CHAR(ch, 'a', 'f') )
|
||||
else if ( IN_RANGE_CHAR( ch, 'a', 'f' ) )
|
||||
{
|
||||
val <<= 4;
|
||||
val += ch - 'a' + 10;
|
||||
@ -855,7 +854,7 @@ inline bool atoo( string_t str, I *out )
|
||||
{
|
||||
unsigned char ch = *str.ptr;
|
||||
|
||||
if ( IN_RANGE_CHAR(ch, '0', '7') )
|
||||
if ( IN_RANGE_CHAR( ch, '0', '7' ) )
|
||||
{
|
||||
val <<= 3;
|
||||
val += ch - '0';
|
||||
@ -898,7 +897,7 @@ inline int IsValidUTF8( unsigned char *src, unsigned int srclen )
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if ( IN_RANGE_CHAR(cp, 0xC2, 0xF4) )
|
||||
else if ( IN_RANGE_CHAR( cp, 0xC2, 0xF4 ) )
|
||||
{
|
||||
if ( UTF8_2_LEAD(cp) )
|
||||
{
|
||||
@ -938,7 +937,7 @@ inline int IsValidUTF8( unsigned char *src, unsigned int srclen )
|
||||
|
||||
if ( !UTF8_TRAIL(cp) )
|
||||
{
|
||||
if ( IN_RANGE_CHAR(cp, 0xC2, 0xF4) )
|
||||
if ( IN_RANGE_CHAR( cp, 0xC2, 0xF4 ) )
|
||||
goto check;
|
||||
|
||||
return 0;
|
||||
@ -967,34 +966,8 @@ inline int IsValidUnicode( const SQChar *src, unsigned int srclen )
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if ( cp <= 0xFF )
|
||||
else if ( cp < 0xA0 )
|
||||
{
|
||||
if ( IN_RANGE(cp, 0xC2, 0xF4) )
|
||||
{
|
||||
if ( UTF8_2_LEAD(cp) )
|
||||
{
|
||||
if ( UTF8_2( srclen, cp, src ) )
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else if ( UTF8_3_LEAD(cp) )
|
||||
{
|
||||
if ( UTF8_3( srclen, cp, src ) )
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
else if ( UTF8_4_LEAD(cp) )
|
||||
{
|
||||
if ( UTF8_4( srclen, cp, src ) )
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
// else [0x7F, 0xC2) & (0xF4, 0xFF]
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1041,18 +1014,21 @@ inline unsigned int UTF8ToSQUnicode( SQChar *dst, unsigned int destSize, const c
|
||||
{
|
||||
switch ( ((unsigned char*)src)[1] )
|
||||
{
|
||||
case '\"': cp = '\"'; src++; break;
|
||||
case '\\': src++; break;
|
||||
case '\"': cp = '\"'; src++; break;
|
||||
case '\'': cp = '\''; src++; break;
|
||||
case 'a': cp = '\a'; src++; break;
|
||||
case 'b': cp = '\b'; src++; break;
|
||||
case 'f': cp = '\f'; src++; break;
|
||||
case 'n': cp = '\n'; src++; break;
|
||||
case 'r': cp = '\r'; src++; break;
|
||||
case 't': cp = '\t'; src++; break;
|
||||
case 'v': cp = '\v'; src++; break;
|
||||
case 'x':
|
||||
{
|
||||
if ( src + sizeof(SQChar) * 2 + 1 < end )
|
||||
{
|
||||
Verify( atox( { src + 2, sizeof(SQChar) * 2 }, &cp ) );
|
||||
atox( { src + 2, sizeof(SQChar) * 2 }, &cp );
|
||||
src += sizeof(SQChar) * 2 + 1;
|
||||
}
|
||||
|
||||
@ -1062,7 +1038,7 @@ inline unsigned int UTF8ToSQUnicode( SQChar *dst, unsigned int destSize, const c
|
||||
{
|
||||
if ( src + sizeof(uint16_t) * 2 + 1 < end )
|
||||
{
|
||||
Verify( atox( { src + 2, sizeof(uint16_t) * 2 }, &cp ) );
|
||||
atox( { src + 2, sizeof(uint16_t) * 2 }, &cp );
|
||||
src += sizeof(uint16_t) * 2 + 1;
|
||||
}
|
||||
|
||||
@ -1074,7 +1050,7 @@ inline unsigned int UTF8ToSQUnicode( SQChar *dst, unsigned int destSize, const c
|
||||
|
||||
goto xffff;
|
||||
}
|
||||
else if ( IN_RANGE(cp, 0xC2, 0xF4) )
|
||||
else if ( IN_RANGE( cp, 0xC2, 0xF4 ) )
|
||||
{
|
||||
if ( UTF8_2_LEAD(cp) )
|
||||
{
|
||||
@ -1111,34 +1087,13 @@ inline unsigned int UTF8ToSQUnicode( SQChar *dst, unsigned int destSize, const c
|
||||
goto xffff;
|
||||
}
|
||||
|
||||
xffff:
|
||||
#if WCHAR_SIZE == 4
|
||||
xffff:
|
||||
supplementary:
|
||||
#endif
|
||||
if ( dst )
|
||||
{
|
||||
if ( destSize >= sizeof(SQChar) )
|
||||
{
|
||||
*dst++ = cp;
|
||||
destSize -= sizeof(SQChar);
|
||||
count += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// out of space
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
count += 1;
|
||||
}
|
||||
|
||||
continue;
|
||||
#else // WCHAR_SIZE == 2
|
||||
xffff:
|
||||
if ( dst )
|
||||
{
|
||||
if ( destSize >= sizeof(SQChar) )
|
||||
if ( sizeof(SQChar) <= destSize )
|
||||
{
|
||||
*dst++ = (SQChar)cp;
|
||||
destSize -= sizeof(SQChar);
|
||||
@ -1157,14 +1112,15 @@ xffff:
|
||||
|
||||
continue;
|
||||
|
||||
#if WCHAR_SIZE == 2
|
||||
supplementary:
|
||||
if ( dst )
|
||||
{
|
||||
if ( destSize > sizeof(SQChar) )
|
||||
if ( sizeof(SQChar) * 2 <= destSize )
|
||||
{
|
||||
UTF16_SURROGATE_FROM_UTF32( dst, cp );
|
||||
dst += 2;
|
||||
destSize -= 2 * sizeof(SQChar);
|
||||
destSize -= sizeof(SQChar) * 2;
|
||||
count += 2;
|
||||
}
|
||||
else
|
||||
@ -1241,6 +1197,7 @@ inline unsigned int SQUnicodeToUTF8( char *dst, unsigned int destSize, const SQC
|
||||
|
||||
switch ( cp )
|
||||
{
|
||||
case '\\':
|
||||
case '\"':
|
||||
if ( escape == kUTFEscapeQuoted )
|
||||
{
|
||||
@ -1248,16 +1205,15 @@ inline unsigned int SQUnicodeToUTF8( char *dst, unsigned int destSize, const SQC
|
||||
mbc[bytes++] = '\\';
|
||||
}
|
||||
mbc[bytes++] = '\\';
|
||||
mbc[bytes++] = '\"';
|
||||
mbc[bytes++] = (unsigned char)cp;
|
||||
goto write;
|
||||
case '\\':
|
||||
case '\a':
|
||||
if ( escape == kUTFEscapeJSON )
|
||||
goto doescape;
|
||||
if ( escape == kUTFEscapeQuoted )
|
||||
{
|
||||
mbc[bytes++] = '\\';
|
||||
mbc[bytes++] = '\\';
|
||||
}
|
||||
mbc[bytes++] = '\\';
|
||||
mbc[bytes++] = '\\';
|
||||
mbc[bytes++] = 'a';
|
||||
goto write;
|
||||
case '\b':
|
||||
if ( escape == kUTFEscapeQuoted )
|
||||
@ -1289,15 +1245,25 @@ inline unsigned int SQUnicodeToUTF8( char *dst, unsigned int destSize, const SQC
|
||||
mbc[bytes++] = '\\';
|
||||
mbc[bytes++] = 't';
|
||||
goto write;
|
||||
case '\v':
|
||||
if ( escape == kUTFEscapeJSON )
|
||||
goto doescape;
|
||||
if ( escape == kUTFEscapeQuoted )
|
||||
mbc[bytes++] = '\\';
|
||||
mbc[bytes++] = '\\';
|
||||
mbc[bytes++] = 'v';
|
||||
goto write;
|
||||
|
||||
default:
|
||||
|
||||
if ( !IN_RANGE_CHAR(cp, 0x20, 0x7E) )
|
||||
if ( !IN_RANGE_CHAR( cp, 0x20, 0x7E ) )
|
||||
{
|
||||
// While UTF8 bytes are valid UTF16, converting them will
|
||||
// make distinct SQ strings indistinguishable to the client
|
||||
#ifndef SQDBG_ESCAPE_UTF8_BYTES_IN_UTF16
|
||||
if ( IN_RANGE(cp, 0xC2, 0xF4) )
|
||||
// Convert UTF8 bytes in UTF16 by default with the assumption of
|
||||
// most editors using UTF8 without BOM,
|
||||
// and files being likely read plain (no conversion/ISO 8859-1)
|
||||
// However, this will make certain distinct SQ strings (e.g. "\xC3\xBC", "\xFC")
|
||||
// indistinguishable to the client
|
||||
#ifndef SQDBG_DONT_CONVERT_UTF8_BYTES_IN_UTF16
|
||||
if ( IN_RANGE( cp, 0xC2, 0xF4 ) )
|
||||
{
|
||||
if ( UTF8_2_LEAD(cp) )
|
||||
{
|
||||
@ -1337,7 +1303,12 @@ inline unsigned int SQUnicodeToUTF8( char *dst, unsigned int destSize, const SQC
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// [0x7F, 0xC2) & (0xF4, 0xFF]
|
||||
|
||||
if ( cp >= 0xA0 ) // [0xA0, 0xFF]
|
||||
goto x7ff;
|
||||
|
||||
doescape:
|
||||
// [0x00, 0x20) & (0x7E, 0xA0)
|
||||
if ( escape == kUTFEscapeQuoted )
|
||||
mbc[bytes++] = '\\';
|
||||
|
||||
@ -1351,7 +1322,7 @@ inline unsigned int SQUnicodeToUTF8( char *dst, unsigned int destSize, const SQC
|
||||
else
|
||||
{
|
||||
mbc[bytes++] = 'x';
|
||||
bytes += printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQChar)cp );
|
||||
bytes += printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQUnsignedChar)cp );
|
||||
}
|
||||
|
||||
goto write;
|
||||
@ -1364,6 +1335,7 @@ inline unsigned int SQUnicodeToUTF8( char *dst, unsigned int destSize, const SQC
|
||||
}
|
||||
else if ( cp <= 0x7FF )
|
||||
{
|
||||
x7ff:
|
||||
UTF8_2_FROM_UTF32( mbc, cp );
|
||||
bytes = 2;
|
||||
}
|
||||
@ -1387,7 +1359,7 @@ inline unsigned int SQUnicodeToUTF8( char *dst, unsigned int destSize, const SQC
|
||||
|
||||
mbc[bytes++] = '\\';
|
||||
mbc[bytes++] = 'x';
|
||||
bytes = bytes + printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQChar)cp );
|
||||
bytes = bytes + printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQUnsignedChar)cp );
|
||||
goto write;
|
||||
}
|
||||
}
|
||||
@ -1478,4 +1450,33 @@ write:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SQUNICODE) && !defined(_WIN32)
|
||||
// Do case insensitive comparison for ASCII characters, ignore the rest
|
||||
inline int sqdbg_wcsicmp( const SQChar *s1, const SQChar *s2 )
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
SQChar c1 = *s1++;
|
||||
SQChar c2 = *s2++;
|
||||
|
||||
if ( !c1 || !c2 )
|
||||
return c1 - c2;
|
||||
|
||||
if ( c1 == c2 )
|
||||
continue;
|
||||
|
||||
if ( c1 >= 'A' && c1 <= 'Z' )
|
||||
c1 |= 0x20;
|
||||
|
||||
if ( c2 >= 'A' && c2 <= 'Z' )
|
||||
c2 |= 0x20;
|
||||
|
||||
if ( c1 == c2 )
|
||||
continue;
|
||||
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SQDBG_STRING_H
|
||||
|
@ -111,7 +111,44 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template< int MEM_CACHE_CHUNKS_ALIGN = 2048 >
|
||||
// GCC requires this to be outside of the class
|
||||
template < bool S >
|
||||
struct _CScratch_members;
|
||||
|
||||
template <>
|
||||
struct _CScratch_members< true >
|
||||
{
|
||||
int m_LastFreeChunk;
|
||||
int m_LastFreeIndex;
|
||||
int m_PrevChunk;
|
||||
int m_PrevIndex;
|
||||
|
||||
int LastFreeChunk() { return m_LastFreeChunk; }
|
||||
int LastFreeIndex() { return m_LastFreeIndex; }
|
||||
int PrevChunk() { return m_PrevChunk; }
|
||||
int PrevIndex() { return m_PrevIndex; }
|
||||
|
||||
void SetLastFreeChunk( int i ) { m_LastFreeChunk = i; }
|
||||
void SetLastFreeIndex( int i ) { m_LastFreeIndex = i; }
|
||||
void SetPrevChunk( int i ) { m_PrevChunk = i; }
|
||||
void SetPrevIndex( int i ) { m_PrevIndex = i; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct _CScratch_members< false >
|
||||
{
|
||||
int LastFreeChunk() { return 0; }
|
||||
int LastFreeIndex() { return 0; }
|
||||
int PrevChunk() { return 0; }
|
||||
int PrevIndex() { return 0; }
|
||||
|
||||
void SetLastFreeChunk( int ) {}
|
||||
void SetLastFreeIndex( int ) {}
|
||||
void SetPrevChunk( int ) {}
|
||||
void SetPrevIndex( int ) {}
|
||||
};
|
||||
|
||||
template< bool SEQUENTIAL, int MEM_CACHE_CHUNKS_ALIGN = 2048 >
|
||||
class CScratch
|
||||
{
|
||||
public:
|
||||
@ -126,8 +163,7 @@ public:
|
||||
|
||||
chunk_t *m_Memory;
|
||||
int m_MemChunkCount;
|
||||
int m_LastFreeChunk;
|
||||
int m_LastFreeIndex;
|
||||
_CScratch_members< SEQUENTIAL > m;
|
||||
|
||||
char *Get( int index )
|
||||
{
|
||||
@ -145,7 +181,7 @@ public:
|
||||
return &chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||
}
|
||||
|
||||
char *Alloc( int size, int *index = NULL, bool sequential = true )
|
||||
char *Alloc( int size, int *index = NULL )
|
||||
{
|
||||
if ( !m_Memory )
|
||||
{
|
||||
@ -166,11 +202,11 @@ public:
|
||||
int chunkIdx;
|
||||
int matchedChunks = 0;
|
||||
|
||||
if ( sequential )
|
||||
if ( SEQUENTIAL )
|
||||
{
|
||||
requiredChunks = ( size - 1 ) / MEM_CACHE_CHUNKSIZE + 1;
|
||||
msgIdx = m_LastFreeIndex;
|
||||
chunkIdx = m_LastFreeChunk;
|
||||
msgIdx = m.LastFreeIndex();
|
||||
chunkIdx = m.LastFreeChunk();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -184,14 +220,17 @@ public:
|
||||
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||
Assert( chunk->count && chunk->ptr );
|
||||
|
||||
if ( sequential )
|
||||
if ( SEQUENTIAL )
|
||||
{
|
||||
int remainingChunks = chunk->count - msgIdx;
|
||||
|
||||
if ( remainingChunks >= requiredChunks )
|
||||
{
|
||||
m_LastFreeIndex = msgIdx + requiredChunks;
|
||||
m_LastFreeChunk = chunkIdx;
|
||||
m.SetPrevChunk( m.LastFreeChunk() );
|
||||
m.SetPrevIndex( m.LastFreeIndex() );
|
||||
|
||||
m.SetLastFreeIndex( msgIdx + requiredChunks );
|
||||
m.SetLastFreeChunk( chunkIdx );
|
||||
|
||||
if ( index )
|
||||
{
|
||||
@ -267,6 +306,7 @@ public:
|
||||
|
||||
void Free( void *ptr )
|
||||
{
|
||||
STATIC_ASSERT( !SEQUENTIAL );
|
||||
Assert( m_Memory );
|
||||
Assert( ptr );
|
||||
|
||||
@ -290,7 +330,8 @@ public:
|
||||
|
||||
Assert( found );
|
||||
|
||||
(*(unsigned char**)&ptr)[ *(int*)ptr + sizeof(int) - 1 ] = 0xdd;
|
||||
if ( *(int*)ptr )
|
||||
(*(unsigned char**)&ptr)[ *(int*)ptr + sizeof(int) - 1 ] = 0xdd;
|
||||
#endif
|
||||
|
||||
memset( (char*)ptr, 0, *(int*)ptr + sizeof(int) );
|
||||
@ -315,12 +356,16 @@ public:
|
||||
|
||||
m_Memory = NULL;
|
||||
m_MemChunkCount = 4;
|
||||
m_LastFreeChunk = 0;
|
||||
m_LastFreeIndex = 0;
|
||||
m.SetLastFreeChunk( 0 );
|
||||
m.SetLastFreeIndex( 0 );
|
||||
m.SetPrevChunk( 0 );
|
||||
m.SetPrevIndex( 0 );
|
||||
}
|
||||
|
||||
void ReleaseShrink()
|
||||
{
|
||||
STATIC_ASSERT( SEQUENTIAL );
|
||||
|
||||
if ( !m_Memory )
|
||||
return;
|
||||
|
||||
@ -359,13 +404,17 @@ public:
|
||||
AssertOOM( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||
}
|
||||
|
||||
m_LastFreeChunk = 0;
|
||||
m_LastFreeIndex = 0;
|
||||
m.SetLastFreeChunk( 0 );
|
||||
m.SetLastFreeIndex( 0 );
|
||||
m.SetPrevChunk( 0 );
|
||||
m.SetPrevIndex( 0 );
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
if ( !m_Memory || ( !m_LastFreeChunk && !m_LastFreeIndex ) )
|
||||
STATIC_ASSERT( SEQUENTIAL );
|
||||
|
||||
if ( !m_Memory || ( !m.LastFreeChunk() && !m.LastFreeIndex() ) )
|
||||
return;
|
||||
|
||||
#ifdef _DEBUG
|
||||
@ -380,8 +429,18 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
m_LastFreeChunk = 0;
|
||||
m_LastFreeIndex = 0;
|
||||
m.SetLastFreeChunk( 0 );
|
||||
m.SetLastFreeIndex( 0 );
|
||||
m.SetPrevChunk( 0 );
|
||||
m.SetPrevIndex( 0 );
|
||||
}
|
||||
|
||||
void ReleaseTop()
|
||||
{
|
||||
STATIC_ASSERT( SEQUENTIAL );
|
||||
|
||||
m.SetLastFreeChunk( m.PrevChunk() );
|
||||
m.SetLastFreeIndex( m.PrevIndex() );
|
||||
}
|
||||
};
|
||||
|
||||
@ -391,212 +450,212 @@ class vector
|
||||
public:
|
||||
typedef unsigned int I;
|
||||
|
||||
CAllocator _base;
|
||||
I _size;
|
||||
CAllocator base;
|
||||
I size;
|
||||
|
||||
vector() : _base(), _size(0)
|
||||
vector() : base(), size(0)
|
||||
{
|
||||
Assert( !bExternalMem );
|
||||
STATIC_ASSERT( !bExternalMem );
|
||||
}
|
||||
|
||||
vector( CAllocator &a ) : _base(a), _size(0)
|
||||
vector( CAllocator &a ) : base(a), size(0)
|
||||
{
|
||||
Assert( bExternalMem );
|
||||
STATIC_ASSERT( bExternalMem );
|
||||
}
|
||||
|
||||
vector( I count ) : _base(), _size(0)
|
||||
vector( I count ) : base(), size(0)
|
||||
{
|
||||
Assert( !bExternalMem );
|
||||
_base.Alloc( count * sizeof(T) );
|
||||
STATIC_ASSERT( !bExternalMem );
|
||||
base.Alloc( count * sizeof(T) );
|
||||
}
|
||||
|
||||
vector( const vector< T > &src ) : _base()
|
||||
vector( const vector< T > &src ) : base()
|
||||
{
|
||||
Assert( !bExternalMem );
|
||||
_base.Alloc( src._base.Size() );
|
||||
_size = src._size;
|
||||
STATIC_ASSERT( !bExternalMem );
|
||||
base.Alloc( src.base.Size() );
|
||||
size = src.size;
|
||||
|
||||
for ( I i = 0; i < _size; i++ )
|
||||
new( &_base[ i * sizeof(T) ] ) T( (T&)src._base[ i * sizeof(T) ] );
|
||||
for ( I i = 0; i < size; i++ )
|
||||
new( &base[ i * sizeof(T) ] ) T( (T&)src.base[ i * sizeof(T) ] );
|
||||
}
|
||||
|
||||
~vector()
|
||||
{
|
||||
Assert( (unsigned int)_size <= _base.Size() );
|
||||
Assert( (unsigned int)size <= base.Size() );
|
||||
|
||||
for ( I i = 0; i < _size; i++ )
|
||||
((T&)(_base[ i * sizeof(T) ])).~T();
|
||||
for ( I i = 0; i < size; i++ )
|
||||
((T&)(base[ i * sizeof(T) ])).~T();
|
||||
|
||||
if ( !bExternalMem )
|
||||
_base.Free();
|
||||
base.Free();
|
||||
}
|
||||
|
||||
T &operator[]( I i ) const
|
||||
{
|
||||
Assert( _size > 0 );
|
||||
Assert( i >= 0 && i < _size );
|
||||
Assert( _size * sizeof(T) <= _base.Size() );
|
||||
return (T&)_base[ i * sizeof(T) ];
|
||||
Assert( size > 0 );
|
||||
Assert( i >= 0 && i < size );
|
||||
Assert( size * sizeof(T) <= base.Size() );
|
||||
return (T&)base[ i * sizeof(T) ];
|
||||
}
|
||||
|
||||
T *base()
|
||||
T *Base()
|
||||
{
|
||||
return _base.Base();
|
||||
return base.Base();
|
||||
}
|
||||
|
||||
I size() const
|
||||
I Size() const
|
||||
{
|
||||
return _size;
|
||||
return size;
|
||||
}
|
||||
|
||||
I capacity() const
|
||||
I Capacity() const
|
||||
{
|
||||
return _base.Size() / sizeof(T);
|
||||
return base.Size() / sizeof(T);
|
||||
}
|
||||
|
||||
T &top() const
|
||||
T &Top() const
|
||||
{
|
||||
Assert( _size > 0 );
|
||||
return (T&)_base[ ( _size - 1 ) * sizeof(T) ];
|
||||
Assert( size > 0 );
|
||||
return (T&)base[ ( size - 1 ) * sizeof(T) ];
|
||||
}
|
||||
|
||||
void pop()
|
||||
void Pop()
|
||||
{
|
||||
Assert( _size > 0 );
|
||||
((T&)_base[ --_size * sizeof(T) ]).~T();
|
||||
Assert( size > 0 );
|
||||
((T&)base[ --size * sizeof(T) ]).~T();
|
||||
}
|
||||
|
||||
T &append()
|
||||
T &Append()
|
||||
{
|
||||
_base.Ensure( ++_size * sizeof(T) );
|
||||
Assert( _size * sizeof(T) <= _base.Size() );
|
||||
return *( new( &_base[ ( _size - 1 ) * sizeof(T) ] ) T() );
|
||||
base.Ensure( ++size * sizeof(T) );
|
||||
Assert( size * sizeof(T) <= base.Size() );
|
||||
return *( new( &base[ ( size - 1 ) * sizeof(T) ] ) T() );
|
||||
}
|
||||
|
||||
void append( const T &src )
|
||||
void Append( const T &src )
|
||||
{
|
||||
_base.Ensure( ++_size * sizeof(T) );
|
||||
Assert( _size * sizeof(T) <= _base.Size() );
|
||||
new( &_base[ ( _size - 1 ) * sizeof(T) ] ) T( src );
|
||||
base.Ensure( ++size * sizeof(T) );
|
||||
Assert( size * sizeof(T) <= base.Size() );
|
||||
new( &base[ ( size - 1 ) * sizeof(T) ] ) T( src );
|
||||
}
|
||||
|
||||
T &insert( I i )
|
||||
T &Insert( I i )
|
||||
{
|
||||
Assert( i >= 0 && i <= _size );
|
||||
Assert( i >= 0 && i <= size );
|
||||
|
||||
_base.Ensure( ++_size * sizeof(T) );
|
||||
Assert( _size * sizeof(T) <= _base.Size() );
|
||||
base.Ensure( ++size * sizeof(T) );
|
||||
Assert( size * sizeof(T) <= base.Size() );
|
||||
|
||||
if ( i != _size - 1 )
|
||||
if ( i != size - 1 )
|
||||
{
|
||||
memmove( &_base[ ( i + 1 ) * sizeof(T) ],
|
||||
&_base[ i * sizeof(T) ],
|
||||
( _size - ( i + 1 ) ) * sizeof(T) );
|
||||
memmove( &base[ ( i + 1 ) * sizeof(T) ],
|
||||
&base[ i * sizeof(T) ],
|
||||
( size - ( i + 1 ) ) * sizeof(T) );
|
||||
}
|
||||
|
||||
return *( new( &_base[ i * sizeof(T) ] ) T() );
|
||||
return *( new( &base[ i * sizeof(T) ] ) T() );
|
||||
}
|
||||
|
||||
void remove( I i )
|
||||
void Remove( I i )
|
||||
{
|
||||
Assert( _size > 0 );
|
||||
Assert( i >= 0 && i < _size );
|
||||
Assert( size > 0 );
|
||||
Assert( i >= 0 && i < size );
|
||||
|
||||
((T&)_base[ i * sizeof(T) ]).~T();
|
||||
((T&)base[ i * sizeof(T) ]).~T();
|
||||
|
||||
if ( i != _size - 1 )
|
||||
if ( i != size - 1 )
|
||||
{
|
||||
memmove( &_base[ i * sizeof(T) ],
|
||||
&_base[ ( i + 1 ) * sizeof(T) ],
|
||||
( _size - ( i + 1 ) ) * sizeof(T) );
|
||||
memmove( &base[ i * sizeof(T) ],
|
||||
&base[ ( i + 1 ) * sizeof(T) ],
|
||||
( size - ( i + 1 ) ) * sizeof(T) );
|
||||
}
|
||||
|
||||
_size--;
|
||||
size--;
|
||||
}
|
||||
|
||||
void clear()
|
||||
void Clear()
|
||||
{
|
||||
for ( I i = 0; i < _size; i++ )
|
||||
((T&)_base[ i * sizeof(T) ]).~T();
|
||||
for ( I i = 0; i < size; i++ )
|
||||
((T&)base[ i * sizeof(T) ]).~T();
|
||||
|
||||
_size = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
void sort( int (*fn)(const T *, const T *) )
|
||||
void Sort( int (*fn)(const T *, const T *) )
|
||||
{
|
||||
Assert( _size * sizeof(T) <= _base.Size() );
|
||||
Assert( size * sizeof(T) <= base.Size() );
|
||||
|
||||
if ( _size > 1 )
|
||||
if ( size > 1 )
|
||||
{
|
||||
qsort( _base.Base(), _size, sizeof(T), (int (*)(const void *, const void *))fn );
|
||||
qsort( base.Base(), size, sizeof(T), (int (*)(const void *, const void *))fn );
|
||||
}
|
||||
}
|
||||
|
||||
void reserve( I count )
|
||||
void Reserve( I count )
|
||||
{
|
||||
Assert( (unsigned int)_size <= _base.Size() );
|
||||
Assert( (unsigned int)size <= base.Size() );
|
||||
|
||||
if ( count == 0 )
|
||||
count = 4;
|
||||
|
||||
if ( (unsigned int)count == _base.Size() )
|
||||
if ( (unsigned int)count == base.Size() )
|
||||
return;
|
||||
|
||||
for ( I i = count; i < _size; i++ )
|
||||
((T&)_base[ i * sizeof(T) ]).~T();
|
||||
for ( I i = count; i < size; i++ )
|
||||
((T&)base[ i * sizeof(T) ]).~T();
|
||||
|
||||
_base.Alloc( count * sizeof(T) );
|
||||
base.Alloc( count * sizeof(T) );
|
||||
}
|
||||
|
||||
void purge()
|
||||
void Purge()
|
||||
{
|
||||
Assert( _size * sizeof(T) <= _base.Size() );
|
||||
Assert( size * sizeof(T) <= base.Size() );
|
||||
|
||||
for ( I i = 0; i < _size; i++ )
|
||||
((T&)_base[ i * sizeof(T) ]).~T();
|
||||
for ( I i = 0; i < size; i++ )
|
||||
((T&)base[ i * sizeof(T) ]).~T();
|
||||
|
||||
_base.Free();
|
||||
_size = 0;
|
||||
base.Free();
|
||||
size = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CBuffer
|
||||
{
|
||||
public:
|
||||
CMemory _base;
|
||||
int _size;
|
||||
int _offset;
|
||||
CMemory base;
|
||||
int size;
|
||||
int offset;
|
||||
|
||||
char *base()
|
||||
char *Base()
|
||||
{
|
||||
return _base.Base() + _offset;
|
||||
return base.Base() + offset;
|
||||
}
|
||||
|
||||
int size() const
|
||||
int Size() const
|
||||
{
|
||||
return _size;
|
||||
return size;
|
||||
}
|
||||
|
||||
int capacity() const
|
||||
int Capacity() const
|
||||
{
|
||||
return _base.Size();
|
||||
return base.Size();
|
||||
}
|
||||
|
||||
void reserve( int count )
|
||||
void Reserve( int count )
|
||||
{
|
||||
Assert( (unsigned int)_size <= _base.Size() );
|
||||
Assert( (unsigned int)size <= base.Size() );
|
||||
|
||||
if ( (unsigned int)count == _base.Size() )
|
||||
if ( (unsigned int)count == base.Size() )
|
||||
return;
|
||||
|
||||
_base.Alloc( count );
|
||||
base.Alloc( count );
|
||||
}
|
||||
|
||||
void purge()
|
||||
void Purge()
|
||||
{
|
||||
_base.Free();
|
||||
_size = 0;
|
||||
_offset = 0;
|
||||
base.Free();
|
||||
size = 0;
|
||||
offset = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -608,16 +667,16 @@ public:
|
||||
|
||||
CBufTmpCache( CBuffer *b ) :
|
||||
buffer(b),
|
||||
size(buffer->_size)
|
||||
size(buffer->size)
|
||||
{
|
||||
buffer->_offset += buffer->_size;
|
||||
buffer->_size = 0;
|
||||
buffer->offset += buffer->size;
|
||||
buffer->size = 0;
|
||||
}
|
||||
|
||||
~CBufTmpCache()
|
||||
{
|
||||
buffer->_offset -= size;
|
||||
buffer->_size = size;
|
||||
buffer->offset -= size;
|
||||
buffer->size = size;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
IScriptVM* makeSquirrelVM();
|
||||
|
||||
int vscript_token = 0;
|
||||
int vscript_debugger_port = 0;
|
||||
|
||||
class CScriptManager : public CTier1AppSystem<IScriptManager>
|
||||
{
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
virtual bool Init() override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
virtual bool ConnectDebugger( int port = 0 ) override;
|
||||
virtual bool ConnectDebugger( int port = 0, float timeout = 0.0f ) override;
|
||||
virtual void DisconnectDebugger() override;
|
||||
|
||||
virtual ScriptLanguage_t GetLanguage() override;
|
||||
@ -284,6 +284,14 @@ public:
|
||||
WriteObject( (const SQObjectPtr&)obj, pBuffer, writeState );
|
||||
}
|
||||
|
||||
void WriteObject( SQGenerator *pObj, CUtlBuffer* pBuffer, WriteStateMap& writeState )
|
||||
{
|
||||
SQObject obj;
|
||||
obj._type = OT_GENERATOR;
|
||||
obj._unVal.pUserPointer = pObj;
|
||||
WriteObject( (const SQObjectPtr&)obj, pBuffer, writeState );
|
||||
}
|
||||
|
||||
void ReadObject( SQObjectPtr &obj, CUtlBuffer* pBuffer, ReadStateMap& readState );
|
||||
|
||||
// Do not implicity add/remove ref
|
||||
@ -327,7 +335,16 @@ namespace SQVector
|
||||
}
|
||||
|
||||
SQUserPointer p;
|
||||
sq_getinstanceup(vm, 1, &p, 0);
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, &p, 0)))
|
||||
{
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
if (!p)
|
||||
{
|
||||
return sq_throwerror(vm, "Accessed null instance");
|
||||
}
|
||||
|
||||
new (p) Vector(x, y, z);
|
||||
|
||||
return 0;
|
||||
@ -343,7 +360,7 @@ namespace SQVector
|
||||
return sq_throwerror(vm, "Expected Vector._get(string)");
|
||||
}
|
||||
|
||||
if (key[0] < 'x' || key['0'] > 'z' || key[1] != '\0')
|
||||
if (key[0] < 'x' || key[0] > 'z' || key[1] != '\0')
|
||||
{
|
||||
return sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
||||
}
|
||||
@ -369,7 +386,7 @@ namespace SQVector
|
||||
return sq_throwerror(vm, "Expected Vector._set(string)");
|
||||
}
|
||||
|
||||
if (key[0] < 'x' || key['0'] > 'z' || key[1] != '\0')
|
||||
if (key[0] < 'x' || key[0] > 'z' || key[1] != '\0')
|
||||
{
|
||||
return sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
||||
}
|
||||
@ -1315,10 +1332,7 @@ bool getVariant(HSQUIRRELVM vm, SQInteger idx, ScriptVariant_t& variant)
|
||||
case OT_INSTANCE:
|
||||
{
|
||||
Vector* v = nullptr;
|
||||
SQUserPointer tag;
|
||||
if (SQ_SUCCEEDED(sq_gettypetag(vm, idx, &tag)) &&
|
||||
tag == TYPETAG_VECTOR &&
|
||||
SQ_SUCCEEDED(sq_getinstanceup(vm, idx, (SQUserPointer*)&v, TYPETAG_VECTOR)))
|
||||
if (SQ_SUCCEEDED(sq_getinstanceup(vm, idx, (SQUserPointer*)&v, TYPETAG_VECTOR)))
|
||||
{
|
||||
variant.Free();
|
||||
variant = (Vector*)malloc(sizeof(Vector));
|
||||
@ -1347,12 +1361,10 @@ SQInteger function_stub(HSQUIRRELVM vm)
|
||||
{
|
||||
SQInteger top = sq_gettop(vm);
|
||||
|
||||
SQUserPointer userptr = nullptr;
|
||||
sq_getuserpointer(vm, top, &userptr);
|
||||
ScriptFunctionBinding_t* pFunc = nullptr;
|
||||
sq_getuserpointer(vm, top, (SQUserPointer*)&pFunc);
|
||||
|
||||
Assert(userptr);
|
||||
|
||||
ScriptFunctionBinding_t* pFunc = (ScriptFunctionBinding_t*)userptr;
|
||||
Assert(pFunc);
|
||||
|
||||
int nargs = pFunc->m_desc.m_Parameters.Count();
|
||||
int nLastHScriptIdx = -1;
|
||||
@ -1449,15 +1461,30 @@ SQInteger function_stub(HSQUIRRELVM vm)
|
||||
|
||||
if (pFunc->m_flags & SF_MEMBER_FUNC)
|
||||
{
|
||||
SQUserPointer self;
|
||||
sq_getinstanceup(vm, 1, &self, nullptr);
|
||||
ClassInstanceData* classInstanceData;
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0)))
|
||||
{
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
if (!self)
|
||||
if (!classInstanceData)
|
||||
{
|
||||
return sq_throwerror(vm, "Accessed null instance");
|
||||
}
|
||||
|
||||
instance = ((ClassInstanceData*)self)->instance;
|
||||
// check that the type of self, or any basetype, matches the function description
|
||||
ScriptClassDesc_t *selfType = classInstanceData->desc;
|
||||
while (selfType != pFunc->m_desc.m_pScriptClassDesc)
|
||||
{
|
||||
if (!selfType)
|
||||
{
|
||||
return sq_throwerror(vm, "Mismatched instance type");
|
||||
}
|
||||
selfType = selfType->m_pBaseDesc;
|
||||
Assert(selfType != classInstanceData->desc); // there should be no infinite loop
|
||||
}
|
||||
|
||||
instance = classInstanceData->instance;
|
||||
}
|
||||
|
||||
ScriptVariant_t script_retval;
|
||||
@ -1466,8 +1493,6 @@ SQInteger function_stub(HSQUIRRELVM vm)
|
||||
SquirrelVM* pSquirrelVM = (SquirrelVM*)sq_getsharedforeignptr(vm);
|
||||
Assert(pSquirrelVM);
|
||||
|
||||
sq_resetobject(&pSquirrelVM->lastError_);
|
||||
|
||||
bool call_success = (*pFunc->m_pfnBinding)(pFunc->m_pFunction, instance, params.Base(), nargs,
|
||||
pFunc->m_desc.m_ReturnType == FIELD_VOID ? nullptr : &script_retval, script_retval_storage);
|
||||
Assert(call_success);
|
||||
@ -1477,6 +1502,7 @@ SQInteger function_stub(HSQUIRRELVM vm)
|
||||
if (!sq_isnull(pSquirrelVM->lastError_))
|
||||
{
|
||||
sq_pushobject(vm, pSquirrelVM->lastError_);
|
||||
sq_release(vm, &pSquirrelVM->lastError_);
|
||||
sq_resetobject(&pSquirrelVM->lastError_);
|
||||
sq_retval = sq_throwobject(vm);
|
||||
}
|
||||
@ -1546,28 +1572,42 @@ SQInteger destructor_stub_instance(SQUserPointer p, SQInteger size)
|
||||
SQInteger constructor_stub(HSQUIRRELVM vm)
|
||||
{
|
||||
ScriptClassDesc_t* pClassDesc = nullptr;
|
||||
sq_gettypetag(vm, 1, (SQUserPointer*)&pClassDesc);
|
||||
if (SQ_FAILED(sq_gettypetag(vm, 1, (SQUserPointer*)&pClassDesc)))
|
||||
{
|
||||
return sq_throwerror(vm, "Expected native class");
|
||||
}
|
||||
|
||||
if (!pClassDesc || (void*)pClassDesc == TYPETAG_VECTOR)
|
||||
{
|
||||
return sq_throwerror(vm, "Unable to obtain native class description");
|
||||
}
|
||||
|
||||
if (!pClassDesc->m_pfnConstruct)
|
||||
{
|
||||
return sqstd_throwerrorf(vm, "Unable to construct instances of %s", pClassDesc->m_pszScriptName);
|
||||
}
|
||||
|
||||
SquirrelVM* pSquirrelVM = (SquirrelVM*)sq_getsharedforeignptr(vm);
|
||||
Assert(pSquirrelVM);
|
||||
SQUserPointer p;
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, &p, 0)))
|
||||
{
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
sq_resetobject(&pSquirrelVM->lastError_);
|
||||
if (!p)
|
||||
{
|
||||
return sq_throwerror(vm, "Accessed null instance");
|
||||
}
|
||||
|
||||
void* instance = pClassDesc->m_pfnConstruct();
|
||||
|
||||
#ifdef DBGFLAG_ASSERT
|
||||
SquirrelVM* pSquirrelVM = (SquirrelVM*)sq_getsharedforeignptr(vm);
|
||||
Assert(pSquirrelVM);
|
||||
// expect construction to always succeed
|
||||
Assert(sq_isnull(pSquirrelVM->lastError_));
|
||||
#endif
|
||||
|
||||
{
|
||||
SQUserPointer p;
|
||||
sq_getinstanceup(vm, 1, &p, 0);
|
||||
new(p) ClassInstanceData(instance, pClassDesc, nullptr, true);
|
||||
}
|
||||
new(p) ClassInstanceData(instance, pClassDesc, nullptr, true);
|
||||
|
||||
sq_setreleasehook(vm, 1, &destructor_stub);
|
||||
|
||||
@ -1577,7 +1617,10 @@ SQInteger constructor_stub(HSQUIRRELVM vm)
|
||||
SQInteger tostring_stub(HSQUIRRELVM vm)
|
||||
{
|
||||
ClassInstanceData* classInstanceData = nullptr;
|
||||
sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0);
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0)))
|
||||
{
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
char buffer[128] = "";
|
||||
|
||||
@ -1607,7 +1650,10 @@ SQInteger tostring_stub(HSQUIRRELVM vm)
|
||||
SQInteger get_stub(HSQUIRRELVM vm)
|
||||
{
|
||||
ClassInstanceData* classInstanceData = nullptr;
|
||||
sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0);
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0)))
|
||||
{
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
const char* key = nullptr;
|
||||
sq_getstring(vm, 2, &key);
|
||||
@ -1629,7 +1675,19 @@ SQInteger get_stub(HSQUIRRELVM vm)
|
||||
}
|
||||
else
|
||||
{
|
||||
sq_retval = sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
||||
// Fallback
|
||||
// Extra stack variables don't need to be popped, they are cleaned up on exit
|
||||
sq_pushroottable(vm);
|
||||
sq_push(vm, -2);
|
||||
|
||||
if ( SQ_SUCCEEDED( sq_rawget(vm, -2) ) )
|
||||
{
|
||||
sq_retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sq_retval = sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
||||
}
|
||||
}
|
||||
|
||||
var.Free();
|
||||
@ -1639,7 +1697,10 @@ SQInteger get_stub(HSQUIRRELVM vm)
|
||||
SQInteger set_stub(HSQUIRRELVM vm)
|
||||
{
|
||||
ClassInstanceData* classInstanceData = nullptr;
|
||||
sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0);
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0)))
|
||||
{
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
const char* key = nullptr;
|
||||
sq_getstring(vm, 2, &key);
|
||||
@ -1660,11 +1721,24 @@ SQInteger set_stub(HSQUIRRELVM vm)
|
||||
classInstanceData->desc->pHelper->Set(classInstanceData->instance, key, var)
|
||||
))
|
||||
{
|
||||
sq_retval = sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
||||
// Fallback
|
||||
sq_pushroottable(vm);
|
||||
sq_push(vm, -3);
|
||||
sq_push(vm, -3);
|
||||
|
||||
if ( SQ_SUCCEEDED( sq_rawset(vm, -3) ) )
|
||||
{
|
||||
// rawset doesn't return correctly, pop env to return val
|
||||
sq_pop(vm, 1);
|
||||
sq_retval = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sq_retval = sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
||||
}
|
||||
}
|
||||
|
||||
var.Free();
|
||||
sq_pop(vm, 1);
|
||||
return sq_retval;
|
||||
}
|
||||
|
||||
@ -2058,17 +2132,26 @@ void SquirrelVM::Shutdown()
|
||||
|
||||
bool VScriptRunScript( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing );
|
||||
|
||||
bool SquirrelVM::ConnectDebugger( int port )
|
||||
bool SquirrelVM::ConnectDebugger( int port, float timeout )
|
||||
{
|
||||
if ( !debugger_ )
|
||||
{
|
||||
debugger_ = sqdbg_attach_debugger( vm_ );
|
||||
|
||||
if ( sqdbg_listen_socket( debugger_, port ) != 0 )
|
||||
if ( sqdbg_listen_socket( debugger_, port ) == 0 && timeout )
|
||||
{
|
||||
sqdbg_destroy_debugger( vm_ );
|
||||
debugger_ = nullptr;
|
||||
return false;
|
||||
float startTime = Plat_FloatTime();
|
||||
|
||||
while ( !sqdbg_is_client_connected( debugger_ ) )
|
||||
{
|
||||
float time = Plat_FloatTime();
|
||||
if ( time - startTime > timeout )
|
||||
break;
|
||||
|
||||
ThreadSleep( 50 );
|
||||
|
||||
sqdbg_frame( debugger_ );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2514,13 +2597,16 @@ bool SquirrelVM::RegisterClass(ScriptClassDesc_t* pClassDesc)
|
||||
sq_newclosure(vm_, tostring_stub, 0);
|
||||
sq_newslot(vm_, -3, SQFalse);
|
||||
|
||||
sq_pushstring(vm_, "_get", -1);
|
||||
sq_newclosure(vm_, get_stub, 0);
|
||||
sq_newslot(vm_, -3, SQFalse);
|
||||
if ( pClassDesc->pHelper )
|
||||
{
|
||||
sq_pushstring(vm_, "_get", -1);
|
||||
sq_newclosure(vm_, get_stub, 0);
|
||||
sq_newslot(vm_, -3, SQFalse);
|
||||
|
||||
sq_pushstring(vm_, "_set", -1);
|
||||
sq_newclosure(vm_, set_stub, 0);
|
||||
sq_newslot(vm_, -3, SQFalse);
|
||||
sq_pushstring(vm_, "_set", -1);
|
||||
sq_newclosure(vm_, set_stub, 0);
|
||||
sq_newslot(vm_, -3, SQFalse);
|
||||
}
|
||||
|
||||
sq_pushstring(vm_, "IsValid", -1);
|
||||
sq_newclosure(vm_, IsValid_stub, 0);
|
||||
@ -2709,10 +2795,8 @@ void SquirrelVM::SetInstanceUniqeId(HSCRIPT hInstance, const char* pszId)
|
||||
HSQOBJECT* obj = (HSQOBJECT*)hInstance;
|
||||
sq_pushobject(vm_, *obj);
|
||||
|
||||
SQUserPointer self;
|
||||
sq_getinstanceup(vm_, -1, &self, nullptr);
|
||||
|
||||
auto classInstanceData = (ClassInstanceData*)self;
|
||||
ClassInstanceData* classInstanceData;
|
||||
sq_getinstanceup(vm_, -1, (SQUserPointer*)&classInstanceData, nullptr);
|
||||
|
||||
classInstanceData->instanceId = pszId;
|
||||
|
||||
@ -2770,11 +2854,10 @@ void* SquirrelVM::GetInstanceValue(HSCRIPT hInstance, ScriptClassDesc_t* pExpect
|
||||
}
|
||||
|
||||
sq_pushobject(vm_, *obj);
|
||||
SQUserPointer self;
|
||||
sq_getinstanceup(vm_, -1, &self, nullptr);
|
||||
ClassInstanceData* classInstanceData;
|
||||
sq_getinstanceup(vm_, -1, (SQUserPointer*)&classInstanceData, nullptr);
|
||||
sq_pop(vm_, 1);
|
||||
|
||||
auto classInstanceData = (ClassInstanceData*)self;
|
||||
|
||||
if (!classInstanceData)
|
||||
{
|
||||
@ -3366,7 +3449,8 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
|
||||
#ifdef _DEBUG
|
||||
bool bAsserted = false;
|
||||
|
||||
if ( pThis->_noutervalues && pThis->_name._type == OT_STRING && pThis->_name._unVal.pString )
|
||||
if ( pThis->_noutervalues && pThis->_name._type == OT_STRING && pThis->_name._unVal.pString &&
|
||||
pThis->_outervalues[0]._type == OT_USERPOINTER )
|
||||
{
|
||||
Assert( pThis->_noutervalues == 1 );
|
||||
Assert( pThis->_outervalues[0]._type == OT_USERPOINTER );
|
||||
@ -3669,23 +3753,25 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
|
||||
|
||||
if ( pThis->_callsstacksize )
|
||||
{
|
||||
int stackidx = -1;
|
||||
|
||||
for ( int i = pThis->_callsstacksize; i--; )
|
||||
for ( int i = 0; i < pThis->_callsstacksize; i++ )
|
||||
{
|
||||
const SQVM::CallInfo *ci = &pThis->_callsstack[i];
|
||||
|
||||
if ( pThis->ci == ci )
|
||||
stackidx = i;
|
||||
|
||||
Assert( !ci->_generator );
|
||||
Assert( ci->_ip && ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions );
|
||||
Assert( ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions &&
|
||||
ci->_ip < ci->_closure._unVal.pClosure->_function->_instructions +
|
||||
ci->_closure._unVal.pClosure->_function->_ninstructions );
|
||||
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci->_etraps );
|
||||
Assert( ci->_closure._type == OT_CLOSURE && ci->_closure._unVal.pClosure );
|
||||
|
||||
WriteObject( ci->_closure, pBuffer, writeState );
|
||||
|
||||
int offset = (intp)ci->_ip - (intp)ci->_closure._unVal.pClosure->_function->_instructions;
|
||||
Assert( ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions <= INT_MAX );
|
||||
|
||||
pBuffer->PutChar( ci->_generator != 0 );
|
||||
if ( ci->_generator )
|
||||
WriteObject( ci->_generator, pBuffer, writeState );
|
||||
|
||||
int offset = ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions;
|
||||
pBuffer->PutInt( offset );
|
||||
pBuffer->PutInt( ci->_etraps );
|
||||
pBuffer->PutInt( ci->_prevstkbase );
|
||||
@ -3694,16 +3780,18 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
|
||||
pBuffer->PutInt( ci->_ncalls );
|
||||
pBuffer->PutChar( ci->_root );
|
||||
|
||||
for ( int j = ci->_etraps; j--; )
|
||||
for ( int j = 0; j < ci->_etraps; j++ )
|
||||
{
|
||||
const SQExceptionTrap &et = pThis->_etraps[j];
|
||||
pBuffer->PutInt( et._extarget );
|
||||
pBuffer->PutInt( et._stackbase );
|
||||
pBuffer->PutInt( et._stacksize );
|
||||
Assert( et._ip == ci->_ip );
|
||||
pBuffer->PutInt( et._stackbase );
|
||||
Assert( et._ip - ci->_ip <= INT_MAX );
|
||||
pBuffer->PutInt( et._ip - ci->_ip );
|
||||
pBuffer->PutInt( et._extarget );
|
||||
}
|
||||
}
|
||||
|
||||
int stackidx = pThis->ci - pThis->_callsstack;
|
||||
Assert( stackidx >= 0 && stackidx < pThis->_callsstacksize );
|
||||
pBuffer->PutInt( stackidx );
|
||||
}
|
||||
@ -3734,29 +3822,37 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
|
||||
|
||||
WriteObject( pThis->_closure, pBuffer, writeState );
|
||||
|
||||
const SQVM::CallInfo &ci = pThis->_ci;
|
||||
const SQVM::CallInfo *ci = &pThis->_ci;
|
||||
|
||||
Assert( !ci._generator );
|
||||
Assert( pThis->_closure._unVal.pClosure == ci._closure._unVal.pClosure );
|
||||
Assert( ci._ip && ci._ip >= ci._closure._unVal.pClosure->_function->_instructions );
|
||||
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci._etraps );
|
||||
Assert( pThis->_closure._unVal.pClosure == ci->_closure._unVal.pClosure );
|
||||
Assert( ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions &&
|
||||
ci->_ip < ci->_closure._unVal.pClosure->_function->_instructions +
|
||||
ci->_closure._unVal.pClosure->_function->_ninstructions );
|
||||
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci->_etraps );
|
||||
|
||||
int offset = (intp)ci._ip - (intp)ci._closure._unVal.pClosure->_function->_instructions;
|
||||
Assert( ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions <= INT_MAX );
|
||||
|
||||
pBuffer->PutChar( ci->_generator != 0 );
|
||||
if ( ci->_generator )
|
||||
WriteObject( ci->_generator, pBuffer, writeState );
|
||||
|
||||
int offset = ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions;
|
||||
pBuffer->PutInt( offset );
|
||||
pBuffer->PutInt( ci._etraps );
|
||||
pBuffer->PutInt( ci._prevstkbase );
|
||||
pBuffer->PutInt( ci._prevtop );
|
||||
pBuffer->PutInt( ci._target );
|
||||
pBuffer->PutInt( ci._ncalls );
|
||||
pBuffer->PutChar( ci._root );
|
||||
pBuffer->PutInt( ci->_etraps );
|
||||
pBuffer->PutInt( ci->_prevstkbase );
|
||||
pBuffer->PutInt( ci->_prevtop );
|
||||
pBuffer->PutInt( ci->_target );
|
||||
pBuffer->PutInt( ci->_ncalls );
|
||||
pBuffer->PutChar( ci->_root );
|
||||
|
||||
for ( int j = ci._etraps; j--; )
|
||||
for ( int j = 0; j < ci->_etraps; j++ )
|
||||
{
|
||||
const SQExceptionTrap &et = pThis->_etraps[j];
|
||||
pBuffer->PutInt( et._extarget );
|
||||
pBuffer->PutInt( et._stackbase );
|
||||
pBuffer->PutInt( et._stacksize );
|
||||
Assert( et._ip == ci._ip );
|
||||
pBuffer->PutInt( et._stackbase );
|
||||
Assert( et._ip - ci->_ip <= INT_MAX );
|
||||
pBuffer->PutInt( et._ip - ci->_ip );
|
||||
pBuffer->PutInt( et._extarget );
|
||||
}
|
||||
|
||||
int stacksize = pThis->_stack.size();
|
||||
@ -3770,7 +3866,6 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
|
||||
}
|
||||
case OT_USERDATA:
|
||||
case OT_USERPOINTER:
|
||||
Assert(0);
|
||||
break;
|
||||
default:
|
||||
AssertMsgAlways( 0, "SquirrelVM::WriteObject: unknown type" );
|
||||
@ -3814,26 +3909,10 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
|
||||
case OT_STRING:
|
||||
{
|
||||
int len = pBuffer->GetInt();
|
||||
char *psz;
|
||||
|
||||
if ( len < 1024 )
|
||||
{
|
||||
psz = (char*)stackalloc( len );
|
||||
}
|
||||
else
|
||||
{
|
||||
psz = (char*)malloc( len );
|
||||
}
|
||||
|
||||
pBuffer->Get( psz, len );
|
||||
|
||||
char *psz = (char*)pBuffer->PeekGet( 0 );
|
||||
pBuffer->SeekGet( CUtlBuffer::SEEK_CURRENT, len );
|
||||
Assert( pBuffer->IsValid() );
|
||||
obj._unVal.pString = SQString::Create( _ss(vm_), psz, len );
|
||||
|
||||
if ( len >= 1024 )
|
||||
{
|
||||
free( psz );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case OT_TABLE:
|
||||
@ -4319,10 +4398,10 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
|
||||
|
||||
if ( pThis->_callsstacksize )
|
||||
{
|
||||
if ( pThis->_callsstacksize >= pThis->_alloccallsstacksize )
|
||||
while ( pThis->_callsstacksize >= pThis->_alloccallsstacksize )
|
||||
pThis->GrowCallStack();
|
||||
|
||||
for ( int i = pThis->_callsstacksize; i--; )
|
||||
for ( int i = 0; i < pThis->_callsstacksize; i++ )
|
||||
{
|
||||
SQVM::CallInfo *ci = &pThis->_callsstack[i];
|
||||
|
||||
@ -4330,23 +4409,31 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
|
||||
ReadObject( closure, pBuffer, readState );
|
||||
Assert( closure._type == OT_CLOSURE && closure._unVal.pClosure );
|
||||
|
||||
int offset = pBuffer->GetInt();
|
||||
int funcsize = sizeof(SQInstruction) * closure._unVal.pClosure->_function->_ninstructions;
|
||||
int start = (intp)(closure._unVal.pClosure->_function->_instructions);
|
||||
int pos = start + offset;
|
||||
ci->_ip = (SQInstruction*)pos;
|
||||
|
||||
Assert( pos < (start + funcsize) );
|
||||
|
||||
// don't read past boundary
|
||||
if ( pos >= (start + funcsize) )
|
||||
if ( pBuffer->GetChar() )
|
||||
{
|
||||
ci->_ip = (SQInstruction*)start;
|
||||
SQObject generator;
|
||||
ReadObject( generator, pBuffer, readState );
|
||||
Assert( generator._type == OT_GENERATOR && generator._unVal.pGenerator );
|
||||
ci->_generator = generator._unVal.pGenerator;
|
||||
}
|
||||
else
|
||||
{
|
||||
ci->_generator = NULL;
|
||||
}
|
||||
|
||||
int offset = pBuffer->GetInt();
|
||||
SQInstruction *start = closure._unVal.pClosure->_function->_instructions;
|
||||
SQInstruction *end = start + closure._unVal.pClosure->_function->_ninstructions;
|
||||
SQInstruction *pos = start + offset;
|
||||
|
||||
Assert( pos >= start && pos < end );
|
||||
|
||||
if ( pos < start || pos >= end )
|
||||
pos = start;
|
||||
|
||||
ci->_ip = pos;
|
||||
ci->_literals = closure._unVal.pClosure->_function->_literals;
|
||||
ci->_closure = closure;
|
||||
ci->_generator = NULL;
|
||||
ci->_etraps = pBuffer->GetInt();
|
||||
ci->_prevstkbase = pBuffer->GetInt();
|
||||
ci->_prevtop = pBuffer->GetInt();
|
||||
@ -4356,13 +4443,13 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
|
||||
|
||||
pThis->_etraps.resize( ci->_etraps );
|
||||
|
||||
for ( int j = ci->_etraps; j--; )
|
||||
for ( int j = 0; j < ci->_etraps; j++ )
|
||||
{
|
||||
SQExceptionTrap &et = pThis->_etraps[j];
|
||||
et._extarget = pBuffer->GetInt();
|
||||
et._stackbase = pBuffer->GetInt();
|
||||
et._stacksize = pBuffer->GetInt();
|
||||
et._ip = ci->_ip;
|
||||
et._stackbase = pBuffer->GetInt();
|
||||
et._ip = ci->_ip + pBuffer->GetInt();
|
||||
et._extarget = pBuffer->GetInt();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4409,41 +4496,49 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
|
||||
|
||||
pThis->_state = (SQGenerator::SQGeneratorState)state;
|
||||
|
||||
SQVM::CallInfo &ci = pThis->_ci;
|
||||
SQVM::CallInfo *ci = &pThis->_ci;
|
||||
|
||||
int offset = pBuffer->GetInt();
|
||||
int funcsize = sizeof(SQInstruction) * closure._unVal.pClosure->_function->_ninstructions;
|
||||
int start = (intp)(closure._unVal.pClosure->_function->_instructions);
|
||||
int pos = start + offset;
|
||||
ci._ip = (SQInstruction*)pos;
|
||||
|
||||
Assert( pos < (start + funcsize) );
|
||||
|
||||
// don't read past boundary
|
||||
if ( pos >= (start + funcsize) )
|
||||
if ( pBuffer->GetChar() )
|
||||
{
|
||||
ci._ip = (SQInstruction*)start;
|
||||
SQObject generator;
|
||||
ReadObject( generator, pBuffer, readState );
|
||||
Assert( generator._type == OT_GENERATOR && generator._unVal.pGenerator );
|
||||
ci->_generator = generator._unVal.pGenerator;
|
||||
}
|
||||
else
|
||||
{
|
||||
ci->_generator = NULL;
|
||||
}
|
||||
|
||||
ci._literals = closure._unVal.pClosure->_function->_literals;
|
||||
ci._closure = closure;
|
||||
ci._generator = NULL;
|
||||
ci._etraps = pBuffer->GetInt();
|
||||
ci._prevstkbase = pBuffer->GetInt();
|
||||
ci._prevtop = pBuffer->GetInt();
|
||||
ci._target = pBuffer->GetInt();
|
||||
ci._ncalls = pBuffer->GetInt();
|
||||
ci._root = pBuffer->GetChar();
|
||||
int offset = pBuffer->GetInt();
|
||||
SQInstruction *start = closure._unVal.pClosure->_function->_instructions;
|
||||
SQInstruction *end = start + closure._unVal.pClosure->_function->_ninstructions;
|
||||
SQInstruction *pos = start + offset;
|
||||
|
||||
pThis->_etraps.resize( ci._etraps );
|
||||
Assert( pos >= start && pos < end );
|
||||
|
||||
for ( int j = ci._etraps; j--; )
|
||||
if ( pos < start || pos >= end )
|
||||
pos = start;
|
||||
|
||||
ci->_ip = pos;
|
||||
ci->_literals = closure._unVal.pClosure->_function->_literals;
|
||||
ci->_closure = closure;
|
||||
ci->_etraps = pBuffer->GetInt();
|
||||
ci->_prevstkbase = pBuffer->GetInt();
|
||||
ci->_prevtop = pBuffer->GetInt();
|
||||
ci->_target = pBuffer->GetInt();
|
||||
ci->_ncalls = pBuffer->GetInt();
|
||||
ci->_root = pBuffer->GetChar();
|
||||
|
||||
pThis->_etraps.resize( ci->_etraps );
|
||||
|
||||
for ( int j = 0; j < ci->_etraps; j++ )
|
||||
{
|
||||
SQExceptionTrap &et = pThis->_etraps[j];
|
||||
et._extarget = pBuffer->GetInt();
|
||||
et._stackbase = pBuffer->GetInt();
|
||||
et._stacksize = pBuffer->GetInt();
|
||||
et._ip = ci._ip;
|
||||
et._stackbase = pBuffer->GetInt();
|
||||
et._ip = ci->_ip + pBuffer->GetInt();
|
||||
et._extarget = pBuffer->GetInt();
|
||||
}
|
||||
|
||||
int stacksize = pBuffer->GetInt();
|
||||
@ -4457,10 +4552,7 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
|
||||
}
|
||||
case OT_USERDATA:
|
||||
case OT_USERPOINTER:
|
||||
{
|
||||
Assert(0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AssertMsgAlways( 0, "SquirrelVM::ReadObject: serialisation error" );
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user