/** * Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. */ class CastlePC extends SimplePC; /** Set to true to suppress the splash screen */ var config bool bSuppressSplash; /** will be true once the splash screen has been shown */ var bool bSplashHasBeenShown; /** If True then we are in attract mode */ var bool bIsInAttractMode; /** If True then we are in benchmark mode */ var bool bIsInBenchmarkMode; /** If True, then a full flythrough loop has been completed in benchmark mode */ var bool bBenchmarkLoopCompleted; /** Track the number of frames and the elapsed time while in benchmark mode to get average frame rate */ var int BenchmarkNumFrames; var float BenchmarkElapsedTime; /** Have we triggered the initial fading out of the Controls Help Menu */ var bool bDoneInitialFade; var MobileMenuPause PauseMenu; // The Pause menu var MobileMenuDebug DebugMenu; // The Debug menu var bool bPauseMenuOpen; var bool bAutoSlide; var float SliderStart, SliderEnd; var float SliderTravelTime; var float SliderTravelDuration; var float AutoAttractTime; var SoundCue OpenMenuSound; var SoundCue CloseMenuSound; var MobileMenuControls TutMenu; /************************************* Tap to Move ************************************/ /** How far the player must have moved within the last 0.5 seconds before we consider them 'stuck' and abort automatic movement */ var float StuckThreshHold; /** Scalar that sets how much the camera should pitch up and down to match the tap-to-move target */ var float TapToMoveAutoPitchAmount; /** Mesh to use for 'tap to move' visual cue in the world */ var StaticMesh TapToMoveVisualMesh; /** Minimum distance from destination before visual cue will vanish */ var float TapToMoveVisualMinDist; /** How fast the visual cue should rotate every frame */ var float TapToMoveVisualRotateSpeed; /** Length of visual cue animation effect */ var float TapToMoveVisualAnimDuration; /** Holds the destination we are moving towards */ var vector TapToMoveDestination; /** We use this to see if we are stuck */ var float LastDistToDestination; /** Time that tap to move visual effect started */ var float TapToMoveVisualEffectStartTime; /** Time that tap to move visual effect ended */ var float TapToMoveVisualEffectEndTime; var SoundCue TapToMoveSound; var SoundCue InvalidTapToMoveSound; var SoundCue TapToMoveStopSound; /** Spawned actor for 'tap to move' visual cue */ var KActorSpawnable TapToMoveVisualActor; /************************************* Tutorial ************************************/ enum ETutorialStage { ETS_None, ETS_Tap, ETS_Swipe, ETS_Sticks, ETS_Done, }; var ETutorialStage TutorialStage; /** Cached reference to the Tutorial Look Zone */ var MobileInputzone TutorialLookZone; /** * Setup the in world indicator for tap to move and some other subsystems */ simulated function PostBeginPlay() { Super.PostBeginPlay(); // Kill existing 'tap to move' actor, if any if( TapToMoveVisualActor != None ) { TapToMoveVisualActor.Destroy(); } // Spawn our 'tap to move' visual cue actor TapToMoveVisualActor = Spawn( class'KActorSpawnable',self,,,,,true); TapToMoveVisualActor.SetCollision( false, false, true ); // Disable collision TapToMoveVisualActor.SetHidden( true ); TapToMoveVisualActor.SetDrawScale3D( vect( 1, 1, 5 ) ); TapToMoveVisualActor.StaticMeshComponent.SetStaticMesh( TapToMoveVisualMesh ); TapToMoveVisualActor.SetPhysics( PHYS_None ); } /** * Make sure we destory the visual tap actor */ event Destroyed() { // Kill existing 'tap to move' actor, if any if( TapToMoveVisualActor != None ) { TapToMoveVisualActor.Destroy(); } super.Destroyed(); } /** * An event that is called after the first tick of GEngine. We are going to hijack this for * initialization purposes. */ event OnEngineInitialTick() { // If we are in preview mode, then skip the flyby, splash and tutorial if (WorldInfo.IsPlayInPreview() || WorldInfo.IsPlayInEditor()) { // Setup some of the default states TutorialStage = ETS_Done; ActivateControlGroup(); ResetMenu(); } else { // trigger Epic Citadel map stuff (see Kismet in EpicCitadel map) CauseEvent('IntroCam'); ConsoleCommand("mobile playsong town_render"); } } /** * The main purpose of this function is to size and reset zones. There's a lot of specific code in * here to reposition zones based on if it's an phone vs pad. */ function SetupZones() { local MobileInputZone Zone; local float Ratio; Super.SetupZones(); // If we have a game class, configure the zones if (MPI != None && WorldInfo.GRI.GameClass != none) { // Find the button zone that exits attract mode. Zone = MPI.FindZone("ExitAttractModeZone"); if (Zone != none) { Zone.OnTapDelegate = ExitAttractTap; } // Find the tap to move zone and setup the tutorial Zone = MPI.FindZone("TapTutorialZone"); if (Zone != none) { Zone.OnTapDelegate = TapToMoveTap; } else { `log("!!!WARNING!!! Tutorial will be broken due to Tap"); } // Find the look zone and setup the tutorial TutorialLookZone = MPI.FindZone("SwipeTutorialZone"); if (TutorialLookZone == none) { `log("!!!WARNING!!! Tutorial will be broken due to Swipe"); } // If we aren't supressing the splash screen, setup the pause menu if (!bSuppressSplash) { PauseMenu = MobileMenuPause(MPI.OpenMenuScene(class'MobileMenuPause')); SliderZone = MPI.FindZone("MenuSlider"); if (SliderZone != none) { SliderZone.OnTapDelegate = MenuSliderTap; SliderZone.OnProcessSlide = ProcessMenuSlide; SliderZone.SizeY = PauseMenu.Height; } } Ratio = ViewportSize.Y / ViewportSize.X; // Find the zone and hook up the delegate so we can perform tap to move Zone = MPI.FindZone("TapToMoveZone"); if (Zone != none) { Zone.OnTapDelegate = TapToMoveTap; } if (FreeLookZone != none) { FreeLookZone.OnTapDelegate = TapToMoveTap; if (Ratio == 0.75 || ViewportSize.X <= 480) { FreeLookZone.VertMultiplier *= 1.75; FreeLookZone.HorizMultiplier *= 3.25; FreeLookZone.Acceleration *= 0.5; } } // Setup the timer to check for inactivity / attract mode //SetTimer(1.0,true,'CheckInactivity'); // Setup a timer that will write out controller stats every 60 seconds. SetTimer(60.0,true,'SaveControllerStats'); // Activate the input group for the flyby (ie: no input) if (MPI != none) { MPI.ActivateInputGroup("InitialFlybyGroup"); } } } /** * Saves out the controller stats for processing */ function SaveControllerStats() { if ((StickLookZone != none) && (StickMoveZone != none) && (FreeLookZone != none)) { ConsoleCommand("mobile recordcontrolstats" @ StickMoveZone.TotalActiveTime @ StickLookZone.TotalActiveTime @ FreeLookZone.TotalActiveTime @ TotalTimeInTapToMove @ NoTapToMoves); StickMoveZone.TotalActiveTime = 0; StickLookZone.TotalActiveTime = 0; FreeLookZone.TotalActiveTime = 0; } TotalTimeInTapToMove = 0; NoTapToMoves = 0; } /** * Every second, we look at various metrics to see if the player has been active. If they haven't been, then * we want switch to attract mode */ function CheckInactivity() { // Quick out if we don't allow attract mode if (CastleGame(WorldInfo.Game) == none || CastleGame(WorldInfo.Game).bAllowAttractMode == false) { return; } //if the pause menu is open, or a submenu is open if ( LocalPlayer(Player).ViewportClient.bDisableWorldRendering || (PauseMenu != none && bPauseMenuOpen) || bIsInAttractMode || bCinematicMode || (MPI.MobileMenuStack.Length>1 && TutMenu == none)) { MPI.MobileInactiveTime = 0; } // Make the call... if (MPI.MobileInactiveTime > AutoAttractTime && !bIsInAttractMode && !bCinematicMode) { EnterAttractMode(); } } /** * Trace, but ignore volumes and triggers unless they are blockers (i.e. BlockingVolume) * * @param TraceOwner is the player's pawn * @param HitLocation holds the location were the trace ends * @param HitNormal holds the orientation of the surface normal where it hit * @param End is where we would like the trace to end * @param Start is where the trace is starting from */ simulated function Actor TraceForTapToMove(Pawn TraceOwner, out vector HitLocation, out vector HitNormal, vector End, vector Start) { local Actor HitActor; local vector HitLoc, HitNorm; local TraceHitInfo HitInfo; // Iterate over each actor along trace... foreach TraceOwner.TraceActors(class'Actor', HitActor, HitLoc, HitNorm, End, Start, , HitInfo,TRACEFLAG_Bullet) { // if it's not a trigger or a volume, use it! if ( (HitActor.bBlockActors || HitActor.bWorldGeometry) && (Volume(HitActor) == None && Trigger(HitActor)==None)) { HitLocation = HitLoc; HitNormal =HitNorm; return HitActor; } } // Found nothing non-volume or -trigger like :( return None; } /** * This is our event handler for taps. * * @param Zone The Zone we are managing * @param EventType The type of event that occurred * @param TouchLocation Where was the touch */ function bool TapToMoveTap(MobileInputZone Zone, ETouchType EventType, Vector2D TouchLocation) { local Vector2D RelLocation; local Vector Origin, Direction, Destination; local Vector HitLocation, HitNormal; local Actor HitActor; local bool bWantReverse; local bool bValidDestination; // Don't perform these traces if if are in attract mode, playing a cinematic or if the movement stick is // currently active. if( !bIsInAttractMode && !bCinematicMode && StickMoveZone.State == ZoneState_Inactive ) { // Figure out the location relative to the current viewport RelLocation.X = TouchLocation.X / ViewportSize.X; RelLocation.Y = TouchLocation.Y / ViewportSize.Y; // Check to see if the user touched near the very bottom of the viewport bWantReverse = false; //( RelLocation.Y >= 0.85 ); // If the user clicked near the bottom of the viewport and is already moving toward a destination, // then cancel the movement in progress. Basically, clicking near the bottom of the viewport is // used to stop moving. if( bWantReverse && IsInState('PlayerTapToMove') ) { // Draw an effect on the HUD MobileHudExt( MyHud ).StartTapToMoveEffect( TouchLocation.X, TouchLocation.Y ); // Play a 'move stopped' sound effect PlaySound( TapToMoveStopSound ); // Cancel touch to move GotoState('PlayerWalking'); } else { NoTapToMoves++; // If we're reversing then flip the touch point along the horizontal axis so we'll walk backwards // in the expected direction if( bWantReverse ) { RelLocation.x = 1.0 - RelLocation.x; } // Deproject and get the world location LocalPlayer(Player).Deproject(RelLocation, Origin, Direction); // If we're reversing then choose a location behind the player a little bit if( bWantReverse ) { Direction.Z = 0.0f; Destination = Origin - Direction * 512; } else { // Moving forward, so cast a way straight out far into the scene Destination = Origin + (Direction * 10240); } // Now trace in to the world and get where to go. HitActor = TraceForTapToMove(Pawn, HitLocation, HitNormal, Destination, Origin); if (HitActor != none) { Destination = HitLocation + (HitNormal * Pawn.GetCollisionHeight() * 2); } if (!PointReachable(Destination)) { // Still not reachable. Then find the ground and see if we can move there. Origin = Destination; Destination.Z = -65535; HitActor = TraceForTapToMove(Pawn, HitLocation, HitNormal, Destination, Origin); if (HitActor != none) { // We hit the ground, step back the collision Height; Destination = HitLocation; Destination.Z += Pawn.GetCollisionHeight(); } } // Unless we're reversing, if the desired location is somehow behind the player then fail the movement if( bWantReverse ) { bValidDestination = true; } else { bValidDestination = ( ( Normal( Destination - Pawn.Location ) dot Vector( Pawn.Rotation ) ) > 0.25 ); } // If the desired location is very close to the player then fail the movement if( ( VSize2D( Destination - Pawn.Location ) < 128.0 ) ) { bValidDestination = false; } if( bValidDestination ) { // Play a 'move succeeded' sound effect PlaySound( TapToMoveSound ); // Draw an effect on the HUD MobileHudExt( MyHud ).StartTapToMoveEffect( TouchLocation.X, TouchLocation.Y ); // Start moving to the new destination! DoTapToMove( Destination, !bWantReverse ); // Don't auto-look at destination when reversing } else { // Play a 'move failed' sound effect PlaySound( InvalidTapToMoveSound ); // Cancel an existing tap-to-move action, if there is one in progress if( IsInState('PlayerTapToMove') ) { GotoState('PlayerWalking'); } } } } return true; } /** * The player has clicked on a spot. Start the move * * @param NewDestination Where do we want to move to * @param bShouldLookAtDestination True if we should also automatically look toward the destination */ function DoTapToMove( vector NewDestination, bool bShouldLookAtDestination ) { // Update position of tap to move visual cue TapToMoveVisualActor.SetLocation( NewDestination + vect( 0, 0, 6 ) ); // Raise up a bit TapToMoveVisualActor.SetHidden( false ); TapToMoveVisualEffectStartTime = WorldInfo.RealTimeSeconds; TapToMoveDestination = NewDestination; LastDistToDestination = VSize(Pawn.Location - TapToMoveDestination); if( bShouldLookAtDestination ) { // Start automatically orientating toward the target point PlayerLookAtDestination(); } GotoState('PlayerTapToMove'); } /** * Initialize the look at system to point to the destination. */ function PlayerLookAtDestination() { if( !bLookAtDestination ) { // Start rotating! bLookAtDestination = true; } // Reset the time of last view change so that we're guaranteed to start looking toward the destination, // even if the user dragged the view right before touching to move TimeOfLastUserViewChange = 0; } /** * Tap to Move requires it's own special state for the player controller */ state PlayerTapToMove { /** * Setup the auto-rotate towards the destination */ event BeginState(Name PreviousStateName) { Super.BeginState(PreviousStateName); LastEnteredTapToMove = WorldInfo.RealTimeSeconds; // If we are in the tutorial, skip to the next step if (TutorialStage == ETS_Tap) { TutMenu.FadeOut(); TutMenu = MobileMenuControls(MPI.OpenMenuScene(class'UDKBase.MobileMenuControls')); TutMenu.Setup(false); MPI.ActivateInputGroup("SwipeTutorialGroup"); TutorialStage = ETS_Swipe; } } /** * Close everything down. */ event EndState(Name NextStateName) { // Track Stats TotalTimeInTapToMove += WorldInfo.RealTimeSeconds - LastEnteredTapToMove; Super.EndState(NextStateName); // Turn off the check to see if we are stuck Cleartimer('CheckIfStuck'); // Stop automatically orientating toward the target point bLookAtDestination = false; // Start hiding the visual cue if we haven't already if( TapToMoveVisualEffectEndTime < TapToMoveVisualEffectStartTime ) { TapToMoveVisualEffectEndTime = WorldInfo.RealTimeSeconds; } } /** * Check to see if the player is stuck. This is called every 1/2 second. It just looks to see if you have most past a threshold since * the last check and if not, considers you stuck. * * We also use this event to determine if enough time has passed that we should start auto-rotating again */ event CheckIfStuck() { local Float DistToDestination; DistToDestination = VSize(Pawn.Location - TapToMoveDestination); if (LastDistToDestination - DistToDestination < StuckThreshHold) { GotoState('PlayerWalking'); } else { LastDistToDestination = DistToDestination; } } /** * Each frame, look to see if the player has decided to use the virtual stick to move. If they have, * we want to abort tap to move. */ function PlayerTick(float DeltaTime) { if (IsStickMoveActive()) { GotoState('PlayerWalking'); } Global.PlayerTick(DeltaTime); } Begin: // Check to see if we're not making progress every so often SetTimer( 0.5, true, 'CheckIfStuck' ); // while we have a valid pawn and move target, and // we haven't reached the target yet while (Pawn != None && !Pawn.ReachedPoint(TapToMoveDestination,none)) { MoveToDirectNonPathPos(TapToMoveDestination,,1,true); } GotoState('PlayerWalking'); } /** * Called from PlayerMove, it's here that we adjust the viewport */ function ProcessViewRotation( float DeltaTime, out Rotator out_ViewRotation, Rotator DeltaRot ) { local float AnimProgress; local vector NewDrawScale; // If we are looking at a desintation, preset it for the super to manage if( bLookAtDestination ) { LookAtDestination = TapToMoveDestination - Pawn.Location; LookAtDestAutoPitchAmount = TapToMoveAutoPitchAmount; } Super.ProcessViewRotation( DeltaTime, out_ViewRotation, DeltaRot); // Animate the tap-to-move visual cue if( TapToMoveVisualEffectEndTime < TapToMoveVisualEffectStartTime ) { // We're fading in! AnimProgress = 1.0 - FMin( ( WorldInfo.RealTimeSeconds - TapToMoveVisualEffectStartTime ) / TapToMoveVisualAnimDuration, 1.0 ); AnimProgress = FInterpEaseInOut( 0.0, 1.0, AnimProgress, 1.5 ); TapToMoveVisualActor.SetRotation( TapToMoveVisualActor.Rotation + MakeRotator( 0, DeltaTime * ( TapToMoveVisualRotateSpeed + 8.0 * AnimProgress * TapToMoveVisualRotateSpeed ), 0 ) ); } else { // We're fading out! AnimProgress = FMin( ( WorldInfo.RealTimeSeconds - TapToMoveVisualEffectEndTime ) / TapToMoveVisualAnimDuration, 1.0 ); AnimProgress = FInterpEaseInOut( 0.0, 1.0, AnimProgress, 1.5 ); TapToMoveVisualActor.SetRotation( TapToMoveVisualActor.Rotation + MakeRotator( 0, DeltaTime * ( 1.0 - AnimProgress ) * TapToMoveVisualRotateSpeed, 0 ) ); if( AnimProgress >= 1.0 ) { // Hide the actor now that we're finished transitioning TapToMoveVisualActor.SetHidden( true ); } } NewDrawScale.X = 1.0 - AnimProgress * 1.0; // Squash to zero from normal size NewDrawScale.Y = 1.0 + AnimProgress * 0.5; // Grow to slightly bigger size NewDrawScale.Z = 1.25 - AnimProgress * 1.25; // Squash to zero from bigger size TapToMoveVisualActor.SetDrawScale3D( NewDrawScale ); } /** * If we're very close to the target, then go ahead and hide the visual cue */ simulated function CheckDistanceToDestination(float DistToDestination) { if( DistToDestination < TapToMoveVisualMinDist ) { if( TapToMoveVisualEffectEndTime < TapToMoveVisualEffectStartTime ) { TapToMoveVisualEffectEndTime = WorldInfo.RealTimeSeconds; } } } /** * notification when a matinee director track starts or stops controlling the ViewTarget of this PlayerController * * @param bNowControlling will be true if we are back in control */ event NotifyDirectorControl(bool bNowControlling, SeqAct_Interp CurrentMatinee) { super.NotifyDirectorControl(bNowControlling, CurrentMatinee); if( bNowControlling ) { // Make sure our tap-to-move actor is hidden TapToMoveVisualActor.SetHidden( true ); } } /** * Enter attrack mode. We need to make sure we kill any active menus/etc. */ exec function EnterAttractMode( bool BeginBenchmarking = false ) { // Make sure we're not currently auto-moving to a destination if( IsInState('PlayerTapToMove') ) { GotoState('PlayerWalking'); } // Kill the tutorial menu if (TutMenu != none) { TutMenu.FadeOut(); TutMenu = none; MPI.ActivateInputGroup("UberGroup"); MobileHudExt(myHUD).FlashSticks(); TutorialStage = ETS_Done; } // Hide the on screen help if it's there if (PauseMenu != none) { PauseMenu.ReleaseHelp(); } // Go in to attract mode CauseEvent('PlayMatinee'); bIsInAttractMode = true; bIsInBenchmarkMode = BeginBenchmarking; bBenchmarkLoopCompleted = false; BenchmarkNumFrames = 0; BenchmarkElapsedTime = 0.0; ResetMenu(); MPI.ActivateInputGroup("AttractGroup"); } exec function OnFlyThroughLoopCompleted() { // Set the benchmark loop completed flag so that we can calculate and display the results of the benchmark fly through bBenchmarkLoopCompleted = true; } /** * Leave attract mode */ exec function ExitAttractMode() { if (bIsInBenchmarkMode) { PauseMenu.InputOwner.Outer.ConsoleCommand("mobile benchmark end"); } bIsInAttractMode = false; bIsInBenchmarkMode = false; bBenchmarkLoopCompleted = false; MPI.MobileInactiveTime = 0; CauseEvent('StopMatinee'); ActivateControlGroup(); ResetMenu(); } /** * Delegate that gets called when the exit attact mode button is tapped */ function bool ExitAttractTap(MobileInputZone Zone, ETouchType EventType, Vector2D TouchLocation) { ExitAttractMode(); PauseMenu.SetDefaultUI(); // set the correct UI return true; } /** * Automatically slide to a new location */ function AutoSlide(float Destination) { SliderStart = SliderZone.CurrentLocation.Y; SliderEnd = Destination; SliderTravelTime = 0; bAutoSlide = true; } /** * Reset the pause menu */ function ResetMenu() { if (bPauseMenuOpen) { PauseMenu.OnResetMenu(); AutoSlide(SliderZone.Y); bPauseMenuOpen = false; PlaySound( CloseMenuSound ); } } /** * Force the Pause Menu to open */ function OpenMenu() { if (!bPauseMenuOpen) { bPauseMenuOpen = true; AutoSlide(PauseMenu.ShownSize); PlaySound( OpenMenuSound ); } } /** * Depending on the state of the pause menu, a tap on it's nub will either auto-open or auto-close it. * This delegate manages the tap. */ function bool MenuSliderTap(MobileInputZone Zone, ETouchType EventType, Vector2D TouchLocation) { if (bPauseMenuOpen) { ResetMenu(); } else { OpenMenu(); } return true; } /** * When you touch and drag on the nub, this code determines what to do. */ function bool ProcessMenuSlide(MobileInputZone Zone, ETouchType EventType, int SlideValue, Vector2D ViewportSizes) { // Align the menu to the touch. PauseMenu.Top = Zone.CurrentLocation.Y - PauseMenu.Height; // somehow the zone size is being reset (on device, but not PC), so this just fixes it. mildly hacky, but no real penalty. Zone.SizeY = PauseMenu.Height; // If we are releasing the menu, see if we need to reset, or if we need to open if (EventType == Touch_Ended && !bPauseMenuOpen) { if (Zone.CurrentLocation.Y >= PauseMenu.ShownSize) { OpenMenu(); } else { AutoSlide(SliderZone.Y); } } return true; } /** * Handle any animations and time criticl code */ function PlayerTick(float DeltaTime) { local int SettingsLocationX; Super.PlayerTick(DeltaTime); if (TutorialStage == ETS_Swipe) { if (TutorialLookZone.State != ZoneState_Inactive) { TutMenu.FadeOut(); TutMenu = none; MPI.ActivateInputGroup("UberGroup"); MobileHudExt(myHUD).FlashSticks(); TutorialStage = ETS_Done; } } // Trigger the fading of the Controls Help screen that we bring up on map load if ( !bDoneInitialFade ) { // @todo: Disabled this for intermediate demo; Consider re-enabling later. // PauseMenu.FadeOutControlsMenu(); bDoneInitialFade = TRUE; } // Handle the menu sliding back in to place if (bAutoSlide) { SliderZone.CurrentLocation.Y = FInterpEaseInOut(SliderStart,SliderEnd, SliderTravelTime/SliderTravelDuration,3.0); SliderTravelTime += DeltaTime; if (SliderTravelTime >= SliderTravelDuration) { SliderZone.CurrentLocation.Y = SliderEnd; bAutoSlide = false; if (!bPauseMenuOpen) { if (bIsInAttractMode) { PauseMenu.SetAttractModeUI(bIsInBenchmarkMode); } else { PauseMenu.SetDefaultUI(); } } } PauseMenu.Top = SliderZone.CurrentLocation.Y - PauseMenu.Height; } // Only pull out the settings menu if it's available (only Android) if (PauseMenu.MenuObjects.length >= 5) { SettingsLocationX = FInterpEaseInOut(MyHUD.SizeX, PauseMenu.Width - PauseMenu.MenuObjects[4].Width + 2, FClamp(SliderZone.CurrentLocation.Y / (PauseMenu.ShownSize - SliderZone.Y), 0.0, 1.0), 3.0); PauseMenu.MenuObjects[4].Left = SettingsLocationX; } // If we are currently benchmarking, track the number of frames and elapsed time. // Note that this assumes a TimeDilation of 1.0 and doesn't properly handle the cases where DeltaTime is clamped because it was super long or super short, but in EpicCitadel benchmark mode these shouldn't be problems in practice. if( bIsInBenchmarkMode && !bBenchmarkLoopCompleted ) { BenchmarkNumFrames += 1; BenchmarkElapsedTime += DeltaTime; } } /** * Show the splash screen */ exec function ShowSplash() { // Activate the tutorial input group then show the splash MPI.ActivateInputGroup("TapTutorialGroup"); if (!bSplashHasBeenShown && !bSuppressSplash && MPI != none) { bSplashHasBeenShown = true; MPI.OpenMenuScene(class'UDKBase.MobileMenuSplash'); } } /** * Display the control help on the screen */ exec function FlashHelp(float Duration) { if (!bPauseMenuOpen) { PauseMenu.FlashHelp(Duration); } } /** * Start the tutorials */ function StartTutorials() { TutMenu = MobileMenuControls(MPI.OpenMenuScene(class'UDKBase.MobileMenuControls')); TutMenu.Setup(true); TutorialStage = ETS_Tap; } exec function SetFootstepsToStone() { FootstepSounds[0]=SoundCue'CastleAudio.Player.Footstep_Walk_01_Cue'; FootstepSounds[1]=SoundCue'CastleAudio.Player.Footstep_Walk_02_Cue'; FootstepSounds[2]=SoundCue'CastleAudio.Player.Footstep_Walk_03_Cue'; FootstepSounds[3]=SoundCue'CastleAudio.Player.Footstep_Walk_04_Cue'; FootstepSounds[4]=SoundCue'CastleAudio.Player.Footstep_Walk_05_Cue'; FootstepSounds[5]=SoundCue'CastleAudio.Player.Footstep_Walk_06_Cue'; } exec function SetFootstepsToSnow() { FootstepSounds[0]=SoundCue'CastleAudio.Player.Footstep_Snow01_Cue'; FootstepSounds[1]=SoundCue'CastleAudio.Player.Footstep_Snow02_Cue'; FootstepSounds[2]=SoundCue'CastleAudio.Player.Footstep_Snow03_Cue'; FootstepSounds[3]=SoundCue'CastleAudio.Player.Footstep_Snow04_Cue'; FootstepSounds[4]=SoundCue'CastleAudio.Player.Footstep_Snow05_Cue'; FootstepSounds[5]=SoundCue'CastleAudio.Player.Footstep_Snow06_Cue'; } defaultproperties { StuckThreshHold=25 TapToMoveAutoPitchAmount=0.25 TapToMoveVisualMesh=StaticMesh'CastleEffects.TouchToMoveArrow' TapToMoveVisualMinDist=230 TapToMoveVisualRotateSpeed=100000 TapToMoveVisualAnimDuration=0.3 AutoAttractTime=45 TapToMoveSound=SoundCue'CastleAudio.UI.UI_TouchToMove_Cue' InvalidTapToMoveSound=SoundCue'CastleAudio.UI.UI_InvalidTouchToMove_Cue' TapToMoveStopSound=SoundCue'CastleAudio.UI.UI_StopTouchToMove_Cue' OpenMenuSound=SoundCue'CastleAudio.UI.UI_MainMenu_Cue' CloseMenuSound=SoundCue'CastleAudio.UI.UI_OK_Cue' bSplashHasBeenShown=false SliderTravelDuration=0.3 TutorialStage=ETS_None FootstepSounds(0)=SoundCue'CastleAudio.Player.Footstep_Walk_01_Cue' FootstepSounds(1)=SoundCue'CastleAudio.Player.Footstep_Walk_02_Cue' FootstepSounds(2)=SoundCue'CastleAudio.Player.Footstep_Walk_03_Cue' FootstepSounds(3)=SoundCue'CastleAudio.Player.Footstep_Walk_04_Cue' FootstepSounds(4)=SoundCue'CastleAudio.Player.Footstep_Walk_05_Cue' FootstepSounds(5)=SoundCue'CastleAudio.Player.Footstep_Walk_06_Cue' }