/*static*/ void EldritchFramework::OnFadeFinished( void* pUIElement, void* pVoid )
{
	Unused( pVoid );
	Unused( pUIElement );

	// HACKHACK: Handle logo fade sequence here because event manager isn't meant for timed UI stuff.
	enum EIntroFadePhases
	{
		ELFP_FadingInLogo,
		ELFP_WaitingLogo,
		ELFP_FadingOutLogo,
		ELFP_Waiting,
		ELFP_Finished,
	};

	WBEventManager* const pEventManager = WBWorld::GetInstance()->GetEventManager();
	ASSERT( pEventManager );

	static EIntroFadePhases sPhase = ELFP_FadingInLogo;
	if( sPhase == ELFP_FadingInLogo )
	{
		DEBUGPRINTF( "Faded in\n" );
		sPhase = ELFP_WaitingLogo;

		static const float kWaitDuration = 0.75f;
		WB_MAKE_EVENT( Fade, NULL );
		WB_SET_AUTO( Fade, Float, Duration, kWaitDuration );
		WB_SET_AUTO( Fade, Float, FadeColorAStart, 0.0f );
		WB_SET_AUTO( Fade, Float, FadeColorAEnd, 0.0f );
		WB_DISPATCH_EVENT( pEventManager, Fade, NULL );
	}
	else if( sPhase == ELFP_WaitingLogo )
	{
		DEBUGPRINTF( "Waited\n" );
		sPhase = ELFP_FadingOutLogo;

		static const float kFadeOutDuration = 0.5f;
		WB_MAKE_EVENT( FadeOut, NULL );
		WB_SET_AUTO( FadeOut, Float, Duration, kFadeOutDuration );
		WB_DISPATCH_EVENT( pEventManager, FadeOut, NULL );
	}
	else if( sPhase == ELFP_FadingOutLogo )
	{
		DEBUGPRINTF( "Faded out\n" );
		sPhase = ELFP_Waiting;

		static const float kWaitDuration = 0.25f;
		WB_MAKE_EVENT( Fade, NULL );
		WB_SET_AUTO( Fade, Float, Duration, kWaitDuration );
		WB_SET_AUTO( Fade, Float, FadeColorAStart, 1.0f );
		WB_SET_AUTO( Fade, Float, FadeColorAEnd, 1.0f );
		WB_DISPATCH_EVENT( pEventManager, Fade, NULL );
	}
	else if( sPhase == ELFP_Waiting )
	{
		DEBUGPRINTF( "Waited\n" );
		sPhase = ELFP_Finished;

		WB_MAKE_EVENT( PopUIScreen, NULL );
		WB_DISPATCH_EVENT( pEventManager, PopUIScreen, NULL );

		static const float kFadeInDuration = 0.5f;
		WB_MAKE_EVENT( FadeIn, NULL );
		WB_SET_AUTO( FadeIn, Float, Duration, kFadeInDuration );
		WB_DISPATCH_EVENT( pEventManager, FadeIn, NULL );

		// HACKHACK: Moved here so it doesn't conflict with logos.
		WB_MAKE_EVENT( CheckForUpdates, NULL );
		WB_DISPATCH_EVENT( pEventManager, CheckForUpdates, NULL );
	}
	else
	{
		// Do nothing, intro has elapsed.
	}
}
/*virtual*/ bool EldritchFramework::TickInput( float DeltaTime )
{
	XTRACE_FUNCTION;

	if( !Framework3D::TickInput( DeltaTime ) )
	{
		return false;
	}

	if( m_Keyboard->OnRise( Keyboard::EB_Escape ) || m_Controller->OnRise( XInputController::EB_Start ) )
	{
		Pause();
	}

#if BUILD_ELDRITCH_TOOLS
	if( m_Keyboard->OnRise( Keyboard::EB_Tab ) )
	{
		m_Tools->ToggleToolMode();
	}

	if( m_Tools->IsInToolMode() )
	{
		m_Tools->TickInput();
		return true;
	}
#endif

#if BUILD_FINAL
	if( m_Keyboard->OnRise( Keyboard::EB_F6 ) )
	{
		m_Game->Checkpoint();
	}
#else
	{
		if( m_Keyboard->OnRise( Keyboard::EB_F6 ) )	// Quicksave
		{
			m_Game->GetSaveLoad()->SaveMaster( "quick.eldritchmastersave" );
		}

		if( m_Keyboard->OnRise( Keyboard::EB_F9 ) )	// Quickload
		{
			PrepareForLoad();
			m_Game->GetSaveLoad()->TryLoadMaster( "quick.eldritchmastersave" );
		}

#if BUILD_WINDOWS_NO_SDL
		// Alt + S saves
		if( m_Keyboard->IsHigh( Keyboard::EB_LeftAlt ) && m_Keyboard->OnRise( Keyboard::EB_S ) )
		{
			SimpleString SaveFileName;
			if( FileUtil::GetSaveFile( GetWindow()->GetHWnd(), "Save Files", "eldritchmastersave", SaveFileName ) )
			{
				m_Game->GetSaveLoad()->SaveMaster( SaveFileName );
			}
		}

		// Alt + L loads
		if( m_Keyboard->IsHigh( Keyboard::EB_LeftAlt ) && m_Keyboard->OnRise( Keyboard::EB_L ) )
		{
			SimpleString LoadFileName;
			if( FileUtil::GetLoadFile( GetWindow()->GetHWnd(), "Save Files", "eldritchmastersave", LoadFileName ) )
			{
				PrepareForLoad();
				m_Game->GetSaveLoad()->TryLoadMaster( LoadFileName );
			}
		}
#endif // BUILD_WINDOWS_NO_SDL
	}
#endif

#if BUILD_DEV
	if( m_Keyboard->OnRise( Keyboard::EB_R ) )
	{
		WBWorld::GetInstance()->Report();
		ReverseHash::ReportSize();
	}

	// Ctrl + Alt + Backspace: Invoke crash
	if( m_Keyboard->IsHigh( Keyboard::EB_LeftAlt ) && m_Keyboard->IsHigh( Keyboard::EB_LeftControl ) && m_Keyboard->OnRise( Keyboard::EB_Backspace ) )
	{
		WBEntity* const pEntity = NULL;
		pEntity->Tick( 0.0f );
	}

	// Shift + Alt + Backspace: Invoke crash by allocating all the memory
	if( m_Keyboard->IsHigh( Keyboard::EB_LeftAlt ) && m_Keyboard->IsHigh( Keyboard::EB_LeftShift ) && m_Keyboard->OnRise( Keyboard::EB_Backspace ) )
	{
		for(;;)
		{
			byte* pArray = new byte[ 32 ];
			pArray[0] = pArray[31];
		}
	}

	if( m_Keyboard->OnRise( Keyboard::EB_Backspace ) )
	{
		m_World->GatherStats();
	}

	// Shift + Ctrl + T is a full restart (new hub), like Resurrect.
	// Ctrl + T is a proxy return to hub (new worlds, same hub), like Return to Library.
	// Alt + T is a travel to next level.
	// Shift + Alt + T is a travel to prev level.
	if( m_Keyboard->OnRise( Keyboard::EB_T ) && m_Keyboard->IsHigh( Keyboard::EB_LeftControl ) )
	{
		WB_MAKE_EVENT( ReturnToHub, NULL );
		WB_SET_AUTO( ReturnToHub, Bool, Restart, true );
		WB_SET_AUTO( ReturnToHub, Bool, FlushHub, m_Keyboard->IsHigh( Keyboard::EB_LeftShift ) );
		WB_DISPATCH_EVENT( WBWorld::GetInstance()->GetEventManager(), ReturnToHub, m_Game );
	}
	else if( m_Keyboard->OnRise( Keyboard::EB_T ) && m_Keyboard->IsHigh( Keyboard::EB_LeftAlt ) )
	{
		if( m_Keyboard->IsHigh( Keyboard::EB_LeftShift ) )
		{
			WB_MAKE_EVENT( GoToPrevLevel, NULL );
			WB_DISPATCH_EVENT( WBWorld::GetInstance()->GetEventManager(), GoToPrevLevel, m_Game );
		}
		else
		{
			WB_MAKE_EVENT( GoToNextLevel, NULL );
			WB_DISPATCH_EVENT( WBWorld::GetInstance()->GetEventManager(), GoToNextLevel, m_Game );
		}
	}
	else if( m_Keyboard->OnRise( Keyboard::EB_T ) )
	{
		RegenerateWorld();
	}
	else if( m_Keyboard->IsHigh( Keyboard::EB_T ) &&
		m_Keyboard->IsHigh( Keyboard::EB_LeftShift ) &&
		m_Keyboard->IsLow( Keyboard::EB_LeftControl ) &&
		m_Keyboard->IsLow( Keyboard::EB_LeftAlt ) )
	{
		RegenerateWorld();
	}
#endif

	return true;
}
/*virtual*/ void EldritchFramework::Initialize()
{
	XTRACE_FUNCTION;

	XTRACE_BEGIN( PreFramework3D );
		ReverseHash::Initialize();

		PackStream::StaticAddPackageFile( "eldritch-base.cpk" );
		FrameworkUtil::MinimalLoadConfigFiles( "Config/default.ccf" );

		InitializePackages();

		InitializeDLC();

		// Load prefs over anything in the defaults.
		LoadPrefsConfig();

		LOADPRINTLEVELS;

		STATICHASH( Version );
		STATICHASH( ContentSyncer );
		SimpleString LocalVersion = ConfigManager::GetString( sVersion, "", sContentSyncer );
		PRINTF( "Version: %s\n", LocalVersion.CStr() );

		XTRACE_BEGIN( InitializeFactories );
			PRINTF( "Initializing factories...\n" );

			PRINTF( "Initializing SDP factories.\n" );
			SDPFactory::InitializeBaseFactories();
#define ADDSDPFACTORY( type ) SDPFactory::RegisterSDPFactory( #type, SDP##type::Factory );
#include "eldritchsdps.h"
#undef ADDSDPFACTORY

			PRINTF( "Initializing UI factories.\n" );
			UIFactory::InitializeBaseFactories();
#define ADDUISCREENFACTORY( type ) UIFactory::RegisterUIScreenFactory( #type, UIScreen##type::Factory );
#include "eldritchuiscreens.h"
#undef ADDUISCREENFACTORY

			PRINTF( "Initializing anim event factories.\n" );
#define ADDANIMEVENTFACTORY( type ) AnimEventFactory::GetInstance()->Register( #type, AnimEvent##type::Factory );
#include "eldritchanimevents.h"
#undef ADDANIMEVENTFACTORY

			PRINTF( "Initializing PE factories.\n" );
			WBParamEvaluatorFactory::InitializeBaseFactories();
#define ADDWBPEFACTORY( type ) WBParamEvaluatorFactory::RegisterFactory( #type, WBPE##type::Factory );
#include "rodinwbpes.h"
#include "eldritchwbpes.h"
#undef ADDWBPEFACTORY

			PRINTF( "Initializing action factories.\n" );
			WBActionFactory::InitializeBaseFactories();
#define ADDWBACTIONFACTORY( type ) WBActionFactory::RegisterFactory( #type, WBAction##type::Factory );
#include "uiwbactions.h"
#include "rodinwbactions.h"
#include "eldritchwbactions.h"
#undef ADDWBPEFACTORY

			PRINTF( "Initializing BT factories.\n" );
			RodinBTNodeFactory::InitializeBaseFactories();
#define ADDRODINBTNODEFACTORY( type ) RodinBTNodeFactory::RegisterFactory( #type, RodinBTNode##type::Factory );
#include "eldritchrodinbtnodes.h"
#undef ADDRODINBTNODEFACTORY

			// Initialize core and Eldritch Workbench component factories.
			PRINTF( "Initializing component factories.\n" );
			WBComponent::InitializeBaseFactories();
#define ADDWBCOMPONENT( type ) WBComponent::RegisterWBCompFactory( #type, WBComp##type::Factory );
#include "rodinwbcomponents.h"
#include "eldritchwbcomponents.h"
#undef ADDWBCOMPONENT
		XTRACE_END;

		PRINTF( "Factories initialized.\n" );

		// Create input system before framework so it will exist for UI. But don't attach devices yet, as they don't exist.
		PRINTF( "Initializing input system.\n" );
		m_InputSystem = new InputSystem;
		m_InputSystem->Initialize( "EldritchInput" );
	XTRACE_END;

	Framework3D::Initialize();

	STATICHASH( DisplayWidth );
	STATICHASH( DisplayHeight );
	m_DisplayWidth	= ConfigManager::GetInt( sDisplayWidth );
	m_DisplayHeight	= ConfigManager::GetInt( sDisplayHeight );

#if BUILD_WINDOWS
	m_CheckForUpdates = new CheckForUpdates( m_UIManager );
#endif

	m_Controller = new XInputController;

	m_TargetManager = new EldritchTargetManager( m_Renderer );
	m_TargetManager->CreateTargets( m_Display->m_Width, m_Display->m_Height );

	m_Audio3DListener = new EldritchSound3DListener;
	m_Audio3DListener->Initialize();

	ASSERT( m_AudioSystem );
	m_AudioSystem->Set3DListener( m_Audio3DListener );

	STATICHASH( FOV );
	const float FOV = ConfigManager::GetFloat( sFOV, 90.0f );

	STATICHASH( ForegroundFOV );
	const float FGFOV = ConfigManager::GetFloat( sForegroundFOV, 60.0f );

	STATICHASH( NearClip );
	const float NearClip = ConfigManager::GetFloat( sNearClip, 0.1f );

	STATICHASH( FarClip );
	const float FarClip = ConfigManager::GetFloat( sFarClip, 0.1f );

	const float fDisplayWidth = static_cast<float>( m_DisplayWidth );
	const float fDisplayHeight = static_cast<float>( m_DisplayHeight );
	const float AspectRatio = fDisplayWidth / fDisplayHeight;

	m_MainView	= new View( Vector(), Angles(), FOV, AspectRatio, NearClip, FarClip );
	m_FGView	= new View( Vector(), Angles(), FGFOV, AspectRatio, NearClip, FarClip );
	CreateHUDView();
	CreateMirrorView();
	CreateMinimapView();

	CreateBuckets();

	m_InputSystem->SetKeyboard( m_Keyboard );
	m_InputSystem->SetMouse( m_Mouse );
	m_InputSystem->SetController( m_Controller );
	m_InputSystem->SetClock( m_Clock );

	WBActionStack::Initialize();

	PRINTF( "Initializing Eldritch.\n" );

	InitializeWorld( HashedString(), false );

	m_Game = new EldritchGame;
	m_Game->RefreshRTDependentSystems();
	m_Game->Initialize();

	// Initialize config stuff
	{
		STATICHASH( InvertY );
		const bool InvertY = ConfigManager::GetBool( sInvertY );

		STATIC_HASHED_STRING( TurnY );
		m_InputSystem->SetMouseInvert( sTurnY, InvertY );
		m_InputSystem->SetControllerInvert( sTurnY, InvertY );

		STATICHASH( ControllerPower );
		const float ControllerPower = ConfigManager::GetFloat( sControllerPower );

		STATIC_HASHED_STRING( MoveX );
		m_InputSystem->SetControllerPower( sMoveX, ControllerPower );
		STATIC_HASHED_STRING( MoveY );
		m_InputSystem->SetControllerPower( sMoveY, ControllerPower );
		STATIC_HASHED_STRING( TurnX );
		m_InputSystem->SetControllerPower( sTurnX, ControllerPower );
		m_InputSystem->SetControllerPower( sTurnY, ControllerPower );
	}

	// Initialize UI sliders. This could be neater.
	// This also pushes the initial values to their respective systems, which is pret-ty terrible design.
	{
		WBEventManager* pEventManager = WBWorld::GetInstance()->GetEventManager();

		{
			STATICHASH( MouseSpeed );
			const float MouseSpeed = ConfigManager::GetFloat( sMouseSpeed, 1.0f );

			STATIC_HASHED_STRING( ControlsOptionsScreen );
			STATIC_HASHED_STRING( MouseSpeedSlider );
			WB_MAKE_EVENT( SetUISliderValue, NULL );
			WB_SET_AUTO( SetUISliderValue, Hash, Screen, sControlsOptionsScreen );
			WB_SET_AUTO( SetUISliderValue, Hash, Widget, sMouseSpeedSlider );
			WB_SET_AUTO( SetUISliderValue, Float, SliderValue, GetSliderValueFromMouseSpeed( MouseSpeed ) );
			WB_DISPATCH_EVENT( pEventManager, SetUISliderValue, NULL );
		}

		{
			STATICHASH( ControllerSpeed );
			const float ControllerSpeed = ConfigManager::GetFloat( sControllerSpeed, 1.0f );

			STATIC_HASHED_STRING( ControlsOptionsScreen );
			STATIC_HASHED_STRING( ControllerSpeedSlider );
			WB_MAKE_EVENT( SetUISliderValue, NULL );
			WB_SET_AUTO( SetUISliderValue, Hash, Screen, sControlsOptionsScreen );
			WB_SET_AUTO( SetUISliderValue, Hash, Widget, sControllerSpeedSlider );
			WB_SET_AUTO( SetUISliderValue, Float, SliderValue, GetSliderValueFromControllerSpeed( ControllerSpeed ) );
			WB_DISPATCH_EVENT( pEventManager, SetUISliderValue, NULL );
		}

		{
			STATICHASH( Brightness );
			const float Brightness = ConfigManager::GetFloat( sBrightness, 1.0f );

			STATIC_HASHED_STRING( BrightnessScreen );
			STATIC_HASHED_STRING( BrightnessSlider );
			WB_MAKE_EVENT( SetUISliderValue, NULL );
			WB_SET_AUTO( SetUISliderValue, Hash, Screen, sBrightnessScreen );
			WB_SET_AUTO( SetUISliderValue, Hash, Widget, sBrightnessSlider );
			WB_SET_AUTO( SetUISliderValue, Float, SliderValue, GetSliderValueFromBrightness( Brightness ) );
			WB_DISPATCH_EVENT( pEventManager, SetUISliderValue, NULL );
		}

		{
			STATIC_HASHED_STRING( DisplayOptionsScreen );
			STATIC_HASHED_STRING( FOVSlider );
			WB_MAKE_EVENT( SetUISliderValue, NULL );
			WB_SET_AUTO( SetUISliderValue, Hash, Screen, sDisplayOptionsScreen );
			WB_SET_AUTO( SetUISliderValue, Hash, Widget, sFOVSlider );
			WB_SET_AUTO( SetUISliderValue, Float, SliderValue, GetSliderValueFromFOV( FOV ) );
			WB_DISPATCH_EVENT( pEventManager, SetUISliderValue, NULL );
		}

		{
			STATICHASH( MasterVolume );
			const float MasterVolume = ConfigManager::GetFloat( sMasterVolume );

			STATIC_HASHED_STRING( AudioOptionsScreen );
			STATIC_HASHED_STRING( VolumeSlider );
			WB_MAKE_EVENT( SetUISliderValue, NULL );
			WB_SET_AUTO( SetUISliderValue, Hash, Screen, sAudioOptionsScreen );
			WB_SET_AUTO( SetUISliderValue, Hash, Widget, sVolumeSlider );
			WB_SET_AUTO( SetUISliderValue, Float, SliderValue, MasterVolume );
			WB_DISPATCH_EVENT( pEventManager, SetUISliderValue, NULL );
		}

		{
			STATICHASH( MusicVolume );
			const float MusicVolume = ConfigManager::GetFloat( sMusicVolume );

			STATIC_HASHED_STRING( AudioOptionsScreen );
			STATIC_HASHED_STRING( MusicVolumeSlider );
			WB_MAKE_EVENT( SetUISliderValue, NULL );
			WB_SET_AUTO( SetUISliderValue, Hash, Screen, sAudioOptionsScreen );
			WB_SET_AUTO( SetUISliderValue, Hash, Widget, sMusicVolumeSlider );
			WB_SET_AUTO( SetUISliderValue, Float, SliderValue, MusicVolume );
			WB_DISPATCH_EVENT( pEventManager, SetUISliderValue, NULL );
		}
	}

	// Initialize UI callbacks
	{
		UIScreenEldSetRes* pSetRes = m_UIManager->GetScreen<UIScreenEldSetRes>( "SetResScreen" );
		pSetRes->SetUICallback( SUICallback( EldritchFramework::OnSetRes, NULL ) );

		UIScreenFade* pFade = m_UIManager->GetScreen<UIScreenFade>( "Fade" );
		pFade->SetFadeCallback( SUICallback( EldritchFramework::OnFadeFinished, NULL ) );
	}

	WB_MAKE_EVENT( ResetToInitialScreens, NULL );
	WB_DISPATCH_EVENT( WBWorld::GetInstance()->GetEventManager(), ResetToInitialScreens, NULL );

	{
		// HACK: Too content aware
		STATIC_HASHED_STRING( MKGLogoScreen );
		WB_MAKE_EVENT( PushUIScreen, NULL );
		WB_SET_AUTO( PushUIScreen, Hash, Screen, sMKGLogoScreen );
		WB_DISPATCH_EVENT( WBWorld::GetInstance()->GetEventManager(), PushUIScreen, NULL );
	}

	// Tick world once to pump the event queue. Fixes title screen bugs.
	m_World->Tick( 0.0f );

	// All done, show the window finally.
	SafeDelete( m_SplashWindow );
#if BUILD_WINDOWS_NO_SDL
	m_Window->Show( m_CmdShow );
#elif BUILD_SDL
	m_Window->Show();
#endif

	// Reattach GL context if needed.
	m_Renderer->Refresh();

	PRINTF( "Eldritch initialization complete.\n" );
}
예제 #4
0
/*virtual*/ void WBCompEldHands::HandleEvent( const WBEvent& Event )
{
	XTRACE_FUNCTION;

	Super::HandleEvent( Event );

	STATIC_HASHED_STRING( OnWorldLoaded );
	STATIC_HASHED_STRING( OnItemEquipped );
	STATIC_HASHED_STRING( OnItemUnequipped );
	STATIC_HASHED_STRING( OnItemsSwapped );
	STATIC_HASHED_STRING( UseRightHand );
	STATIC_HASHED_STRING( UseLeftHand );
	STATIC_HASHED_STRING( ShowHands );
	STATIC_HASHED_STRING( HideHands );
	STATIC_HASHED_STRING( PlayHandAnim );
	STATIC_HASHED_STRING( SetHandMeshes );

	const HashedString EventName = Event.GetEventName();
	if( EventName == sOnWorldLoaded )
	{
		if( GetItemInRightHand() == GetWeapon() )
		{
			WB_MAKE_EVENT( OnWeaponEquipped, GetEntity() );
			WB_SET_AUTO( OnWeaponEquipped, Entity, Weapon, GetWeapon() );
			WB_DISPATCH_EVENT( GetEventManager(), OnWeaponEquipped, GetEntity() );
		}

		RestoreHandAnimations();

		UpdateWeaponHUD();
	}
	else if( EventName == sOnItemEquipped )
	{
		STATIC_HASHED_STRING( Item );
		WBEntity* const pItem = Event.GetEntity( sItem );
		ASSERT( pItem );

		// Hide fists and show ammo when we equip a weapon
		if( pItem == GetWeapon() )
		{
			WB_MAKE_EVENT( Hide, GetEntity() );
			WB_DISPATCH_EVENT( GetEventManager(), Hide, GetFists() );

			WB_MAKE_EVENT( OnWeaponEquipped, GetEntity() );
			WB_SET_AUTO( OnWeaponEquipped, Entity, Weapon, pItem );
			WB_DISPATCH_EVENT( GetEventManager(), OnWeaponEquipped, GetEntity() );

			ShowWeaponHUD();
		}
		
		if( pItem == GetItemInRightHand() ||
			pItem == GetItemInLeftHand() )
		{
			AddAnimationsToHand( pItem );
		}

		if( pItem == GetWeaponAlt() )
		{
			// When traveling to a new world and spawning an item in the alt slot, immediately hide it
			WB_MAKE_EVENT( Hide, GetEntity() );
			WB_DISPATCH_EVENT( GetEventManager(), Hide, GetWeaponAlt() );

			ShowWeaponAltHUD();
		}
	}
	else if( EventName == sOnItemUnequipped )
	{
		// Show fists when we unequip a weapon
		STATIC_HASHED_STRING( Item );
		WBEntity* const pItem = Event.GetEntity( sItem );
		if( pItem == GetWeapon() )
		{
			WB_MAKE_EVENT( Show, GetEntity() );
			WB_DISPATCH_EVENT( GetEventManager(), Show, GetFists() );

			WB_MAKE_EVENT( OnWeaponUnequipped, GetEntity() );
			WB_DISPATCH_EVENT( GetEventManager(), OnWeaponUnequipped, GetEntity() );

			// Revert to the fists animations
			AddAnimationsToHand( GetFists(), EH_Right );

			// HACK: Play the idle animation. I could add an event for "restored equip focus"
			// or whatever and hook this up in data, but eh. That somehow feels worse.
			STATIC_HASHED_STRING( Idle );
			PlayAnimation( GetFists(), sIdle, EH_Right );

			HideWeaponHUD();
		}
	}
	else if( EventName == sOnItemsSwapped )
	{
		// HACK, since the only things we swap (currently) are Weapon/WeaponAlt

		// Hide the alt weapon, show the right hand item
		WB_MAKE_EVENT( Hide, GetEntity() );
		WB_DISPATCH_EVENT( GetEventManager(), Hide, GetWeaponAlt() );

		WB_MAKE_EVENT( Show, GetEntity() );
		WB_DISPATCH_EVENT( GetEventManager(), Show, GetItemInRightHand() );

		AddAnimationsToHand( GetItemInRightHand() );

		STATIC_HASHED_STRING( Idle );
		PlayAnimation( GetItemInRightHand(), sIdle, EH_Right );

		UpdateWeaponHUD();

		WB_MAKE_EVENT( OnWeaponEquipped, GetEntity() );
		WB_SET_AUTO( OnWeaponEquipped, Entity, Weapon, GetItemInRightHand() );
		WB_DISPATCH_EVENT( GetEventManager(), OnWeaponEquipped, GetEntity() );
	}
	else if( EventName == sUseRightHand )
	{
		WBEntity* const pWeapon = GetItemInRightHand();
		if( pWeapon )
		{
			STATIC_HASHED_STRING( InputEdge );
			const int InputEdge = Event.GetInt( sInputEdge );

			{
				WB_MAKE_EVENT( Use, GetEntity() );
				WB_SET_AUTO( Use, Int, InputEdge, InputEdge );
				WB_DISPATCH_EVENT( GetEventManager(), Use, pWeapon );
			}
		}
	}
	else if( EventName == sUseLeftHand )
	{
		WBEntity* const pPower = GetItemInLeftHand();
		if( pPower )
		{
			STATIC_HASHED_STRING( InputEdge );
			const int InputEdge = Event.GetInt( sInputEdge );

			{
				WB_MAKE_EVENT( Use, GetEntity() );
				WB_SET_AUTO( Use, Int, InputEdge, InputEdge );
				WB_DISPATCH_EVENT( GetEventManager(), Use, pPower );
			}
		}
	}
	else if( EventName == sShowHands )
	{
		DecrementHideHandsRefs();
	}
	else if( EventName == sHideHands )
	{
		IncrementHideHandsRefs();
	}
	else if( EventName == sPlayHandAnim )
	{
		STATIC_HASHED_STRING( AnimatingEntity );
		WBEntity* const pAnimatingEntity = Event.GetEntity( sAnimatingEntity );

		STATIC_HASHED_STRING( AnimationName );
		const HashedString AnimationName = Event.GetHash( sAnimationName );

		// Don't play hand anim if we're restoring the alternate weapon
		if( pAnimatingEntity == GetItemInRightHand() || pAnimatingEntity == GetItemInLeftHand() )
		{
			const EHand Hand = GetHandEnum( pAnimatingEntity );
			PlayAnimation( pAnimatingEntity, AnimationName, Hand );
		}
	}
	else if( EventName == sSetHandMeshes )
	{
		STATIC_HASHED_STRING( LeftHandMesh );
		const SimpleString LeftHandMesh = Event.GetString( sLeftHandMesh );

		STATIC_HASHED_STRING( LeftHandTexture );
		const SimpleString LeftHandTexture = Event.GetString( sLeftHandTexture );

		STATIC_HASHED_STRING( RightHandMesh );
		const SimpleString RightHandMesh = Event.GetString( sRightHandMesh );

		STATIC_HASHED_STRING( RightHandTexture );
		const SimpleString RightHandTexture = Event.GetString( sRightHandTexture );

		SetHandMeshes( LeftHandMesh, LeftHandTexture, RightHandMesh, RightHandTexture );
		RestoreHandAnimations();
	}
}