0 of 0

File information

Last updated

Original upload

Created by

lasyan3

Uploaded by

lasyan3

Virus scan

Safe to use

111 comments

  1. deleted2868792
    deleted2868792
    • account closed
    • 2 kudos
    could you let me know what to change in the script so the mod would still works as intended but roach stops just before going into deep water?

    I like that he can cross rivers/etc....but it is annoying that he "kills" himself and disapears because he falls in deep water....i would like to make him a bit more "cleaver". XD
    1. lasyan3
      lasyan3
      • member
      • 35 kudos
      sorry it's been too long I made this mod. You should try by yourself, comparing the mod's files with vanilla ones and figure how to do (if possible).
    2. JovianStone
      JovianStone
      • supporter
      • 37 kudos
      Check out exploration.ws at line 1120 :

      content\scripts\game\vehicles\horse\states\exploration.ws

      default WATER_MAX_DEPTH = 1.0

      That'll make it vanilla water depth.
    3. JovianStone
      JovianStone
      • supporter
      • 37 kudos
      Actually never mind, that doesn't work. But this works, just search for
      "Mod Water Check Only" to see what I changed, and compare to mod. Sorry, but I can't figure out how to paste
      code without losing all indentations....

      Spoiler:  
      Show

      /***********************************************************************/
      /** © 2015 CD PROJEKT S.A. All rights reserved.
      /** THE WITCHER® is a trademark of CD PROJEKT S. A.
      /** The Witcher game is based on the prose of Andrzej Sapkowski.
      /***********************************************************************/
      enum EHorseWaterTestResult
      {
      HWTR_Normal,
      HWTR_Adjusted,
      HWTR_ToDeep
      }

      state Exploration in W3HorseComponent
      {
      private var parentActor : CActor;

      private var isStopping : bool;
      private var isSlowlyStopping : bool;
      private var destSpeed : float;
      private var currSpeed : float;
      private var staminaCooldown : float;
      private var staminaCooldownTimer : float;
      private var staminaBreak : bool;
      private var speedImpulseTimestamp : float;
      private var dismountRequest : bool;
      private var roadFollowBlock : float;
      private var speedLocks : array<name>;
      private var speedRestriction : float;
      private var useSimpleStaminaManagement : bool;
      private var inclinationCheckCollisionGroups : array<name>;
      private var waterCheckCollisionGroups : array<name>;
      private var threatSum : float;
      private var triedDoubleTap : bool;
      private var mac : CMovingAgentComponent;
      private var isFollowingRoad : bool;
      private var shouldGoToCanterAfterStop : bool;
      private var grassCollider : CComponent;

      private var currSpeedSound : float;
      private var desiredSpeedSound : float;

      private var jumpStartPos, jumpEndPos : Vector;
      privatevar noSaveLock : int;

      const var MIN_SPEED : float;
      const var SLOW_SPEED : float;
      const var WALK_SPEED : float;
      const var TROT_SPEED : float;
      const var GALLOP_SPEED : float;
      const var CANTER_SPEED : float;

      default isStopping = false;
      default staminaCooldown = 3.f;
      default dismountRequest = false;
      default speedRestriction = 5.f;
      default useSimpleStaminaManagement = false;


      default MIN_SPEED = 0.f;
      default SLOW_SPEED = 0.5f;
      default WALK_SPEED = 1.f;
      default TROT_SPEED = 2.f;
      default GALLOP_SPEED = 3.f;
      default CANTER_SPEED = 4.f;





      event OnEnterState( prevStateName : name )
      {
      super.OnEnterState( prevStateName );

      theInput.RegisterListener( this, 'OnSpeedPress', 'Canter' );
      theInput.RegisterListener( this, 'OnSpeedHold', 'Gallop' );
      theInput.RegisterListener( this, 'OnDecelerate', 'Decelerate' );
      theInput.RegisterListener( this, 'OnStop', 'Stop' );
      theInput.RegisterListener( this, 'OnHorseJump', 'HorseJump' );
      theInput.RegisterListener( this, 'OnHorseDismountKeyboard', 'HorseDismount' );

      parentActor = (CActor)(parent.GetEntity());
      mac = parentActor.GetMovingAgentComponent();

      parentActor.SetBehaviorVariable( 'isCanterEnabled', 0.0 );

      Prepare();
      InitCollisionGroups();
      ResetSoundParameters();

      mac.SetEnabledFeetIK(true);

      theGame.GetGuiManager().EnableHudHoldIndicator(IK_Pad_B_CIRCLE, IK_None, "panel_input_action_horsedismount", 0.4, 'HorseDismount');

      grassCollider = parent.GetEntity().GetComponent( "CDynamicColliderComponent4" );
      }

      event OnLeaveState( nextStateName : name )
      {
      CleanUpJump();
      ResetForceStop();
      Restore();
      UnregisterInput();

      mac.SetEnabledFeetIK(true);

      super.OnLeaveState( nextStateName );
      }

      private function CleanUpJump()
      {
      EndJump();
      OnBehJumpEnded();
      }

      private function UnregisterInput()
      {
      theInput.UnregisterListener( this, 'Canter' );
      theInput.UnregisterListener( this, 'Gallop' );
      theInput.UnregisterListener( this, 'Decelerate' );
      theInput.UnregisterListener( this, 'Stop' );
      theInput.UnregisterListener( this, 'HorseJump' );
      theInput.UnregisterListener( this, 'HorseDismount' );
      theGame.GetGuiManager().DisableHudHoldIndicator();
      }





      private function IsSpeedLocked( optional ignoredLock : name ) : bool
      {
      if( ignoredLock != '' )
      {
      if( speedLocks.Size() == 1 && speedLocks.Contains( ignoredLock ) )
      {
      return false;
      }
      else
      {
      return speedLocks.Size() > 0;
      }
      }
      else
      {
      return speedLocks.Size() > 0;
      }
      }

      private function ToggleSpeedLock( lockName : name, toggle : bool )
      {
      if( toggle )
      {
      if( !speedLocks.Contains( lockName ) )
      {
      speedLocks.PushBack( lockName );
      }
      }
      else
      {
      speedLocks.Remove( lockName );

      if( !speedLocks.Contains( 'OnStop' ) && lockName != 'OnGallop' && theInput.IsActionPressed( 'Gallop' ) && !dismountRequest && currSpeed <= GALLOP_SPEED )
      {
      if( shouldGoToCanterAfterStop )
      {
      destSpeed = CANTER_SPEED;
      }
      GallopPressed();
      }
      }
      }

      private function LeaveThisState()
      {
      timeAfterDismountFinished = 0.f;
      parent.PopState( true );
      }





      var threatApplicationTimestamp : float;

      private var dismountFinishedTimeStamp : float;
      private var timeAfterDismountFinished : float;

      default dismountFinishedTimeStamp = -1.f;
      default timeAfterDismountFinished = 0.f;

      event OnTick( dt : float )
      {
      parent.OnTick( dt );

      if( dismountRequest || thePlayer.IsActionAllowed( EIAB_Movement ) )
      {
      UpdateLogic( dt );
      UpdateDebugGUI();
      }
      else
      {
      ResetRotation();
      }

      if ( !parent.user )
      {
      timeAfterDismountFinished += dt;


      if ( timeAfterDismountFinished > 2.f )
      {
      LeaveThisState();
      }
      }
      }

      event OnMountStarted( entity : CEntity, vehicleSlot : EVehicleSlot )
      {
      parent.OnMountStarted( entity, vehicleSlot );
      LeaveThisState();
      }

      event OnMountFinished( entity : CEntity )
      {
      parent.OnMountFinished(entity);
      }

      event OnDismountStarted( entity : CEntity )
      {
      thePlayer.SetBehaviorVariable( 'playerWouldLikeToMove', 0.0f );
      UnregisterInput();
      parent.OnDismountStarted( entity );
      }
      event OnDismountFinished( entity : CEntity, vehicleSlot : EVehicleSlot )
      {
      parent.OnDismountFinished( entity, vehicleSlot );
      parent.ResetPanic();
      timeAfterDismountFinished = 0.f;
      }

      event OnIdleBegin()
      {
      parent.OnIdleBegin();
      isInJumpAnim = false;
      isStopping = false;
      isSlowlyStopping = false;

      if ( !parent.user )
      LeaveThisState();

      ResetForceStop();


      }

      event OnIdleEnd()
      {
      parent.OnIdleEnd();
      }

      event OnHorseFastStopBegin()
      {
      isStopping = true;
      }

      event OnHorseFastStopEnd()
      {
      if ( dismountRequest )
      parent.IssueCommandToDismount( DT_normal );

      isStopping = false;
      }

      event OnTakeDamage( action : W3DamageAction )
      {
      var actorAttacker : CNewNPC;
      var isMonster : bool;
      var threatMult : int;

      if( parentActor.HasAbility( 'DisableHorsePanic' ) || thePlayer.HasBuff( EET_Mutagen25 ) )
      return false;

      actorAttacker = (CNewNPC)action.attacker;
      isMonster = actorAttacker.IsMonster();

      if( isMonster )
      threatMult = 2;
      else
      threatMult = 1;

      parentActor.AddPanic( actorAttacker.GetThreatLevel() * 10 * threatMult );
      }


      event OnCriticalEffectAdded( criticalEffect : ECriticalStateType )
      {
      if( parentActor.HasAbility( 'DisableHorsePanic' ) || thePlayer.HasBuff( EET_Mutagen25 ) )
      {
      if( thePlayer.IsActionAllowed( EIAB_Movement ) )
      {
      return false;
      }
      else if( !isInJumpAnim )
      {
      parent.ShakeOffRider( DT_shakeOff );
      }
      }
      else if( criticalEffect != ECST_Swarm )
      {
      parentActor.AddPanic( 100 );


      if( !thePlayer.IsInCombat() )
      {
      parent.ShakeOffRider( DT_shakeOff );
      }
      }
      }

      var cachedCombatAction : EVehicleCombatAction;
      event OnCombatAction( action : EVehicleCombatAction )
      {
      cachedCombatAction = action;

      if ( action == EHCA_Attack || action == EHCA_ShootCrossbow || action == EHCA_ThrowBomb )
      {
      if ( currSpeed > MIN_SPEED )
      {
      if ( action != EHCA_Attack )
      speedRestriction = GALLOP_SPEED;

      ToggleSpeedLock('OnAttack',true);
      }
      }
      else if ( action == EHCA_CastSign )
      speedRestriction = TROT_SPEED;
      else
      speedRestriction = GALLOP_SPEED;
      }

      event OnCombatActionEnd()
      {
      speedRestriction = CANTER_SPEED;
      ToggleSpeedLock('OnAttack',false);
      }

      event OnSettlementEnter()
      {
      /* ++MOD Gallop in Settlements
      if( thePlayer.GetIsHorseRacing() )
      {
      --MOD Gallop in Settlements */
      return false;
      /* ++MOD Gallop in Settlements
      }
      else
      {
      speedRestriction = GALLOP_SPEED;


      if( currSpeed > speedRestriction )
      thePlayer.DisplayActionDisallowedHudMessage(EIAB_Undefined, , true);
      }
      --MOD Gallop in Settlements */
      }

      event OnSettlementExit()
      {
      speedRestriction = CANTER_SPEED;
      }

      event OnCanGallop()
      {
      return speedRestriction >= CANTER_SPEED && CanCanter();
      }

      event OnCanCanter()
      {
      if ( speedRestriction >= GALLOP_SPEED )
      return true;
      return false;
      }

      event OnStopTheVehicleInstant()
      {
      Reset();
      parent.OnStopTheVehicleInstant();
      }

      private var stopRequest : bool;

      event OnForceStop()
      {
      destSpeed = MIN_SPEED;
      speedRestriction = MIN_SPEED;
      stopRequest = true;
      }

      event OnHorseStop()
      {
      destSpeed = MIN_SPEED;
      }

      private function ResetForceStop()
      {
      if ( stopRequest )
      {
      stopRequest = false;
      speedRestriction = CANTER_SPEED;
      }
      }

      event OnJumpHack()
      {
      if( !isInJumpAnim )
      parent.GenerateEvent( 'jumpHACK' );
      }

      private var isRefusingToGo : bool;
      public var collisionAnimTimestamp : float;
      public var collsionAnimCooldown : float;
      default collsionAnimCooldown = 1.0;

      event OnHorseWalkBackWallStart()
      {
      isRefusingToGo = true;
      }

      event OnHorseWalkBackWallEnd()
      {
      isRefusingToGo = false;
      }

      private function CanPlayCollisionAnim() : bool
      {
      return collisionAnimTimestamp + collsionAnimCooldown < theGame.GetEngineTimeAsSeconds();
      }





      private var prediction : CHorsePrediction;

      private final function Prepare()
      {
      Reset();

      if( !prediction )
      {
      prediction = new CHorsePrediction in this;
      }
      }

      private final function Restore()
      {
      Reset();

      parent.InternalResetVariables();

      thePlayer.GetVisualDebug().RemoveBar( 'horseSpeed' );
      thePlayer.GetVisualDebug().RemoveBar( 'horseStamina' );
      thePlayer.GetVisualDebug().RemoveBar( 'horseStaminaBar' );
      thePlayer.GetVisualDebug().RemoveBar( 'horsePanic' );
      thePlayer.GetVisualDebug().RemoveBar( 'pitch' );
      }

      private final function Reset()
      {
      currSpeed = MIN_SPEED;
      destSpeed = MIN_SPEED;

      speedLocks.Clear();

      staminaBreak = false;
      dismountRequest = false;
      stopRequest = false;
      isInJumpAnim = false;
      isStopping = false;

      startSlidingTimeStamp = -1.f;
      notSlidingTimeStamp = -1.f;

      parent.GetEntity().SetBehaviorVariable('rotationBlend',0.f);

      theGame.ReleaseNoSaveLock( noSaveLock );

      theGame.GetGuiManager().EnableHudHoldIndicator(IK_Pad_B_CIRCLE, IK_None, "panel_input_action_horsedismount", 0.4, 'HorseDismount');
      }

      private final function ResetRotation()
      {
      parent.InternalSetRotation( 0.f );
      parent.InternalSetDirection( 0.f );
      }





      private const var INPUTMAG_TROT : float;
      private const var INPUTMAG_WALK : float;

      default INPUTMAG_TROT = 0.9;
      default INPUTMAG_WALK = 0.6;

      private final function ProcessControlInput( lr : float, fb : float, timeDelta : float, useLocalSpace : bool )
      {
      var inputVec, inputVecInWS : Vector;
      var mac : CMovingAgentComponent;
      var horseHeadingInCamSpace : float;
      var dir, rot : float;
      var inputMagnitude : float;
      var predInfo : SPredictionInfo;
      var braking : bool;
      var prevDir: float;
      var steeringCorrection : bool;
      var stickInput : bool;

      if( ( !thePlayer.GetIsMovable() && !dismountRequest ) || speedRestriction == MIN_SPEED )
      {
      destSpeed = MIN_SPEED;
      parent.InternalSetRotation( 0.f );
      parent.InternalSetDirection( 0.f );
      return;
      }

      if( lr || fb )
      {
      inputVec.X = lr;
      inputVec.Y = fb;
      if( useLocalSpace )
      inputVecInWS = GetInputVectorInLocalSpace( lr, fb );
      else
      inputVecInWS = GetInputVectorInCamSpace( lr, fb );

      stickInput = true;
      }
      else
      {
      inputVec = parent.GetEntity().GetHeadingVector();
      inputVecInWS = inputVec;
      }

      if( ShouldApplyCorrection( lr, fb ) )
      {
      steeringCorrection = ApplyCorrection( inputVecInWS, dir, lr, fb );
      thePlayer.GetVisualDebug().AddText( 'SteeringCorrection', "SteeringCorrection : On ", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) );
      }
      else
      {
      if( isFollowingRoad && roadFollowBlock == 0.0 )
      {
      roadFollowBlock = 1.0;
      isFollowingRoad = false;
      mac= ((CActor)parent.GetEntity()).GetMovingAgentComponent();
      mac.ResetRoadFollowing();
      }
      thePlayer.GetVisualDebug().AddText( 'SteeringCorrection', "SteeringCorrection : Off", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 255, 0, 0 ) );
      }

      if( isFollowingRoad && ( lr || fb ) && roadFollowBlock == 0.0 )
      {
      roadFollowBlock = 1.0;
      isFollowingRoad = false;
      mac= ((CActor)parent.GetEntity()).GetMovingAgentComponent();
      mac.ResetRoadFollowing();
      }

      if( lr || fb || steeringCorrection )
      {
      inputMagnitude = VecLength2D( inputVec );

      if( steeringCorrection )
      {

      }
      else if( useLocalSpace )
      {
      dir = -VecHeading( inputVec );
      }
      else
      {
      horseHeadingInCamSpace = AngleDistance( theCamera.GetCameraHeading(), parent.GetHeading() );
      dir = AngleDistance( -VecHeading( inputVec ), horseHeadingInCamSpace );
      }

      dir = AngleNormalize180( dir ) / 180.f;

      if( steeringCorrection )
      {
      rot = dir * 2 * inputMagnitude;
      }
      else if( useLocalSpace )
      {
      if( theInput.LastUsedGamepad() )
      {
      rot = ClampF(dir,-0.5,0.5) * inputMagnitude;
      if ( currSpeed <= TROT_SPEED )
      rot *= 0.8;
      }
      else
      rot = dir;
      }
      else
      {
      if ( currSpeed <= TROT_SPEED )
      rot = 2 * dir * inputMagnitude;
      else
      rot = 1.5 * dir * inputMagnitude;
      }

      prevDir = parent.InternalGetDirection();

      if( ( speedLocks.Contains( 'OnStop' ) && AbsF(dir) < 0.17f ) )
      {
      parent.InternalSetRotation( 0.f );
      parent.InternalSetDirection( 0.f );
      }

      else if( inputMagnitude >= 0.9 && ( useLocalSpace && AbsF(dir) >= 0.75f ) || ( !useLocalSpace && AbsF( dir ) > 0.75f && AbsF( prevDir ) < 0.17f && destSpeed > MIN_SPEED ) && !parent.IsInCustomSpot() )
      {
      // +++===modRoachNeverStops
      //parent.InternalSetRotation( 0.f );
      //parent.InternalSetDirection( 0.f );
      //destSpeed = MIN_SPEED;
      //braking = true;
      //PlayVoicesetSlowerHorse();
      // ---===modRoachNeverStops
      }
      else if( parent.riderSharedParams.mountStatus != VMS_mountInProgress )
      {

      if ( prevDir > 0.9f && dir < -0.7f )
      {
      if ( useLocalSpace )
      parent.InternalSetRotation( 0.5f );
      else
      parent.InternalSetRotation( 1.f );

      parent.InternalSetDirection( 1.f );
      }
      else if ( prevDir < -0.9f && dir > 0.7f )
      {
      if ( useLocalSpace )
      parent.InternalSetRotation( -0.5f );
      else
      parent.InternalSetRotation( -1.f );

      parent.InternalSetDirection( -1.f );
      }
      else
      {
      parent.InternalSetRotation( rot );
      parent.InternalSetDirection( dir );
      }
      }

      if( braking )
      {
      }
      else if( !IsSpeedLocked() && stickInput && currSpeed < GALLOP_SPEED && ( currSpeed > MIN_SPEED || AbsF( dir ) < 0.05 ) )
      {
      if( currSpeed < TROT_SPEED )
      {
      if( inputMagnitude > INPUTMAG_TROT )
      {
      destSpeed = TROT_SPEED;
      }
      else if( inputMagnitude > INPUTMAG_WALK )
      {
      destSpeed = WALK_SPEED;
      }
      else
      {
      destSpeed = SLOW_SPEED;
      }

      SpursKick();
      speedImpulseTimestamp = theGame.GetEngineTimeAsSeconds();
      }
      }
      }
      else
      {
      ResetRotation();

      if( speedImpulseTimestamp + 0.2 > theGame.GetEngineTimeAsSeconds() )
      {
      destSpeed = MIN_SPEED;
      }

      if( destSpeed > MIN_SPEED )
      {
      predInfo = prediction.CollectPredictionInfo( parent, 10.f, 0.f, parent.inWater );

      if( predInfo.turnAngle != 0.f )
      {
      dir = -predInfo.turnAngle / 180.f;
      rot = dir;



      parent.InternalSetRotation( rot );
      parent.InternalSetDirection( dir );
      }
      }
      }

      if ( IsRiderInCombatAction() )
      OnCombatAction( cachedCombatAction );
      }

      private function ShouldApplyCorrection( stickInputX : float, stickInputY : float ) : bool
      {
      var inputVec : Vector;
      var inputHeading : float;
      var horseHeading : float;
      var angleDistanceBetweenInputAndHorse : float;

      inputVec = GetInputVectorInCamSpace( stickInputX, stickInputY );
      angleDistanceBetweenInputAndHorse = AbsF( AngleDistance( VecHeading( inputVec ), parent.GetHeading() ) );

      if( !stickInputX && !stickInputY )
      {
      if( theInput.IsActionPressed( 'Canter' ) )
      return true;
      else
      return false;
      }
      else if( currSpeed > TROT_SPEED && angleDistanceBetweenInputAndHorse > 55.0 )
      {
      return false;
      }
      else if( currSpeed > MIN_SPEED && angleDistanceBetweenInputAndHorse < 55.0 )
      {
      return true;
      }
      else if( isStopping )
      {
      return true;
      }
      else
      return false;

      }

      private function ApplyCorrection( inputVector : Vector, out correctedDir, stickInputX : float, stickInputY : float ) : bool
      {
      var stickInput : bool;
      var horseHeadingVec: Vector;
      var mac : CMovingAgentComponent;
      var currentDir : float;

      var speed : float;
      var speedModifier : float;
      var dirModifier : float = 1.0;
      var followRoad : bool;
      var maxAngleForAdjustingDir : float;

      var cachedVec : Vector;
      var correctedDirV : Vector;
      var desiredDirectionVec : Vector;
      var angleDistance : float;

      var startPos, endPos : Vector;

      stickInput = stickInputX || stickInputY;
      horseHeadingVec = parent.GetEntity().GetHeadingVector();
      mac= ((CActor)parent.GetEntity()).GetMovingAgentComponent();
      currentDir = parent.GetEntity().GetHeading();
      speedModifier = MaxF( 0.25, stickInputY );

      if( currSpeed == CANTER_SPEED )
      {
      speed = 18.75;

      if( !stickInput && !thePlayer.GetIsHorseRacing() )
      {
      dirModifier = 3.0;
      followRoad = true;
      maxAngleForAdjustingDir = 90.0;
      }
      else
      {
      dirModifier = 2.0;
      speed *= speedModifier;
      maxAngleForAdjustingDir = 15.0;
      }

      correctedDirV = VecNormalize2D( inputVector * 0.3 + horseHeadingVec * 0.7 );
      }
      else if( currSpeed == GALLOP_SPEED )
      {
      speed = 12.5;

      if ( !stickInput && !thePlayer.GetIsHorseRacing() )
      {
      dirModifier = 2.0;
      followRoad = true;
      maxAngleForAdjustingDir = 90.0;
      }
      else
      {
      dirModifier = 2.0;
      speed *= speedModifier;
      maxAngleForAdjustingDir = 15.0;
      }

      correctedDirV = VecNormalize2D( inputVector * 0.3 + horseHeadingVec * 0.7 );
      }
      else
      {
      speed = 3.75 * speedModifier;
      dirModifier = 1.5;
      maxAngleForAdjustingDir = 90.0;

      correctedDirV = VecNormalize2D( inputVector * 0.4 + horseHeadingVec * 0.6 );
      }

      cachedVec = correctedDirV;

      desiredDirectionVec = inputVector;

      if( followRoad && !thePlayer.GetIsHorseRacing() && roadFollowBlock == 0.0 )
      {
      if( mac.StartRoadFollowing( speed, 45.0, 10.0, correctedDirV ) )
      isFollowingRoad = true;
      else
      isFollowingRoad = false;
      }

      if( !parent.IsInCustomSpot() )
      {
      if( !isFollowingRoad )
      mac.AdjustRequestedMovementDirectionNavMesh( correctedDirV, speed, maxAngleForAdjustingDir, 10, 6, desiredDirectionVec );
      }
      else
      {
      if( currSpeed > TROT_SPEED )
      {
      isFollowingRoad = true;
      }
      }


      if( cachedVec == correctedDirV )
      {
      correctedDirV = inputVector;
      }

      correctedDir = VecHeading( correctedDirV );
      angleDistance = AngleDistance( currentDir, correctedDir );

      correctedDir = ClampF( angleDistance * dirModifier, -180, 180 );


      startPos = parent.GetEntity().GetWorldPosition();
      endPos = startPos + speed * correctedDirV;
      ((CActor)parent.GetEntity()).GetVisualDebug().AddArrow( 'correctionLine', startPos, endPos, 1, 0.3, 0.3, true, Color( 255, 255, 255 ), true, 1.0 );

      return true;
      }

      private function ShouldStopBecauseOfCorrection( inputVecInWS : Vector, correctionVec : Vector ) : bool
      {
      var angleDistBetwenHorseHeadingAndInput : float;
      var angleDistBetwenHorseHeadingAndCorrection : float;
      var angleDistBetwenInputAndCorrection : float;
      var horseHeading : float;

      horseHeading = parent.GetEntity().GetHeading();
      angleDistBetwenHorseHeadingAndInput = AngleDistance( horseHeading, VecHeading(inputVecInWS) );
      angleDistBetwenHorseHeadingAndCorrection = AngleDistance( horseHeading, VecHeading(correctionVec) );
      angleDistBetwenInputAndCorrection = AngleDistance( VecHeading(inputVecInWS), VecHeading(correctionVec) );


      if ( AbsF(angleDistBetwenInputAndCorrection) < 10 )
      return false;

      if ( AbsF(angleDistBetwenHorseHeadingAndInput) > 45 && ( AbsF(angleDistBetwenHorseHeadingAndCorrection) > 150 || AbsF(angleDistBetwenInputAndCorrection) > 45 ) )
      {
      return true;
      }

      return false;
      }

      const var HEADING_WT : float;
      const var INPUT_WT : float;

      default HEADING_WT = 1.0;
      default INPUT_WT = 0.25;







      const var NAVDATA_RADIUS : float;
      const var NAVDATA_LENGTH_MOD_TROT : float;
      const var NAVDATA_LENGTH_MOD_GALLOP : float;
      const var NAVDATA_LENGTH_MOD_CANTER : float;

      default NAVDATA_RADIUS = 2.0;
      default NAVDATA_LENGTH_MOD_TROT = 5.0;
      default NAVDATA_LENGTH_MOD_GALLOP = 10.0;
      default NAVDATA_LENGTH_MOD_CANTER = 15.0;

      private function PerformNavDataTest() : bool
      {
      var startPoint, endPoint : Vector;
      var initialHeading : Vector;
      var lengthMod : float;

      startPoint = parent.GetWorldPosition();
      initialHeading = parent.GetHeadingVector();

      if( currSpeed <= TROT_SPEED )
      {
      lengthMod = NAVDATA_LENGTH_MOD_TROT;
      }
      else if( currSpeed == GALLOP_SPEED )
      {
      lengthMod = NAVDATA_LENGTH_MOD_GALLOP;
      }
      else
      {
      lengthMod = NAVDATA_LENGTH_MOD_CANTER;
      }

      endPoint = startPoint + initialHeading * lengthMod;

      if( theGame.GetWorld().NavigationLineTest( startPoint, endPoint, NAVDATA_RADIUS, false, true ) )
      {
      return true;
      }

      return false;
      }

      const var INCLINATION_MAX_ANGLE : float;
      const var INCLINATION_BASE_DIST : float;
      const var INCLINATION_TESTS_COUNT_TROT : int;
      const var INCLINATION_TESTS_COUNT_GALLOP : int;
      const var INCLINATION_TESTS_COUNT_CANTER : int;
      const var INCLINATION_Z_OFFSET : float;

      default INCLINATION_MAX_ANGLE = 45.0;
      default INCLINATION_BASE_DIST = 2.0;
      default INCLINATION_TESTS_COUNT_TROT = 2;
      default INCLINATION_TESTS_COUNT_GALLOP = 4;
      default INCLINATION_TESTS_COUNT_CANTER = 6;
      default INCLINATION_Z_OFFSET = 2.1;

      private function PerformInclinationTest( stickInputX : float, stickInputY : float ) : bool
      {
      var startPoint, rawEndPoint, tempEndPoint : Vector;
      var linkingStartPoint, linkingEndPoint, linkingTempPoint, normal : Vector;
      var initialHeading : Vector;
      var inputVec : Vector;
      var horseHeadingVec : Vector;
      var angle : float;
      var i, iterationsCount : int;
      var speed : float;

      startPoint = parent.GetWorldPosition();
      speed = MaxF( currSpeed, destSpeed );


      if( stickInputX || stickInputY )
      {
      inputVec = GetInputVectorInCamSpace( stickInputX, stickInputY );
      horseHeadingVec = parent.GetHeadingVector();

      initialHeading = VecNormalize2D( inputVec * 0.5 + horseHeadingVec * 1.0 );
      }
      else
      {
      initialHeading = parent.GetHeadingVector();
      }

      if( speed <= TROT_SPEED )
      {
      iterationsCount = INCLINATION_TESTS_COUNT_TROT;
      }
      else if( speed == GALLOP_SPEED )
      {
      iterationsCount = INCLINATION_TESTS_COUNT_GALLOP;
      }
      else
      {
      iterationsCount = INCLINATION_TESTS_COUNT_CANTER;
      }

      if( thePlayer.GetIsHorseRacing() )
      {
      iterationsCount = (int)( MaxF( 2.0, ( iterationsCount / 2 ) ) );
      }

      for( i = 0; i < iterationsCount; i += 1 )
      {
      rawEndPoint = startPoint + initialHeading * INCLINATION_BASE_DIST;
      angle = GetInclinationBetweenPoints( startPoint, rawEndPoint, tempEndPoint, INCLINATION_Z_OFFSET );

      if( angle == 180.0 )
      return false;

      if( i < 2 && !thePlayer.GetIsHorseRacing() )
      {
      linkingStartPoint = startPoint;
      linkingStartPoint.Z += 2.35;
      linkingEndPoint = tempEndPoint;
      linkingEndPoint.Z += 0.5;

      if( theGame.GetWorld().StaticTrace( linkingStartPoint, linkingEndPoint, linkingTempPoint, normal, inclinationCheckCollisionGroups ) )
      return false;
      }

      if( angle < -INCLINATION_MAX_ANGLE )
      {

      return false;
      }
      else if( angle > INCLINATION_MAX_ANGLE && !thePlayer.GetIsHorseRacing() )
      {
      if( currSpeed > TROT_SPEED )
      {
      destSpeed = MinF( currSpeed, TROT_SPEED );
      }
      else
      {
      return false;
      }
      }

      switch( i )
      {
      case 0:
      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c1', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
      break;
      case 1:
      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c2', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
      break;
      case 2:
      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c3', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
      break;
      case 3:
      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c4', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
      break;
      case 4:
      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c5', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
      break;
      default:
      break;
      }



      startPoint = tempEndPoint;
      }

      return true;
      }

      private function GetInclinationBetweenPoints( startPoint : Vector, rawEndPoint : Vector, out endPoint : Vector, zOffset : float ) : float
      {

      var rawEndPointWithZOffsetUp, rawEndPointWithZOffsetDown, normal : Vector;
      var heightDiff : float;

      rawEndPointWithZOffsetUp = rawEndPoint;
      rawEndPointWithZOffsetUp.Z += zOffset;
      rawEndPointWithZOffsetDown = rawEndPoint;
      rawEndPointWithZOffsetDown.Z -= zOffset;

      if( !theGame.GetWorld().SweepTest( rawEndPointWithZOffsetUp, rawEndPointWithZOffsetDown, 0.05, endPoint, normal, inclinationCheckCollisionGroups ) )
      {
      return 180.0;
      }




      if( startPoint.Z * endPoint.Z >= 0 )
      {
      heightDiff = AbsF( startPoint.Z - endPoint.Z );
      }
      else
      {
      heightDiff = AbsF( startPoint.Z ) + AbsF( endPoint.Z );
      }

      if( startPoint.Z >= endPoint.Z )
      {
      return -Rad2Deg( AtanF( heightDiff, INCLINATION_BASE_DIST ) );
      }
      else
      {
      return Rad2Deg( AtanF( heightDiff, INCLINATION_BASE_DIST ) );
      }
      }

      private function GetLocalInclination( optional inPoint : Vector ) : float
      {
      var startPoint, rawEndPoint, tempEndPoint : Vector;
      var initialHeading : Vector;

      if( inPoint != Vector( 0, 0, 0 ) )
      startPoint = inPoint;
      else
      startPoint = parent.GetWorldPosition();

      initialHeading = parent.GetHeadingVector();
      rawEndPoint = startPoint + initialHeading * 1.5;

      return GetInclinationBetweenPoints( startPoint, rawEndPoint, tempEndPoint, 2.0 );
      }

      const var WATER_MAX_DEPTH : float;
      const var WATER_DIST_TROT : float;
      const var WATER_DIST_GALLOP : float;
      const var WATER_DIST_CANTER : float;

      default WATER_MAX_DEPTH = 2.0;
      default WATER_DIST_TROT = 3;
      default WATER_DIST_GALLOP = 8;
      default WATER_DIST_CANTER = 10;

      private function PerformWaterTest( stickInputX : float, stickInputY : float ) : bool
      {
      var startPoint, endPoint, cachedEndPoint, bridgeCheckUp, bridgeCheckDown, bridgeCheckOutPoint, normal : Vector;
      var initialHeading : Vector;
      var inputVec : Vector;
      var horseHeadingVec : Vector;
      var waterDepth : float;
      var speed : float;

      startPoint = parent.GetWorldPosition();
      speed = MaxF( currSpeed, destSpeed );

      if( stickInputX || stickInputY )
      {
      inputVec = GetInputVectorInCamSpace( stickInputX, stickInputY );
      horseHeadingVec = parent.GetHeadingVector();

      initialHeading = VecNormalize2D( inputVec * 0.5 + horseHeadingVec * 1.0 );
      }
      else
      {
      initialHeading = parent.GetHeadingVector();
      }

      if( speed <= TROT_SPEED )
      {
      endPoint = startPoint + initialHeading * WATER_DIST_TROT;
      cachedEndPoint = endPoint;
      endPoint.Z += WATER_DIST_TROT + 1.0;
      }
      else if( speed == GALLOP_SPEED )
      {
      endPoint = startPoint + initialHeading * WATER_DIST_GALLOP;
      cachedEndPoint = endPoint;
      endPoint.Z += WATER_DIST_GALLOP + 1.0;
      }
      else
      {
      endPoint = startPoint + initialHeading * WATER_DIST_CANTER;
      cachedEndPoint = endPoint;
      endPoint.Z += WATER_DIST_CANTER + 1.0;
      }


      bridgeCheckUp = cachedEndPoint;
      bridgeCheckUp.Z += 5.0;
      bridgeCheckDown = cachedEndPoint;
      bridgeCheckDown.Z -= 10.0;
      if( theGame.GetWorld().SweepTest( bridgeCheckUp, bridgeCheckDown, 0.05, bridgeCheckOutPoint, normal, waterCheckCollisionGroups ) )
      {
      return true;
      }

      waterDepth = theGame.GetWorld().GetWaterDepth( endPoint, true );

      if( waterDepth < WATER_MAX_DEPTH || waterDepth == 10000.0 )
      {

      return true;
      }
      else
      {



      return false;
      }
      }





      private function PerformWaterJumpTest() : bool
      {
      var startPoint, endPoint, endPointWithBuffer, bridgeCheckUp, bridgeCheckDown, bridgeCheckOutPoint, normal : Vector;
      var initialHeading : Vector;
      var horseHeadingVec : Vector;
      var waterDepth : float;
      var testedPoints : array<Vector>;
      var i : int;

      startPoint = parent.GetWorldPosition();
      initialHeading = parent.GetHeadingVector();

      if( currSpeed <= TROT_SPEED )
      {
      endPoint = startPoint + initialHeading * 5.0;
      endPointWithBuffer = startPoint + initialHeading * 10.0;
      }
      else if( currSpeed == GALLOP_SPEED )
      {
      endPoint = startPoint + initialHeading * 8.0;
      endPointWithBuffer = startPoint + initialHeading * 14.0;
      }
      else
      {
      endPoint = startPoint + initialHeading * 9.0;
      endPointWithBuffer = startPoint + initialHeading * 22.0;
      }



      testedPoints.PushBack( endPoint );
      testedPoints.PushBack( endPointWithBuffer );

      for( i = 0; i < 2; i += 1 )
      {

      bridgeCheckUp = testedPoints[i];
      bridgeCheckUp.Z += 5.0;
      bridgeCheckDown = testedPoints[i];
      bridgeCheckDown.Z -= 10.0;
      if( !theGame.GetWorld().SweepTest( bridgeCheckUp, bridgeCheckDown, 0.05, bridgeCheckOutPoint, normal, waterCheckCollisionGroups ) )
      {
      waterDepth = theGame.GetWorld().GetWaterDepth( testedPoints[i], true );





      if( waterDepth > WATER_MAX_DEPTH && waterDepth != 10000.0 )
      {
      return false;
      }
      }
      else
      {


      }
      }

      return true;
      }

      private function PerformFallJumpTest() : bool
      {
      var startPoint, endPoint, endPointWithZOffsetUp, endPointWithZOffsetDown, intersectionPoint, tempVector : Vector;
      var afterLandingEndPoint : Vector;
      var initialHeading : Vector;
      var anticipationDist : float;
      var afterLandingDist : float;
      var angle : float;

      startPoint = parent.GetWorldPosition();
      initialHeading = parent.GetHeadingVector();

      if( currSpeed <= TROT_SPEED )
      {
      anticipationDist = 5.0;
      afterLandingDist = 4.0;
      }
      else if( currSpeed == GALLOP_SPEED )
      {
      anticipationDist = 7.0;
      afterLandingDist = 5.0;
      }
      else
      {
      anticipationDist = 9.0;
      afterLandingDist = 6.0;
      }

      endPoint = startPoint + initialHeading * anticipationDist;


      endPointWithZOffsetUp = endPoint;
      endPointWithZOffsetUp.Z += 10.0;
      endPointWithZOffsetDown = endPoint;

      if( theGame.GetWorld().StaticTrace( endPointWithZOffsetUp, endPointWithZOffsetDown, intersectionPoint, tempVector, inclinationCheckCollisionGroups ) )
      {

      afterLandingEndPoint = intersectionPoint + initialHeading * afterLandingDist;
      angle = GetInclinationBetweenPoints( intersectionPoint, afterLandingEndPoint, tempVector, 4.5 );





      if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE )
      {
      return false;
      }
      else
      {

      angle = GetInclinationBetweenPoints( afterLandingEndPoint, afterLandingEndPoint - parent.GetWorldRight()*0.5 , tempVector, 4.5 );
      if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE || angle > 90 )
      {
      return false;
      }


      angle = GetInclinationBetweenPoints( afterLandingEndPoint, afterLandingEndPoint + parent.GetWorldRight()*0.5 , tempVector, 4.5 );
      if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE || angle > 90 )
      {
      return false;
      }


      angle = GetLocalInclination( tempVector );
      if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE )
      return false;
      else
      return true;
      }
      }


      endPointWithZOffsetUp = endPoint;
      endPointWithZOffsetDown = startPoint + initialHeading * ( anticipationDist + 4.0 );
      endPointWithZOffsetDown.Z -= 8.0;

      if( !theGame.GetWorld().StaticTrace( endPointWithZOffsetUp, endPointWithZOffsetDown, intersectionPoint, tempVector, inclinationCheckCollisionGroups ) )
      {
      return false;
      }
      else
      {

      afterLandingEndPoint = intersectionPoint + initialHeading * afterLandingDist;
      angle = GetInclinationBetweenPoints( intersectionPoint, afterLandingEndPoint, tempVector, 4.5 );



      if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE )
      {
      return false;
      }
      else
      {

      angle = GetLocalInclination( tempVector );
      if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE )
      return false;
      else
      return true;
      }
      }

      return true;
      }

      private function PerformObstructionJumpTest() : bool
      {
      var startPoint, endPoint, tempEndPoint, normal : Vector;
      var initialHeading : Vector;

      startPoint = parent.GetWorldPosition();
      initialHeading = parent.GetHeadingVector();
      endPoint = startPoint + initialHeading * 3.0;

      startPoint.Z += 1.5;
      endPoint.Z += 1.5;

      if( theGame.GetWorld().StaticTrace( startPoint, endPoint, tempEndPoint, normal, inclinationCheckCollisionGroups ) )
      {
      return false;
      }

      return true;
      }

      private function PerformAutoJumpTest( stickInputX : float, stickInputY : float ) : bool
      {
      var startPoint : Vector;
      var testedHeading : Vector;
      var inputVec : Vector;
      var horseHeadingVec : Vector;
      var furthestAccessiblePointForJumpTest : Vector;
      var angleDistanceBetweenInputAndHorse : float;
      var angleDistanceBetweenCameraAndHorse : float;
      var anticipationDist : float;
      var afterLandingDist : float;

      startPoint = parent.GetWorldPosition();


      if( stickInputX || stickInputY )
      {
      inputVec = GetInputVectorInCamSpace( stickInputX, stickInputY );
      horseHeadingVec = parent.GetHeadingVector();

      testedHeading = VecNormalize2D( inputVec * 0.25 + horseHeadingVec * 1.0 );
      }
      else
      {
      testedHeading = parent.GetHeadingVector();
      }


      if( theInput.IsActionPressed( 'Canter' ) )
      {
      if( !LineTest( startPoint, testedHeading, 2.5, 1.0, furthestAccessiblePointForJumpTest, true ) )
      {
      if( SweepTest( startPoint, testedHeading, anticipationDist, 0.9, 0.45 ) )
      {
      return false;
      }

      angleDistanceBetweenInputAndHorse = AbsF( AngleDistance( VecHeading( inputVec ), parent.GetHeading() ) );
      angleDistanceBetweenCameraAndHorse = AbsF( AngleDistance( VecHeading( theCamera.GetCameraDirection() ), parent.GetHeading() ) );
      if( ( !( stickInputX || stickInputY ) && angleDistanceBetweenCameraAndHorse <= 45 ) || ( ( stickInputX || stickInputY ) && angleDistanceBetweenInputAndHorse <= 45 ) )
      {
      if( currSpeed == CANTER_SPEED )
      {
      anticipationDist = 8.0;
      afterLandingDist = 4.0;
      }
      else
      {
      anticipationDist = 6.5;
      afterLandingDist = 3.0;
      }

      if( CircleTest( startPoint, testedHeading, anticipationDist, 0.5 ) )
      {
      if( SweepTest( startPoint, testedHeading, anticipationDist, 2.1, 0.75 ) )
      {
      if( LineTest( startPoint + testedHeading * anticipationDist, testedHeading, afterLandingDist, 0.0, furthestAccessiblePointForJumpTest ) )
      {
      return true;
      }
      }
      }
      }
      }
      }

      return false;
      }

      private function GetInputVectorInCamSpace( stickInputX : float, stickInputY : float ) : Vector
      {
      var inputVec : Vector;
      var inputHeading : float;

      inputVec.X = stickInputX;
      inputVec.Y = stickInputY;
      inputVec = VecNormalize2D(inputVec);
      inputHeading = AngleDistance( theCamera.GetCameraHeading(), -VecHeading( inputVec ) );
      inputVec = VecFromHeading( inputHeading );

      return inputVec;
      }

      private function GetInputVectorInLocalSpace( stickInputX : float, stickInputY : float ) : Vector
      {
      var inputVec : Vector;
      var inputHeading : float;

      inputVec.X = stickInputX;
      inputVec.Y = stickInputY;
      inputVec = VecNormalize2D(inputVec);
      inputHeading = AngleDistance( parent.GetEntity().GetHeading(), -VecHeading( inputVec ) );
      inputVec = VecFromHeading( inputHeading );

      return inputVec;
      }





      private const var NAVTEST_RADIUS : float;

      default NAVTEST_RADIUS = 0.2;

      private function LineTest( startPos : Vector, heading : Vector, anticipationDist : float, speedFactor : float, out furthestAccessiblePoint : Vector, optional sideTests : bool ) : bool
      {
      var endPos : Vector;
      var endPosLeft, endPosRight : Vector;

      endPos = startPos + heading * anticipationDist + ( parent.GetHeadingVector() * speedFactor * currSpeed );

      if( theGame.GetWorld().NavigationLineTest( startPos, endPos, NAVTEST_RADIUS, false, true ) )
      {

      return true;
      }
      else if( sideTests )
      {


      endPosLeft = startPos + VecRotateAxis( endPos - startPos, Vector( 0, 0, 1 ), Deg2Rad( 30.0 ) );
      endPosRight = startPos + VecRotateAxis( endPos - startPos, Vector( 0, 0, 1 ), Deg2Rad( -30.0 ) );

      if( theGame.GetWorld().NavigationLineTest( startPos, endPosLeft, NAVTEST_RADIUS, false, true ) )
      {

      return true;
      }
      else if ( theGame.GetWorld().NavigationLineTest( startPos, endPosRight, 0.15, false, true ) )
      {


      return true;
      }
      else
      {


      theGame.GetWorld().NavigationClearLineInDirection( startPos, endPos, NAVTEST_RADIUS, furthestAccessiblePoint );
      return false;
      }

      }
      else
      {

      theGame.GetWorld().NavigationClearLineInDirection( startPos, endPos, NAVTEST_RADIUS, furthestAccessiblePoint );
      return false;
      }
      }

      private function CircleTest( startPos : Vector, heading : Vector, anticipationDist : float, radius : float ) : bool
      {
      var endPos : Vector;
      var dummyFloat : float;

      endPos = startPos + heading * anticipationDist;




      if( theGame.GetWorld().NavigationCircleTest( endPos, radius ) )
      {
      if( theGame.GetWorld().NavigationComputeZ( endPos, endPos.Z - 4.0, endPos.Z + 1.0, dummyFloat ) )
      {
      return true;
      }
      else
      {
      return false;
      }
      }
      else
      {
      return false;
      }
      }

      private function SweepTest( startPos : Vector, heading : Vector, anticipationDist : float, heightOffset : float, radius : float ) : bool
      {
      var endPos, outPos, normal : Vector;

      endPos = startPos + heading * anticipationDist;

      startPos.Z += heightOffset;
      endPos.Z += heightOffset;




      if( !theGame.GetWorld().SweepTest( startPos, endPos, radius, outPos, normal, inclinationCheckCollisionGroups ) )
      return true;
      else
      return false;
      }





      private var rl, fb : float;
      private final function UpdateLogic( dt : float )
      {
      var actorParent : CActor;
      var player : W3PlayerWitcher;
      var slidingDisablesControll : bool;

      if( GetSubmergeDepth() < -2.f || CheckSliding( slidingDisablesControll ) )
      OnHideHorse();

      if( roadFollowBlock > 0.0 )
      {
      roadFollowBlock -= dt;
      if( roadFollowBlock < 0.0 )
      roadFollowBlock = 0.0;
      }

      useSimpleStaminaManagement = parent.ShouldUseSimpleStaminaManagement();

      if( thePlayer.GetIsMovable() && IsHorseControllable() && !dismountRequest && !slidingDisablesControll )
      {
      rl = theInput.GetActionValue( 'GI_AxisLeftX' );
      fb = theInput.GetActionValue( 'GI_AxisLeftY' );
      }
      else
      {
      rl = 0.0;
      fb = 0.0;
      }

      parent.inputApplied = rl || fb;

      SetTimeoutForCurrentSpeed();
      MaintainCameraVariables( dt );
      MaintainGrassCollider();

      if( ( !useSimpleStaminaManagement && destSpeed > GALLOP_SPEED ) || ( !IsSpeedLocked() && destSpeed > MIN_SPEED && !rl && !fb ) || ( !IsSpeedLocked() && destSpeed > TROT_SPEED ) )
      {
      if( maintainSpeedTimer > speedTimeoutValue )
      {
      destSpeed = MaxF( MIN_SPEED, destSpeed - 1.f );
      maintainSpeedTimer = 0.0;
      }
      else
      {
      maintainSpeedTimer += dt;
      }
      }

      actorParent = (CActor)parent.GetEntity();

      if ( useSimpleStaminaManagement && currSpeed > GALLOP_SPEED && !isFollowingRoad )
      {
      actorParent.DrainStamina( ESAT_FixedValue, 3.33f*dt, 1.f, '', 0.f, 1.f );

      if ( actorParent.GetStat( BCS_Stamina ) <= 0.f )
      {
      staminaBreak = true;
      staminaCooldownTimer = 0.f;
      theGame.VibrateControllerVeryLight();
      }
      }

      destSpeed = MinF( destSpeed, speedRestriction );

      if( currSpeed > destSpeed && currSpeed < GALLOP_SPEED )
      PlayVoicesetSlowerHorse();

      ProcessControlInput( rl, fb, dt, parent.IsControllableInLocalSpace() || parent.riderSharedParams.mountStatus == VMS_mountInProgress );

      // START modRoachNeverStops
      if( !PerformNavDataTest() && !isInJumpAnim )
      {
      //if( PerformInclinationTest( rl, fb ) && PerformWaterTest( rl, fb ) )
      if( PerformWaterTest( rl, fb ) ) // ++Mod Water Check Only
      {
      ToggleSpeedLock( 'OnNavStop', false );

      if( PerformAutoJumpTest( rl, fb ) )
      {
      Jump();
      }
      }
      else if( !isFollowingRoad && !parent.ShouldIgnoreTests() )
      {
      destSpeed = MIN_SPEED;
      ToggleSpeedLock( 'OnNavStop', true );
      if( !isRefusingToGo && parent.isInIdle && CanPlayCollisionAnim() && ( rl != 0.0 || fb != 0.0 ) )
      {
      parent.GenerateEvent( 'WallCollision' );
      collisionAnimTimestamp = theGame.GetEngineTimeAsSeconds();
      }
      }
      else
      {
      ToggleSpeedLock( 'OnNavStop', false );
      }
      }
      else
      {
      ToggleSpeedLock( 'OnNavStop', false );
      }
      //ToggleSpeedLock( 'OnNavStop', false ); // ++Mod Water Check Only
      // END modRoachNeverStops

      if( requestJump )
      {
      if( PerformObstructionJumpTest() && PerformWaterJumpTest() && PerformFallJumpTest() )
      {
      Jump();
      }
      else
      {
      if( !isRefusingToGo && parent.isInIdle && CanPlayCollisionAnim() )
      {
      parent.GenerateEvent( 'WallCollision' );
      collisionAnimTimestamp = theGame.GetEngineTimeAsSeconds();
      }
      requestJump = false;
      }
      }

      if( staminaBreak )
      {
      if ( staminaCooldownTimer > staminaCooldown )
      {
      staminaBreak = false;
      }

      staminaCooldownTimer += dt;

      currSpeed = MinF( GALLOP_SPEED, currSpeed );
      destSpeed = currSpeed;
      }


      if ( currSpeed != destSpeed )
      {
      currSpeed = destSpeed;
      if ( currSpeed == MIN_SPEED && !parent.isInIdle )
      isSlowlyStopping = true;
      else
      isSlowlyStopping = false;
      }

      parent.InternalSetSpeedMultiplier( 1.f );
      parent.InternalSetSpeed( currSpeed );


      CalculateSoundParameters( dt );
      thePlayer.SoundParameter( "horse_speed", currSpeedSound, 'head' );
      actorParent.SoundParameter( "horse_stamina", actorParent.GetStatPercents( BCS_Stamina ) * 100 );
      }

      private var startSlidingTimeStamp : float;
      private var notSlidingTimeStamp : float;

      private const var SLIDING_MINSLIDINGCOEF : float;
      private const var SLIDING_MAXSLIDINTIME : float;
      private const var SLIDING_MAXROTATIONSPEED: float;

      default SLIDING_MINSLIDINGCOEF = 0.4f;
      default SLIDING_MAXSLIDINTIME = 2.5f;
      default SLIDING_MAXROTATIONSPEED = 60.f;

      private final function CheckSliding( out _slidingDisablesControll : bool ) : bool
      {
      var mac : CMovingPhysicalAgentComponent;
      var movementAdjustor: CMovementAdjustor;
      var ticket, emptyTicket: SMovementAdjustmentRequestTicket;
      var l_sliding, l_onGround : bool;
      var l_slidingTime, l_slideCoef : float;
      var l_slideDir : Vector;

      _slidingDisablesControll = false;

      mac = (CMovingPhysicalAgentComponent)parentActor.GetMovingAgentComponent();

      if ( mac )
      {
      l_sliding = mac.IsSliding();
      l_onGround = mac.IsOnGround();

      if ( l_sliding || ( !l_onGround && !isInJumpAnim ) )
      {
      notSlidingTimeStamp = -1.f;

      if ( startSlidingTimeStamp <= 0.f )
      startSlidingTimeStamp = theGame.GetEngineTimeAsSeconds();

      if ( l_sliding )
      {
      l_slideDir = mac.GetSlideDir();
      l_slideCoef = mac.GetSlideCoef();



      LogChannel('HorseSliding',"Sliding Coef: " + l_slideCoef );
      movementAdjustor = mac.GetMovementAdjustor();
      ticket = movementAdjustor.GetRequest('HorseSliding');
      if ( ticket == emptyTicket )
      ticket = movementAdjustor.CreateNewRequest('HorseSliding');
      movementAdjustor.MaxRotationAdjustmentSpeed( ticket,SLIDING_MAXROTATIONSPEED );
      movementAdjustor.RotateTo(ticket,VecHeading( l_slideDir ) );
      _slidingDisablesControll = true;
      }

      l_slidingTime = theGame.GetEngineTimeAsSeconds() - startSlidingTimeStamp;

      if ( l_slidingTime >= SLIDING_MAXSLIDINTIME && l_slideCoef >= SLIDING_MINSLIDINGCOEF )
      {
      LogChannel('HideHorse',"Hide reason: slidingTime: " + l_slidingTime + " and slideCoef: " + l_slideCoef);
      return true;
      }
      }
      else
      {
      movementAdjustor = mac.GetMovementAdjustor();
      movementAdjustor.CancelByName('HorseSliding');
      mac.SetEnabledFeetIK( true, 0.5 );
      if ( notSlidingTimeStamp <= 0 )
      notSlidingTimeStamp = theGame.GetEngineTimeAsSeconds();


      if ( theGame.GetEngineTimeAsSeconds() - notSlidingTimeStamp >= 0.5 )
      {
      if ( startSlidingTimeStamp > 0.f )
      {
      l_slidingTime = theGame.GetEngineTimeAsSeconds() - startSlidingTimeStamp;
      LogChannel('HorseSliding',"Sliding Stopped. Slide time: " + l_slidingTime );
      }
      startSlidingTimeStamp = -1.f;
      }
      }
      }

      return false;
      }






      private var requestJump : bool;
      private var isInJumpAnim : bool;

      private final function Jump()
      {
      if( !((CActor)parent.GetEntity()).IsInAir() )
      {
      parent.GenerateEvent( 'jump' );
      }

      requestJump = false;
      }

      event OnBehJumpStarted()
      {
      var horse : CActor;
      horse = (CActor)parent.GetEntity();

      isInJumpAnim = true;
      requestJump = false;
      startTestingLanding = false;
      jumpStartPos = parent.GetEntity().GetWorldPosition();

      parent.SetVariable( 'onGround', 0.f );

      horse.AddAnimEventChildCallback(parent,'Jumping','OnAnimEvent_Jumping');
      ((CMovingPhysicalAgentComponent)horse.GetMovingAgentComponent()).SetAnimatedMovement( true );
      horse.SetIsInAir(true);

      parent.userCombatManager.OnAirBorn();
      theGame.CreateNoSaveLock( 'horse_in_air', noSaveLock );

      theGame.GetGuiManager().DisableHudHoldIndicator();
      }

      event OnBehJumpEnded()
      {
      var horse : CActor;
      horse = (CActor)parent.GetEntity();

      horse.RemoveAnimEventChildCallback(parent,'Jumping');

      isInJumpAnim = false;
      theGame.ReleaseNoSaveLock( noSaveLock );
      if ( parent.user == thePlayer )
      theGame.GetGuiManager().EnableHudHoldIndicator(IK_Pad_B_CIRCLE, IK_None, "panel_input_action_horsedismount", 0.4, 'HorseDismount');
      }

      event OnHideHorse()
      {
      parent.OnHideHorse();
      }

      event OnKillHorse()
      {
      parent.OnKillHorse();
      }

      private var startTestingLanding : bool;

      event OnAnimEvent_Jumping( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
      {
      var mac : CMovingPhysicalAgentComponent;
      if( animEventType == AET_DurationStart )
      {
      startTestingLanding = true;
      }
      else
      {
      mac = (CMovingPhysicalAgentComponent)((CActor)parent.GetEntity()).GetMovingAgentComponent();
      if( mac.IsOnGround() )
      OnHitGround();
      }
      }

      event OnHitGround()
      {
      var horse : CActor;
      horse = (CActor)parent.GetEntity();

      if( horse.IsInAir() && startTestingLanding )
      {
      jumpEndPos = parent.GetEntity().GetWorldPosition();

      if( parent.CanTakeDamageFromFalling() )
      {
      ((CGameplayEntity)parent.GetEntity()).OnDamageFromFalling( parent, 0.0, -(jumpStartPos.Z - jumpEndPos.Z) + 5.0 );
      }
      else
      {
      parent.SetCanTakeDamageFromFalling( true );
      }

      EndJump();

      theGame.VibrateControllerLight();
      if ( parent.user == thePlayer )
      theGame.GetGuiManager().EnableHudHoldIndicator(IK_Pad_B_CIRCLE, IK_None, "panel_input_action_horsedismount", 0.4, 'HorseDismount');
      }
      }

      function EndJump()
      {
      var horse : CActor;
      horse = (CActor) parent.GetEntity();

      if ( horse && horse.IsInAir() )
      {
      parent.SetVariable( 'onGround', 1.f );

      ((CMovingPhysicalAgentComponent)horse.GetMovingAgentComponent()).SetAnimatedMovement( false );
      horse.SetIsInAir( false );

      parent.userCombatManager.OnLanded();
      }
      }

      event OnCheckHorseJump()
      {
      return isInJumpAnim;
      }





      private var maintainSpeedTimer : float;
      private var speedTimeoutValue : float;
      private var accelerateTimestamp : float;
      private const var DOUBLE_TAP_WINDOW: float;

      default DOUBLE_TAP_WINDOW = 0.4;

      private function CanCanter() : bool
      {
      return true; // ++Mod Gallop in Settlements
      //return ( thePlayer.m_SettlementBlockCanter < 1 ) || ( thePlayer.GetIsHorseRacing() ); // ++Mod Gallop in Settlements
      }


      event OnSpeedPress( action : SInputAction )
      {
      var actorParent : CActor;

      if( IsHorseControllable() && !dismountRequest && thePlayer.IsActionAllowed( EIAB_Movement ) )
      {
      if( IsPressed( action ) )
      {

      if( accelerateTimestamp + DOUBLE_TAP_WINDOW >= theGame.GetEngineTimeAsSeconds() )
      {
      triedDoubleTap = true;
      }
      else
      {
      triedDoubleTap = false;
      }

      if(CanCanter() && (!IsSpeedLocked() || speedLocks.Contains( 'OnAttack' )) )
      {
      if( currSpeed >= CANTER_SPEED )
      {
      destSpeed = CANTER_SPEED;
      ToggleSpeedLock( 'OnGallop', true );
      }
      else if(triedDoubleTap)
      {
      destSpeed = CANTER_SPEED;

      SpursKick();

      if( useSimpleStaminaManagement )
      ToggleSpeedLock( 'OnGallop', true );
      }

      if( !FactsDoesExist("debug_fact_stamina_pony") && !useSimpleStaminaManagement )
      {
      if( destSpeed > GALLOP_SPEED )
      {
      actorParent = (CActor)parent.GetEntity();
      actorParent.DrainStamina( ESAT_Sprint, 0.f, speedTimeoutValue );

      if( actorParent.GetStat( BCS_Stamina ) < 0.1f )
      {
      staminaBreak = true;
      staminaCooldownTimer = 0.f;
      }
      }
      }
      }

      accelerateTimestamp = theGame.GetEngineTimeAsSeconds();
      maintainSpeedTimer = 0.f;
      }
      else if( IsReleased( action ) )
      {
      shouldGoToCanterAfterStop = false;
      ToggleSpeedLock( 'OnGallop', false );
      }
      }
      }


      event OnSpeedHold( action : SInputAction )
      {
      var horseCompToFollow : W3HorseComponent;

      thePlayer.SetBehaviorVariable( 'playerWouldLikeToMove', 1.0f );

      if( IsHorseControllable() && IsPressed( action ) && !dismountRequest )
      {
      if ( !IsSpeedLocked() && OnCanCanter() )
      {

      GallopPressed();
      SpursKick();
      }
      }
      else if( IsReleased( action ) )
      {
      ToggleSpeedLock( 'OnGallop', false );
      }


      if( triedDoubleTap && !CanCanter() && IsPressed( action ) )
      {
      //thePlayer.DisplayActionDisallowedHudMessage( EIAB_Undefined, , thePlayer.m_SettlementBlockCanter >= 1 ); // ++Mod Gallop in Settlements
      }
      }

      event OnDecelerate( action : SInputAction )
      {
      if( IsReleased( action ) )
      {
      if( IsHorseControllable() && !IsRiderInCombatAction() && !dismountRequest )
      {
      if( currSpeed == MIN_SPEED )
      {
      parent.GenerateEvent( 'rearing' );
      }
      }
      }
      }

      event OnStop( action : SInputAction )
      {
      if( IsPressed( action ) && IsHorseControllable() && !dismountRequest )
      {
      destSpeed = MIN_SPEED;
      ToggleSpeedLock( 'OnStop', true );

      if(ShouldProcessTutorial('TutorialHorseStop'))
      {
      FactsAdd("tut_horse_stopping");
      }
      }
      else if( IsReleased( action ) )
      {
      ToggleSpeedLock( 'OnStop', false );
      parent.InternalSetDirection( 0.f );
      if(ShouldProcessTutorial('TutorialHorseStop'))
      {
      FactsRemove("tut_horse_stopping");
      }
      }
      }

      private var jumpPressTimestamp : float;

      event OnHorseJump( action : SInputAction )
      {
      var dummyParameter : Vector;

      if ( IsPressed( action ) )
      jumpPressTimestamp = theGame.GetEngineTimeAsSeconds();

      if ( thePlayer.playerAiming.GetCurrentStateName() == 'Aiming' )
      return false;

      if( IsHorseControllable() && !IsRiderInCombatAction() && parent.IsFullyMounted() && parent.GetPanicPercent() < 0.99 )
      {
      if( !dismountRequest && IsReleased( action ) && ( jumpPressTimestamp + 0.2 > theGame.GetEngineTimeAsSeconds() )&& thePlayer.GetIsMovable() && !isInJumpAnim )
      {
      requestJump = true;

      }
      }
      }

      event OnHorseDismountKeyboard( action : SInputAction )
      {
      if( IsPressed( action ) )
      {
      if( !DismountHorse() )
      {
      theInput.ForceDeactivateAction('HorseJump');
      }
      else
      {
      theGame.GetGuiManager().DisableHudHoldIndicator();
      }
      }
      }

      event OnHorseDismount()
      {
      if( !DismountHorse() )
      {
      theInput.ForceDeactivateAction('HorseJump');
      }
      else
      {
      theGame.GetGuiManager().DisableHudHoldIndicator();
      }
      }

      private function DismountHorse() : bool
      {
      if ( thePlayer.IsActionAllowed( EIAB_DismountVehicle ) && !IsRiderInCombatAction() && !isInJumpAnim && !dismountRequest && parent.canDismount && !parent.IsInHorseAction() )
      {
      SetupDismount();
      return true;
      }
      return false;
      }

      event OnSmartDismount()
      {
      SetupDismount();
      }

      public function SetupDismount()
      {
      if( ( currSpeed == MIN_SPEED && !isSlowlyStopping ) || isStopping )
      {
      OnForceStop();
      parent.user.SetBehaviorVariable('dismountType',0.f);
      }
      else if( currSpeed >= GALLOP_SPEED && VecLength2D( GetHorseVelocity() ) > 6.0 )
      {
      parent.user.SetBehaviorVariable('dismountType',2.f);
      destSpeed = GALLOP_SPEED;
      }
      else
      {
      parent.user.SetBehaviorVariable('dismountType',1.f);
      destSpeed = TROT_SPEED;
      }

      if( !isStopping )
      parent.IssueCommandToDismount( DT_normal );

      dismountRequest = true;
      }





      private function IsRiderInCombatAction() : bool
      {
      return parent.userCombatManager.IsInCombatAction();
      }

      private final function UpdateDebugGUI()
      {
      var p : float;
      var text : string;
      var rot : EulerAngles;

      var actorParent : CActor;

      rot = parent.GetWorldRotation();

      p = currSpeed / 2.f;
      text = "Speed: " + currSpeed;

      thePlayer.GetVisualDebug().AddBarColorAreas( 'horseSpeed', 50, 50, 250, 50, p, text );

      thePlayer.GetVisualDebug().AddBar( 'horseStamina', 305, 50, 25, 50, 1.f, Color(0,0,0) );

      actorParent = (CActor)parent.GetEntity();
      if ( !staminaBreak )
      {
      text = "Stamina: " + actorParent.GetStat( BCS_Stamina );
      }
      else
      {
      text = "Stamina: " + actorParent.GetStat( BCS_Stamina ) + " <break>";
      }
      p = actorParent.GetStatPercents( BCS_Stamina );
      thePlayer.GetVisualDebug().AddBarColorSmooth( 'horseStaminaBar', 50, 110, 280, 30, p, Color(255,255,0), text );

      text = "Panic: " + actorParent.GetStat( BCS_Panic ) + " / " + actorParent.GetStatMax( BCS_Panic );
      p = actorParent.GetStatPercents( BCS_Panic );
      thePlayer.GetVisualDebug().AddBarColorAreas( 'horsePanic', 50, 150, 280, 30, p, text );

      text = "pitch: " + rot.Pitch;
      thePlayer.GetVisualDebug().AddBarColorSmooth( 'pitch', 50, 180, 280, 30, 0, Color(0,255,0), text );
      }

      private function SetTimeoutForCurrentSpeed()
      {
      switch( currSpeed )
      {
      case CANTER_SPEED:
      {
      if( thePlayer.IsInCombat() )
      speedTimeoutValue = 2.0;
      else
      speedTimeoutValue = 0.5;
      break;
      }
      case GALLOP_SPEED:
      {
      if( thePlayer.IsInCombat() )
      speedTimeoutValue = 2.0;
      else
      speedTimeoutValue = 0.5;
      break;
      }
      case TROT_SPEED:
      if ( dismountRequest )
      speedTimeoutValue = 0.5;
      else
      speedTimeoutValue = 0.0;
      break;

      case WALK_SPEED:
      if ( dismountRequest )
      speedTimeoutValue = 0.5;
      else
      speedTimeoutValue = 0.0;
      break;

      case SLOW_SPEED:
      if ( dismountRequest )
      speedTimeoutValue = 0.5;
      else
      speedTimeoutValue = 0.0;
      break;

      case MIN_SPEED:
      speedTimeoutValue = 0.0;
      break;
      }
      }

      private function IsHorseControllable() : bool
      {
      var actor : CActor;

      actor = (CActor)parent.GetEntity();

      return actor && actor.GetBaseAttitudeGroup() != 'animals_peacefull' && parent.controllable;
      }

      private function MaintainCameraVariables( dt : float )
      {
      if( currSpeed == CANTER_SPEED )
      {
      parent.inCanter = true; // ++Mod No Camera Change on Horseback, set to false
      parent.inGallop = false;
      }
      else if( currSpeed == GALLOP_SPEED )
      {
      parent.inGallop = true; // ++Mod No Camera Change on Horseback, set to false
      parent.inCanter = false;
      }
      else
      {
      parent.inCanter = false;
      parent.inGallop = false;
      }
      }

      private function MaintainGrassCollider()
      {
      if( !grassCollider )
      return;

      if( currSpeed == CANTER_SPEED )
      {
      grassCollider.SetPosition( Vector( 1.5, -0.3, 0.0, 1.0 ) );
      }
      else if( currSpeed == GALLOP_SPEED )
      {
      grassCollider.SetPosition( Vector( 1.1, -0.3, 0.0, 1.0 ) );
      }
      else
      {
      grassCollider.SetPosition( Vector( 0.7, -0.3, 0.0, 1.0 ) );
      }
      }

      private function GallopPressed()
      {
      if( OnCanCanter() )
      {
      if( currSpeed < GALLOP_SPEED && destSpeed != CANTER_SPEED )
      destSpeed = GALLOP_SPEED;

      ToggleSpeedLock( 'OnGallop', true );
      }
      }

      private function SpursKick()
      {
      if( !IsRiderInCombatAction() && currSpeed < destSpeed )
      {
      if( currSpeed != GALLOP_SPEED )
      {
      PlayVoicesetFasterHorse();

      if( destSpeed == CANTER_SPEED )
      parent.GenerateEvent( 'spursKickHard' );
      else
      parent.GenerateEvent( 'spursKick' );
      }
      }
      }

      private var voicsetTimeStamp : float;
      private var voicsetFasterTimeStamp : float;
      private var voicsetSlowerTimeSTamp : float;

      private const var VOICESET_COOLDOWN : float; default VOICESET_COOLDOWN= 2.0;
      private const var VOICESET_FASTER_COOLDOWN : float; default VOICESET_FASTER_COOLDOWN= 5.0;
      private const var VOICESET_SLOWER_COOLDOWN : float; default VOICESET_SLOWER_COOLDOWN= 5.0;

      private function PlayVoicesetFasterHorse()
      {
      var currentTime : float = theGame.GetEngineTimeAsSeconds();

      if( thePlayer.IsInGameplayScene() )
      {
      return;
      }

      if ( CanPlayVoiceset(currentTime) && voicsetFasterTimeStamp + VOICESET_FASTER_COOLDOWN <= currentTime && RandRange(100) < 25 )
      {
      if ( parent.IsPlayerHorse() )
      thePlayer.PlayVoiceset( 100,'FasterHorseRoach' );
      else
      thePlayer.PlayVoiceset( 100,'FasterHorse' );

      voicsetFasterTimeStamp = currentTime;
      voicsetTimeStamp = currentTime;
      }
      }

      private function PlayVoicesetSlowerHorse()
      {
      var currentTime : float = theGame.GetEngineTimeAsSeconds();

      if( thePlayer.IsInGameplayScene() )
      {
      return;
      }

      if ( CanPlayVoiceset(currentTime) && voicsetSlowerTimeSTamp + VOICESET_SLOWER_COOLDOWN <= currentTime && RandRange(100) < 25 )
      {
      if ( parent.IsPlayerHorse() )
      thePlayer.PlayVoiceset( 100,'SlowerHorseRoach' );
      else
      thePlayer.PlayVoiceset( 100,'SlowerHorse' );

      voicsetSlowerTimeSTamp = currentTime;
      voicsetTimeStamp = currentTime;
      }
      }

      private function CanPlayVoiceset( _currentTime : float ) : bool
      {
      return ( parent.user == GetWitcherPlayer() ) && !dismountRequest && thePlayer.IsUsingHorse() && !thePlayer.IsThreatened() && !thePlayer.IsSpeaking() && (voicsetTimeStamp + VOICESET_COOLDOWN <= _currentTime );
      }

      private function GetHorseVelocity() : Vector
      {
      return ((CActor)parent.GetEntity()).GetMovingAgentComponent().GetVelocity();
      }

      private function GetSubmergeDepth() : float
      {
      return ((CMovingPhysicalAgentComponent)((CActor)parent.GetEntity()).GetMovingAgentComponent()).GetSubmergeDepth();
      }

      private function IsHorseOnNavMesh() : bool
      {
      return ((CMovingPhysicalAgentComponent)((CActor)parent.GetEntity()).GetMovingAgentComponent()).IsOnNavigableSpace();
      }

      private function InitCollisionGroups()
      {
      inclinationCheckCollisionGroups.PushBack( 'Terrain' );
      inclinationCheckCollisionGroups.PushBack( 'Static' );
      inclinationCheckCollisionGroups.PushBack( 'Destructible' );
      inclinationCheckCollisionGroups.PushBack( 'Door' );

      waterCheckCollisionGroups.PushBack( 'Static' );
      waterCheckCollisionGroups.PushBack( 'Destructible' );
      }

      private function CalculateSoundParameters( dt : float )
      {
      if( desiredSpeedSound != currSpeed )
      {
      desiredSpeedSound = currSpeed;
      }

      currSpeedSound = InterpTo_F( currSpeedSound, desiredSpeedSound, dt, 2.0 );
      }

      private function ResetSoundParameters()
      {
      currSpeedSound = 0.0;
      desiredSpeedSound = 0.0;
      }
      }

    4. JovianStone
      JovianStone
      • supporter
      • 37 kudos
      <deleted>
      posting in wrong place
    5. hanz00
      hanz00
      • member
      • 1 kudos
      I'm sorry to necro your post from January JovianStone, but I'm trying to figure out both of your fixes but none that I do seems to be working (I got zero knowledge in programming), I've edited the line in "Mod Water Check Only" and make it exactly like yours but the horse still went straight into water and disappear afterwards.
      As for the galloping in the city I'm totally lost, I got so far as line 370 where I replace the line beneath "else" with "return false;" but from there I can't figure it out..
      When you said to comment out the text starting from line 1970 I have no idea until which line, also maybe I understand it wrong..

      Can you please (if you have the spare time) to elaborate it some more?
      Or even better can you perhaps upload the file of your edited version of this mod's "exploration.ws" for me to compare?
      Thank you in advance :D
    6. Lobuno
      Lobuno
      • member
      • 52 kudos
      @hanz00, here you are: exploration.ws_fixed.rar
    7. Nickone720
      Nickone720
      • supporter
      • 0 kudos
      That worked! Thank u!
  2. zMaZT3Rz
    zMaZT3Rz
    • supporter
    • 29 kudos
    Man it'd be nice if Roach didn't come to a full stop when you come across a small bump. Going back to this after Red Dead Redemption 2's god-like horse controls is painful
  3. DamienXIII
    DamienXIII
    • member
    • 5 kudos
    Is this mod compatible with Next-Gen Update.....?????
    1. iGPR3
      iGPR3
      • member
      • 0 kudos
      ever find out?
    2. DamienXIII
      DamienXIII
      • member
      • 5 kudos
      No.....
    3. ElementaryLewis
      ElementaryLewis
      • premium
      • 645 kudos
      No it doesn't. Try this one: Improved Horse Controls
    4. lasyan3
      lasyan3
      • member
      • 35 kudos
      Downloading the v4.04 right now, I'm gonna give a compatibility update on all my mods this week, promise ;)
    5. lasyan3
      lasyan3
      • member
      • 35 kudos
      Updated for patch 4.04!
  4. kamikad3e123
    kamikad3e123
    • member
    • 8 kudos
    Error [mod0000_mergedfiles]game\vehicles\horse\states\exploration.ws(548): Could not find function 'IsSlowMoActive'
    Error [mod0000_mergedfiles]game\vehicles\horse\states\exploration.ws(1910): Could not find function 'IsSlowMoActive'
    Error [mod0000_mergedfiles]game\vehicles\horse\states\exploration.ws(1912): Could not find function 'SetSlowMoActive'
    Error [mod0000_mergedfiles]game\vehicles\horse\states\exploration.ws(1915): Could not find function 'IsSlowMoActive'
    this mod and Alt horse control from Immersion Cam
    UPD: Sorry, my bad
    1. Eisenh31m
      Eisenh31m
      • member
      • 0 kudos
      how do you fix it?
    2. Kagezod
      Kagezod
      • member
      • 0 kudos
      Use Script Merge to Fix
  5. Daydreamer2202
    Daydreamer2202
    • supporter
    • 2 kudos
    This mod works perfectly on next gen and together with Leave Roach Alone and The Stable mod as long as you use the script merger
    1. ElementaryLewis
      ElementaryLewis
      • premium
      • 645 kudos
      Unfortunatly, this is one of the script mod that require to update to be 100% Next Gen Compatible.
      So I hope lasyan3 will look about it (or someone else).
  6. tragedya
    tragedya
    • member
    • 0 kudos
    With this mod, you can't gallop in cities and you still have stamina.
    1. ElementaryLewis
      ElementaryLewis
      • premium
      • 645 kudos
      Not the mod purpose. It's vanilla things.
  7. Snowiez
    Snowiez
    • member
    • 1 kudos
    mine still stops
  8. ElementaryLewis
    ElementaryLewis
    • premium
    • 645 kudos
    ;
  9. MerseyRockoff
    MerseyRockoff
    • premium
    • 414 kudos
    This might be the best mod on Nexus. Not kidding.
  10. fresssocke
    fresssocke
    • member
    • 0 kudos
    Can you merge it with Galloping In Cities? (http://www.nexusmods.com/witcher3/mods/385/?)
    1. lasyan3
      lasyan3
      • member
      • 35 kudos
      From what I see, all you need is to select C file on the merge conflict and that'll do the trick.
    2. aidenphillip
      aidenphillip
      • member
      • 2 kudos
      Huge thanks, it would be much better if you release a merged mod with galloping in the cities for some newbees
      Endorsed! one of the must have in Witcher 3, it's hard to play without this mod
    3. ropoooo
      ropoooo
      • member
      • 0 kudos
      Lasyan3, I thank ye!